首页 > 编程知识 正文

strtok返回值,strstr函数用法

时间:2023-05-05 17:33:21 阅读:144944 作者:4148

strtok函数的使用是一个自古以来就经常谈论的问题。 这个函数的作用很大,争论也很大。 以下表述可能与部分资料有区别,也可能与你原来的认识不同,所以尽量用实验证明。 有必要说明实验环境。 是winxp vc6.0、极端平民化的实验环境。 本文使用的源代码大部分来自网络,但作为例子我会稍微修改一下。 当然,因为本人的水平有限,所以有不良之处是不可避免的。 请在谅解的基础上试着进行实验。

strtok函数的原型为char*strtok(char*s,char *delim ),功能为“parsesintotokensseparatedbycharactersindelim.if sis null, thesavedpointerinsave _ ptrisusedasthenextstartingpoint .”翻译成中文时,作用于字符串s,以delim中包含的字符为分隔符,将s分成一个子字符串; 如果s为NULL,则保存在函数中的指针SAVE_PTR将在下一次调用中开始。

函数的返回值是指向划分的子列的指针。

这个定义与国内一些网站的说法有一些差异,这些差异导致很多人对strtok没有正确的认识。 在调用一些函数之前,我希望你阅读官方文档(大多数是英语),而不是阅读虚假的、误导的资料。

使用strtok需要注意的有以下几点:

1 .函数的作用是分解字符串。 分解是指没有生成新的字符串,只是对s指示的内容进行了加工。 因此,源字符串s发生了变化! 将源字符串s转换为charbuffer[info_max_SZ]=',Fred male 25,John male 62,Annafemale16 '; 过滤器字符串delim为char *delim=' ',空格为分隔符。

在上图的代码中,结果是这样的。

首先,buffer发生了变化此时打印buffer的值时,会显示“,Fred”,但后面的' male 25…16 '会飞走。 实际上,strtok函数根据delim中的分隔符找到Fred后面的空格,即第一个出现位置,并将其修改为“/0”。 剩下的位置不变。 这很好地解释了为什么打印缓冲区的值时只显示“,Fred”,而不是缓冲区的所有内容。因此,使用strtok时一定要慎重,以防止源字符串被修改。

了解buffer的变化后,可以很好地说明函数的返回值。 返回值buf是分隔符的前一个子列。 (其实这个表达不准确。 有关详细信息,请参阅)3)中返回值的详细信息。注意,由变量的地址可知,buf依然指向源字符串。

如果分隔符delim没有变化,则停止截图。

2.若要在第一次提取子串完毕之后,继续对源字符串s进行提取,应在其后(第二次,第三次。。。第n次)的调用中将strtok的第一个参数赋为空值NULL。

第一次调用的结果如上所述,提取了',Fred '。 我们想继续以空间为界,提取后面的' male '等。 由上图可知,在第1次以后的调用中,向strtok的第一个参数传递null(http://www.Sina.com/),可以依次提取

, 接下来类推。

关于为什么分配null值,请记住结论,或者调查strtok的源代码。 正文的最后有几个介绍。

当然,也有人喜欢看不按套路出牌,而是不给空值继续代入buffer会怎么样。 其实,答案想了也知道。 再次传递buffer,相当于从字符串的开头开始查找分隔符delim,而且此时buffer只是被修正了(可见部分为)、Fred () ),因此其结果必然是找到了分隔符delim

3 .函数返回值的研究,如“1”所述,为表示函数继续从上一次调用隐式保存的位置,继续分解字符串;对于上述的第二次调用来说,第一次调用结束前用一个this指针指向了分界符的下一位,即'm’所在的位置,所以只要打印buf的值,就可以很好地输出子串的内容。

在提取到子串的情况下,strtok的返回值(假设返回值赋给了指针buf)是提取出的子串的指针。这个指针指向的是子串在源字符串中的起始位置。子串末尾的下一个字符在提取前为分隔符,提取后被修改成了'/0’。

从上图可以看到,buffer不包含分隔符delim。 调用strtok后buf的值为

由于未找到,源字符串buffer保持不变,buf指向源字符串的起始地址,打印输出的值是整个字符串的完整值。

在没有提取到子串的情况下,函数会返回什么值呢?

百度

科上说,“当没有被分割的串时则返回NULL。”这是一个很模棱两可的说法。如果想要确切的了解清楚这个问题,可能需要看一下strtok的实现原理。这里先以实验说明。

 

第一次调用strtok,毫无疑问,buf指向",Fred”。

第二次调用strtok,由于第一个参数为NULL,表示函数继续以上次调用所保存的this指针的位置开始分解,即对"male 25”分解。分解完毕后,buf指向"male”。

第三次调用strtok,参数继续设定为NULL,此时即对第二次保存的this指针的位置开始分解,即对"25”分解。因为无法找到包含分隔符delim的子串,所以buf指向"25”。

第四次调用,参数仍为NULL,此时第三次调用保存的this指针已指向字符串的末尾'/0’,已无法再进行分解。因此函数返回NULL,这也就是百度百科中所提到的“当没有被分割的串时函数返回NULL。”

 

4.参数 分隔符delim的探讨(delim是分隔符的集合)

很多人在使用strtok的时候,都想当然的以为函数在分割字符串时完整匹配分隔符delim,比如delim=”ab”,则对于"acdab”这个字符串,函数提取出的是"acd”。至少我在第一次使用的时候也是这么认为的。其实我们都错了,我是在看函数的源代码时才发现这个问题的,且看下面的例子。

源字符串为buffer,分隔符delim为 逗号和空格,按照一般的想法我们会以为调用函数后,buf的值为"Fred,male,25”,结果是这样么?

第一次调用之后的结果竟然是"Fred”,而非我们所想的结果。这是为什么呢?

我们回到GNU C Library中对strtok的功能定义:“Parse S into tokens separated by characters in DELIM”。也就是说包含在delim中的字符均可以作为分隔符,而非严格匹配。可以把delim理解为分隔符的集合。这一点是非常重要的~

当然,我们在分解字符串的时候,很少使用多个分隔符。这也导致,很多人在写例子的时候只讨论了一个分隔符的情况。有更多的人在看例子的时候也就错误的认识了delim的作用。

5.待分解的字符串,首字符就为分隔符

首字符为分隔符不能算作一个很特殊的情况。按照常规的分解思路也能正确分解字符串。

我想说明的是,strtok对于这种情况采用了比常规处理更快的方式。

如上图例子所示。仅用一次调用就可以得到以逗号分隔的字符串"Fred male 25”,而F前面的','被忽略了。由此可见,strtok在调用的时候忽略了起始位置开始的分隔符。这一点,可以从strtok的源代码得到证实。

 

6.不能向第一个参数传递字符串常量!

本文中所举的例子都将源字符串保存为字符串数组变量。若你将源字符串定义成字符串常量,可想而知,程序会因为strtok函数试图修改源字符串的值,而抛出异常。

 

好了,本文详细介绍了使用strtok的注意事项,(二)中我将详细介绍strtok不能实现的一些功能并引出strtok_r函数,最后介绍一下两个函数的实现。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。