3.长度受限制的字符串函数介绍
上面介绍的都是没有长度限制字符函数,它们都是进行到\0就停止,而接下来的三个函数有长度限制
strncpy char * strncpy ( char * destination, const char * source, size_t num );
1
strncpy与strcpy的区别就是:strcpy会将源字符串一直拷贝到\0,而strncpy会拷贝前num个字符
strncpy是不会在拷贝后自动加\0的
//验证strncpy是不会在拷贝后自动加'\0'的 #include <stdio.h> #include <string.h> int main() { char arr1[20] = "xxxxxxx"; char arr2[] = "abcdef"; strncpy(arr1, arr2,2); return 0; }
将arr2前2个字符拷贝到arr1中,在监视中看到:
所以可知:strncpy不会自动添加\0
num比源字符串要长,多出来的部分用\0来补
//验证num比源字符串要长,多出来的部分用\0来补 #include <stdio.h> #include <string.h> int main() { char arr1[20] = "xxxxxxxxxxxxx"; char arr2[] = "abc"; strncpy(arr1, arr2,6); return 0; }
模拟实现strncpy
#include <stdio.h> #include<assert.h> #include <string.h> char* my_strncpy(char* str1, char* str2, int n) { char* ret = str1; assert(str1 && str2); if (n < 0) return; while (n>0) { if (*str2 == '\0') { *str1 = '\0'; str1++; n--; } else { *str1 = *str2; str1++; str2++; n--; } } return ret; }
这里模拟实现时,要注意当num大于源字符串长度时需要补\0这点,其余地方很简单
strncat char * strncat ( char * destination, const char * source, size_t num ); 1
将source字符串中的前num个字符追加到destination后面
追加后,函数会在追加后的destination后面自动加\0
如果num大于source的大小,则多余的部分补\0
模拟实现strncat
#include <stdio.h> #include<assert.h> #include <string.h> char* my_strncat(char* str1, char* str2, int n) { char* ret = str1; assert(str1 && str2); if (n < 0) return; while (*str1 != '\0') { str1++; } while (n > 0) { if (*str2 == '\0') { *str1 = '\0'; str1++; n--; } else { *str1 = *str2; str1++; str2++; n--; } } *str1 = '\0'; return ret; }
strncmp int strncmp ( const char * str1, const char * str2, size_t num ); 1
比较到出现另个字符不一样或者一个字符串结束或者num个字符全部比较完。
返回值的情况与strcmp相同
模拟实现strncmp
#include <stdio.h> #include<assert.h> #include <string.h> int my_strncmp(char* str1, char* str2, int n) { assert(str1 && str2); if (n < 0) return; while (n > 0) { while (*str1 == *str2) { if (n == 1) { return 0; } str1++; str2++; n--; } if (*str1 > *str2) return 1; else return -1; } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 4.字符串查找 strstr char * strstr ( const char *str1, const char * str2); 1 在str1字符串中查找str2字符串 返回str2在str1中出现的一个位置的地址 模拟实现strstr #include <stdio.h> #include<assert.h> #include <string.h> void* my_strstr(char* str1, char* str2) { assert(str1 && str2); if (*str2 == '0') { return (char*)str1; } const char* s1 = str1; const char* s2 = str2; const char* cp = str1; while (*cp) { s1 = cp; s2 = str2; while (*s1 != '\0' && *s2 != '\0' && *s1 == *s2) { s1++; s2++; } if (*s2 == '0') { return (char*)cp; } cp++; } return NULL; }
strtok char * strtok ( char * str, const char * sep ); 1
sep参数是个字符串,定义了用作分隔符的字符集合
第一个参数指定一个字符串,它包含了0个或者多个由sep字符串中一个或者多个分隔符分割的标记。
#include <stdio.h> #include <string.h> int main() { char arr1[] = "abc#defa|gh"; char arr2[] = "#|"; strtok(arr1,arr2); }
有一个字符串abc#defa|gh,可以看出它被字符#和|分隔开,strtok的作用是取出被字符#和|分隔开的每块字符串
strtok函数找到str中的下一个标记,并将其用 \0 结尾,返回一个指向这个标记的指针。(注:strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容并且可修改。)
#include <stdio.h> #include <string.h> int main() { char arr1[] = "abc#defa|gh"; char arr2[] = "#|"; char arr3[20] = { 0 }; strcpy(arr3, arr1);//防止strtok直接修改被操作的字符串,所以需要拷贝一份 char* ret = strtok(arr3, arr2); printf("%s", ret); return 0; }
取出第一块被分隔的字符串abc并且将#改为\0,此时的arr3为abc\0defa|gh,ret为abc的地址,输出ret为:
strtok函数的第一个参数不为 NULL ,函数将找到str中第一个标记,strtok函数将保存它在字符串中的位置。
strtok函数的第一个参数为 NULL ,函数将在同一个字符串中被保存的位置开始,查找下一个标记。
如果字符串中不存在更多的标记,则返回 NULL 指针。
#include <stdio.h> #include <string.h> int main() { char arr1[] = "abc#defa|gh"; char arr2[] = "#|"; char arr3[20] = { 0 }; strcpy(arr3, arr1);//防止strtok直接修改被操作的字符串,所以需要拷贝一份 char* ret = strtok(arr3, arr2); printf("%s\n", ret); ret = strtok(NULL, arr2);//为了取出剩下部分的字符串,第一个参数需要改为NULL printf("%s\n", ret); ret = strtok(NULL, arr2); printf("%s\n", ret); return 0; }
如果一个字符串被某些字符分隔为很多部分,如果我们一个一个地取出就会使代码冗长,这里我们可以使用循环解决
#include <stdio.h> #include <string.h> int main() { char arr1[] = "abc#defa|gh"; char arr2[] = "#|"; char arr3[20] = { 0 }; strcpy(arr3, arr1); char* ret = NULL; for (ret = strtok(arr3, arr2); ret != NULL; ret = strtok(NULL, arr2)) { printf("%s\n", ret); } return 0; }
输出结果:
5.错误信息报告
strerror char * strerror ( int errnum ); 1
C语言的库函数在运行的时候,如果发生一些错误,就会将错误码放到一个变量中:erron
错误码是一些数字:0 1 2 3 4 5……
strerror就是返回这些错误码对应的字符串的首字符地址
我们可以看一下这些错误码对应的错误信息
int main() { printf("%s\n", strerror(0)); printf("%s\n", strerror(1)); printf("%s\n", strerror(2)); printf("%s\n", strerror(3)); printf("%s\n", strerror(4)); printf("%s\n", strerror(5)); return 0; }
当然,平常使用时并不需要我们将具体数字传入函数中
我们通常将变量errno传入函数中strerror(errno)
而这个errno变量在头文件errno.h中,使用前必须添加这个头文件。
另外还有一个perror函数,使用这个函数,可以直接将错误信息打印出来,并且如果perror中传了字符串,这个函数会先将传过去的字符串打印出来,再打印一个冒号,最后打印错误信息