C语言中,字符串就是char类型的一维数组,以字符串结束标志\0(或null)结尾。 如果用字符串给字符数组赋值,编译器将在字符串末尾自动添加’\0’
char *p = “abcde”;
char s[] = “abcde”; //相当于 char s[] = {‘a’, ‘b’, ‘c’, ‘d’, ‘e’, ‘\0’};
用字符串给字符数组赋值时由于要添加结束符 ‘\0’,数组的长度要比字符串的长度(字符串长度不包括 ‘\0’)大1。
ANSI C提供了一些字符串处理函数,其原型都位于标准头文件string.h中。字符串处理函数所使用的变量常被声明为register存储类型,以获得更快的执行速度。在C语言中,为作为参数传递给函数的字符串分配足够的空间是程序员的责任。 [Note carefully that it is programmer’s responsibility to allocate sufficient space for the strings that are passed as arguments to these functions.]
函数定义中,有些参数被定义为const char 类型,这意味着指针所指向的字符串不可被修改,但指针本身可以被修改指向其它位置。[The type qualifier const in this context telling the compiler that the character pointed to in memory should not be changed. The pointer itself, however, can be changed.]
size_t strlen(const char *s);
返回字符串s中\0之前的字符串数量。ANSI C要求size_t类型为无符号整数,通常即相当于unsigned int。
size_t strlen(const char *s){
size_t n;
for (n = 0; *s != '\0'; ++s)
++n;
return n;
}
//循环持续执行,直至遇见字符串结束标志'\0'
int strcpy(char *s1, const char *s2);
字符串s2 到\0为止的字符被复制到s1。s1中原有的内容被覆盖。它假定s1有足够的空间来容纳结果字符串。该函数返回s1。
char *strcpy (char *s1, const char *s2){
register char *p = s1;
while (*p++ = *s2++)
;
return s1;
}
// char *p = s1; //其实也可,声明为register是为了加快执行速度
// while ((*p++ = *s2++) != 0)
// *p++相当于*(p++),这意味着p本身被增值。 while循环中,p所指向的字符被赋值为s2所指向的字符值,然后p和s2都各自增值指向下一字符。
// 当s2指向null字符\0(其值为0),0被赋给p所指向的字符,相当于设置了字符串结束标志,且整个表达式的值为0
char *strcat(char *s1, const char *s2);
将字符串s2连接到s1之后,覆盖s1的”\0”字符串,返回字符串s1。
char *strcat(char *s1, register const char *s2){
register char *p = s1; // 1. Initialized
while (*p) // 2. Go to the END
++p;
while (*p++ = *s2++) // 3. Copy Char
;
return s1;
}
//1. 被初始化的是p,而不是*p。指针p被初始化为指针值s1,从而p和s1指向相同的内存位置
//2. 当p指向字符串结束标志\0时,表达式*p的值为0,控制退出while语句。
//3. 该while开始时,p指向s1所指向的字符串尾部的null字符。因此s2的字符将被逐一复制到内存,覆盖s1尾部的null字符及其之后的内容。
int strcmp(const char *s1, const char *s2);
接受两个字符串参数,根据词典顺序比较大小。s1 小于/等于/大于 s2,分别返回一个 负/零/正 的整数。
int strcmp(const char *s1, const char *s2){
for ( ; *s1 == *s2; s1++, s2++)
if (*s1 == '\0')
return 0;
return ((*(unsigned char *)s1 < *(unsigned char *)s2) ? -1 : +1);
}