strtok

在处理文本的时候,我们最常用到的是读入字符串,然后对字符串进行处理。在分析、处理字符串的过程中就经常会用到根据特定分隔符对字符串进行分割。在C++语言中提供了strtok函数可以供我们完成字符串切割的功能。它的声明为

char *strtok(char *__str, const char *__sep);  //__str是要分割的字符串,__sep是分隔符集合

看一个例子:

char str[] = "hello Chris";
char *p = strtok(str, " ");
while(p != nullptr){cout << p << endl;p = strtok(nullptr, " ");
}
cout << str << Lendl;输出:    HelloChrisHello

strtok将一个字符串“Hello Chris”,按照“ ”作为分隔符,分割成为“Hello”和“Chris”。

在使用上第一次传入的是指向要被分割的字符串的指针,而后序需要传入nullptr。这里面只能够传入nullptr,因为可以看下面的输出,当第一次分割后,str的输出是Hello。这时候,str已经不再指向“Hello Chris”,而是指向“Hello”。这说明strtok对原字符串的分割是破坏性地分割。当strtok在参数str的字符串中发现参数delim中包含的分割字符时,则会将该字符改为\0 字符。在第一次调用时,strtok必需给予参数s字符串,往后的调用则将参数s设置成nullptr。每次调用成功则返回指向被分割出片段的指针。

那么我们传入的是nullptr,strtok如何知道我们下一次要分割的字符串的起始位置那?这是因为strtok使用了静态分配的空间来存储被分割的字符串位置。这也就是说,当我们传入nullptr的时候,strtok就会去静态空间检查存储的指针,把这个指针取出来再进行分割。由于strtok这种实现形式,可以推测到1.strtok在多线程中使用时是不安全的;2.我们无法使用strtok将一个字符串进行多层次的分割。看下面的一个例子:

    char str[] = "boy,Lilei|girl,Lili";char *p = strtok(str, "|");while(p != nullptr){char *p1 = strtok(p, ",");while (p1 != nullptr){cout << p1 << endl;p1 = strtok(nullptr, ",");}p = strtok(nullptr, "|");}输出:   boyLilei

可以看到原意我们希望对字符串进行逐层解析,但是最后的结果并不是我们想要的。

strtok_r

为了解决上述strtok的弊端,C语言引进了strtok_r,我们先来看一下strtok_r的原型:

char *strtok_r(char *__str, const char *__sep, char **__lasts);  //__lasts,保存下一次要分割字符串的指针

在strtok_r中前两项的输入参数和strtok相同,而相比于strtok用一个静态变量保存下一次要分割字符串的指针,strtok_r使用一个单独的二维指针来保存。再看上面的例子,我们用strtok_r去实现。

    char str[] = "boy,Lilei|girl,Lili";char *savP, *savP1;char *p = strtok_r(str, "|", &savP);while(p != nullptr){char *p1 = strtok_r(p, ",", &savP1);while (p1 != nullptr){cout << p1 << endl;p1 = strtok_r(nullptr, ",", &savP1);}p = strtok_r(nullptr, "|", &savP);}输出:   boyLileigirlLili

可以看到实现我们最初的目的。

  strtok_s

strtok_s和strtok_r有相同的实现形式和功能,不同的是strtok_s是windows环境下的实现形式,而strtok_r是Linux下的实现形式。

对于strtok_s和strtok_r,我们可以对其进行封装成更加单的实现形式:

#if defined __GNUC__
#define STRTOK(savP, delm)     strtok_r(nullptr, delm, &savP)
#elif defined _MSC_VER
#define STRTOK(savP, delm)     strtok_s(nullptr, delm, &savP)
#endif    

再来看上面的例子:

    char str[] = "boy,Lilei|girl,Lili";char *savP, *savP1;savP = str;char *p = STRTOK(savP, "|");while(p != nullptr){savP1 = p;char *p1 = STRTOK(savP1, ",");while (p1 != nullptr){cout << p1 << endl;p1 = STRTOK(savP1, ",");}p = STRTOK(savP, "|");}输出:    boyLileigirlLili

这样的形式更加简洁。

strok、strtok_r和strtok_s相关推荐

  1. 00014__strok、strtok_r和strtok_s

    https://blog.csdn.net/zhangsj1007/article/details/81365732

  2. strtok、strtok_s、strtok_r 字符串分割函数

    1.strtok函数 函数原型:char * strtok (char *str, const char * delimiters); 参数:str,待分割的字符串(c-string):delimit ...

  3. 字符串切割函数strtok、strtok_s、strtok_r的区别

    strtok函数 头文件:#include <string.h> 函数原型:char * strtok (char *str, const char * delimiters); 参数:s ...

  4. C语言必知必会-strtok赞歌

    strtok的赞歌 标记解析(Tokenizing)是最简单也是最常见的解析问题,也就是根据分隔符把一个字符串分割为几个部分.这个定义覆盖了所有这种类型的任务.根据空白分隔符(例如" \t\ ...

  5. strtok strtok_s strsep

    c 语言下的字符串分割函数: 一.strtok(): 原型:char *strtok(char s[], const char *delim); 分解字符串为一组字符串.s为要分解的字符串,delim ...

  6. strtok函数和可重入函数strtrok_s、strtok_r的使用和注意事项

    strtok函数--按照指定的分隔符将字符串分割 函数原型: char *strtok(char s[], const char *delim) 参数一:要被分割的字符串 参数二:指定的分隔符 内部实 ...

  7. strtok and strtok_s

    语言的运行库为了支持多线程特性,必须做出一些改进.一种改进的办法就是修改所有的线程不安全的函数的参数列表,改成某种线程安全的版本.比如MSVC的CRT就提供了线程安全版本的strtok()函数:str ...

  8. strtok和strtok_r

    strtok和strtok_r 原型:char *strtok(char *s, char *delim); 功能:分解字符串为一组字符串.s为要分解的字符串,delim为分隔符字符串. 说明:首次调 ...

  9. linux c warning: implicit declaration of function 'strtok_r'解决方案

    解决方法:警告的文件头部 添加 #define _GNU_SOURCE 编译时出现警告 warning: implicit declaration of function 'strtok_r' war ...

最新文章

  1. 今天分享个用Python爬虫爬取Bilibili弹幕的小例子解析
  2. 快来捡武器:Black Hat USA 将推出的8款安全工具
  3. 【转】细数中国十大名校的IT牛人
  4. 网状结构的解藕-中介者模式
  5. Qt无法用UTF-8编辑问题
  6. matlab计算截断误差,Matlab相位截断误差仿真综述.doc
  7. HDU1598【最小生成树拓展】
  8. Docker上部署MySQLCluster(基于mysql/mysql-cluster镜像)
  9. 告别复杂WCF扩展 REST过程 ,让他 so easy
  10. scala 类及抽象类入门
  11. V-rep学习笔记:转动关节1
  12. Edraw Office Viewer Component
  13. 基于ExtendSim的六西格玛银行排队模型
  14. linux 核显驱动程序,在Ubuntu系统上安装英特尔核显驱动安装器的方法
  15. 【2014-08-23】Beyong Coding
  16. 洛谷 P3373 线段树模板题
  17. [原创]服装鞋帽企业配送中心优化方案 WMS仓储管理系统
  18. 求生之路显示服务器列表指令,求生之路2指令大全 所有可用指令一览_游戏狗
  19. 泰克示波器CVI开发|泰克示波器波形抓取数据控制软件NS-Scope
  20. 可爱的小老鼠计算机教案,小班音乐鼠标小老鼠教案

热门文章

  1. Caffe小玩意(1)-可视化网络结构
  2. ddos压力测试软件
  3. Linux系统网络桥接
  4. Python冷门知识
  5. LOJ #2838. 「JOISC 2018 Day 3」比太郎的聚会 根号分治
  6. 华为如何拍火烧云_华为手机10大摄影模式最全操作指南!2分钟教你妙用拍大片!...
  7. word 编辑文章发现 空格变成省略号 换行符什么
  8. 高帧率手机 Flutter 列表慢慢拖动的时候会有明显的抖动
  9. 基于条件LayerNorm的多任务文本分类模型
  10. 网络信息安全(二)——ARP攻击实验演示(如何优雅切断别人网络)