探索C语言之字符串分割函数:strtok和strsep的区别

  • 概述
  • strsep - extract token from string(linux 下)
  • strtok, strtok_r - extract tokens from strings
  • 相同点
  • 不同点
  • 什么时候使用它们?

概述

在c语言中,字符串分割函数主要有两种:一是strtok函数,另一个就是strsep函数。
下面我们对这两个函数作一个详细解释说明。


strsep - extract token from string(linux 下)

#include <string.h>char *strsep(char **s, const char *delim);
//会修改数据源。可重入的,注意这里虽然改动stringp的内容,主要是不在使用static静态变量了。

作用:
stringp为指向欲分割的字符串,delim为分隔符,函数将返回分隔符前面的字符串,stringp将指向分隔符之后的字符串。
Be cautious when using this function. If you do use it, note that:
This function modifies its first argument.
This function cannot be used on constant strings.
The identity of the delimiting character is lost.


strtok, strtok_r - extract tokens from strings

#include <string.h>char *strtok(char *str, const char *delim);
//会修改数据源。外部加锁才线程安全(strtok执行结束再解锁执行另一个strtok循环知道工作完成) char
*strtok_r(char *str, const char *delim, char **saveptr);

代码示例:*


#include <string.h>
#include <stdio.h> int main(int arg, const char *argv[]) {/*字符串不能为常量*/ char* string = strdup("/home/yinlijun/project:/home/yinlijun:/home/someone");char* p;while((p = strsep(&string, ":")) != NULL) /*第一个参数设为二级指针,字符串中所有的第二个参数(子串)最后会被替代成‘/0’*/ { printf("%s/n", p);}free(string); return 0; }

相同点

对该函数的调用序列将str拆分为token,这些token是由作为定界符一部分的任何字符分隔的连续字符的序列。
首次调用时,该函数需要一个C字符串作为str的参数,该字符串的第一个字符用作扫描令牌的起始位置。
在随后的调用中,该函数需要一个空指针,并使用最后一个标记结束后的位置作为扫描的新起始位置。
为了确定token的开头和结尾,该函数首先从起始位置扫描未包含在定界符中的第一个字符(该字符成为token的开头)。
然后从token的开头开始扫描定界符中包含的第一个字符,该字符成为token的末尾。如果找到终止的空字符,扫描也会停止。
token的此结尾将自动替换为空字符(NULL),并且token的开头由函数返回。
一旦在对strtok的调用中找到了str的终止null字符,此函数的所有后续调用(将null指针作为第一个参数)都将返回null指针。
找到下一个标记的点由在下一次调用时使用的函数在内部保留(不需要特殊的库实现来避免数据争用)。
两者都会对原字符串进行修改。


不同点

  • strtok内部记录上次调用字符串的位置,所以是不可重入的,不支持多线的,其可重入版本为strtok_r。
  • strsep使用传入的参数来确定字符串的起始位置,是可重入的,也是Linux kernel推荐的函数,strtok的替代品。
  • strtok()是被标准化(C标准,并因此也通过POSIX),
    但strsep()不规范(由C或POSIX;它是GNU C库中可用的,和起源于BSD).因此,可移植的代码strtok()比strsep().更容易使用
  • strtok()允许在单个标记之间使用多个分隔符,而strsep()期望标记之间使用单个分隔符,并将相邻分隔符解释为空标记.

什么时候使用它们?

  • 使用strsep函数,当您需要处理空字段,或者在不同字段之间使用单个分隔符,并且在不介意可移植性的情况下。
  • 使用strtok_r函数,当您希望在字段之间允许多个分隔符,不需要处理空字段,并且要求代码具有良好的POSIX兼容性。
  • 尽量避免使用strtok函数,因为它是不可重入的,容易导致问题。尤其在多线程环境中,strtok的使用可能导致程序出现不稳定的行为。

您可以strsep()在需要空字段时使用,而不是在字段之间允许多个分隔符,并且在您不介意可移植性时使用.
你会使用strtok_r(),当你想允许标记之间的多个分隔符,你不想空字符(和POSIX足够的便携式你).
strtok()如果你不这样做,你只会在有人威胁你的生命时使用.而你只能用它足够长的时间让你摆脱危及生命的境地; 然后你会再次放弃使用它.它有毒; 不要使用它.编写自己的strtok_r()或者strsep()使用它会更好strtok().

为什么strtok()有毒?
strtok()如果在库函数中使用,该函数是有毒的.如果您的库函数使用strtok(),则必须清楚地记录.
那是因为:

  • 如果任何调用函数正在使用strtok()并调用也使用的函数strtok(),则会中断调用函数.
  • 如果你的函数调用任何调用的函数strtok(),那将破坏你的函数的使用strtok().
  • 如果您的程序是多线程的,那么strtok()在任何给定时间最多只能有一个线程使用- 跨越一系列strtok()调用.

此问题的根源是调用之间保存的状态,允许strtok()在停止的位置继续.除了"不要使用strtok()" 之外,没有合理的方法来解决问题.

  • strsep()如果可用,您可以使用.
  • 您可以使用POSIX(strtok_r()如果可用).
  • strtok_s()如果可用,您可以使用Microsoft .
  • 名义上,您可以使用ISO/IEC 9899:2011附件K.3.7.3.1功能strtok_s(),但其界面strtok_r()与微软的界面不同strtok_s()

探索C语言之字符串分割函数:strtok和strsep的区别相关推荐

  1. 字符串分割函数--strtok与strsep

    在c/c++中,字符串分割函数主要有两种:一是strtok函数,另一个就是strsep函数.下面我们对这两个函数作一个详细解释说明. 1.strtok 原形: char* strtok(char *s ...

  2. 字符串分割函数strtok和strsep使用注意事项

    转载自 https://blog.csdn.net/astrotycoon/article/details/50813959 为什么写本文 最近工作中经常需要解析字符串,并且这些字符串都有一个共同的特 ...

  3. c语言strsep,C/C++ 字符串分割: strtok 与 strsep 函数说明(示例代码)

    函数原型: char *strtok(char *s, const char *delim); char *strsep(char **s, const char *delim); 功能:strtok ...

  4. strtok(), strtok_s() 字符串分割函数

    strtok(), strtok_s() 字符串分割函数 //strtok()函数原型/*_Check_return_ _CRT_INSECURE_DEPRECATE(strtok_s) _CRTIM ...

  5. PHP字符串分割函数explode,strtok,str_spli的用法

    PHP字符串函数在PHP网站开发中广泛使用,比如使用PHP字符串函数对字符串分割.截取.匹配.替换等处理.PHP字符串函数对于PHP入门学习者来说必不可少,本文将主要介绍PHP字符串分割函数处理心得, ...

  6. c语言中字符切割函数split,c 语言 指针 C语言字符串分割函数split实现

    c语言也有类似其他语言的split字符串分割函数,就是strtok使用方法如下://用逗号做分隔符,读出内容//char s[] = "123-sldkf-123ls-343434-dfjd ...

  7. c语言将字符串按空格分割_如何在c++中实现字符串分割函数split详解

    前言 在学习c++中string相关基本用法的时候,发现了sstream的istringstream[1]可以将字符串类似于控制台的方式进行输入,而实质上这个行为等同于利用空格将一个字符串进行了分割, ...

  8. C++中string如何实现字符串分割函数split()——4种方法

    如: string str1 = "This is a test"; string str2 = "This-is-a-test"; string str2 = ...

  9. Split字符串分割函数

    非常非常常用的一个函数Split字符串分割函数. Dim myTest myTest = "aaa/bbb/ccc/ddd/eee/fff/ggg"Dim arrTest arrT ...

最新文章

  1. vue从入门到进阶:指令与事件(二)
  2. RMSD:通过旋转计算两个分子间的最小rmsd
  3. 不投降就是成功 --- 我看《新喜剧之王》
  4. 限制edit只能输入数字
  5. linux系统性能优化及瓶颈分析
  6. web.config中httpRunTime的属性(转)
  7. 智能布线系统,“智”在何方
  8. mybatis多个foreach_MyBatis中使用foreach完成复杂查询
  9. 求一个特定函数在定义区间上的值是否都为素数
  10. C语言符号常量的使用,C语言常量与符号常量
  11. 京东员工p级别分几级_一文揭秘字节跳动、华为、京东的薪资职级
  12. PAT甲级 1097
  13. ios 添加浮动效果_自定义悬浮窗详解(模拟IOS小球拖动,轮盘滑动)
  14. ET服务器框架——部署与运维笔记(一)
  15. tp5.1 保利威视 云课堂 三分屏 PC直播DEMO(不适合普通直播)
  16. 普通带条件查询接口报错 Handler dispatch failed; nested exception is java.lang.NoClassDefFoundError:
  17. 关于offer、三方协议、福利等就业常识
  18. 乐酷工作室孙志伟:Testin云测试有广度有深度 省钱省力值得信赖
  19. phpcms选择文件无法加载插件怎么办_浏览器显示无法加载插件怎么办
  20. 侧边栏固定定位到版心两侧

热门文章

  1. pandas 生成笛卡尔集
  2. ubuntu 8.10安装配置经验(Intrepid Ibex)——转载
  3. Word2Vec中的gensim报错from gensim.models.word2vec import Vocab报错问题
  4. 热门的智慧养老产品有哪些?解读新政策后的超全资料整合
  5. 解决网页百度转码的问题
  6. RPC论文翻译(Implementing Remote Procedure Calls)
  7. Python最新就业信息
  8. Java修饰符——final
  9. 从零到完成安卓项目实战【安卓端+后端】
  10. Dubbo之默认协议dubbo