1.5 strncpy🎁
char * strncpy ( char * destination, const char * source, size_t num );
- 拷贝num个字符从源字符串到目标空间。
- 如果源字符串的长度小于num,则拷贝完源字符串之后,在目标的后边追加0,直到num个。
整体区别其实就比strcpy多了一个参数(size_t num)限制。
这里要注意的是,如果需要拷贝的个数大于整体的源字符串的大小,那么拷贝的时候不够就用'\0'或者0来补充
int main() { char arr1[] = "abcdef"; char arr2[20] = "xxxxx"; strncpy(arr2,arr1,20); printf("%s\n", arr2); return 0; }
因为arr1(源字符串)整体大小是6+1=7(它包含的'\0'), 所以补的时候只需要补三个'\0'就行了
个人认为:
只需要看要拷贝的那个个数是多少,然后把源字符串加上'\0'的总体个数相减就行
也就是10-(6+1)=3,所以要补的'\0'个数就是 3个
1.6 strncat💨
char * strncat ( char * destination, const char * source, size_t num );
1.6.1strncat的正常调用
#include<stdio.h> #include<string.h> int main() { char arr1[20] = "hello \0xxxxxxxxxxxx"; char arr2[] = "abcdef"; strncat(arr1, arr2, 10); printf("%s\n", arr1); return 0; }
可以看到拷贝前的状况:
拷贝之后:
这个函数的情况其实时,你让我追加几个就追加几个,追加完之后我就会在后面再补一个'\0',也不会多拷贝数据
总结:追加的时候源字符串只有7个字符(6+1),这里已经包括’\0’了,那就停止了,并不会多拷贝’\0'
1.6.2模拟实现strncat💫
记住拷贝完字符串在后面补一个'\0'即可。
#include<stdio.h> #include<assert.h> int main() { char arr1[20] = "hello \0xxxxxxxxxxxx"; char arr2[] = "abcdef"; int n = 0; scanf("%d", &n); char* p = arr1; char* q = arr2; assert(arr1); assert(arr2); while (*p) { p++; } while (n--) { *p = *q; p++; q++; } *p = '\0'; printf("%s",arr1); printf("\n"); }
关于strncat模拟实现不多说了,毕竟下面的自己追加自己的情况才是重点
模拟实现strncat,自己追加自己的情况💦
#include<stdio.h> #include<assert.h> int main() { char arr1[20] = "hello \0xxxxxxxxxxxx"; int n = 0; scanf("%d", &n); char* p = arr1; char* q = arr1; assert(arr1); while (*p) { p++; } while (n--) { *p = *q; p++; q++; } *p = '\0'; printf("%s",arr1); printf("\n"); }
图解:
上面的第一个图是p指针和q指针初始化的位置
第二个图它们的最终位置
个人理解:
到n--成0的时候,假设拷贝三次,到第三个字符的时候,q指针最终还是会走一下
因为这是模拟实现库函数,是方便理解库函数的实现逻辑的
也就是q指针的最终位置,所以说库函数也是这样,strncat,是会把q指针的最终位置改成'\0'的
关于everything:
提示打开,everything的时候可以观察到以上库函数的代码实现,但这不是源代码,是参考代码
像这样把上面的.c文件直接拖拽过来即可。
1.7 strncmp
int strncmp( const char * str1, const char * str2, size_t num);
strncmp的正常操作
#include<stdio.h> int main() { char arr1[] = "abcdefadawdawfwa"; char arr2[] = "abcq"; int ret = strncmp(arr1, arr2, 8); printf("%d\n", ret); return 0; }
个人理解:
如果n(要拷贝的个数)比str1或者str2其中一个要大,或者比两个都要大,那就找最短的字符串,比完就ok了
1.8 strstr
char * strstr ( const char *str1, const char * str2);
#include<stdio.h> int main() { char arr1[] = "abcdefgh"; char arr2[] = "de"; char* p = strstr(arr1, arr2); if (p == NULL) { printf("找不到\n"); } else { printf("%s\n", p); } return 0; }
找到了:
找不到:
1.8.1strstr的模拟实现❗❗❗
前提准备:
str1和str2是用来记录初始位置的,而s1和s2是借助遍历字符串的
cp呢是匹配成功的时候返回匹配成功的字符串的指针。
总共就五个指针,只有三个是要用到的分别是s1,s2和cp。
#include<stdio.h> char* my_strstr(const char* str1, const char* str2) { char* s1 = NULL; char* s2 = NULL; char* cp = (char*)str1;//匹配成功的时候返回匹配成功的字符串的指针,跟下面的那个str2一样的情况 while (*cp) { s1 = cp; s2 = (char*)str2;//编译器报警阿,把一个相对安全的指针交给一个不安全的指针,这个权限是放大了 while (*s1 && *s2 && *s1 == *s2) { s1++; s2++; } if (*s2 == '\0') { return cp; } cp++; } return NULL; } int main() { char arr1[] = "abcdebcdf"; char arr2[] = "bcd"; char* p = my_strstr(arr1, arr2); if (p == NULL) { printf("找不到\n"); } else { printf("%s\n", p); } return 0; }
执行:
图解:根据代码配合图理解即可。两图的指针指向情况均为它们的最终位置!
1.最基本的匹配情况:
2.上难度了
一点小疑惑:❓
1.为什么不拿str1和str2走?
str1和str2是用来记住起始位置的,当两者走远的时候,想回到起始位置,就没有人知道起始位置在哪里了,就借助s1和s2来往后遍历字符即可
2.*s1存在的必要性,有必要吗?
有必要:
比如说
aabcdefgh和bcd
s1肯定是比s2指向的字符串长对不对,但是如果你手动去干预,aabc\0defgh
while(*s1)这个条件就有存在的必要,加上*s1 只是咱们更加严格一点
3.这个while(*cp)循环又是干啥的?
如果匹配成功 就直接返回cp了
但是如果没有 就要从str1后面一位继续开始匹配
简单来说:
如果匹配成功了,这个只用走一遍
进入循环,出去循环
如果一次匹配失败
进入循环,再进入循环,再进入循环.........出去循环,直到匹配成功为止
接下来还有下半章的知识,欢迎各位大佬的指导和补充!