字符串函数及其模拟实现(2)
文章目录一、strncpy代码演示二、strcmp代码演示模拟实现三、strcat代码演示四、strncmp代码演示五、strstr代码演示模拟实现六、strtok代码演示七、strerror代码演示perror代码演示一、strncpychar*strncpy(char*destination,constchar*source,size_tnum 功能字符串拷贝将 source 指向的字符串拷⻉到 destination 指向的空间中最多拷贝 num个字符。参数destination 指针指向⽬的地空间 source 指针指向源头数据 num 从source指向的字符串中最多拷贝的字符个数返回值strncpy 函数返回的⽬标空间的起始地址代码演示#includestdio.h#includestring.hintmain(){chararr1[20]{0};chararr2[]abcdefghi;char*strstrncpy(arr1,arr2,5);printf(%s\n,arr1);printf(%s\n,str);return0;}⽐较strcpy和strncpy函数1strcpy 函数拷⻉到 \0 为⽌如果⽬标空间不够的话容易出现越界⾏为2strncpy 函数指定了拷⻉的⻓度源字符串不⼀定要有 \0 同时在设计参数的时候就会多⼀层二、strcmpintstrcmp(constchar*str1,constchar*str2);功能⽤来⽐较 str1 和 str2 指向的字符串从两个字符串的第⼀个字符开始⽐较如果两个字符的ASCII码值相等就⽐较下⼀个字符。直到遇到不相等的两个字符或者字符串结束。参数str1 指针指向要⽐较的第⼀个字符串str2 指针指向要⽐较的第⼆个字符串返回值◦ 第⼀个字符串⼤于第⼆个字符串则返回⼤于0的数字◦ 第⼀个字符串等于第⼆个字符串则返回0◦ 第⼀个字符串⼩于第⼆个字符串则返回⼩于0的数字代码演示#includestdio.h#includestring.hintmain(){chararr1[]abcdef;chararr2[]abq;intretstrcmp(arr1,arr2);printf(%d\n,ret);if(ret0)printf(arr1 arr2\n);elseif(ret0)printf(arr1 arr2\n);elseprintf(arr1 arr2\n);return0;}模拟实现intmy_strcmp(constchar*str1,constchar*str2){intret0;assert(str1!NULL);assert(str2!NULL);while(*str1*str2){if(*str1\0)return0;str1;str2;}return*str1-*str2;}三、strcatchar*strncat(char*destination,constchar*source,size_tnum);功能字符串追加将 source 指向的字符串的内容追加到 destination 指向的空间最多追加 num 个字符。参数destination 指针指向了⽬标空间source 指针指向了源头数据num 最多追加的字符的个数返回值返回的是⽬标空间的起始地址代码演示#includestdio.h#includestring.hintmain(){chararr1[20]hello ;chararr2[]world;char*strstrncat(arr1,arr2,5);printf(%s\n,arr1);printf(%s\n,str);return0;}strcat和strncat对⽐ • 参数不同 strncat 多了⼀个参数• strcat 函数在追加的时候要将源字符串的所有内容包含 \0 都追加过去但是 strncat 函数指定了追加的⻓度。• strncat 函数中源字符串中不⼀定要有 \0 了。• strncat 更加灵活也更加安全。四、strncmpintstrncmp(constchar*str1,constchar*str2,size_tnum);功能字符串⽐较⽐较 str1 和 str2 指向的两个字符串的内容最多⽐较 num 字符。参数str1 指针指向⼀个⽐较的字符串str2 指针指向另外⼀个⽐较的字符串num 最多⽐较的字符个数返回值• 第⼀个字符串⼤于第⼆个字符串则返回⼤于0的数字• 第⼀个字符串等于第⼆个字符串则返回0• 第⼀个字符串⼩于第⼆个字符串则返回⼩于0的数字代码演示#includestdio.h#includestring.hintmain(){chararr1[]abcdef;chararr2[]abcqw;intret1strncmp(arr1,arr2,3);printf(%d\n,ret1);intret2strncmp(arr1,arr2,4);printf(%d\n,ret2);return0;}strcmp和strncmp⽐较• 参数不同• strncmp可以⽐较任意⻓度了• strncmp函数更加灵活更加安全五、strstrchar*strstr(constchar*str1,constchar*str2);功能strstr 函数查找 str2 指向的字符串在 str1 指向的字符串中第⼀次出现的位置。简⽽⾔之在⼀个字符串中查找⼦字符串。strstr 的使⽤得包含string.h参数str1 指针指向了被查找的字符串str2 指针指向了要查找的字符串返回值• 如果str1指向的字符串中存在str2指向的字符串那么返回第⼀次出现位置的指针• 如果str1指向的字符串中不存在str2指向的字符串那么返回NULL代码演示#includestdio.h#includestring.hintmain(){charstr[]This is a simple string;char*pch;pchstrstr(str,simple);if(pch!NULL)printf(%s\n,pch);elseprintf(查找的字符串不存在\n);return0;}模拟实现char*strstr(constchar*str1,constchar*str2){char*cp(char*)str1;char*s1,*s2;//特殊情况str2是空字符串时直接返回str1if(!*str2)return((char*)str1);while(*cp){s1cp;s2(char*)str2;while(*s1*s2!(*s1-*s2))s1,s2;if(!*s2)return(cp);//返回第⼀次出现的起始cp;}return(NULL);//找不到则返回NULL}strstr函数的实现有多种可以暴⼒查找也有⼀种⾼效⼀些的算法KMP…六、strtokchar*strtok(char*str,constchar*delim);功能• 分割字符串根据 delim 参数中指定的分隔符将输⼊字符串 str 拆分成多个⼦字符串。• 修改原始字符串 strtok 会直接在原始字符串中插⼊ ‘\0’ 终⽌符替换分隔符的位置因此原始字符串会被修改。参数1. str ⾸次调⽤时传⼊待分割的字符串后续调⽤传⼊ NULL 表⽰继续分割同⼀个字符串。2. delim 包含所有可能分隔符的字符串每个字符均视为独⽴的分隔符。返回值• 成功时返回指向当前⼦字符串的指针。• 没有更多⼦字符串时返回 NULL 。使⽤步骤1. ⾸次调⽤传⼊待分割字符串和分隔符。2. 后续调⽤传⼊ NULL 和相同的分隔符继续分割。3. 结束条件当返回 NULL 时表⽰分割完成。代码演示#includestdio.h#includestring.hintmain(){chararr[]192.168.6.111;constchar*sep.;constchar*strNULL;charbuf[30]{0};strcpy(buf,arr);//将arr中的字符串拷⻉到buf中对buf的内容进⾏切割for(strstrtok(buf,sep);str!NULL;strstrtok(NULL,sep)){printf(%s\n,str);}return0;}注意• 破坏性操作 strtok 会直接修改原始字符串将其中的分隔符替换为 ‘\0’ 。如果需要保留原字符串应先拷⻉⼀份。• 连续分隔符多个连续的分隔符会被视为单个分隔符不会返回空字符串。• 空指针处理如果输⼊的 str 为 NULL 且没有前序调⽤⾏为未定义。七、strerrorchar*strerror(interrnum);功能1. strerror 函数可以通过参数部分的 errnum 表⽰错误码得到对应的错误信息并且返回这个错误信息字符串⾸字符的地址。2. strerror 函数只针对标准库中的函数发⽣错误后设置的错误码的转换。3. strerror 的使⽤需要包含string.h(在不同的系统和C语⾔标准库的实现中都规定了⼀些错误码⼀般是放在 errno.h 这个头⽂件中说明的C语⾔程序启动的时候就会使⽤⼀个全局的变量 errno 来记录程序的当前错误码只不过程序启动的时候 errno 是 0表⽰没有错误当我们在使⽤标准库中的函数的时候发⽣了某种错误就会将对应的错误码存放在 errno 中⽽⼀个错误码的数字是整数很难理解是什么意思所以每⼀个错误码都是有对应的错误信息的。strerror函数就可以将错误码对应的错误信息字符串的地址返回)参数errnum 表⽰错误码(这个错误码⼀般传递的是 errno 这个变量的值在C语⾔有⼀个全局的变量叫 errno 当库函数的调⽤发⽣错误的时候就会讲本次错误的错误码存放在 errno 这个变量中使⽤这个全局变量需要包含⼀个头⽂件 errno.h )返回值函数返回通过错误码得到的错误信息字符串的⾸字符的地址。代码演示#includeerrno.h#includestring.h#includestdio.h//我们打印⼀下0~10这些错误码对应的信息intmain(){inti0;for(i0;i10;i){printf(%d: %s\n,i,strerror(i));}return0;}在Windows11 VS2022环境下输出的结果如下0:No error1:Operation not permitted2:No such file or directory3:No such process4:Interrupted function call5:Input/output error6:No such device or address7:Arg list toolong8:Exec format error9:Bad file descriptor10:No child processes举例#includestdio.h#includestring.h#includeerrno.hintmain(){FILE*pFileNULL;//fopen函数以读的形式打开⽂件如果⽂件不存在则打开失败。pFilefopen(unexist.ent,r);if(pFileNULL){printf(错误信息是%s\n,strerror(errno));return1;//错误返回}return0;}输出错误信息是No such file or directoryperror类似的可以了解perror函数相当于⼀次将上述代码中的第11⾏完成了直接将错误信息打印出来。 perror 函数打印完参数部分的字符串后再打印⼀个冒号和⼀个空格再打印错误信息。代码演示#includestdio.h#includestring.h#includeerrno.hintmain(){FILE*pFileNULL;pFilefopen(unexist.ent,r);if(pFileNULL){perror(错误信息是);return1;}return0;}输出错误信息是:No such file or directory