✨✨欢迎大家来到Celia的博客✨✨
🎉🎉创作不易,请点赞关注,多多支持哦🎉🎉
所属专栏:C语言
目录
引言
在头文件<string.h>中,包含了许多字符串函数,本篇文章将详细介绍以及实现常用的字符串函数。
一、strcmp与strncmp
1.1 strcmp
int strcmp ( const char * str1, const char * str2 );
1.1.1 作用
拥有两个指针参数,分别指向两个字符串的首地址,用于比较两个字符串的大小,若str1>str2,返回值>0,若str1<str2,返回值<0,若两个字符串相等,则返回0。
比较规则:依次比较相同位置下的字符的ASC码值,与字符串长度没有直接联系。
1.1.2 模拟实现思路
我们需要从字符串的首元素开始依次向后比较,这个环节可以用一个循环来实现,如果循环过程中,两个元素相等且这两个元素都是'\0',则说明这两个字符串相等。反之,如果有其中一对字符不相等,则会跳出循环,返回两个字符的差值(ASC码的差值)即可。
1.1.3 代码实现
int my_strcmp(const char* str1, const char* str2) { while (*str1 == *str2) { str1++; str2++; if (*str1 == '\0')//在循环内,这两个指针指向的元素是相等的 return 0; } return *str1 - *str2; }
1.2 strncmp
int strncmp ( const char * str1, const char * str2, size_t num );
1.2.1 作用
strncmp与strcmp相比多了一个无符号整型参数 ,用来传输需要进行比较的字符数量,也就是说,我们可以控制比较前 num 个字符。
1.2.2 模拟实现思路
大体思路不变,只需要让循环的次数受到限制即可。
1.2.3 代码实现
int my_strncmp(const char* str1, const char* str2,size_t num) { while (*str1 == *str2) { num--; str1++; str2++; if (num == 0) return 0; } return *str1 - *str2; }
二、strcat与strncat
2.1 strcat
char * strcat ( char * destination, const char * source );
2.1.1 作用
拥有两个指针参数,分别指向两个字符串的首地址,用于把source指向的字符串拼接到destination指向的字符串后,并返回destination所指向的字符串的首地址。
2.1.2 模拟实现思路
既然是拼接字符串,那么首先就要找到目标字符串的结束符('\0'),并记录位置,再进行拷贝。
2.1.3 代码实现
char* my_strcat(char* destination, const char* source) { assert(destination && source);//断言,避免空指针 char* p = destination;//记录首地址 while (*++destination != '\0');//找到目标字符串的结束符位置,注意前置自增,否则会跳过\0 while (*destination++ = *source++);//赋值 return p;//返回首地址 }
2.2 strncat
char * strncat ( char * destination, const char * source, size_t num );
2.2.1 作用
与strcat相比多了一个无符号整型参数,用于实现固定字符数量的拼接。
2.2.2 模拟实现思路
与strcat一样,首先要找到目标字符串的结束符,然后进行固定次数的赋值操作,最后在字符串的结尾补充一个\0。
2.2.3 代码实现
char* my_strncat(char* str1, const char* str2, size_t num) { assert(str1 && str2); char* p = str1; while (*++str1);//找到结束符 while (num--)//固定次数的赋值操作 { *str1++ = *str2++; } (*str1) = '\0';//补充结束符 return p; }
三、strcpy与strncpy
3.1 strcpy
char * strcpy ( char * destination, const char * source );
3.1.1 作用
拥有两个指针参数,分别指向两个字符串的首地址,用于把source所指向的字符串拷贝至destination所指向的字符串,并且返回destination所指向的字符串的首地址。
3.1.2 模拟实现思路
我们只需要用一个循环遍历整个source字符串,将source中的每一个元素拷贝至destination字符串。
3.1.3 代码实现
char* my_strcpy(char* str1, const char* str2) { assert(str1 && str2);//断言 char* p = str1; while (*str1++ = *str2++);//赋值 return p; }
3.2 strncpy
char * strncpy ( char * destination, const char * source, size_t num );
3.2.1 作用
与strcpy相比多了一个无符号整型参数,用于拷贝固定数量的字符。
3.2.2 模拟实现思路
我们需要在循环内控制赋值的次数,拷贝的方式与strcpy相同。
3.2.3 代码实现
char* my_strncpy(char* str1, const char* str2, size_t num) { assert(str1 && str2); char* p = str1; while (num--)//控制次数 { *str1++ = *str2++; } return p; }
注意:目标字符串在拷贝完成后不需要添加结束符
四、strstr
char * strstr ( const char * str1, const char * str2 );
4.1 作用
拥有两个指针参数,分别指向两个字符串的首地址,用于查找目标字符串中的子字符串,并且返回这个子字符串在目标字符串中第一次出现的首地址。
4.2 模拟实现思路
- 我们需要一个额外的指针 cur 来记录每一次查找的首地址,以便于最后返回地址。
- 我们需要两个额外的指针变量p1,p2,分别用于比对目标字符串和被查找的字符串中的元素。
- 当查找失败时,当前的 cur 位置将不再适用,需要向后移动一位,指向被查找的字符串的指针应重新回到初始位置。
- 如果p1和p2所指向的元素相同,则继续向后比较,这里可以用while循环来实现。
- 当指向被查找的字符串的指针遇到\0时,说明查找成功,返回cur。
- 如果cur移动到目标字符串的\0位置,说明查找失败,目标字符串中没有被查找的子字符串,返回空指针(NULL)。
4.3代码实现
char* my_strstr(const char* str1, const char* str2) { const char* s1 = NULL;//只用于比对,不希望更改目标,可以用const修饰 const char* s2 = NULL; const char* cur = str1;//第一次开始比对的位置为目标字符串的首元素 if (*str2 == '\0')//当被查找的字符串为空时,直接返回目标字符串即可(判断隐藏的\0) { return (char*)str1; } while (*cur)//当cur移动到目标字符串的末尾,查找失败,会跳出循环(\0的值为0) { s1 = cur;//记录目标字符串 s2 = str2;//记录被查找的字符串 while (* s1 != '\0' && * s2 != '\0' && * s1 == * s2)//相等且不为\0时 { s1++;//继续进行比对,直到一方遇到\0跳出循环 s2++; } if (*s2 == '\0')//如果指向被查找的字符串的指针指向的元素为\0,说明查找成功,返回cur { return (char*)cur;//强制类型转换 } cur++;//当指向两个字符串的指针指向的元素不同时,当前cur位置不再适用,自加 } return NULL;//查找失败返回空指针 }