一:strstr函数的使用
strstr是在一个字符串中寻找子字符串
功能:返回str2在str1第一次出现的位置
如果没出现,就返回NULL
#include <stdio.h> #include <string.h> int main() { char str1[] = "abcdefg"; //char str2[] = "cde"; char str2[] = "cdc";//str1找不到cdc返回 null char *s=strstr(str1, str2);//在str1中寻找str2,并返回第一次str2在str1出现的位置 printf("%s\n", s);//cdefg return 0; }
strstr的模拟实现
设置一个指针cp,表示可能str1中找到str2的地址,便于打印
设置一个指针s2 ,表示每次寻找时str2的首字符地址。
设置一个指针s1,表示每次寻找时,str1的地址
#include <stdio.h> #include <assert.h> char* my_strstr(const char* str1, const char* str2) { assert(str1 && str2); if (*str2 == '\0')//规定如果str2为""返回str1的值 return str1; char* cp = str1;//用cp遍历str1中可能符合要求的地址,从str1的首字符到最后一个字符'\0' //后面返回cp,便于打印 char* s1 = NULL; char* s2 = NULL; while (*cp) { s1 = cp; s2 = str2;//每次遍历前用s2代表str2的首字符的地址 while (*s1 == *s2&&*s1)//&&*s1表示*s1和*s2均不等于'\0' { s1++; s2++; } if (*s2 =='\0')//当*s2='\0'时,说明s2从首字符遍历到了最后一个字符'\0' { return cp;// } cp++;//当cp为str1的手字符时,不符合要求,cp++,表示cp在str1的地址向后一个元素 } return NULL;//当*cp='\0'时,说明在str1中找不到str2,返回null } int main() { char str1[] = "abcdef"; char str2[] = "abcdef"; char *s=my_strstr(str1, str2); if (s != NULL) printf("%s\n", s); else printf("找不到\n"); return 0; }
二:strncpy的使用及模拟使用
strncpy的使用
与strcpy最大的区别就是 规定了拷贝的长度,
#include <stdio.h> #include <string.h> int main() { char a1[] = "abcdedf"; char a2[10] = "xxx"; char* s = strncpy(a2, a1,5);//a2从a1中拷贝了5个字节 printf("%s\n", s);//abcde return 0; }
strncpy的模拟实现
#include <stdio.h> #include <assert.h> char* my_strncpy(char* a2, const char* a1, size_t width) { assert(a2 && a1); char* start = a2; while (width--)//每拷贝一次拷贝长度-1 { *a2 = *a1;//实现拷贝 a2++; a1++; } return start; } int main() { char a1[] = "abccdefg"; char a2[10] = { 0 }; printf("%s\n",my_strncpy(a2, a1, 4)); return 0; }
可能有同学疑问,strncpy拷贝过程中并没有拷贝’\0’,为什么编译器没有报错,而是打印了我们想要的结果呢?
哈哈,我们想一块去了,虽然strncpy拷贝过程中并没有拷贝’\0’,但我们给a2初始化了10个’\0’.
三:strncat的使用及模拟实现
strncat的使用
与strcat函数相似,只是规定了追加的长度,可能不是追加了一个字符数组
#include <stdio.h> #include <string.h> int main() { char a1[20] = "hello ";//未初始化的元素全部是'\0' char a2[] = "world!!!"; strncat(a1, a2,6);//将a2中的6个元素追加到a1中 printf("%s\n", a1); return 0; }
strncat的模拟实现
#include <stdio.h> #include <assert.h> char* my_strncat( char* a1,const char* a2, size_t width) { assert(a1 && a2); char* start = a1; while (*a1 != '\0') { a1++; }//*a1='\0'时开始追加 while (width--) { //a2追加到a1上 *a1 = *a2; a1++; a2++; } return start;//返回a1的首元素的地址,便于链式访问 } int main() { char a1[20] = "hello "; char a2[] = "world!!!!!!!!!!!!!!!!"; //链式访问 printf("%s\n", my_strncat(a1, a2, 7)); }
四:strtok的使用
今天是2023年9月10日,可以写成2023.9.10我们可以得到2023
9
10
吗?
strtok函数就可以实现
#include <stdio.h> #include <string.h> int main() { char a[] = "2023.9.10"; char b[10] = { 0 }; strcpy(b, a);//strtok函数分割的一般是临时拷贝的内容,并且可以修改 char* p = ".";//p参数指向一个字符串,定义了用作分隔符的集合 char* s=strtok(b, p);//字符指针用于存储字符串,s指向字符串首字符的地址 //strtok的第一个参数不为NULL,函数将找到b中的第一个标记 . strtok并将保存它在字符串中的位置 printf("%s\n", s); s=strtok(NULL, p); //第二次传NULL,就表示接着上次找,也就是从 . 后面的地址开始找 printf("%s\n", s); s=strtok(NULL, p);//同第二次调用同理 //如果字符串中没有标记了,则返回NULL指针 printf("%s\n", s); return 0; }
上面的代码比较笨,如果分隔符多了,就会使代码变得非常繁琐,下面使用循环的方法,能达到更好的效果。
```c #include <stdio.h> #include <string.h> int main() { char a[] = "2023.9.10"; char b[20] = { 0 }; char* p = "."; char* r = NULL; strcpy(b, a); //如果字符串中没有标记了,则返回NULL指针,也就结束了循环 for (r = strtok(b, p); r != NULL; r = strtok(NULL, p)) { printf("%s\n", r); } return 0; }
五:strerror函数的使用
strerror可以把参数部分的错误码对应的错误信息的字符串地址返回来,strerror函数的使用需要头文件string.h
错误码一般放在errno.h这个头文件中说明的。
当库函数调用失败的时候,会讲错误码记录到errno这个变量中
errno是一个C语言的全局变量。