字符串函数(strncpy/cat/cmp、strstr、strtok、strerror)

1、strcmp使用和实现

strcmp就是比较两个字符串的大小;

  1. 如果str1 大于 str2 ,返回大于0 的数
  2. 如果str1 等于 str2 ,返回0
  3. 如果str1 小于 str2 ,返回小于0 的数

有两个参数,str1字符串的地址,str2字符串的地址;返回大于0或者等于0的数那类型是int ;

strcmp比较的是两个字符串大小,它是挨个挨个字符串去比较,不是管你字符串长度有多长,挨个比较字符串背后的ASCII码,你的码大,那个字符串的就是大;

比如arr和arr1,abcd都是相等的,但是arr后面还有一个斜杠0,是斜杠0和arr1的e去比较,arr就比arr1小,结果就是<;

或者abz和abcdefg比较,挨个比较,z就是比c的ASCII码值大,所以abz比它大;

strcmp实现:

  1. 首先就是看它的原型去模拟,参数、返回值都对得上;

  2. assert是防止使用得指针变量是空指针;

  3. 字符之间挨个比较,while循环,判断*str1 == *str2 ,为真,就是往后走str1++,str2++;

  4. 如果比较得时候*str1不等于*str2 ,循环结束,返回两个字符相减得结果,根据返回得结果就可以判断,谁大谁小;

  5. 还有一种情况当两个字符都是指向\0,相等;就是直接返回0;为什么再循环里面?因为两个为\0也是相等得,后面会++;越界访问;一旦它们某个\0相等,直接返回0;

1.2、待n不带n的区别

strncpy和strncat、strncmp中的n表示num、数字,数量;

它们跟strcpy、strcat、strcmp的区别就是前者是有长度限制的,你要告诉我拷贝几个,追加几个,是有确定的数量的;后者是没有长度限制的,全给你拷贝、追加;

2、strncpy使用和实现

跟strcpy是一样的,只不过多了一个参数num;要你拷贝几个字符;

比如说第一张情况;你要拷贝6个,就给你拷贝6个,拷完 ;第二种情况如果你要拷贝6个,实际被拷贝的只有3个字符,也会拷贝过去,多余的3个会给你补\0;

strncpy实现:

  1. 看原型写参数,原参数都一样,多了一个num;
  2. strncpy跟strcpy一样,返回的是字符串的地址,返回ret
  3. assert防止NULL;
  4. 因为有拷贝的字符限制,while是有比较次数限制的num,num--;然后就是交换,没什么好说的
  5. 第二个循环就是模拟,要拷贝的字符不够怎么办,还是按照次数num,再第一个循环里面拷贝了多少就--;拷贝到\0停止,进入第二个循环,把剩下的次数dest++,全部转为\0;

3、strncat使用和实现

跟strcat是一样的,原参数是一样的;多个num参数,限制你追加num个字符;

把arr数组内容追加到arr1里面,追加是从\0开始的;

第一种情况;刚好把字符全部追加到arr1数组里,然后后面给你加了一个\0;

第二种情况;要拷贝的字符与num不匹配,它会像strncpy,一样拷贝过去,但是剩下的strncat只会补一个\0,比如abcde,我num=10;那后面只会追加xxxabcde\0xx;

strncat实现:

  1. 参数一样,多个num参数;
  2. 把dest先装起来,后面dest会变;
  3. assert整起来;
  4. 既然从\0开始追加,那就先把\0找出来;第一个循环
  5. 第二个循环就是赋值,把arr1的值追加到arr里面;是有num次数的;
  6. 追加完,单独补个\0;

4、strncmp使用和实现

参数一样,多个num参数;

限制你比较几个字符;

第一个情况;像我这一样就是比较6个字符,且相等,为0;

第二个情况;假设abzde和abcdefg比较6个字符,z比c大,前者大;

第三个情况;假设abc和abcdefg比较6个字符,还在挨个比较,前者最后是\0,后者是d跟\0比,后者大;

strncmp实现:

  1. 参数是一样的
  2. assert一样的
  3. 有num次数的循环,相等就下一个字符,第一种情况,num次数消耗之前,遇到不相等,返回它俩的差值;
  4. 第二种情况;比较的字符次数比完了相等,返回0;为什么是num=1,就返回?以我写的这两个数组为例,算一下,当num=2的时候循环进去,判断的是d字符,但是判断完后面就++了,就是上一个字符判断完,指针就已经指向下一个字符去了;当num1等于1是就已经是最后一个字符e了,判断完了,就返回;不加这条件,当num=0;已经越界访问了;

5、strstr使用和实现

strstr就是一个字符串再另一个字符串出现的位置

如果找到相匹配字符串出现的位置,就返回那个位置;否则找不到,返回NULL;

参数:

  1. 两个都是字符串的地址
  2. 返回类型是返回str2在str1中出现位置的那个地址;

arr2就是def,返回的是在arr1中首次出现的地址;打印出来的结果;

用起来容易,实现起来有点复杂;

1、两个字符串参数,都要const修饰,只是访问不修改;返回类型是const char*;

2、有两个数组,一个str1,一个str2;(左图)一开始指针指向的位置,str1开始逐个字符比较,看是否相同,期间都不相同,str2按兵不动,str1++;直到str1指向d,str1发起起义;(中间的图),并记录下来这个位置,str2看到是str1指向也是d,信号来了,出兵;开始逐个比较都相等;(右图),直到str2遇到\0,str1遇到g,它们俩不一样,但是结束了,str2已经胜利了,遇到\0,str1记录下了str2开始的位置,但是怎么找回去呢?不可能在减回去,不合适;所以除了str1和str2,还是需要另外一个指针记录下来它们起义的位置;这是一种情况;一次就匹配成功;

3、第二种情况,多次匹配;以下这个列子就是要多次匹配才能匹配上;从str1和str2都在最开始的位置,不相同,str1先++,去找相同的;找打了第一个b,str1说是一样的,(左图),先记录下来这个位置,str2发现一样也开始出发;后面发现不对劲,str2指向c,str1却指向b,不一样得从头来过;(中图),str1原先记录得位置不行了,一开始就是那个位置,往后匹配不了,那就从原来的下一个位置开始匹配,并且记录下来;str1找回去容易,但是str2找回去难;(右图)所以还需要两个指针,记录下两个数组一开始的位置,方便找回来;后面就是重新匹配,一直匹配到str2遇到\0,说明已经找到你了,但是我的返回值就是指针,找到第一个匹配字符串开始的地址,那就把蓝色箭头指向的位置返回就好了,因为我们已经记录下来了。

看图,在写代码,会好理解一点

1、先把str1和str2的位置先存起来,让s1和s2代替,挨个比较,再定义一个cur变量,记录当前位置,当前位置是str1;

2、cur就是记录当前比较的位置,其实就是while循环从str1挨个遍历字符,每个位置都是开始匹配的位置;当一个开始的位置没有匹配成功,就cur++,往下一个字符开始;当第一个循环while(*cur)遍历完整个str1都没有找到,那就说明没有找到匹配的字符,返回NULL空指针;

3、先从当前位置匹配一次,把cur也就是当前str1的位置给s1,让s1去挨个遍历str1字符;把str2给s2让去挨个遍历要匹配的字符;

4、while循环就是判断当前开始匹配的位置跟str2的字符时候匹配,满足条件就++,下一个,当循环结束的时候,s2就已经指向str2中\0了,那说明已经找到了,找到就返回当前位置cur。

while循环有三个条件;第一个s1就是当s1是\0的时候,说明s1已经找完了,不需要再往后找了;*s1==*s2判断两个字符是否相等,不相等就为假,但是它和*s2是特殊的,s2为假的时候,s2就是\0,循环结束了;循环结束跳出来,需要加个if 判断;说明找到了,返回当前位置。

有一点特殊,当一开始要匹配的字符串就是只有\0,直接返回源数组

结合代码画图,更好理解,或者看些视频。

6、strtok函数

这个函数是很有意思的,就是把对字符串进行切分;根据它的分隔符集合里的分隔符,对应到字符串中的分隔符,分成一个个字符串

参数:

  1. 第一个参数就是要分割的字符串
  2. 第一个参数就是分隔符的集合,也可以当中字符串
  3. 返回的是分割字符串的地址

arr1就是要分割的字符串;arr2就是分割符的集合;就是你看arr1就像个网址,那些...就是分割符,邮箱那些@也是分隔符,#%&*都是;strtok都是根据arr2里面的分隔符集合来分割的,把那些分隔符都放进去,strstr看到要分割的字符,有那些分隔符字符串里分隔符,就会去分割;

分割是怎样分割的呢?看见分割符就是把分割符换成\0,并且记录下这次分割的地址;

strstr是有两种情况的:

  1. 第一个参数不为NULL,就是正常给字符串,就是返回第一个标记字符串的地址,把分割符改成\0,并记录改的位置,也就是\0的位置
  2. 第一个参数为NULL,就会从,上次记录的位置,往后分割,返回标记字符串的地址,把分割符改成\0,并记录改的位置,也就是\0的位置

那可以这样第一个分割符改一个参数,就记录了位置;身下的字符串,给NULL,都会从上记录下的位置往后拿;当拿到最后没得拿就会返回NULL;

实际这样写不太好,可以写成for循环,第一个只执行一次,判断不为NULL,打印;上来传NULL;再从一开始记录得位置获取字符串得地址;再判断;如此循环直到取不了字符串地址。

7、strerror函数

当用库函数时,会报错是有错误信息,这是错误信息是1,2,3,4这些数字代表得,难理解;比如一些网站404,是什么意思;但是strerror函数就是把这些信息翻译翻译出来;

但是这些错误信息都存在一个errno的变量里面;产生错误就会存放在里面,会覆盖掉之前的错误信息;需要包括头文件#include<errno.h>;

参数:

  1. 第一个参数是错误信息;
  2. 返回的是strerror翻译后的错误信息字符串地址

比如用fopen打开一个文件打开成功返回的是FILE* 类型的指针,但是打开不了,就返回NULL,会报错;

我们打开一个不存在的文件,返回NULL,就会把fopen放在errno变量里的报错信息,翻译并返回错误信息字符串的地址,打印出来。

8、perror函数

它跟strerror函数是一样的,只不过这个是一步到位,直接帮你打印;

perror就是printf + strerror,结合在一起;

也可以在perror函数里加上解释的字符串;红色框框都是perror函数直接给你的;

感谢观看

以上函数实现自己写的,能力有限,有错请指出

相关推荐
lly2024062 小时前
C# 数据类型
开发语言
不爱吃糖的程序媛2 小时前
鸿蒙PC端运行C语言程序:从编译到部署的全流程实战
c语言·华为·harmonyos
树欲静而风不止慢一点吧2 小时前
Qt5/6版本对应的Emscripten版本
开发语言·qt
微爱帮监所写信寄信3 小时前
微爱帮监狱寄信写信系统后台PHP框架优化实战手册
android·开发语言·人工智能·网络协议·微信·https·php
历程里程碑3 小时前
滑动窗口秒解LeetCode字母异位词
java·c语言·开发语言·数据结构·c++·算法·leetcode
思成Codes3 小时前
Go 语言中数组与切片的本质区别
开发语言·后端·golang
Tandy12356_3 小时前
手写TCP/IP协议栈——TCP结构定义与基本接口实现
c语言·网络·c++·网络协议·tcp/ip·计算机网络
Gofarlic_oms13 小时前
Cadence许可证全生命周期数据治理方案
java·大数据·运维·开发语言·人工智能·安全·自动化
成为大佬先秃头3 小时前
渐进式JavaScript框架:Vue — API
开发语言·javascript·vue.js