C++ strtok()无法截取连续两个分隔符之间的空字符串, 解决方法

前言

  • 问题描述:
    与前台约定按顺序解析对应信息, 如果中间出现空数据(或者出现连续两个分隔符), 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会返回源字符串

如有不足, 望不吝赐教, 感谢!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值