String in C or C++
读书笔记
C语言
在C语言中,字符串指的是一个以’\0’结尾的char数组。关于字符串的函数通常需
要传入一个字符型指针。
// 注意区别
char * str1 = "hello" ; // 常量字符串!,在文字常量,编译时求值,不可修改
char str2[] = "hello" ; // char数组,运行时求值;可修改
更详细的区别和内存分区见别人博客char *c和char c[]区别
另外注意下长度sizeof 和 strlen的区别,strlen会比sizeof小1,因为’\0’的存在
几个常见函数实现
- strcpy
char *strcpy ( char *destination, const char *source ){
//copy source string to destination string
while (*destination ++ = *source ++) ;
// '\0'的ascii为第0个
// *destination ++ 为 *(destination ++); *和++在c中的优先级一样,但是从右到左的结合顺序
// 另外pa[i]在C语言中转换为*(pa +i);
}
- strcat
char *strcat ( char *destination, const char *source ){
//Appends a copy of the source string to the destination string.
while (*source != '\0')
sourse ++;
while (*destination != '\0'){
*sourse++ = *destination++;
}
}
- strcmp 相等返回0;str1 大于小于str2 返回正数或负数
int strcmp ( const char *str1, const char *str2 ){
for (; *str1 == *str2; str1++, str2++ ){
// 注意结束条件 为 "==" !
if (*str1 == '\0')
retrun 0
}
retrun *str1 - *str2;
}
- strstr 字符串匹配,重点这个实现
- Brute-Force 算法,暴力求解;顺序遍历母串str,将每个字符作为匹配的起始字符,判断是否匹配子串target。时间复杂度 O(m*n)
char *strstr (char *str, const char *target ){
if (*target == NULL) return str;
char *p1 = (char *)str;
while (*p1){
char *p1Begin = p1; // 保存返回的头节点
char *p2 = (char *)target;
while (*p1 && *p2 && *p1 == *p2 ){
p1++;
p2++;
}
if (*p2 == '\0')
return p1Begin;
p1 = p1Begin + 1;
}
return NULL;
}
另外一个为Rabin-Karp解法,其原理为将每一个匹配子串映射为一个hash值。例如,将子串看做一个多进制数,比较它的值与母串中相同长度子串的hash值,如果相同,再细致地按字符确认字符串是否确实相同。顺序计算母串hash值的过程中,使用增量计算的方法:扣除最高位的hash值,增加最低位的hash值。因此能在平均情况下做到O(m+n)。
其他可以看这个url http://www.cnblogs.com/yusenwu/p/4771993.html
- strlen
size_t strlen ( const char *str ){
// Returns the length of the C string str.
int n;
for (n = 0; *str != '\0';s++)
n ++;
return n;
}
- atoi
int atoi (constrt char *str){
// convert char string to an int
// char* b = "s500" return 0.
int i=0 , n = 0;
for (; str[i] >= '0'&&str[i]<='9';++i)
n = 10*n + (str[i]-'0');
return n;
}
- atof
// convert char string to a double
double atof(char s[]) {
double val;
double power;
int i;
int sign;
for (i = 0; isspace(s[i]); i++) //跳过空白行
;
sign = (s[i] == '-') ? -1 : 1;
if (s[i] == '-' || s[i] == '+') {
i++;
}
for (val = 0.0; isdigit(s[i]); i++) {
val = 10.0 * val + (s[i] - '0');
}
if(s[i] == '.') {
i++;
}
for (power = 1.0; isdigit(s[i]); i++) {
val = 10 * val + (s[i] - '0');
power *= 10.0; // 小数点部分
}
return val = sign * val / power;
}
另外,对于经常出现的strcpy和memmove,这里也给出
// 防止内存重叠的正确版本,dest丢失(结束到重叠的未复制的)数据,失败。
void *memmove(void *dest, const void *src, size_t n){
char *p1 = dest;
const char *p2 = src;
if (p2 < p1){
//内存重叠,p1低地址会被p2高地址覆盖
p2 += n;
p1 += n;
while ( n-- != 0)
*--p1 = * --p2; //逆向复制
} else {
while (n-- !=0)
*p1++ = *p2++; //正向复制
}
return p1;
}
C++语言
在C++中,String是一个类,并且可以通过调用类函数实现判断字符串长度,字
串等等操作。
一般面试的时候,要求实现String的构造函数、拷贝构造函数、赋值函数、析构函数这几个非常重要的部分。
class String {
public:
String(const char *str = NULL); //通用构造函数
String(const String &str); //拷贝构造函数
~String(); //析构函数
String& operator=(const String &str); //重载=
friend ostream& operator<<(ostream &os, String &str); //输出
private:
char* data ; // 字符串
size_t length; // 长度
};
String::String(const char *str ){
if ( *str == NULL){
length = 0;
data = new char[1];
*data = '\0';
} else {
length = strlen(str);
data = new char[length +1];
strcpy (data, str);
}
}
String::~String(){
length = 0;
delete[] data;
}
String::String(const String &str){
// 深拷贝
length = str.length;
data = new char[length +1];
strcpy (data, str.data);
}
String& String::operator=(const String &str){
if (this == &str) return *this;
delete []data;
length = str.length;
data = new char[length + 1];
strcpy(data, str.data);
return *this;
}
ostream& operator<<(ostream &os, String &str)//输出
{
os << str.data;
return os;
}
String的更多成员实现可以查看这篇博客http://www.cnblogs.com/zhizhan/p/4876093.html