C语言函数: 字符串函数及模拟实现strtok()、strstr()、strerror()
创始人
2024-06-01 03:02:41
0

C语言函数: 字符串函数及模拟实现strtok()、strstr()、strerror()

strstr()函数:

        作用:字符串查找。在一串字符串中,查找另一串字符串是否存在。

形参:

4b2e6b20082d41528eadfab74266debc.png

       str2在str1中寻找。返回值是char*的指针

        原理:如果在str1中找到了str2,则返回在str1中存在的str2的字符串的第一个字符的地址。如果在str1中每找到str2,则返回NULL(空指针)。

举例:

#define _CRT_SECURE_NO_WARNINGS#include int main()
{char arr1[] = "abcdefgh";char arr2[] = "bcde";char arr3[] = "bcdeh";char* a1 = strstr(arr1, arr2);char* a2 = strstr(arr1, arr3);return 0;
}

        a1是在arr1中寻找arr2,在arr1[1]~arr1[4]上找到了与arr2一样的字符串,则返回arr1中字符'b'的地址。

        a2是在arr1中寻找arr3,在arr1中并未找到与arr1一样的字符串,则返回NULL。

#define _CRT_SECURE_NO_WARNINGS#include int main()
{char arr1[] = "abcdefgh";char arr2[] = "bcde";char arr3[] = "bcdeh";char* a1 = strstr(arr1, arr2);char* a2 = strstr(arr1, arr3);if (a1 != NULL){printf("arr2找到了");//结果:arr2找到了}if (a2 == NULL){printf("arr3没找到");//结果:arr3没找到}return 0;
}

strstr()函数的模拟实现:

char* my_strstr(const char* str1, const char* str2)//因为两个地址值不会改变,所以加const
{assert(str1 && str2);//防止两个参数为NULLchar* pt1 = NULL;char* pt2 = NULL;char* nc = str1;//用于在字符串中找到与str2首元素一样字符。while (*nc)//当str1中找完了,都没有找到和str2中首元素一样的字符时停止循环。{pt1 = nc;//用于定位到每次找到和str2中首元素一样的字符的地址。pt2 = str2;//用于指向str2的首元素地址。while (*pt1 && *pt2 && ( * pt1 == *pt2))//找到和str2中首元素一样的字符{pt1++;pt2++;}if (*pt2 == '\0')//当上面的循环走完,ptr2的指向\0时,说明在str1中找到了和str2一样的字符串{return nc;//返回当时的字符串。}nc++;//当这个str1中的元素和str2不匹配,就要看下一个字符是否匹配。}return NULL;
}

        

int main()
{char arr1[] = "abbcdef";char arr2[] = "bcd";char* a1 = my_strstr(arr1, arr2);if (a1 != NULL){printf("arr2找到了\n");//结果:arr2找到了}else{printf("arr2没找到\n");}return 0;
}

        

补充:还有一种算法:KMP算法。也是一个字符串查找的算法。


strtok()函数:

        作用:对字符串进行切分(分割)

        #include

参数:

a8252c78062a410c91484cd68d05255b.png

        str是将被分割的字符串

        sep是需要传入的是字符串,sep内包含了需要作为分割符的字符的集合

        71ff5a9b43c14eddb52b3d06b567d768.png

        如果要将str中分为三个部分:www、qq、com

        那么就需要在@和.处进行分割。因此,@和.就是分割符,将分隔符放入sep字符串中,此时就是 :分割符的字符的集合

       

原理:

       这里有个字符串str :"www@qq.com\0"

        strtok()会将按照sep所指示的,在str中寻找sep内存在的字符。

        找到@后,会将@改成\0。

        strtok()返回@之前的字符串的首元素地址,即:str中第一个'w'的地址。

        并且strtok会记录此时\0的位置。

        strtok有两种机制:

        1.如果strtok不为NULL,那么会保存@的位置(@会被改成\0)     

        2.如果strtok为 NULL,那么会从上次strtok所保存@的位置,继续往下找seq中的字符,如果找到,接着分割。最后再保存被改成\0的位置。

        最后:如果strtok找到了没被改的\0,也就是字符串末尾的\0时,返回NULL。

        

        那么有疑问了,strtok是怎么保存@的位置呢?

        其实,想要保存某个数据,实际上就是创建一个全局变量。只要创建了全局变量,程序运行到哪里,无论在哪个函数中,都可以被使用。

        因此,strtok就是利用全局变量的能力,从而保存了@的位置。那么strtok是怎么保存的呢?难道直接在代码中写上一个全局变量吗?显然不是。

        strtok其实是使用static修饰了存放@位置的变量,因为static基本含义就是让一个变量成为全局变量。

        static函数名除了对该函数声明的文件可见外,其他文件都无法访问。也就是只能被本文件中的函数调用,而不能被同一程序中的其他文件的函数调用。

        static可以限定变量或函数为静态存储。静态函数会被自动分配在一个一直使用的存储区,直到程序结束才从内存消失,static限定的变量或函数不会和同一程序中其他文件同名的相冲突。如果用static限定内部变量,则该变量从程序一开始就用有内存,不会随其所在函数的调用和退出而分配和消失。

        

#define _CRT_SECURE_NO_WARNINGS#include 
#include void cc()
{static int opp = 0;opp++;printf("%d", opp);
}int main()
{cc();//结果:1int opp = 3;cc();//结果:2return 0;
}

使用建议:

        因为strtok的会对str字符串本身进行修改,如果不想对strtok进行修改时,可以用strcpy进行拷贝,然后对拷贝的字符串使用strtok

        

char arr[] = "www@qq.com";char* p = "@.";char tmp[20] = { 0 };strcpy(tmp, arr);//拷贝

实验:

        

#define _CRT_SECURE_NO_WARNINGS#include 
#include 
#include int main()
{char arr[] = "www@qq.com";char* p = "@.";char tmp[20] = { 0 };strcpy(tmp, arr);char* ret = NULL;ret = strtok(tmp, p);printf("%s\n", ret);//wwwret = strtok(NULL,p);printf("%s\n", ret);//qqret = strtok(NULL, p);printf("%s\n", ret);//comret = strtok(NULL, p);printf("%s\n", ret);//(null)return 0;
}

        创建了一个ret用于存放,每次strtok返回的字符串首元素地址。

        第一次调用 strtok(tmp, p)拿到了(返回)'w'的地址,保存了@(\0)的位置。

        第二次调用strtok(NULL,p)拿到了(返回)'q'的地址,保存了.(\0)的位置。

        第三次调用strtok(NULL,p)拿到了(返回)'c'的地址,\0的位置。

        第四次调用strtok(NULL,p)拿到了(返回)NULL,这是因为\0后面找不到p内包含的字符了。

        结果打印三个部分:www、qq、com

代码强化:

        这一个一个地调用strtok显然是不合理地。

        并且我们发现除了第一次调用strtok,传入地第一个参数是一个活指针之外,后面的几次调用使用的都是NULL,因此我们可以创建一个循环,从而分割它们。

        

#define _CRT_SECURE_NO_WARNINGS#include 
#include 
#include int main()
{char arr[] = "www@qq.com";char* p = "@.";char tmp[20] = { 0 };strcpy(tmp, arr);char* ret = NULL;for ( ret = strtok(tmp, p); ret != NULL; ret = strtok(NULL, p)){printf("%s\n", ret);}return 0;
}

        for(初始化值;判断条件;对值改变)

        初始化值,执行了strtok第一次调用。

        判断条件,如果为strtok返回了NULL,说明没有分隔符了,for循环就停止。

        对值改变,做到了除第一次以外,后n次地对strtok地调用。

        

模拟实现:

       C语言源码剖析与实现——strtok()系列函数实现_strtok源码_C+G的博客-CSDN博客


strerror

        作用:翻译错误码。在使用库函数的时候,如果失败了都会出现错误码,而这串错误码你完全不懂是什么意思,比如:5,这个错误码的意思是什么呢?肯定不知道吧。

        错误码的作用是告诉你,你的代码执行过程中出现的错误。比如内存空间不足等等...

参数:

        头文件:#include

d954914288674d1ebd423beeb356dcfd.png

        strerror返回的是一个地址,这个地址指向了一个字符串。这个字符串就是strerror从错误码所翻译出来的一句话。

        

#define _CRT_SECURE_NO_WARNINGS#include 
#include 
#include 
#include int main()
{printf("%s\n", strerror(0));printf("%s\n", strerror(1));printf("%s\n", strerror(2));return 0;
}

 

        除此之外,还有许多C语言内部的错误码。

errno:

        errno是C语言定义的一个全局变量,它的作用是存放代码执行过程中出现的错误码。

        它不需要人为的定义,当用到它的时候只需要引头文件:#include

        

举例:

        

#define _CRT_SECURE_NO_WARNINGS#include 
#include 
#include 
#include int main()
{//fopen:打开文件FILE* pf = fopen("test.txt", "r");//test.txt不存在if(pf ==NULL)//fopen找不到test.txt会返回空指针printf("%s\n", strerror(errno));//返回错误信息return 0;
}

模拟实现:

        单纯的翻译代码,因此不做实现。

 

相关内容

热门资讯

Python|位运算|数组|动... 目录 1、只出现一次的数字(位运算,数组) 示例 选项代...
张岱的人物生平 张岱的人物生平张岱(414年-484年),字景山,吴郡吴县(今江苏苏州)人。南朝齐大臣。祖父张敞,东...
西游西后传演员女人物 西游西后传演员女人物西游西后传演员女人物 孙悟空 六小龄童 唐僧 徐少华 ...
名人故事中贾岛作诗内容简介 名人故事中贾岛作诗内容简介有一次,贾岛骑驴闯了官道.他正琢磨着一句诗,名叫《题李凝幽居》全诗如下:闲...
和男朋友一起优秀的文案? 和男朋友一起优秀的文案?1.希望是惟一所有的人都共同享有的好处;一无所有的人,仍拥有希望。2.生活,...
戴玉手镯的好处 戴玉手镯好还是... 戴玉手镯的好处 戴玉手镯好还是碧玺好 女人戴玉?戴玉好还是碧玺好点佩戴手镯,以和田玉手镯为佳!相嫌滑...
依然什么意思? 依然什么意思?依然(汉语词语)依然,汉语词汇。拼音:yī    rán基本解释:副词,指照往常、依旧...
高尔基的散文诗 高尔基的散文诗《海燕》、《大学》、《母亲》、《童年》这些都是比较出名的一些代表作。
心在飞扬作者简介 心在飞扬作者简介心在飞扬作者简介如下。根据相关公开资料查询,心在飞扬是一位优秀的小说作者,他的小说作...
卡什坦卡的故事赏析? 卡什坦卡的故事赏析?讲了一只小狗的故事, 我也是近来才读到这篇小说. 作家对动物的拟人描写真是惟妙...
林绍涛为简艾拿绿豆糕是哪一集 林绍涛为简艾拿绿豆糕是哪一集第三十二集。 贾宽认为是阎帅间接导致刘映霞住了院,第二天上班,他按捺不...
小爱同学是女生吗小安同学什么意... 小爱同学是女生吗小安同学什么意思 小爱同学,小安同学说你是女生。小安是男的。
内分泌失调导致脸上长斑,怎么调... 内分泌失调导致脸上长斑,怎么调理内分泌失调导致脸上长斑,怎么调理先调理内分泌,去看中医吧,另外用好的...
《魔幻仙境》刺客,骑士人物属性... 《魔幻仙境》刺客,骑士人物属性加点魔幻仙境骑士2功1体质
很喜欢她,该怎么办? 很喜欢她,该怎么办?太冷静了!! 太理智了!爱情是需要冲劲的~不要考虑着考虑那~否则缘...
言情小说作家 言情小说作家我比较喜欢匪我思存的,很虐,很悲,还有梅子黄时雨,笙离,叶萱,还有安宁的《温暖的玄》 小...
两个以名人的名字命名的风景名胜... 两个以名人的名字命名的风景名胜?快太白楼,李白。尚志公园,赵尚志。
幼儿教育的代表人物及其著作 幼儿教育的代表人物及其著作卡尔威特的《卡尔威特的教育》,小卡尔威特,他儿子成了天才后写的《小卡尔威特...
海贼王中为什么说路飞打凯多靠霸... 海贼王中为什么说路飞打凯多靠霸气升级?凯多是靠霸气升级吗?因为之前刚到时确实打不过人家因为路飞的实力...
运气不好拜财神有用吗运气不好拜... 运气不好拜财神有用吗运气不好拜财神有没有用1、运气不好拜财神有用。2、拜财神上香前先点蜡烛,照亮人神...