求字符串长度
strlen
函数功能
字符串长度,求一个字符串中字符的个数(不包含’\0’)。
函数参数
size_t strlen( const char *string ); # size_t 是函数的返回类型 # char* string 是函数参数
函数使用
#include <stdio.h> #include <string.h> //strlen对应头文件 int main() { char arr[] = "abcdef"; int len = strlen(arr); printf("%d\n", len); return 0; }
模拟实现(初阶)
#include <stdio.h> #include <assert.h> //assert对应头文件 size_t my_strlen(const char* str) { assert(str != NULL); //检查str是否为空指针 int count = 0; while (*str != '\0') { str++; count++; } return count; } int main() { char arr[] = "abcdef"; int len = my_strlen(arr); printf("%d\n", len); return 0; }
模拟实现(进阶)
#include <stdio.h> #include <assert.h> //assert对应头文件 size_t my_strlen(const char* str) //const用于保护源字符串不被修改 { assert(str != NULL); char* head = str; //记录字符串开头的地址 while (*str++); //找到字符串结束的地址 return str - head - 1; //指针-指针得到元素个数,-1减去\0 } int main() { char arr[] = "abcdef"; int len = my_strlen(arr); printf("%d\n", len); return 0; }
注意事项
- 字符串以 ‘\0’ 作为结束标志,strlen函数返回的是在字符串中 ‘\0’ 前面出现的字符个数(不包含’\0’)。
- 函数参数指向的字符串必须要以 ‘\0’ 结束,否则得到的就是随机值(strlen会一直往后找,直到遇到’\0’才结束)。(常考)
- 注意函数的返回值为size_t,是无符号的。(易错:可能出现算术转换)
长度不受限制的字符串函数
strcpy
函数功能
字符串拷贝,把一个字符串里面的内容拷贝到另一个字符串中去(包括’\0’)。
函数参数
char* strcpy(char * destination, const char * source ); # char* 是函数的返回值,返回的是目标空间的起始地址 # source 是要拷贝的字符串 # destination 是目标空间
函数使用
#include <stdio.h> #include <string.h> //strcpy对应头文件 int main() { char arr1[] = "abcdef"; char arr2[10] = ""; strcpy(arr2, arr1); printf("%s\n", arr2); return 0; }
模拟实现(初阶)
#include <stdio.h> #include <assert.h> //assert对应头文件 char* my_strcpy(char* dest, const char* src) //const用于保护源字符串 { assert(dest && src); //保证传递过来的不是空串 char* ret = dest; //记录目标空间的起始地址 while (*src != '\0') { *dest = *src; dest++; src++; } *dest = *src; //将末尾的'\0'赋给dest return ret; } int main() { char arr1[] = "abcdef"; char arr2[10] = ""; my_strcpy(arr2, arr1); printf("%s\n", arr2); return 0; }
模拟实现(进阶)
#include <stdio.h> #include <assert.h> //assert对应头文件 char* my_strcpy(char* dest, const char* src) //const用于保护源字符串 { assert(dest && src); //保证传递过来的不是空串 char* ret = dest; //记录目标空间的起始地址 while (*dest++ = *src++); //连同末尾的'\0'一起赋给了dest return ret; } int main() { char arr1[] = "abcdef"; char arr2[10] = ""; my_strcpy(arr2, arr1); printf("%s\n", arr2); return 0; }
注意事项
- 源字符串必须以 ‘\0’ 结束。
- 会将源字符串中的 ‘\0’ 拷贝到目标空间。
- 目标空间必须足够大,以确保能存放源字符串。
- 目标空间必须可变。
strcat
函数功能
字符串追加,在一个字符串的末尾追加另外一个字符串(包括’\0’)。
函数参数
char * strcat ( char * destination, const char * source ); # char* 是函数的返回值,返回的是目标空间的起始地址 # source 是要追加的字符串 # destination 是目标空间
函数使用
#include <stdio.h> #include <string.h> //strcat对应头文件 int main() { char arr1[] = "world!"; char arr2[20] = "hello "; strcat(arr2, arr1); printf("%s\n", arr2); return 0; }
模拟实现(初阶)
#include <stdio.h> #include <assert.h> //字符串追加可以分为两部分:1、找到目标字符串的末尾 2、字符串拷贝 char* my_strcat(char* dest, const char* src) //const用于保护源字符串 { assert(dest && src); //保证传递过来的不是空串 char* ret = dest; //记录目标空间的起始地址 while (*dest != '\0') //找到目标空间的末尾 { dest++; } while (*src != '\0') { *dest = *src; dest++; src++; } *dest = *src; //将末尾的'\0'赋给dest return ret; } int main() { char arr1[] = "world!"; char arr2[20] = "hello "; my_strcat(arr2, arr1); printf("%s\n", arr2); return 0; }
模拟实现(进阶)
#include <stdio.h> #include <assert.h> //字符串追加可以分为两部分:1、找到目标字符串的末尾 2、字符串拷贝 char* my_strcat(char* dest, const char* src) //const用于保护源字符串 { assert(dest && src); //保证传递过来的不是空串 char* ret = dest; //记录目标空间的起始地址 while (*dest++ != '\0'); //找到目标空间的末尾 dest--; //抵消最后一次自增的副作用 while (*dest++ = *src++); //字符串拷贝 return ret; } int main() { char arr1[] = "world!"; char arr2[20] = "hello "; my_strcat(arr2, arr1); printf("%s\n", arr2); return 0; }
注意事项
- 源字符串必须以 ‘\0’ 结束。
- 目标空间必须有足够的大,能容纳下源字符串的内容。
- 目标空间必须可修改。
- strcat 函数不能自己给自己追加。(追加会覆盖掉末尾的’\0’,导致死循环)
strcmp
函数功能
字符串比较,以字节为单位比较两个字符串的大小
函数参数
int strcmp ( const char * str1, const char * str2 ); # int 函数返回值 # char* str1 char* str2 用于比较的两个字符串
函数返回值
>0 : str1 大于 str2; =0 : str1 等于 str2; <0 : str1 小于 str2
函数使用
#include <stdio.h> #include <string.h> //strcmp对应头文件 int main() { char str1[] = "abcdef"; char str2[] = "abq"; int ret = strcmp(str1, str2); printf("%d\n", ret); return 0; }
模拟实现
#include <stdio.h> #include <assert.h> //assert对应头文件 int my_strcmp(const char* str1, const char* str2) { assert(str1 && str2); while (*str1 == *str2 && *str1 != '\0' && *str2 != '\0') //找到字符串中不相等字符的位置 { str1++; str2++; } if (*str1 != '\0' && *str2 != '\0') //如果此位置不是字符串末尾,则不相等,返回差值 return *str1 - *str2; return 0; //若前面没返回,说明相等,返回0 } int main() { char str1[] = "abcdef"; char str2[] = "abq"; int ret = my_strcmp(str1, str2); printf("%d\n", ret); return 0; }
注意事项
- 对每一对字符进行比较,直到遇到不相等的字符或者遇到’\0’。
- 比较的是每一对字符的ASCII值。
长度受限制的字符串函数
由于strcpy、strcat、strcmp等字符串函数存在安全隐患(目标空间小于源空间等问题),C语言还提供了另外几种相对安全的字符串函数,即strncpy、strncat、strncmp,这些字符串函数相比于原字符串函数多了一个参数,用于指定操作的字节数。(注意:strncpy、strncat、strncmp函数只是相对安全,并不是绝对安全,多一个参数只是起到一个提醒作用)
strncpy
函数功能
字符串拷贝,把一个字符串中num个字节的内容拷贝到另一个字符串中去。
函数参数
char * strncpy ( char * destination, const char * source, size_t num ); # char* 是函数的返回值,返回的是目标空间的起始地址 # source 是要拷贝的字符串 # destination 是目标空间 # num 是要拷贝的字节数
函数使用
#include <stdio.h> #include <string.h> //strncpy对应的头文件 int main() { char arr1[] = "abcdef"; char arr2[10] = ""; strncpy(arr2, arr1, sizeof(arr1) / sizeof(arr1[0]) * 1); //sizeof(arr)/sizeof(arr[0]) 求得数组元素个数,*1 乘以每个元素的大小,得到整个数组的字节数 printf("%s\n", arr2); return 0; }
模拟实现
//模拟实现strncpy #include <stdio.h> #include <assert.h> char* my_strncpy(char* dest, const char* src, size_t num) { assert(dest && src); char* ret = dest; //记录目标空间的起始地址 while (num--) { *dest = *src; if (*dest == '\0') //如果*dest为0,说明将src的结束字符赋给了dest,这种情况下源字符串的长度小于num { while (num--) { //如果源字符串的长度小于num,则拷贝完源字符串之后,在目标的后边追加0,直到num个。(与库函数的实现方式保持一致) *dest++ = 0; } break; } dest++; src++; } *dest = '\0'; //在dest的末尾补上结束字符 return ret; } int main() { char arr1[] = "abc"; char arr2[10]; my_strncpy(arr2, arr1, 4); printf("%s\n", arr2); return 0; }
注意事项
- 拷贝num个字符从源字符串到目标空间。
- 如果源字符串的长度小于num,则拷贝完源字符串之后,在目标的后边追加0,直到num个。
strncat
函数功能
字符串追加,将一个字符串中num个字节的内容追加到另一个字符串的末尾,并在最后面加上’\0’。
函数参数
char * strncat ( char * destination, const char * source, size_t num ); # char* 是函数的返回值,返回的是目标空间的起始地址 # source 是要追加的字符串 # destination 是目标空间 # num 是要追加的字节数
函数使用
#include <stdio.h> #include <string.h> //strncat对应的头文件 int main() { char arr1[] = "world!"; char arr2[20] = "hello "; strncat(arr2, arr1, sizeof(arr1) / sizeof(arr1[0]) * 1); //sizeof(arr)/sizeof(arr[0]) 求得数组元素个数,*1 乘以每个元素的大小,得到整个数组的字节数 printf("%s\n", arr2); return 0; }
模拟实现
#include <stdio.h> #include <assert.h> char* my_strncat(char* dest, const char* src, size_t num) { assert(dest && src); char* ret = dest; //记录目标空间的起始地址 //找到dest末尾 while (*dest != '\0') { dest++; } //strncpy while (num--) { *dest = *src; if (*dest == '\0') //如果*dest为0,说明将src的结束字符赋给了dest,这种情况下源字符串的长度小于num { //如果源字字符串的长度小于num,则只复制到终止空字符的内容。(与库函数的实现方式保持一致) return ret; //直接返回 } dest++; src++; } *dest = '\0'; //如果循环正常结束,则在dest的末尾补上结束字符 return ret; } int main() { char arr1[20] = "abcdef"; char arr2[] = "ABCDEF"; my_strncat(arr1, arr2, 5); printf("%s\n", arr1); return 0; }
注意事项
- 将源字符串中num个字节的内容追加到目标字符串的末尾,并在最后添加’\0’。
- 如果源中字符串的长度小于num,则只复制到终止空字符的内容
strncmp
函数功能
字符串比较,比较两个字符串中前num个字节的大小。
函数参数
int strncmp ( const char * str1, const char * str2, size_t num ); # int 函数返回值 # char* str1 char* str2 用于比较的两个字符串 # num 要比较的字节数
函数返回值
>0 : str1 大于 str2; =0 : str1 等于 str2; <0 : str1 小于 str2
函数使用
#include <stdio.h> #include <string.h> //strncmp对应的头文件 int main() { char arr1[] = "abcdef"; char arr2[] = "abcq"; int len = strncmp(arr2, arr1, 3); printf("%d\n", len); return 0; }
注意事项
- 对前num对字节中的每一对字符进行比较,直到遇到不相等的字符。
- 比较的是每一对字符的ASCII值。