1.3.3. 问题回答
字符串自己给自己追加的话:
假设字符串char arr[20]="abcd"给自己追加 strcat(arr,arr); 我们先把隐藏的'\0'写出来 "abcd\0" 第一步找到目标字符串的'\0' 第二步进行逐步赋值,直到源头字符串src找到'\0'为止 "abcda" 注意到仅仅只进行了一次赋值,'\0'就被'a'给覆盖了,也就是说源头字符串src将永远无法找到'\0',所以 : 如果字符串自己给自己追加的话,'\0'会被覆盖,所以循环会变为死循环
所以一定不能自己给自己追加,否则程序会崩溃
1.4. strcmp
strcmp:字符串比较函数
1.4.1 strcmp函数剖析
C语言标准规定: int strcmp ( const char * str1, const char * str2 ); 字符串比较函数strcmp: 依次比较两个字符串str1与str2对应位置的ascii码值 1.如果相同,则str1++,str2++,进行下一个位置元素的比较 2.如果最终两者相同,则返回0 3.如果str1 > str2:返回大于0的数字 4.如果str1 < str2:返回小于0的数字 假设str1 = "abcd" str2 = "abde" str3 = "abc" 则str1与str2的'a'与'b'均相同,跳过,到达'c'和'd'之后,因为'c'的ASCII码值小于'd',所以返回<0的数字 str1与str3的'a'和'b'和'c'均相同,到达'd'和'\0'之后,因为'd'的ASCII码值大于'\0',所以返回>0的数字 注意:'\0'的ASCII码值是最小的,为0 在VS编译器上: 2.如果最终两者相同,则返回0 3.如果str1 > str2:返回1 4.如果str1 < str2:返回-1 英语好的老铁可以看一下 This function starts comparing the first character of each string. If they are equal to each other, it continues with the following pairs until the characters differ or until a terminatingnull-character is reached.
1.4.2 strcmp函数模拟实现
int my_strcmp(const char* str1, const char* str2) { assert(str1 != NULL); assert(str2 != NULL); while (*str1 == *str2) { str1++; str2++; } return *str1 - *str2; } int main() { char arr1[] = "acdf"; char arr2[] = "an"; int ret = my_strcmp(arr1, arr2); printf("%d", ret);//返回<0的数字,因为'c'<'n' return 0; }
1.5. strstr
strstr:字符串查找函数
1.5.1 strstr函数剖析
char * strstr ( const char *str1, const char * str2); Returns a pointer to the first occurrence of str2 in str1, or a null pointer if str2 is not part of str1. 返回str2在str1里出现的对应的str1中"首"元素的地址 假设:str1="abbbcde",str2="bbcde" 也就是说返回str1中第二个'b'的位置
1.5.2 strstr函数模拟实现
这里采用BF暴力算法:
char* my_strstr(const char* str1, const char* str2) { char* cp = str1; char* s1 = cp; char* s2 = str2; while (*cp) { while (*s1 && *s2 && *s1 == *s2) { s1++; s2++; } if (*s2 == '\0') return cp; else if (*s1 == '\0') return NULL; else { cp++; s1 = cp; s2 = str2; } } return NULL; }
具体思想是: 1.先用cp,str2作为标志位, 进行匹配时: 1.如果s1与s2对应位置的字符相同,则s1与s2均后移 直到*s1为'\0',或*s2为'\0',或s2与s1的对应位置的字符不同退出while循环, 当退出while循环后如果*s2为'\0',则表示匹配成功,返回cp 2.如果s1与s2对应位置的字符不同,则cp后移,s1退到cp,s2退到str2,再进行匹配,如果cp指向了'\0'时还没有匹配成功 也就意味着已经彻底匹配失败了,返回NULL 3.如果退出时是因为*s1为'\0',则表示彻底匹配失败,返回NULL
下面请大家看一下具体实现流程
1.6 strtok
字符串切割函数
1.6.1 strtok函数剖析
char * strtok ( char * str, const char * sep ); sep参数是个字符串,定义了用作分隔符的字符集合 第一个参数指定一个字符串,它包含了0个或者多个由sep字符串中一个或者多个分隔符分割的标 记。 1.strtok函数找到str中的下一个标记,并将其用 '\0' 结尾,返回一个指向这个标记的指针。(注: strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容 并且可修改。) 2.strtok函数的第一个参数不为 NULL ,函数将找到str中第一个标记,strtok函数将保存它在字符串 中的位置。 3.strtok函数的第一个参数为 NULL ,函数将在同一个字符串中被保存的位置开始,查找下一个标 记。 4.如果字符串中不存在更多的标记,则返回 NULL 指针。 从中可以看出strtok具有记忆性
演示:
int main() { char arr[] = "helloworld@yeah.net"; char copy[30]; strcpy(copy, arr); char sep[] = "@."; char* ret = strtok(copy, sep); printf("%s\n", ret);//helloworld ret = strtok(NULL, sep); printf("%s\n", ret);//yeah ret = strtok(NULL, sep); printf("%s\n", ret);//net return 0; } 这里还可以用for循环来简化代码 int main() { char arr[] = "helloworld@yeah.net"; char copy[30]; strcpy(copy, arr); char sep[] = "@."; char* ret = NULL; 因为ret只需设置为strtok(copy,sep)一次,所以可以考虑作为for循环的初始条件 其余所有调用都只需要传NULL,sep即可,所以考虑作为for循环的更新条件 当ret为NULL时,切割成功完成,所以可以作为for循环的终止条件 for (ret = strtok(copy, sep); ret != NULL; ret = strtok(NULL, sep)) { printf("%s\n", ret); } return 0; }
二.有长度限制的字符串函数
上面的strcpy,strcat,strcmp函数都是需要找到’\0’的字符串,也就是如果找不着’\0’会继续向下找,所以不安全(可能会出现越界访问的情况)
所以接下来我们介绍一下三个有长度限制的函数:
strncpy
strncat
strncmp
2.1. strncpy
char * strncpy ( char * destination, const char * source, size_t num ); Copies the first num characters of source to destination. If the end of the source C string(which is signaled by a null-character) is found before num characters have been copied, destination is padded with zeros until a total of num characters have been written to it. 1.拷贝num个字符从源字符串到目标空间。 2.如果源字符串的长度小于num,则拷贝完源字符串之后,在目标的后边追加'\0',直到num个。
int main() { char arr1[] = "abcdef"; char arr2[] = "xxx"; strncpy(arr1, arr2, 2); printf("%s\n", arr1);//xxcdef return 0; }
2.2. strncat
char * strncat ( char * destination, const char * source, size_t num ); Appends the first num characters of source to destination, plus a terminating null-character. If the length of the C string in source is less than num, only the content up to the terminating null-character is copied.
将源代码的第一个num字符附加到目标代码中,再加上一个终止的’\0’
如果源代码中的C字符串的长度小于num,则只复制直到终止的空字符的内容。
int main() { char arr1[30] = "abcd"; char arr2[] = "efgh"; //strncat(arr1, arr2, 4); //printf("%s\n", arr1);//abcdefgh //strncat(arr1, arr2, 2); //printf("%s\n", arr1);//abcdef strncat(arr1, arr1, 4); printf("%s\n", arr1);//abcdabcd 由此可见,我们可以通过strncat函数来让arr1:"abcd"变为"abcdabcd" 实现"翻倍" }
2.3. strncmp
int strncmp ( const char * str1, const char * str2, size_t num ); 只比较num个字符来返回比较结果 int main() { char arr1[] = "abcdef"; char arr2[] = "abdcdef"; int ret = strncmp(arr1, arr2, 2); printf("比较前两个字符:%d\n", ret);//0 ret = strncmp(arr1, arr2, 3); printf("比较前三个字符:%d\n", ret);//-1 int len1 = strlen(arr1); int len2 = strlen(arr2); ret = strncmp(arr1 + len1 - 3, arr2 + len2 - 3, 3); printf("比较后三个字符:%d\n", ret);//0 }
以上就是字符串函数专题的讲解,希望能给大家带来帮助,谢谢大家.