C++中string如何实现字符串分割函数split()

C++中string实现字符串分割方法

一、使用stringstream流
二、使用string类提供的find方法与strsub方法
三、使用C库函数strtok
四、使用regex_token_iterator(正则表达式)
一、使用stringstream流
这里我们只需要用到 istringstream(字符串输入流) 构造字符串流,然后从字符串流中按照一定的格式读取数据即可。

通常我们使用 cin 从流中读取数据,而我们也可以使用 getline 读取,而后者在读取时可以选择接受的数据格式,其函数原型如下:

// istream & getline(char* buf, int bufSize);	// 读到 \n 为止
istream & getline(char* buf, int bufSize, char delim); //读到 delim 字符为止
	// \n 或 delim 都不会被读入 buf,但会被从文件输入流缓冲区中取走

因此,我们可以按照此方式设计一个C++中的string split函数。

void Stringsplit(string str,const const char split)
{
	istringstream iss(str);	// 输入流
	string token;			// 接收缓冲区
	while (getline(iss, token, split))	// 以split为分隔符
	{
		cout << token << endl; // 输出
	}
}

如果我们想要将分割后的子串带出,可以再重载一个有三个参数的版本。

void Stringsplit(string str, const const char split,vector<string>& res)
{
	istringstream iss(str);	// 输入流
	string token;			// 接收缓冲区
	while (getline(iss, token, split))	// 以split为分隔符
	{
		res.push_back(token);
	}
}

如此,我们就设计出了我们的Stringsplit() 函数。该函数有以下 2 种语法格式

void Stringsplit(string str,const const char split);
// 默认将传入的字符串str以split为分隔符进行分割,并将得到的子串打印在屏幕上,无返回值
void Stringsplit(string str, const const char split,vector<string>& rst);
// 默认将传入的字符串str以split为分隔符进行分割,    不会将子串打印在屏幕上,无返回值
// 					分割的子串将会保存在rst数组中被带出函数。

以上,我们简单的设计了一种C++中的分割字符串的函数,下面来看一个测试用例:

int main() {

	string str("This is a test");
	Stringsplit(str, ' ');		// 打印子串
	
	vector<string> strList;
	string str2("This-is-a-test");
	Stringsplit(str2, '-', strList);	// 将子串存放到strList中
	for (auto s : strList)
		cout << s << " ";
	cout << endl;

	return 0;
}

二、使用string类提供的find方法与strsub方法
函数原型:

size_type find( const basic_string& str, size_type pos = 0 ) const;

参数
str - 要搜索的 string , pos - 开始搜索的位置
返回值
找到的子串的首字符位置,或若找不到这种子串则为 npos 。

函数原型:

basic_string substr( size_type pos = 0, size_type count = npos ) const;

参数
pos - 要包含的首个字符的位置 ,count - 子串的长度
返回值
含子串 [pos, pos+count) 的 string 。

由以上两个函数我们便可以设计出我们的Stringsplit()来。同时,因为find()函数查找的可以是字符串,因此我们的分隔符可以是单个的字符,也可以是一个字符串。

// 使用字符分割
void Stringsplit(const string& str, const char split, vector<string>& res)
{
	if (str == "")		return;
	//在字符串末尾也加入分隔符,方便截取最后一段
	string strs = str + split;
	size_t pos = strs.find(split);

	// 若找不到内容则字符串搜索函数返回 npos
	while (pos != strs.npos)
	{
		string temp = strs.substr(0, pos);
		res.push_back(temp);
		//去掉已分割的字符串,在剩下的字符串中进行分割
		strs = strs.substr(pos + 1, strs.size());
		pos = strs.find(split);
	}
}

下面是一个测试用例:

int main()
{
vector strList;
string str(“This-is-a-test”);
Stringsplit(str, ‘-’, strList);
for (auto s : strList)
cout << s << " ";
cout << endl;

vector<string> strList2;
string str2("This%20is%20a%20test");
Stringsplit(str2, "%20", strList2);
for (auto s : strList2)
	cout << s << " ";
cout << endl;
return 0;

}

三、使用C库函数strtok
char* strtok( char* str, const char* delim );
1
参数
str - 指向要记号化的空终止字节字符串的指针
delim - 指向标识分隔符的空终止字节字符串的指针
返回值
指向下个记号起始的指针,或若无更多记号则为空指针。

需要注意的是,该函数使用一个全局的静态变量来保存每次分割后的位置,因此在多线程中是不安全的,这里我们也可以选择使用它的线程安全版本 char *strtok_r(char *str, const char *delim, char **saveptr); 。

void Stringsplit(const string& str, const string& split, vector<string>& res)
{
	char* strc = new char[str.size() + 1];
	strcpy(strc, str.c_str());   // 将str拷贝到 char类型的strc中
	char* temp = strtok(strc, split.c_str());
	while (temp != NULL)
	{
		res.push_back(string(temp));		
		temp = strtok(NULL, split.c_str());	// 下一个被分割的串
	}
	delete[] strc;
}

如此,我们的使用 strtok 版本的Stringsplit() 就完成了。不过,我们使用这种方法实现的字符串分割函数只能根据字符来分割,而我们传入的参数是字符串类型,这样可能会对函数的使用这造成误导(注:参数传入字符串用的双引号,传入字符用的单引号),因此我们也可以使用下面的方法封装一个参数是字符类型的函数。

void Stringsplit(const string& str, const char split, vector<string>& res)
{
	Stringsplit(str, string(1,split), res);	// 调用上一个版本的Stringsplit()
}

下面给出一个测试用例,我们分别使用单/双引号传入分割的限定字符。

int main()
{
	vector<string> strList;
	string str("This+is+a+test");
	Stringsplit(str, '+', strList);
	for (auto s : strList)
		cout << s << " ";
	cout << endl;

	vector<string> strList2;
	string str2("This-is-a-test");
	Stringsplit(str2, "-", strList2);
	for (auto s : strList2)
		cout << s << " ";
	cout << endl;


	return 0;
}

四、使用regex_token_iterator(正则表达式)
正则表达式(regular expression)描述了一种字符串匹配的模式(pattern),可以用来检查一个串是否含有某种子串、将匹配的子串替换或者从某个串中取出符合某个条件的子串等。

而在C++的正则中,把这种操作称为Tokenize分词(或者叫切割)。这种操作刚好可以满足我们的需求,用模板类regex_token_iterator<>提供分词迭代器,可以完成字符串的分割。

有关C++正则表达式参考:C++ std::regex | 正则表达式

代码参考:

void Stringsplit(const string& str, const string& split, vector<string>& res)
{
	//std::regex ws_re("\\s+"); // 正则表达式,匹配空格 
	std::regex reg(split);		// 匹配split
	std::sregex_token_iterator pos(str.begin(), str.end(), reg, -1);
	decltype(pos) end;              // 自动推导类型 
	for (; pos != end; ++pos)
	{
		res.push_back(pos->str());
	}
}

测试用例:

int main()
{
	// 单个字符分词
	vector<string> strList;
	string str("This is a test");
	Stringsplit(str," ", strList);
	for (auto s : strList)
		cout << s << " ";
	cout << endl;

	// 使用字符串分词
	vector<string> strList2;
	string str2("ThisABCisABCaABCtest");
	Stringsplit(str2, "ABC", strList2);
	for (auto s : strList2)
		cout << s << " ";
	cout << endl;
}
  • 20
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: C++ 标准库并没有提供 split 函数来直接对 string 进行分割。但是可以使用 STL 的其他容器和算法来实现字符串分割。可以使用 stringstream 将 string 转换为流,并使用 getline 函数读取每一部分。也可以使用 find 和 substr 函数找到分隔符并进行分割。 ### 回答2: C++string类型提供了一些方法来对字符串进行分割操作,其最常用的方法是使用stringstream来获取字符串的子串。 stringstream可以将字符串拆分成一系列的子项,然后通过读取每个子项的值来获取其的信息。我们可以定义一个stringstream并使用其getline()方法来将字符串拆分成多个子项,然后再将每个子项转换为相应的数据类型。 下面是一个基本的示例,演示如何使用stringstream来分割字符串: ```c++ #include <iostream> #include <sstream> #include <string> #include <vector> using namespace std; int main() { string s = "hello,world,how,are,you"; stringstream ss(s); string segment; vector<string> segments; while (getline(ss, segment, ',')) { segments.push_back(segment); } for (int i = 0; i < segments.size(); i++) { cout << segments[i] << endl; } return 0; } ``` 在这个示例,我们定义了一个名为s的字符串,它包含了一些逗号分隔的单词。我们的目标是将这些单词分割为多个子项,存储在一个名为segments的向量,然后打印每个子项。为了实现这个目标,我们首先定义了一个stringstream对象ss,并将s传递给它作为初始参数。然后,我们定义了一个名为segment的字符串变量,以及一个vector<string>类型的segments向量,用来存储每个子项。在while循环内部,我们使用getline()方法从stringstream对象ss获取每个子项,并使用push_back()方法将其添加到segments向量。最后,我们通过迭代segments向量并打印每个子项的值来完成操作。 总之,使用C++stringstream和vector对象,我们可以轻松地对字符串进行分割操作,并将分割后的子项存储在一个方便的容器。这使得我们可以更方便地处理字符串数据,并使代码更加简洁易读,提高程序的可维护性和可读性。 ### 回答3: C++string字符串可以使用split函数将其分割成若干子字符串split函数实现可以通过手动循环实现,也可以使用C++11标准下的stringstream和getline函数实现。 手动循环实现: 1. 首先定义一个string类型的变量result和vector类型的变量v,用于存储分割出的子字符串。 2. 然后使用while循环遍历原始字符串,每次找到分割符,就先将之前的子字符串push_back进vector,然后继续搜索。遍历到原始字符串最后一个字符时,也应该将最后一个子字符串push_back进vector。 3. 循环结束后,将最后一个子字符串push_back进vector。 4. 最后返回存储子字符串的vector即可。 stringstream和getline实现: 1. 首先将原始字符串放进stringstream。 2. 定义一个vector变量v,用于存储分割出的子字符串。 3. 使用while循环,每次调用getline函数stringstream读取一行,指定分割符为要分割的字符,将读取出来的子字符串push_back进vector。 4. 循环结束后,将存储子字符串的vector返回即可。 无论采用哪种实现方式,都需要注意一些细节问题,如分割符为空白字符(空格、制表符等)、原始字符串分割符开头或结尾等情况。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值