目录七、strncpy 函数的使用八、strncat 函数的使用九、strncmp 函数的使用十、strstr 的使用和模拟实现1strstr的使用2strstr的模拟实现十一、strtok 函数的使用十二、strerror 函数的使用1strerror的使用2perror函数七、strncpy 函数的使用strcmp库函数的原型与作用:char* strncpy(char* dest, const char* src, size_t n);strncpy 安全版 strcpy最多只拷贝 n 个字符防止越界它不会无脑拷贝到 \0而是你让它拷贝多少它就拷贝多少遇到 \0 就提前停止拷贝src后面补 0 继续拷贝直到凑够 n 个如果 src 长度 n不会自动加 \0#include stdio.h #include string.h int main() { char dest[20] xxxxxxxxx; // 先填满方便观察 char src[] Hello\0World; strncpy(dest, src, 8); // 只拷贝前 8 个字符 printf(%s\n, dest); return 0; }运行截图我们将src的前8个字符都拷贝进dest字符数组中当我们拷贝到第六个字符时为\0终止拷贝但我们仍然要补两个\0给dest直到凑到我们指定的8个字符为止所以这个代码打印的是Hello但dest数组中存储的是Hello\0\0\0x我们可以在调试中看看拷贝后dest内所存储的具体字符确实和我们分析的一致而且此函数拷贝后不会自动补0目标空间原有的未覆盖的值不会改变就比如下面这串代码#include stdio.h #include string.h int main() { char dest[20] xxxxxxxxx; // 先填满方便观察 char src[] Hello World; strncpy(dest, src, 5); // 只拷贝前 5 个字符 printf(%s\n, dest); return 0; }运行截图可见我们需要拷贝src的前五个字符Hello我们确实发现src单纯只拷贝了Hello给dest并没有给dest补\0dest中未被覆盖的xxxx没有改变所以才会打印Helloxxxx,末尾\0是原来dest就有的\0八、strncat 函数的使用strncat 库函数的原型与作用:char* strncat(char* destination, const char* source, size_t n);自动找到 dest 末尾的 \0从这里开始拼接覆盖 \0最多拼接n个字符拼接完成后会自动在最后添加 \0最关键#include stdio.h #include string.h int main() { char str1[20]; char str2[20]; strcpy(str1, To be ); strcpy(str2, or not to be); strncat(str1, str2, 6); printf(%s\n, str1); return 0; }运行截图虽然我们只拼接了str2的六个字符or not这末尾并没有\0但我们依然能正确拼接并且能正确打印这就证实了strncat函数确实在拼接完成后会在目标空间的末尾自动添加\0九、strncmp 函数的使用strncmp 库函数的原型与作用:int strncmp(const char* str1, const char* str2, size_t n);指定前n个字符进行ASCLL码值的比较遇到\0就提前停止比较返回ASCLL码差值防止越界更安全返回值含义0前 n 个字符完全相等 0*str1 *str2 0*str1 *str2#include stdio.h #include string.h int main() { char a[] HelloWorld; char b[] HelloKitty; // 只比较前 5 个字符 printf(%d\n, strncmp(a, b, 5)); return 0; }运行截图我们比较的是前五个字符虽然a字符串和b字符串不相等但他们前五个字符是相等的所以返回值为0十、strstr 的使用和模拟实现1strstr的使用strstr 库函数的原型与作用:char* strstr(const char* str1, const char* str2);在 str1 中查找 str2并将第一次出现的位置的地址返回找不到返回 NULL字符串的比较匹配不包括\0匹配的是\0之前的字符串#include stdio.h #include string.h int main() { char str[] This is a simple string; char* pch strstr(str, simple); // 1. 查找子串 strncpy(pch, sample, 6); // 2. 替换字符串 printf(%s\n, str); // 3. 打印结果 return 0; }上面这串代码非常经典是对于strstr库函数的使用让我们来分析一下首先我们拥有一个字符数组str接着我们创建了一个字符指针变量pch用于存放strstr(str, simple)的返回值这一步表示在str数组中查找是否有simple这串字符串找到了之后就返回str中第一次出现simple的地址也就是str中simple首字符s的地址我们将这个地址存入pch接着我们用了strncpy函数strncpy(pch, sample, 6)将sample替换simple紧接着打印我们就会打印出This is a sample string运行截图2strstr的模拟实现#include stdio.h //模拟实现strstr char* my_strstr(const char* str1, const char* str2) { if (!*str2) return (char*)str1; const char* a str1; const char* b str2; const char* c NULL; while (*a) { c a; //存储a的起始地址 while (*a *b *a *b) { a; b; } if (*b \0) return (char*)c; a c 1; b str2; } return NULL; } //主函数 int main() { char str[] This is a simple string; char* pch my_strstr(str, simple); // 1. 查找子串 strncpy(pch, sample, 6); // 2. 替换字符串 printf(%s\n, str); // 3. 打印结果 return 0; }外层循环找起点从哪开始比内层循环比到底连续比完所有字符我们首先写了一个if语句if (!*str2){return (char*)str1;}这是因为当str2为空字符串时C语言规定strstr直接返回str1的地址所以我们首先写了一个这样的语句接着因为我们不想动原字符串str1和str2所以我们创建了两个指针变量a和b将str1和str2的字符串复制进去再进行后续一系列的比较接着我们又创建了一个指针变量c是用于存储我们在str1第一次找到str2字符串的起始地址便于返回我们的循环逻辑是外层while (*a)遍历a字符串只要a没到\0我们就继续判断紧接着我们将a的起始地址记录到c中然后我们进行内层循环如果*a *b *a *b它们都没到\0而且它们此地址的字符相等我们就让a;b;一直对比到结束循环结束后如果*b\0就说明我们找到了如果不等于那么我们就要让a后往挪一个字符再重新进行比较也就是我们的ac1而且b也要返回起始位置重新遍历所以我们写b str2;最后如果我们一直遍历完ab都没有到\0那就说明b不是a的子串我们就return空指针NULL这就是我们的strstr模拟实现的整体逻辑运行截图还有一点要注意就是我们return的值都要强制类型转化为char*因为我们创建的变量是带有const的和没有const不一样它们是被const修饰的指针不是普通指针如果不强制类型转换就会出现以下警告十一、strtok 函数的使用strtok 库函数的原型与作用:char *strtok(char *str, const char *delim);strtok函数的作用能按照指定的分隔符把一个长字符串切割成多个子字符串str第一次调用传入待分割的原始字符串后续调用必须传入NULL表示继续分割上一次的字符串delim分隔符字符串可以是一个或多个分隔符比如空格、逗号、分号等#include stdio.h #include string.h int main() { char str[] apple,banana,orange,grape; const char* token ,; char* retstrtok(str, token); while (ret! NULL) { printf(%s\n, ret); retstrtok(NULL, token); } return 0; }我们在使用的时候我们第一次调用strtok函数传的第一个参数是我们的字符数组名第二个参数是我们要分割的分隔符字符串这时候strtok返回的就是分离出来的第一个字符串apple的地址在之后我们在调用strtok函数我们传的第一个参数都只能是NULL第二个依然是分隔符字符串strtok会依次分割出一段字符串并返回这串字符串的地址因为函数内部会记住上次分割到哪了接着往下分割然后就依次返回后面每个子串的地址运行截图我们把代码部分的while循环改写成for循环更简洁#include stdio.h #include string.h int main() { char str[] apple,banana,orange,grape; const char* token ,; for (char* ret strtok(str, token); ret ! NULL; ret strtok(NULL, token)) { printf(%s\n, ret); } return 0; }运行截图十二、strerror 函数的使用1strerror的使用strerror 库函数的原型与作用:#include string.h #include errno.h char *strerror(int errnum);在C语言当中当程序启动时我们是有一个全局变量errno来记录我们的错误码每个错误码都对应着一个错误信息只不过程序启动的时候errno是0表示没有错误当我们在使用标准库中的函数的时候发生了某种错误就会将对应的错误码存放在errno中strerror函数的作用就是可以把参数部分错误码对应的错误信息的字符串地址返回回来下面让我们来看看0~10错误码对应的错误信息#include errno.h #include string.h #include stdio.h int main() { int i 0; // 打印 0~10 错误码对应的信息 for (i 0; i 10; i) { printf(错误码%d%s\n, i, strerror(i)); } return 0; }运行截图下面我们来看看具体场景中使用strerror函数#include stdio.h #include string.h #include errno.h int main() { FILE* f fopen(不存在的文件.txt, r); if (f NULL) //如果打开失败就执行以下指令 { // errno 自动被系统赋值strerror转成文字 printf(错误%s\n, strerror(errno)); printf(%d\n, errno); } return 0; }我们以“只读的形式”打开了一个不存在的文件因为系统找不到这个文件所以会产生错误码随后我们调用strerror(errno)将这个错误码对应的内容打印了出来这样做的好处是可以判断文件是否打开成功失败就打印原因然后进行修改避免程序崩溃让代码更安全运行截图2perror函数perror 函数相当于一次性将上述代码中的printf(错误%s\n, strerror(errno))完成了直接将错误信息打印出来使用需要头文件#includestdio.h我们来看看使用效果#include stdio.h int main() { FILE* f fopen(不存在的文件.txt, r); if (f NULL) //如果打开失败就执行以下指令 { // errno 自动被系统赋值strerror转成文字 perror(错误); printf(%d\n, errno); } return 0; }运行截图prror会自动将我们传进去的提示字符串例如上面传的错误打印出来并自动添加一个:和一个空格 接着自动打印我们的错误信息核心区别strerror(errno)返回字符串地址需自己 printf 打印perror()直接打印不用 printf自动一步到位感谢大家的观看新人求互三关注我必回关下章见
0基础C语言积跬步之字符函数与字符串函数(下)
发布时间:2026/5/20 10:31:29
目录七、strncpy 函数的使用八、strncat 函数的使用九、strncmp 函数的使用十、strstr 的使用和模拟实现1strstr的使用2strstr的模拟实现十一、strtok 函数的使用十二、strerror 函数的使用1strerror的使用2perror函数七、strncpy 函数的使用strcmp库函数的原型与作用:char* strncpy(char* dest, const char* src, size_t n);strncpy 安全版 strcpy最多只拷贝 n 个字符防止越界它不会无脑拷贝到 \0而是你让它拷贝多少它就拷贝多少遇到 \0 就提前停止拷贝src后面补 0 继续拷贝直到凑够 n 个如果 src 长度 n不会自动加 \0#include stdio.h #include string.h int main() { char dest[20] xxxxxxxxx; // 先填满方便观察 char src[] Hello\0World; strncpy(dest, src, 8); // 只拷贝前 8 个字符 printf(%s\n, dest); return 0; }运行截图我们将src的前8个字符都拷贝进dest字符数组中当我们拷贝到第六个字符时为\0终止拷贝但我们仍然要补两个\0给dest直到凑到我们指定的8个字符为止所以这个代码打印的是Hello但dest数组中存储的是Hello\0\0\0x我们可以在调试中看看拷贝后dest内所存储的具体字符确实和我们分析的一致而且此函数拷贝后不会自动补0目标空间原有的未覆盖的值不会改变就比如下面这串代码#include stdio.h #include string.h int main() { char dest[20] xxxxxxxxx; // 先填满方便观察 char src[] Hello World; strncpy(dest, src, 5); // 只拷贝前 5 个字符 printf(%s\n, dest); return 0; }运行截图可见我们需要拷贝src的前五个字符Hello我们确实发现src单纯只拷贝了Hello给dest并没有给dest补\0dest中未被覆盖的xxxx没有改变所以才会打印Helloxxxx,末尾\0是原来dest就有的\0八、strncat 函数的使用strncat 库函数的原型与作用:char* strncat(char* destination, const char* source, size_t n);自动找到 dest 末尾的 \0从这里开始拼接覆盖 \0最多拼接n个字符拼接完成后会自动在最后添加 \0最关键#include stdio.h #include string.h int main() { char str1[20]; char str2[20]; strcpy(str1, To be ); strcpy(str2, or not to be); strncat(str1, str2, 6); printf(%s\n, str1); return 0; }运行截图虽然我们只拼接了str2的六个字符or not这末尾并没有\0但我们依然能正确拼接并且能正确打印这就证实了strncat函数确实在拼接完成后会在目标空间的末尾自动添加\0九、strncmp 函数的使用strncmp 库函数的原型与作用:int strncmp(const char* str1, const char* str2, size_t n);指定前n个字符进行ASCLL码值的比较遇到\0就提前停止比较返回ASCLL码差值防止越界更安全返回值含义0前 n 个字符完全相等 0*str1 *str2 0*str1 *str2#include stdio.h #include string.h int main() { char a[] HelloWorld; char b[] HelloKitty; // 只比较前 5 个字符 printf(%d\n, strncmp(a, b, 5)); return 0; }运行截图我们比较的是前五个字符虽然a字符串和b字符串不相等但他们前五个字符是相等的所以返回值为0十、strstr 的使用和模拟实现1strstr的使用strstr 库函数的原型与作用:char* strstr(const char* str1, const char* str2);在 str1 中查找 str2并将第一次出现的位置的地址返回找不到返回 NULL字符串的比较匹配不包括\0匹配的是\0之前的字符串#include stdio.h #include string.h int main() { char str[] This is a simple string; char* pch strstr(str, simple); // 1. 查找子串 strncpy(pch, sample, 6); // 2. 替换字符串 printf(%s\n, str); // 3. 打印结果 return 0; }上面这串代码非常经典是对于strstr库函数的使用让我们来分析一下首先我们拥有一个字符数组str接着我们创建了一个字符指针变量pch用于存放strstr(str, simple)的返回值这一步表示在str数组中查找是否有simple这串字符串找到了之后就返回str中第一次出现simple的地址也就是str中simple首字符s的地址我们将这个地址存入pch接着我们用了strncpy函数strncpy(pch, sample, 6)将sample替换simple紧接着打印我们就会打印出This is a sample string运行截图2strstr的模拟实现#include stdio.h //模拟实现strstr char* my_strstr(const char* str1, const char* str2) { if (!*str2) return (char*)str1; const char* a str1; const char* b str2; const char* c NULL; while (*a) { c a; //存储a的起始地址 while (*a *b *a *b) { a; b; } if (*b \0) return (char*)c; a c 1; b str2; } return NULL; } //主函数 int main() { char str[] This is a simple string; char* pch my_strstr(str, simple); // 1. 查找子串 strncpy(pch, sample, 6); // 2. 替换字符串 printf(%s\n, str); // 3. 打印结果 return 0; }外层循环找起点从哪开始比内层循环比到底连续比完所有字符我们首先写了一个if语句if (!*str2){return (char*)str1;}这是因为当str2为空字符串时C语言规定strstr直接返回str1的地址所以我们首先写了一个这样的语句接着因为我们不想动原字符串str1和str2所以我们创建了两个指针变量a和b将str1和str2的字符串复制进去再进行后续一系列的比较接着我们又创建了一个指针变量c是用于存储我们在str1第一次找到str2字符串的起始地址便于返回我们的循环逻辑是外层while (*a)遍历a字符串只要a没到\0我们就继续判断紧接着我们将a的起始地址记录到c中然后我们进行内层循环如果*a *b *a *b它们都没到\0而且它们此地址的字符相等我们就让a;b;一直对比到结束循环结束后如果*b\0就说明我们找到了如果不等于那么我们就要让a后往挪一个字符再重新进行比较也就是我们的ac1而且b也要返回起始位置重新遍历所以我们写b str2;最后如果我们一直遍历完ab都没有到\0那就说明b不是a的子串我们就return空指针NULL这就是我们的strstr模拟实现的整体逻辑运行截图还有一点要注意就是我们return的值都要强制类型转化为char*因为我们创建的变量是带有const的和没有const不一样它们是被const修饰的指针不是普通指针如果不强制类型转换就会出现以下警告十一、strtok 函数的使用strtok 库函数的原型与作用:char *strtok(char *str, const char *delim);strtok函数的作用能按照指定的分隔符把一个长字符串切割成多个子字符串str第一次调用传入待分割的原始字符串后续调用必须传入NULL表示继续分割上一次的字符串delim分隔符字符串可以是一个或多个分隔符比如空格、逗号、分号等#include stdio.h #include string.h int main() { char str[] apple,banana,orange,grape; const char* token ,; char* retstrtok(str, token); while (ret! NULL) { printf(%s\n, ret); retstrtok(NULL, token); } return 0; }我们在使用的时候我们第一次调用strtok函数传的第一个参数是我们的字符数组名第二个参数是我们要分割的分隔符字符串这时候strtok返回的就是分离出来的第一个字符串apple的地址在之后我们在调用strtok函数我们传的第一个参数都只能是NULL第二个依然是分隔符字符串strtok会依次分割出一段字符串并返回这串字符串的地址因为函数内部会记住上次分割到哪了接着往下分割然后就依次返回后面每个子串的地址运行截图我们把代码部分的while循环改写成for循环更简洁#include stdio.h #include string.h int main() { char str[] apple,banana,orange,grape; const char* token ,; for (char* ret strtok(str, token); ret ! NULL; ret strtok(NULL, token)) { printf(%s\n, ret); } return 0; }运行截图十二、strerror 函数的使用1strerror的使用strerror 库函数的原型与作用:#include string.h #include errno.h char *strerror(int errnum);在C语言当中当程序启动时我们是有一个全局变量errno来记录我们的错误码每个错误码都对应着一个错误信息只不过程序启动的时候errno是0表示没有错误当我们在使用标准库中的函数的时候发生了某种错误就会将对应的错误码存放在errno中strerror函数的作用就是可以把参数部分错误码对应的错误信息的字符串地址返回回来下面让我们来看看0~10错误码对应的错误信息#include errno.h #include string.h #include stdio.h int main() { int i 0; // 打印 0~10 错误码对应的信息 for (i 0; i 10; i) { printf(错误码%d%s\n, i, strerror(i)); } return 0; }运行截图下面我们来看看具体场景中使用strerror函数#include stdio.h #include string.h #include errno.h int main() { FILE* f fopen(不存在的文件.txt, r); if (f NULL) //如果打开失败就执行以下指令 { // errno 自动被系统赋值strerror转成文字 printf(错误%s\n, strerror(errno)); printf(%d\n, errno); } return 0; }我们以“只读的形式”打开了一个不存在的文件因为系统找不到这个文件所以会产生错误码随后我们调用strerror(errno)将这个错误码对应的内容打印了出来这样做的好处是可以判断文件是否打开成功失败就打印原因然后进行修改避免程序崩溃让代码更安全运行截图2perror函数perror 函数相当于一次性将上述代码中的printf(错误%s\n, strerror(errno))完成了直接将错误信息打印出来使用需要头文件#includestdio.h我们来看看使用效果#include stdio.h int main() { FILE* f fopen(不存在的文件.txt, r); if (f NULL) //如果打开失败就执行以下指令 { // errno 自动被系统赋值strerror转成文字 perror(错误); printf(%d\n, errno); } return 0; }运行截图prror会自动将我们传进去的提示字符串例如上面传的错误打印出来并自动添加一个:和一个空格 接着自动打印我们的错误信息核心区别strerror(errno)返回字符串地址需自己 printf 打印perror()直接打印不用 printf自动一步到位感谢大家的观看新人求互三关注我必回关下章见