C++中分割字符串需根据需求选择方法:简单分隔用find+substr性能高;注重简洁可用stringstream+getline;复杂模式选regex;避免使用strtok。

C++里要分割字符串,说白了,就是把一个长字符串按照某个或某些分隔符,切成一小段一小段的子字符串,然后通常会把这些子字符串放到一个容器里,比如
std::vector<std::string>
在C++中,分割字符串没有像Python那样内置的
split()
std::string::find
std::string::substr
这是最基础,也是最能体现C++“控制力”的一种方法。它的核心思想就是在一个循环里,不断地查找分隔符的位置,然后用
substr
#include <iostream>
#include <string>
#include <vector>
// 这是一个我自己经常会封装起来的工具函数
std::vector<std::string> splitByFindSubstr(const std::string& s, char delimiter) {
std::vector<std::string> tokens;
std::string::size_type start = 0;
std::string::size_type end = s.find(delimiter);
while (end != std::string::npos) {
tokens.push_back(s.substr(start, end - start));
start = end + 1; // 跳过分隔符
end = s.find(delimiter, start);
}
// 添加最后一个token,因为循环会在最后一个分隔符处结束
tokens.push_back(s.substr(start));
return tokens;
}
// 示例用法:
// int main() {
// std::string text = "apple,banana,orange,grape";
// char delimiter = ',';
// std::vector<std::string> result = splitByFindSubstr(text, delimiter);
// for (const auto& s : result) {
// std::cout << s << std::endl;
// }
// // 输出:
// // apple
// // banana
// // orange
// // grape
// return 0;
// }个人看法: 这种方法虽然看起来有点“土”,需要写循环,但它的好处是性能通常不错,因为你对每次查找和截取都有明确的控制。对于简单的单字符分隔符,并且对性能有一定要求时,这往往是我的首选。缺点是,如果需要处理多个分隔符,或者分隔符是字符串,代码会稍微复杂一些。
立即学习“C++免费学习笔记(深入)”;
std::stringstream
std::getline
这是C++标准库中一个非常优雅且常用的分割方式,尤其适合处理以行或特定分隔符分隔的数据流。
std::stringstream
std::getline
#include <iostream>
#include <string>
#include <vector>
#include <sstream> // 使用stringstream需要包含这个头文件
std::vector<std::string> splitByStringStream(const std::string& s, char delimiter) {
std::vector<std::string> tokens;
std::stringstream ss(s); // 将字符串s作为stringstream的初始内容
std::string item;
while (std::getline(ss, item, delimiter)) { // 从ss中读取,直到遇到delimiter
tokens.push_back(item);
}
return tokens;
}
// 示例用法:
// int main() {
// std::string text = "one;two;three;four";
// char delimiter = ';';
// std::vector<std::string> result = splitByStringStream(text, delimiter);
// for (const auto& s : result) {
// std::cout << s << std::endl;
// }
// // 输出:
// // one
// // two
// // three
// // four
// return 0;
// }个人看法: 我觉得这种方法在代码简洁性和可读性上做得非常好。如果你处理的是CSV文件、日志文件,或者任何以固定分隔符组织的文本数据,
stringstream
getline
find/substr
strtok
strtok
#include <iostream>
#include <string>
#include <vector>
#include <cstring> // strtok需要这个头文件
// 示例用法:
// int main() {
// char text_cstr[] = "alpha beta gamma delta"; // 注意:strtok会修改原字符串,所以需要可修改的char数组
// const char* delimiter = " ";
//
// std::vector<std::string> tokens;
// char* token = strtok(text_cstr, delimiter);
// while (token != nullptr) {
// tokens.push_back(token);
// token = strtok(nullptr, delimiter); // 后续调用传nullptr
// }
// for (const auto& s : tokens) {
// std::cout << s << std::endl;
// }
// return 0;
// }个人看法:
strtok
如果你的分隔符不是简单的字符,而是一个复杂的模式(比如空白字符、多个不同的分隔符组合),那么
std::regex
#include <iostream>
#include <string>
#include <vector>
#include <regex> // 正则表达式需要这个头文件
std::vector<std::string> splitByRegex(const std::string& s, const std::string& regex_str) {
std::vector<std::string> tokens;
std::regex re(regex_str);
// std::sregex_token_iterator 用于遍历匹配到的token
// -1 表示我们想要的是不匹配正则表达式的部分(也就是分隔符之间的内容)
std::sregex_token_iterator first{s.begin(), s.end(), re, -1}, last;
for (; first != last; ++first) {
if (!first->str().empty()) { // 避免添加空字符串,如果分隔符连续出现
tokens.push_back(*first);
}
}
return tokens;
}
// 示例用法:
// int main() {
// std::string text = " value1 value2,value3;value4 ";
// // 分隔符可以是空格、逗号或分号,并处理连续分隔符和首尾空白
// std::string regex_delimiter = "[ ,;]+"; // 匹配一个或多个空格、逗号或分号
// std::vector<std::string> result = splitByRegex(text, regex_delimiter);
// for (const auto& s : result) {
// std::cout << s << std::endl;
// }
// // 输出:
// // value1
// // value2
// // value3
// // value4
// return 0;
// }个人看法: 正则表达式的强大之处在于它能处理几乎任何复杂的分割需求。但它的代价是性能相对较低,而且代码的可读性也可能会因为正则表达式本身的复杂性而下降。所以,如果简单的字符分割能搞定,我不会轻易动用正则表达式。只有当分隔符规则非常复杂,或者需要灵活匹配多种分隔符时,它才成为不可替代的选择。
谈到C++字符串分割,性能和陷阱是两个绕不开的话题。毕竟,C++的精髓之一就是对性能的追求,而字符串操作往往是性能瓶颈的常客。
性能优化:
std::string::find
std::string::substr
std::stringstream
std::getline
std::regex
std::string::substr
std::string_view
std::string
vector
tokens.reserve(estimated_count)
std::vector
vector
std::string
substr
常见陷阱:
" ,apple,banana,"
find/substr
stringstream
"apple,,banana"
std::getline
find/substr
strtok
strtok
"##"
std::string::find
std::getline
char
find/substr
std::regex
char
处理多分隔符和空字符串,是字符串分割中比较常见的“高级”需求。
处理多分隔符:
std::string text = "apple,banana;orange"
// 替换函数示例
void replaceAll(std::string& s, const std::string& from, const std::string& to) {
size_t start_pos = 0;
while((start_pos = s.find(from, start_pos)) != std::string::npos) {
s.replace(start_pos, from.length(), to);
start_pos += to.length(); // 确保从替换后的位置继续查找
}
}
// 使用:
// std::string data = "value1,value2;value3";
// replaceAll(data, ";", ","); // 将分号替换为逗号
// std::vector<std::string> parts = splitByStringStream(data, ',');find
find/substr
find
// 查找任意一个分隔符的位置
std::string::size_type find_any_of(const std::string& s, const std::string& delimiters, std::string::size_type pos = 0) {
return s.find_first_of(delimiters, pos);
}
// 然后在splitByFindSubstr中替换 s.find(delimiter) 为 find_any_of(s, " ,;", start)std::regex
"[ ,;]+"
splitByRegex
处理空字符串情况:
空字符串通常是由于以下几种情况产生的:
,apple,banana,
apple,,banana
处理方法通常是在分割结果生成后进行过滤:
// 在 splitByFindSubstr 或 splitByStringStream 函数的末尾,或者调用后:
std::vector<std::string> filtered_tokens;
for (const auto& token : tokens) {
if (!token.empty()) { // 检查字符串是否为空
filtered_tokens.push_back(token);
}
}
// 也可以使用C++11的lambda和erase-remove idiom
// tokens.erase(std::remove_if(tokens.begin(), tokens.end(), [](const std::string& s){ return s.empty(); }), tokens.end());在
std::regex
if (!first->str().empty())
在我看来,处理这些“脏数据”是字符串分割的必经之路。你得明确你的业务逻辑是否需要保留空字符串,还是应该直接过滤掉。通常情况下,我们都是需要过滤掉的,除非空字符串本身具有某种业务含义。
在实际项目中,字符串分割无处不在,从配置解析到数据处理,再到日志分析,它的身影随处可见。
应用场景:
key=value
=
,
|
最佳实践:
std::string::find
std::string::substr
std::stringstream
std::getline
std::regex
strtok
std::vector<std::string>
vector
text = "hello"
,
"hello"
string_view
std::stoi
在我多年的开发经验里,字符串分割真的是个高频操作。很多时候,一个看似简单的分割,背后可能隐藏着各种边界条件和性能陷阱。所以,多思考一步,选择最适合当前场景的方法,并考虑好各种异常情况,才能写出健壮、高效的代码。
以上就是c++++如何分割字符串_c++字符串分割实用方法集锦的详细内容,更多请关注php中文网其它相关文章!
c++怎么学习?c++怎么入门?c++在哪学?c++怎么学才快?不用担心,这里为大家提供了c++速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号