前言
- 问题描述:
与前台约定按顺序解析对应信息, 如果中间出现空数据(或者出现连续两个分隔符), strtok就会出问题.
看下面这个例子:
1 #include <string.h>
2 #include <stdio.h>
3
4 int main()
5 {
6 char str[] = "abc||de|fghi";
7
8 char* p = strtok(str, "|");
9 for(int i = 0; p != NULL; ++i)
10 {
11 printf("substr[%d]:%s\n", i, p);
12 p = strtok(NULL, "|");
13 }
14
15 return 0;
16 }
源字符串为:“abc||de|fghi”
分隔符为: ‘|’
运行结果为:
中间abc与de之间的连续两个’|’, strtok在分隔的时候, 直接把空字符串跳过了,
而有的时候, 即使分隔符间是空字符串, 我们也是需要获取的;
那么此时strtok就无法满足需要了, 下面是我用c++实现的, 可以截取空串的方法.
方法介绍
#include <stdio.h>
#include <string>
#include <vector>
/*
名称:my_split(const std::string& src, const char& delim,
std::vector<std::string>& vec)
功能:用分隔符将源字符串分隔为多个子串并传出; n个分隔符, 分n+1个子串
参数:
src-传入参数, 源字符串;
delim-传入参数, 分隔符;
vec-传出参数, 子串的集合;
返回值:
0-成功;
其它-失败;
*/
int my_split(const std::string& src, const char& delim,
std::vector<std::string>& vec)
{
int src_len = src.length();
int find_cursor = 0;
int read_cursor = 0;
if (src_len <= 0) return -1;
vec.clear();
while (read_cursor < src_len){
find_cursor = src.find(delim, find_cursor);
//1.找不到分隔符
if (-1 == find_cursor){
if (read_cursor <= 0) return -1;
//最后一个子串, src结尾没有分隔符
if (read_cursor < src_len){
vec.push_back(src.substr(read_cursor, src_len - read_cursor));
return 0;
}
}
//2.有连续分隔符的情况
else if (find_cursor == read_cursor){
//字符串开头为分隔符, 也按空子串处理, 如不需要可加上判断&&(read_cursor!=0)
vec.push_back(std::string(""));
}
//3.找到分隔符
else
vec.push_back(src.substr(read_cursor, find_cursor - read_cursor));
read_cursor = ++find_cursor;
if (read_cursor == src_len){
//字符串以分隔符结尾, 如不需要末尾空子串, 直接return
vec.push_back(std::string(""));
return 0;
}
}//end while()
return 0;
}
调用
int main(int argc, char* argv[])
{
std::vector<std::string> vecSrc;
std::vector<std::string> vecSplit;
vecSrc.push_back(std::string("|Hello||world|"));
vecSrc.push_back(std::string("Hello||world"));
for (auto src : vecSrc){
vecSplit.clear();
int iRet = my_split(src, '|', vecSplit);
if (0 == iRet){
printf("src:%s, vecSplit.size():%d\n", src.c_str(), vecSplit.size());
int idex = 0;
for (auto it : vecSplit)
printf("vec[%d]:%s\n", idex++, it.c_str());
}
printf("---------------------------------\n");
}
return 0;
}
运行结果:
可以看到, Hello和World之间的空字符串, 也能通过分隔符截取出来了.
如果开头或结尾有分隔符, 会将开头或结尾处都截出空子串,
类似刀切割绳子, 即:n个分隔符, 必有n+1个子串;
若不需要开头和结尾分隔子串, 可参照注释修改两行代码即可.
结语
上述方法比strtok有以下优点:
- 没有用到static变量, 故线程安全;
- 传入源字符串为const引用, 不会改变源字符串;
- 可以截取到连续分隔符间的空串;
- 如果首次未找到分隔符将会返回失败, 而strtok会返回源字符串
如有不足, 望不吝赐教, 感谢!