目录

使用strtok()完成分割

使用strsep()完成分割

使用strtok_r()完成分割

实现字符串分割


前言

最近遇到了一个字符串分割的问题,在C++的标准库里面没有字符分割函数split()。我想这个问题今后可能还会再遇见,所以使用C/C++中的字符串分割方法完成相应的功能。

需求:对一个字符串进行分割,然后将分割后的数据存起来,想用的时候像用数组那样拿就行了。所以在完成分割后,需要使用vector将相应的数据保存起来。

使用strtok()完成分割

char * strtok ( char * str,const char * delim );
其中str是需要分割的字符串。delim是分隔符标识。
在<cstring>  <string.h>中定义

该函数被设计为多次调用,以从同一字符串中获取连续的token。

如果 str != NULL,该调用被视为 strtok 对此特定字符串的第一个调用。该函数搜索中不包含的第一个字符 delim。

如果找不到这样的字符,则根本没有标记str,并且该函数返回空指针。

如果找到了这样的字符,则这是token的开头。然后,函数从该点开始搜索包含delim的第一个字符。

如果未找到这样的字符,str则只有一个标记,以后调用strtok将返回一个空指针

如果找到了这样的字符,则将其替换为空字符'\0',并将指向下一个字符的指针存储在静态位置中,以供后续调用。

然后,该函数将指针返回到token的开头

如果str == NULL,则该调用将被视为对后续调用strtok:该函数从上次调用中保留的位置继续。行为与先前存储的指针作为str传递的行为相同。

#include <cstring>
#include <iostream>int main()
{char input[100] = "A, bird, came, down, the, walk";char *token = std::strtok(input, ", ");while (token != NULL) {std::cout << token << '\n';token = std::strtok(NULL, ", ");}
}

笔记:

(1)此函数具有破坏性:它将 '\0' 字符写入 str 字符串的元素中。

(2)每次对该函数的调用都会修改一个静态变量:不是线程安全的。

(3)与大多数其他strtok不同,每个后续标记中的定界符可以不同,甚至可以取决于先前标记的内容。

(4)其中delim可以包含多个分隔符,strtok函数会将str内容按分隔符分割。如果对数据格式有要求,需要注意这一点。

源自百度百科:

下面的说明摘自于Linux内核2.6.29,说明了这个函数已经不再使用,由速度更快的strsep()代替。

/** linux/lib/string.c** Copyright (C) 1991, 1992 Linus Torvalds*//** stupid library routines.. The optimized versions should generally be found
* as inline code in <asm-xx/string.h>
* These are buggy as well..
* * Fri Jun 25 1999, Ingo Oeser <ioe@informatik.tu-chemnitz.de>
* - Added strsep() which will replace strtok() soon (because strsep() is
* reentrant and should be faster). Use only strsep() in new code, please.
** * Sat Feb 09 2002, Jason Thomas <jason@topic.com.au>,
* Matthew Hawkins <matt@mh.dropbear.id.au>
* - Kissed strtok() goodbye
*/

使用strsep()完成分割

strsep函数用于分解字符串为一组字符串。其原型为:

char *strsep(char **s, const char *delim);

存在的问题

#include <stdio.h>
#include <stdlib.h>
#include <string.h>//char *strsep(char **str, const char *delim);
int main(void) {char source[] = "hello, world! welcome to china!";char delim[] = " ,!";char *input = strdup(source);char *token = strsep(&input, delim);while (token != NULL) {printf(token);printf("-");token = strsep(&input, delim);printf("\n");}free(input);return 0;
}

为什么使用strsep()分割字符串后会多出几个" - " ?

原因是:如果输入的串的有连续的多个字符属于delim,strtok会返回NULL,而strsep会返回空串 ""。如果想用strsep函数分割字符串必须进行返回值是否是空串的判断。

使用strtok_r()完成分割

strtok是一个线程不安全的函数,因为它使用了静态分配的空间来存储被分割的字符串位置,线程安全的函数是strtok_r()。

char *strtok_r(char *str, const char *delim, char **saveptr);

strtok_r函数是strtok函数的可重入版本。str为要分解的字符串,delim为分隔符字符串。char **saveptr参数是一个指向char *的指针变量,用来在strtok_r内部保存切分时的上下文,以应对连续调用分解相同源字符串。

第一次调用strtok_r时,str参数必须指向待提取的字符串,saveptr参数的值可以忽略。连续调用时,str赋值为NULL,saveptr为上次调用后返回的值,不要修改。一系列不同的字符串可能会同时连续调用strtok_r进行提取,要为不同的调用传递不同的saveptr参数。

strtok_r实际上就是将strtok内部隐式保存的this指针,以参数的形式与函数外部进行交互。由调用者进行传递、保存甚至是修改。需要调用者在连续切分相同源字符串时,除了将str参数赋值为NULL,还要传递上次切分时保存下的saveptr。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>  //char *strtok_r(char *str, const char *delim, char **saveptr);
int main()
{char *Src = "Can I help you";char Buffer[100];char *delim = " ";char *saveptr = NULL;char *input = NULL;strncpy(Buffer, Src, sizeof(Buffer) - 1);input = Buffer;while(NULL != ( input = strtok_r( input, delim, &saveptr))){printf("input[%s]   saveptr[%s]\n", input,saveptr);input = NULL;}return 0;
}

实现字符串分割

以上函数都会改变源字符串,所以在完成split函数功能时,要先复制一个副本,对副本进行分割后返回相应的值才是正确的思路。

#include <iostream>
#include <vector>
#include <cstring>using namespace std;namespace tyler
{
//strtok版本
//char *strtok(char s[], const char *delim);vector <string> stringsplit(const string &str, const char *delim){vector <std::string> strlist;int size = str.size();char *input = new char[size+1];strcpy(input, str.c_str());char *token = std::strtok(input, delim);while (token != NULL) {strlist.push_back(token);token = std::strtok(NULL, delim);}delete []input;return strlist;}//另一种写法
//for(token = strtok(input, delim); token != NULL; token = strtok(NULL, delim))
//{
//}//strsep版本
//char *strsep(char **stringp, const char *delim);vector <string> stringsplit1(const string &str, const char *delim){vector <std::string> strlist;char *p = const_cast<char*>(str.c_str());char *input = strdup(p);       //strdup()在内部调用了malloc()为变量分配内存,不需要使用返回的字符串时,需要用free()释放相应的内存空间,否则会造成内存泄漏。char *token = strsep(&input, delim);while (token != NULL) {if(strcmp(token, "") == 0)token = strsep(&input, delim);else{strlist.push_back(token);token = strsep(&input, delim);}}free(input);return strlist;}//strtok_r版本
//char *strtok_r(char *str, const char *delim, char **saveptr);vector <string> stringsplit2(const string &str, const char *delim){vector <std::string> strlist;char *saveptr = NULL;char *p = const_cast<char*>(str.c_str());char *input = strdup(p);       //strdup()在内部调用了malloc()为变量分配内存,不需要使用返回的字符串时,需要用free()释放相应的内存空间,否则会造成内存泄漏。while(NULL != ( input = strtok_r( input, delim, &saveptr) )){//printf("input[%s] saveptr[%s]\n",input,saveptr);strlist.push_back(input);input = NULL;}free(input);return strlist;}
}int main()
{string str = "hello, world! welcome to china!";cout << str <<endl;vector<string> asd = tyler::stringsplit2(str, " ,!");cout << "StringList:";for(int i = 0; i < asd.size(); ++i){cout << "[" << asd[i] << "]";}cout <<endl;cout << "String:" << str <<endl;return 0;
}

参考:

https://baike.baidu.com/item/strtok_r

https://blog.csdn.net/yafeng_jiang/article/details/7109285

https://www.cnblogs.com/carsonzhu/p/5859552.html

https://blog.csdn.net/zhouzhenhe2008/article/details/74011399

C++实现字符串分割函数split()相关推荐

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

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

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

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

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

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

  4. Java字符串分割函数split

    Java中的我们可以利用split把字符串按照指定的分割符进行分割,然后返回字符串数组,下面是string.split的用法实例及注意事项: 1.split 方法  将一个字符串分割为子字符串,然后将 ...

  5. SQL Server自定义字符串分割函数——Split

    我相信大部分人都碰到过,处理数据的时候,字段的值是以 ',' (逗号)分隔的形式,所以我也不能避免. 然后我才知道,sql 是没有类似于 C# 和 Javascript 这种分割字符串的方法.( Sp ...

  6. java对于 进行字符串分隔_Java字符串分割函数split中以·点分割的问题

    问题描述: // 把字符串"192.168.1.1"按照小圆点进行分割,分割成"192","168","1"," ...

  7. Split字符串分割函数

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

  8. C++的字符串分割函数

    转载:http://blog.csdn.net/shanzhizi/article/details/17189267 C++的字符串没有分割函数,因此需要自己写方便使用.而受到开发工具的影响,有很多用 ...

  9. php 字符串分割出数字,php 字符串分割函数的总结

    在php中字符串分割函数有很多很多,下面我来给各位朋友来介绍各种php中字符串分割实例,有需要的朋友可进入参考参考. PHP函数split()的基本语法为 array split ( string $ ...

最新文章

  1. Java锁有哪些种类,以及区别
  2. python 向量元素判断_python;计算向量的元素
  3. LRU算法四种实现方式介绍
  4. 5分钟能回答的人,年薪25万美金以上
  5. 管家婆辉煌2虚拟服务器,管家婆辉煌:三步轻松完成软狗组网!
  6. (转)Spring Boot(八):RabbitMQ 详解
  7. 最好的Linux C/C++ IDE Windows ALL IDE,第一效率,第零浪漫
  8. pandas python groupby_python – pandas groupby方法实际上是如何工作的?
  9. mysql 主主复制
  10. Asp.net.Ajax控件学习
  11. Jpg格式如何变成gif动图?仅需三步快速合成gif
  12. 路由器的下一跳计算(网关)
  13. 2018年最新传智播客黑马WEB前端36期全套视频教程
  14. 【干货】PCB线宽与电流关系
  15. UE4-如何做一个简单的TPS角色(二)-实现角色基础移动
  16. 使用scrapy爬取京东产品详细信息
  17. Ardunio开发实例-BMM150数字地磁传感器
  18. matlab 坐标移动,如何移动坐标轴到指定的位置
  19. 对 Mac 原生终端模拟器的增强
  20. Oracle - 回滚段

热门文章

  1. 内存管理:_CrtDumpMemoryLeaks和_CrtSetBreakAlloc
  2. 原始 H.264 码流播放
  3. Socket之UDP客户端【Python】
  4. 记一次clickhouse查询问题Double-distributed IN/JOIN subqueries is denied (distributed_product_mode = ‘deny‘)
  5. 音视频技术开发周刊 | 203
  6. Google发布Objectron数据集
  7. 360视频云Web前端HEVC播放器实践剖析
  8. 时永方:做到这三点,你就是多媒体内行了
  9. Janus流媒体服务器框架分析
  10. nginx源码初读(8)--让烦恼从数据结构开始(ngx_event)