人无完人持之以恒方能见真我共同进步文章目录一、strncpy函数的使用二、strncat函数的使用三、strncmp函数的使用四、strstr的使用和模拟实现五、strtok函数的使用六、strerror和perror函数的使用1.strerror函数2.perror函数一、strncpy函数的使用我们之前学习的strcpy的作用是把源字符串拷贝到目标空间内而且经过我们的模拟实现我们也意识到它拷贝的时候会把目标空间的内容给替换了我们可以来测试一下可以看到将arr2的内容拷贝到arr1中时把arr1原本的内容替换了那假设我们不想让它全部拷贝过来只是拷取一部分OK不OK这个时候就要引入我们带n的字符串函数那个多出来的n就代表数量是我们想拷贝字符串时要拷贝的字符的个数而不带n的字符串函数和带n的字符串函数的根本区别是带n的字符串函数更灵活可以指定拷贝的字符的个数所以也叫带n的字符串函数为受限制的字符串函数不带n的为不受限制的字符串函数接下来我们来看看本次讲到的strncpy函数的原型char * strncpy ( char * destination, const char * source, size_t num );它的参数与strcpy的区别就是多了最后一个参数它的作用就是指定我们要拷贝的字符的个数它的特点如下拷num个字符从源字符串到标空间如果源字符串的度于num则拷完源字符串之后在标的后边追加直到num个#include stdio.h #include string.h int main() { char arr1[20] abcdef; char arr2[20] ghijklmn; strncpy(arr1, arr2, 3); printf(%s , arr1); return 0; }可以看到只拷贝了arr2中的前三个字符进arr1并且覆盖了arr1的前三个字符这就是strncpy的作用至于strncpy的模拟实现与strcpy的模拟实现相似这里就不再过多讲解二、strncat函数的使用strncat也是带n家族的一员多n的原因和strncpy差不多就是用来指定要追加到目标空间的字符的个数它的原型如下char * strncat ( char * destination, const char * source, size_t num );它的特点是将source指向字符串的前num个字符追加到destination指向的字符串末尾再追加个 字符如果source指向的字符串的字符个数于num的时候只会将字符串中到 的内容追加到destination指向的字符串末尾了解到这里我们来尝试使用一下strncat把arr2的前3个字符追加到arr1里如下#include stdio.h #include string.h int main() { char arr1[20] abcdef; char arr2[20] ghijklmn; strncat(arr1, arr2, 3); printf(%s , arr1); return 0; }运行结果如果后面的第三个参数num大于arr2的大小会发生什么呢运行结果调试结果:三、strncmp函数的使用strncmp的作用就是比较str1和str2的前num个字符如果相等就继续往后较最多较num个字如果在这num个字符中发现不样就看此时哪个字符串更大前者大就返回大于0的数如果后者大就返回小于0的数如果num个字符都相等就是相等返回0我们来看看它的原型int strncmp ( const char * str1, const char * str2, size_t num );我们来使用它比较arr1和arr2前三个字符的大小:#include stdio.h #include string.h int main() { char arr1[20] abcdef; char arr2[20] ghijklmn; int ret strncmp(arr1, arr2, 3); printf(在前三个字符的比较中); if (ret 0) printf(arr1 arr2 ); else if (ret 0) printf(arr1 arr2 ); else printf(arr1 arr2 ); return 0; }运行结果四、strstr的使用和模拟实现这是一个对我们来说比较新的函数我们来仔细介绍一下使用方法以及它的模拟实现它的作用就是返回后一个字符串在前一个字符串中第次出现的位置并且字符串的较匹配不包含 字符以 作为结束标志接下来我们来看看strstr的原型const char* strstr ( const char* str1, const char* str2);它的原型中参数看起来很简单就是两个字符串那它的返回值是啥捏有两种情况:如果在字符串str1中找到了字符串str2那么就返回str1中找到str2的起始位置如果没有在字符串str1中找到字符串str2那么就返回一个NULL所以在使用的时候我们就可以通过它的返回值来确认是否找到对应的字符串如果返回非空指针那么就是找到了返回空指针就是没有找到接下来我们用实例来加深理解#include stdio.h #include string.h void isfind(const char* x) { if (x) printf(找到了 ); else printf(没找到 ); } int main() { char arr1[20] abcdef; char arr2[20] ghijklmn; char arr3[20] cde; isfind(strstr(arr1, arr2)); isfind(strstr(arr1, arr3)); return 0; }运行结果我们来模拟实现一下 strstr函数命名my_strstr函数参数可以照抄strstr函数的原型如下const char* my_strstr ( const char* str1, const char* str2);函数实现1老样子assert进行断言2然后我们来分析这个函数可能出现的情况按照我们正常去想就会想到首先就去看str1和str2指向的字符相不相等不相等就两个指针都往后找直到它们指向的字符相等3随后往后开始找但是会出现一个问题万一这一次匹配不上只有前几个字符相等后面并不相等那我们怎么找到之前开始匹配的位置呢如图4所以我们让str1和str2直接往后走是不妥的这样一旦匹配失败我们就记不住当时开始匹配的位置也就不能进行下一次匹配所以我们可以重新创建三个指针变量5有两个用来装下str1一个用来代替str1往后走一个用来记住当前第一次匹配的位置至于str1就老老实实待在原地不要动6还有一个用来装str2这样如果匹配失败就把str2重新赋值给这个变量让它重新指向str2的开头创建如下const char* my_strstr(const char* str1, const char* str2) { assert(str1 str2); const char* s1 str1;//代替str1用来往后匹配字符 const char* s2 str2;//代替str2用来往后匹配字符 const char* cp str1;//记录开始匹配字符的位置 }7有了以上的经验我们为了避免犯错可以使用思路比较简单的暴力匹配就是创建一个循环我们对cur进行解引用只要里面不是结束标志我们就进入循环然后看这个位置的字符是否和str2的第一个字符相等8如果不相等我们就让cp让我们的当前位置往前挪动一下如果相等就进行完整的匹配这里还是有两种情况一是如果完全匹配那么就返回cp就是我们开始匹配时的位置二是如果不能完全匹配那么就还是让cp并且将cp重新赋值给s1将str2重新赋值给s29现在我们就来看进行一次匹配的过程也很简单我们还是创建一个while循环如果s1和s2解引用不是 并且解引用后相等那我们就让s1和s2加加一直往后走当循环结束时我们就判断s2解引用后是否是 如果是说明完全匹配上了就返回cp不是那么说明没有完全匹配就让cp开始下一次循环查找10最后一步就是如果我们遍历了s1中的所有字符还是发现两个字符串没有完全匹配的地方就直接返回空指针NULLconst char* my_strstr(const char* str1, const char* str2) { assert(str1 str2); if(*str2 ) { return (char*)str1; } const char* s1 str1; const char* s2 str2; const char* cp str1; while (*cp) { s1 cp;//重新赋值 s2 str2;//重新赋值 while (*s1 *s2 *s1 *s2) { s1; s2; } if (*s2 ) return cp; cp; } return NULL; }这是一般的情况我们换一种更复杂的情况测试可以看到我们实现的函数还是成功帮我们完成了任务这里的strstr函数的实现就到此结束了,模拟实现这个函数要考虑多种情况希望大家能够下来多敲敲欢迎大家在评论区留言五、strtok函数的使用这也是一个新函数它的作用是什么呢它可以按照我们给出的分隔符来分割我们的字符串现在我们先来了解一下它的原型char * strtok ( char * str, const char * sep);接下来我们来总结一下它的特点sep参数指向个字符串定义了作分隔符的字符集合第个参数指定个字符串它包含了0个或者多个由sep字符串中个或者多个分隔符分割的标记strtok函数找到str中的下个标记并将其 结尾返回个指向这个标记的指针注strtok函数会改变被操作的字符串所以被strtok函数切分的字符串般都是临时拷的内容并且可修改strtok函数的第个参数不为 NULL 函数将找到str中第个标记strtok函数将保存它在字符串中的位置strtok函数的第个参数为 NULL 函数将在同个字符串中被保存的位置开始查找下个标记如果字符串中不存在更多的标记则返回 NULL 指针比如我们的邮箱由两个分隔符分隔开来就是符合和(.)点号我们想把这个邮箱地址分隔开来可以这样操作#include stdio.h #include string.h int main() { char arr1[] BANZHANCHAXIANG163.com; char arr2[] .; char* ret1 strtok(arr1, arr2); char* ret2 strtok(NULL, arr2); char* ret3 strtok(NULL, arr2); printf(%s %s %s , ret1, ret2, ret3); return 0; }运行结果可以看到我们成功把这个邮箱分成了三个部分但是有一个问题这里有两个分隔符我们就写了三行代码,这样的代码看起来是不是很挫而且如果有n个分隔符就会变得很麻烦这时候就可以用下面的方法#include stdio.h #include string.h int main() { char arr1[] BANZHANCHAXIANG163.com; char arr2[] .; char* p NULL; for (p strtok(arr1, arr2); p ! NULL; p strtok(NULL, arr2)) { printf(%s , p); } return 0; }运行结果我们利用for循环初始化只进行一次的技巧来调用第一次的strtok并且将它赋值给p指针随后我们调用strtok的第一个参数就只需要传空指针就可以写在循环的调整部分而中间的循环结束条件为什么设置为不等于NULL呢因为当我们的字符串分隔完毕没有分隔符后函数就会返回一个空指针p也就等于空指针了此时用来退出循环刚好六、strerror和perror函数的使用1.strerror函数strerror 函数可以把参数部分错误码对应的错误信息的字符串地址返回来在不同的系统和C语标准库的实现中都规定了些错误码般是放在errno.h 这个头件中说明的C语程序启动的时候就会使个全局的变量errno来记录程序的当前错误码只不过程序启动的时候errno是0表没有错误但是如果当我们在使标准库中的函数的时候发了某种错误就会将对应的错误码存放在errno中而个错误码的数字是整数很难理解是什么意思所以每个错误码都是有对应的错误信息的strerror函数就可以将错误对应的错误信息字符串的地址返回可以用%s的形式将错误信息打印出来#include stdio.h #include string.h int main() { int i 0; for (i 0; i 10; i) { printf(%s , strerror(i)); } return 0; }在Windows11VS2022环境下输出的结果如下我们可以测试使用文件操作测试一下#include stdio.h #include string.h #include errno.h int main () { FILE * pFile; pFile fopen (data.txt,r); if (pFile NULL) printf (fopen: %s , strerror(errno)); return 0; }在当前路径的代码目录上并没有data.txt这个文件自然不能打开文件进行读操作所以这个代码会在errno.h中产生一个错误码这个时候我们就把这个错误码打印出来2.perror函数接下来我们也可以了解下 perror 函数perror函数的使用更加简单方便可以直接将错误信息打印出来perror函数的参数里可以写上可能出现错误的命令的名字它可以打印参数部分的字符串后再打印个冒号和个空格再打印错误信息#include stdio.h #include string.h #include errno.h int main () { FILE * pFile; pFile fopen (data.txt,r); if (pFile NULL) perror(fopen); return 0; }到这里我们一些常见的函数基本介绍完了大家也可以自行去这个网站学习 cplusplus下一期我们继续学习内存函数的使用和模拟实现
在21世纪的我用C语言探寻世界本质——字符函数和字符串函数(2)
人无完人持之以恒方能见真我共同进步文章目录一、strncpy函数的使用二、strncat函数的使用三、strncmp函数的使用四、strstr的使用和模拟实现五、strtok函数的使用六、strerror和perror函数的使用1.strerror函数2.perror函数一、strncpy函数的使用我们之前学习的strcpy的作用是把源字符串拷贝到目标空间内而且经过我们的模拟实现我们也意识到它拷贝的时候会把目标空间的内容给替换了我们可以来测试一下可以看到将arr2的内容拷贝到arr1中时把arr1原本的内容替换了那假设我们不想让它全部拷贝过来只是拷取一部分OK不OK这个时候就要引入我们带n的字符串函数那个多出来的n就代表数量是我们想拷贝字符串时要拷贝的字符的个数而不带n的字符串函数和带n的字符串函数的根本区别是带n的字符串函数更灵活可以指定拷贝的字符的个数所以也叫带n的字符串函数为受限制的字符串函数不带n的为不受限制的字符串函数接下来我们来看看本次讲到的strncpy函数的原型char * strncpy ( char * destination, const char * source, size_t num );它的参数与strcpy的区别就是多了最后一个参数它的作用就是指定我们要拷贝的字符的个数它的特点如下拷num个字符从源字符串到标空间如果源字符串的度于num则拷完源字符串之后在标的后边追加直到num个#include stdio.h #include string.h int main() { char arr1[20] abcdef; char arr2[20] ghijklmn; strncpy(arr1, arr2, 3); printf(%s , arr1); return 0; }可以看到只拷贝了arr2中的前三个字符进arr1并且覆盖了arr1的前三个字符这就是strncpy的作用至于strncpy的模拟实现与strcpy的模拟实现相似这里就不再过多讲解二、strncat函数的使用strncat也是带n家族的一员多n的原因和strncpy差不多就是用来指定要追加到目标空间的字符的个数它的原型如下char * strncat ( char * destination, const char * source, size_t num );它的特点是将source指向字符串的前num个字符追加到destination指向的字符串末尾再追加个 字符如果source指向的字符串的字符个数于num的时候只会将字符串中到 的内容追加到destination指向的字符串末尾了解到这里我们来尝试使用一下strncat把arr2的前3个字符追加到arr1里如下#include stdio.h #include string.h int main() { char arr1[20] abcdef; char arr2[20] ghijklmn; strncat(arr1, arr2, 3); printf(%s , arr1); return 0; }运行结果如果后面的第三个参数num大于arr2的大小会发生什么呢运行结果调试结果:三、strncmp函数的使用strncmp的作用就是比较str1和str2的前num个字符如果相等就继续往后较最多较num个字如果在这num个字符中发现不样就看此时哪个字符串更大前者大就返回大于0的数如果后者大就返回小于0的数如果num个字符都相等就是相等返回0我们来看看它的原型int strncmp ( const char * str1, const char * str2, size_t num );我们来使用它比较arr1和arr2前三个字符的大小:#include stdio.h #include string.h int main() { char arr1[20] abcdef; char arr2[20] ghijklmn; int ret strncmp(arr1, arr2, 3); printf(在前三个字符的比较中); if (ret 0) printf(arr1 arr2 ); else if (ret 0) printf(arr1 arr2 ); else printf(arr1 arr2 ); return 0; }运行结果四、strstr的使用和模拟实现这是一个对我们来说比较新的函数我们来仔细介绍一下使用方法以及它的模拟实现它的作用就是返回后一个字符串在前一个字符串中第次出现的位置并且字符串的较匹配不包含 字符以 作为结束标志接下来我们来看看strstr的原型const char* strstr ( const char* str1, const char* str2);它的原型中参数看起来很简单就是两个字符串那它的返回值是啥捏有两种情况:如果在字符串str1中找到了字符串str2那么就返回str1中找到str2的起始位置如果没有在字符串str1中找到字符串str2那么就返回一个NULL所以在使用的时候我们就可以通过它的返回值来确认是否找到对应的字符串如果返回非空指针那么就是找到了返回空指针就是没有找到接下来我们用实例来加深理解#include stdio.h #include string.h void isfind(const char* x) { if (x) printf(找到了 ); else printf(没找到 ); } int main() { char arr1[20] abcdef; char arr2[20] ghijklmn; char arr3[20] cde; isfind(strstr(arr1, arr2)); isfind(strstr(arr1, arr3)); return 0; }运行结果我们来模拟实现一下 strstr函数命名my_strstr函数参数可以照抄strstr函数的原型如下const char* my_strstr ( const char* str1, const char* str2);函数实现1老样子assert进行断言2然后我们来分析这个函数可能出现的情况按照我们正常去想就会想到首先就去看str1和str2指向的字符相不相等不相等就两个指针都往后找直到它们指向的字符相等3随后往后开始找但是会出现一个问题万一这一次匹配不上只有前几个字符相等后面并不相等那我们怎么找到之前开始匹配的位置呢如图4所以我们让str1和str2直接往后走是不妥的这样一旦匹配失败我们就记不住当时开始匹配的位置也就不能进行下一次匹配所以我们可以重新创建三个指针变量5有两个用来装下str1一个用来代替str1往后走一个用来记住当前第一次匹配的位置至于str1就老老实实待在原地不要动6还有一个用来装str2这样如果匹配失败就把str2重新赋值给这个变量让它重新指向str2的开头创建如下const char* my_strstr(const char* str1, const char* str2) { assert(str1 str2); const char* s1 str1;//代替str1用来往后匹配字符 const char* s2 str2;//代替str2用来往后匹配字符 const char* cp str1;//记录开始匹配字符的位置 }7有了以上的经验我们为了避免犯错可以使用思路比较简单的暴力匹配就是创建一个循环我们对cur进行解引用只要里面不是结束标志我们就进入循环然后看这个位置的字符是否和str2的第一个字符相等8如果不相等我们就让cp让我们的当前位置往前挪动一下如果相等就进行完整的匹配这里还是有两种情况一是如果完全匹配那么就返回cp就是我们开始匹配时的位置二是如果不能完全匹配那么就还是让cp并且将cp重新赋值给s1将str2重新赋值给s29现在我们就来看进行一次匹配的过程也很简单我们还是创建一个while循环如果s1和s2解引用不是 并且解引用后相等那我们就让s1和s2加加一直往后走当循环结束时我们就判断s2解引用后是否是 如果是说明完全匹配上了就返回cp不是那么说明没有完全匹配就让cp开始下一次循环查找10最后一步就是如果我们遍历了s1中的所有字符还是发现两个字符串没有完全匹配的地方就直接返回空指针NULLconst char* my_strstr(const char* str1, const char* str2) { assert(str1 str2); if(*str2 ) { return (char*)str1; } const char* s1 str1; const char* s2 str2; const char* cp str1; while (*cp) { s1 cp;//重新赋值 s2 str2;//重新赋值 while (*s1 *s2 *s1 *s2) { s1; s2; } if (*s2 ) return cp; cp; } return NULL; }这是一般的情况我们换一种更复杂的情况测试可以看到我们实现的函数还是成功帮我们完成了任务这里的strstr函数的实现就到此结束了,模拟实现这个函数要考虑多种情况希望大家能够下来多敲敲欢迎大家在评论区留言五、strtok函数的使用这也是一个新函数它的作用是什么呢它可以按照我们给出的分隔符来分割我们的字符串现在我们先来了解一下它的原型char * strtok ( char * str, const char * sep);接下来我们来总结一下它的特点sep参数指向个字符串定义了作分隔符的字符集合第个参数指定个字符串它包含了0个或者多个由sep字符串中个或者多个分隔符分割的标记strtok函数找到str中的下个标记并将其 结尾返回个指向这个标记的指针注strtok函数会改变被操作的字符串所以被strtok函数切分的字符串般都是临时拷的内容并且可修改strtok函数的第个参数不为 NULL 函数将找到str中第个标记strtok函数将保存它在字符串中的位置strtok函数的第个参数为 NULL 函数将在同个字符串中被保存的位置开始查找下个标记如果字符串中不存在更多的标记则返回 NULL 指针比如我们的邮箱由两个分隔符分隔开来就是符合和(.)点号我们想把这个邮箱地址分隔开来可以这样操作#include stdio.h #include string.h int main() { char arr1[] BANZHANCHAXIANG163.com; char arr2[] .; char* ret1 strtok(arr1, arr2); char* ret2 strtok(NULL, arr2); char* ret3 strtok(NULL, arr2); printf(%s %s %s , ret1, ret2, ret3); return 0; }运行结果可以看到我们成功把这个邮箱分成了三个部分但是有一个问题这里有两个分隔符我们就写了三行代码,这样的代码看起来是不是很挫而且如果有n个分隔符就会变得很麻烦这时候就可以用下面的方法#include stdio.h #include string.h int main() { char arr1[] BANZHANCHAXIANG163.com; char arr2[] .; char* p NULL; for (p strtok(arr1, arr2); p ! NULL; p strtok(NULL, arr2)) { printf(%s , p); } return 0; }运行结果我们利用for循环初始化只进行一次的技巧来调用第一次的strtok并且将它赋值给p指针随后我们调用strtok的第一个参数就只需要传空指针就可以写在循环的调整部分而中间的循环结束条件为什么设置为不等于NULL呢因为当我们的字符串分隔完毕没有分隔符后函数就会返回一个空指针p也就等于空指针了此时用来退出循环刚好六、strerror和perror函数的使用1.strerror函数strerror 函数可以把参数部分错误码对应的错误信息的字符串地址返回来在不同的系统和C语标准库的实现中都规定了些错误码般是放在errno.h 这个头件中说明的C语程序启动的时候就会使个全局的变量errno来记录程序的当前错误码只不过程序启动的时候errno是0表没有错误但是如果当我们在使标准库中的函数的时候发了某种错误就会将对应的错误码存放在errno中而个错误码的数字是整数很难理解是什么意思所以每个错误码都是有对应的错误信息的strerror函数就可以将错误对应的错误信息字符串的地址返回可以用%s的形式将错误信息打印出来#include stdio.h #include string.h int main() { int i 0; for (i 0; i 10; i) { printf(%s , strerror(i)); } return 0; }在Windows11VS2022环境下输出的结果如下我们可以测试使用文件操作测试一下#include stdio.h #include string.h #include errno.h int main () { FILE * pFile; pFile fopen (data.txt,r); if (pFile NULL) printf (fopen: %s , strerror(errno)); return 0; }在当前路径的代码目录上并没有data.txt这个文件自然不能打开文件进行读操作所以这个代码会在errno.h中产生一个错误码这个时候我们就把这个错误码打印出来2.perror函数接下来我们也可以了解下 perror 函数perror函数的使用更加简单方便可以直接将错误信息打印出来perror函数的参数里可以写上可能出现错误的命令的名字它可以打印参数部分的字符串后再打印个冒号和个空格再打印错误信息#include stdio.h #include string.h #include errno.h int main () { FILE * pFile; pFile fopen (data.txt,r); if (pFile NULL) perror(fopen); return 0; }到这里我们一些常见的函数基本介绍完了大家也可以自行去这个网站学习 cplusplus下一期我们继续学习内存函数的使用和模拟实现