《C语言入门》
热情篇 — — 热情像一对翅膀,带我飞过山岭。
目录
1.求字符串长度
strlen():这个函数在前面的文章里已经介绍过了。用来计算字符串的长度,只针对字符串,‘\0’前出现多少字符,字符串的长度就是多少。
库函数:size_t strlen ( const char * str );
注意: 库函数返回值为size_t,是无符号的。假如有这样的代码:
int main() { if (strlen("abc") - strlen(abcde) > 0) { printf(">\n"); } else { printf("<=\n"); } return 0; }
分析:
验证:
综上所述:上述代码的结果应该是:>。
strlen()的模拟实现:
方法1:计数器
//1.计数器版本 int my_strlen1(char* str) { //计数器 int count = 0; //寻找'\0'的位置 while (*str != '\0') { str++; count++; } return count; }
方法2:指针-指针
//指针-指针 int my_strlen2(char* str) { char* ret = str; while (*str != '\0') { str++; } return (int)(str - ret); }
方法3:递归
//递归 int my_strlen3(char* str) { if (*str != '\0') return 1 + my_strlen3(str + 1); else return 0; }
2.长度不受限制的字符串函数
strcpy
库函数:char* strcpy(char * destination, const char * source );这个函数在之前的文章中也介绍过。作用是把源字符串中的字符串复制到目标空间中。
注意:
1.源字符串必须以 '\0' 结束。
2.会将源字符串中的 '\0' 拷贝到目标空间。
3.目标空间必须足够大,以确保能存放源字符串。
4.目标空间必须可变。
strcpy()的模拟实现:
//模拟实现strcpy void my_cpy(char* dest,char* res) { //目标数组要足够大,且可以变化 while (*dest++ = *res++); } int main() { char arr1[20] = ""; char arr2[] = "hello"; my_cpy(arr1,arr2); printf("%s",arr1); return 0; }
strcat
库函数:char * strcat ( char * destination, const char * source );将源字符串追加到目标字符串。
注意:
源字符串必须以 '\0' 结束。源字符串会覆盖掉目标字符串的‘\0’
目标空间必须有足够的大,能容纳下源字符串的内容。
目标空间必须可修改。字符串不能追加一个自己,例如:strcat(arr1,arr1);
strcat()的模拟实现:
#include <assert.h> char* my_strcat(char* dest, const char* res) { //记录目的字符串的首元素位置 char* ret = dest; assert(dest && res); //找到目的字符数组的'\0' while (*dest) { dest++; } //添加要追加的字符串,包括'\0' while (*dest++ = *res++); return ret; } int main() { char arr1[20] = "hello "; char arr2[] = "world"; my_strcat(arr1, arr2); printf("%s", arr1); return 0; }
strcmp
库函数: int strcmp ( const char * str1, const char * str2 );这个函数之前也介绍过。比较字符串的大小。
注意:
比较的不是字符串的长度,而是字符对应的ASCLL值。
第一个字符串大于第二个字符串,则返回大于0的数字
第一个字符串等于第二个字符串,则返回0
第一个字符串小于第二个字符串,则返回小于0的数字
strcmp ()的模拟实现:
//模拟实现strcmp #include <stdio.h> #include <assert.h> int my_strcmp(char* str1, char* str2) { //断言 assert(str1 && str2); //从起始位置开始比较,如果相等就继续向后寻找 //注意:‘\0’相等的情况除外 //'\0'的ASCII值是0,所以当*str1或者*str2出现'\0'时不会进入循环 while (*str1 == *str2) { if (*str1 == '\0') { //两个字符串比较完毕,相等。 return 0; } str1++; str2++; } //如果不相等直接放回他们相减的值 return (*str1 - *str2); } int main() { char* p = "aabce"; char* q = "aadce"; int ret = my_strcmp(p,q); if (ret > 0) { printf("arr1 > arr2"); } else if (ret < 0) { printf("arr1 < arr2"); } else { printf("arr1 = arr2"); } return 0; }
3. 长度受限制的字符串函数
strncpy
库函数:char * strncpy ( char * destination, const char * source, size_t num );
拷贝num个字符从源字符串到目标空间。理解了上面的代码,剩下的模拟实现都是大同小异的。
模拟实现://模拟实现strncpy void my_strncpy(char* str1,char* str2,int num) { //计数器 int count = 0; while (*str1++ = *str2++) { count++; if (count >= num) { break; } } } int main() { char arr1[20] = "##############"; char arr2[20] = "hello"; my_strncpy(arr1,arr2,3); printf("%s",arr1); return 0; }
strncat
库函数:char * strncat ( char * destination, const char * source, size_t num );
追加num个字符从源字符串到目标空间。模拟实现:
//模拟实现strcat char* my_strcat(char* str1,char* str2,int num) { //记录str1首元素的位置 char* ret = str1; while (*str1) { //找到目的字符串的末尾 str1++; } //添加要追加的字符串 int count = 0; while (*str1++ = *str2++) { if (count >= num) { *(str1-1) = '\0'; break; } count++; } return ret; } int main() { char arr1[20] = "hello "; char arr2[20] = "world"; my_strcat(arr1,arr2,4); printf("%s",arr1); return 0; }
strncmy
库函数:int strncmp ( const char * str1, const char * str2, size_t num );
比较前num个字符是否相等。
模拟实现:
//模拟实现strncmp int my_strncmp(char* str1,char* str2,int num) { int count = 0; //如果字符相等 while (*str1 == *str2) { count++; //只比较前num个字符 if (count >= num) { return 0; break; } str1++; str2++; } return *str1 - *str2; } int main() { char arr1[20] = "abczhang"; char arr2[20] = "abcxiyang"; int ret = my_strncmp(arr1,arr2,3); if (ret > 0) { printf("arr1 > arr2"); } else if (ret < 0) { printf("arr1 < arr2"); } else { printf("arr1 = arr2"); } return 0; }
4.字符串查找和截断
strstr
库函数:char * strstr ( const char *str1, const char * str2);
在字符串中查找字符串。
分析: 字符串1"zxybbbcd",字符串2"bbc"。预期效果:查找到:bbcd
1.两个字符串同时开始比较,如果第一个字符不相等,str1向后移动,移动到该位置的字符和str2的字符相等,这时要记录下str1的位置。
2.找到起始相同的位置后,两个字符串同时向后移动比较,如果str2的位置找到了'\0',在这之前的字符都相等,就找到了这个字符串str2。反之,str1返回到上次记录的新str1+1的位置,str2返回首字符的位置,重新进行比较。往复循环
画图理解:
模拟实现:
//模拟实现strstr char* my_strstr(char* str1,char* str2) { char* s1 = NULL; char* s2 = NULL; char* new_str1 = str1;//更新str1的位置 //如果要查找的是空字符串 if (*str2 == '\0') { return str1; } //如果相等 while (*new_str1) { s1 = new_str1;//更新str1的位置 s2 = str2;//str2复位进入到下次查找 while ( *s1 && *s2 && (*s1 == *s2) ) { s1++; s2++; } //当*s2 = '\0'的时候,证明找到了 if (*s2 == '\0') { return new_str1; } new_str1++; } //str1已经查找到'\0',没找到! return NULL; } int main() { char arr1[20] = "zxybbbcd"; char arr2[20] = "bbc"; char* ret = my_strstr(arr1,arr2); if (ret == NULL) { printf("没找到!"); } else { printf("找到了:%s",ret); } return 0; }
strtok
char * strtok ( char * str, const char * sep );
根据指定的符号切割字符串。strtok函数找到str中的下一个标记,并将其用 \0 结尾,返回一个指向这个标记的指针。
strtok函数的第一个参数不为 NULL ,函数将找到str中第一个标记,并更新这个位置。
strtok函数的第一个参数为 NULL ,函数将在同一个字符串中更新的位置开始,查找下一个标记。
如果字符串中不存在更多的标记,则返回 NULL 指针。
应用:分割这样的字符串zxy@qq.com代码实现:
int main() { char arr1[20] = "zxy@qq.com"; char* p = "@."; char arr2[30] = { 0 }; strcpy(arr2,arr1); char* ret = NULL; for (ret = strtok(arr2,p);ret != NULL; ret = strtok(NULL,p)) { printf("%s\n",ret); } return 0; }