std::regex_token_iterator 是最直接支持按任意正则模式分割的方案,适用于分隔符不固定场景,但 C++11 的 std::regex 在部分旧编译器(如 GCC)中存在兼容性问题。

用 std::regex_token_iterator 分割字符串并转整数
这是最直接支持“按任意正则模式分割”的方案,适合分隔符不固定(如多个空格、混合逗号/分号)的场景。但要注意:C++11 的 std::regex 在某些旧编译器(如 GCC std::regex_token_iterator 构造时若正则无效会抛 std::regex_error,务必捕获。
典型用法:
#include <regex>
#include <vector>
#include <string>
#include <sstream>
<p>std::string s = "12, 34 ; 56\t78";
std::regex re(R"([\s;,]+)"); // 匹配空格、逗号、分号、制表符等
std::vector<int> nums;
for (std::sregex_token_iterator it(s.begin(), s.end(), re, -1); it != std::sregex_token_iterator(); ++it) {
if (!it->str().empty()) {
nums.push_back(std::stoi(it->str()));
}
}</p>-
-1表示取非匹配部分(即分割后的子串),不是匹配结果本身 - 空字符串可能被切出来(尤其首尾有分隔符时),需显式跳过
-
std::stoi遇到非法字符会抛std::invalid_argument,生产环境应加try/catch
手写循环 + std::stringstream 处理简单分隔符
当分隔符是单个字符(如纯空格、纯逗号),不用正则更轻量、更可控。但 std::stringstream 默认只认空白符(isspace),对逗号、分号无效——必须手动找位置或换流方式。
推荐做法是用 std::getline 指定分隔符:
立即学习“C++免费学习笔记(深入)”;
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
std::string s = "1,2,3,4";
std::vector<int> nums;
std::stringstream ss(s);
std::string token;
while (std::getline(ss, token, ',')) {
if (!token.empty()) {
nums.push_back(std::stoi(token));
}
}
- 分隔符只能是单字节字符,
','可以,"|>"不行 - 连续分隔符(如
"1,,2")会产生空token,必须判空 - 比正则快一个数量级,且无运行时正则编译开销
避免 std::stoi 崩溃的三种检查方式
用户输入或日志解析中,字符串常含非数字内容(如 "123abc"、"-"、空格混入)。直接调 std::stoi 会崩溃,不能只靠异常兜底。
- 先用
std::all_of(token.begin(), token.end(), ::isdigit)——但忽略负号和正号,需手动处理开头的'-'或'+' - 用
std::strtol更稳妥:char* end; long v = std::strtol(token.c_str(), &end, 10);,检查end != token.c_str() && *end == '\0' - C++17 起可用
std::from_chars(无异常、无内存分配):auto [ptr, ec] = std::from_chars(token.data(), token.data() + token.size(), num);,检查ec == std::errc::success
性能敏感场景下别用 std::regex
实测在百万次分割中,std::regex 比手写 find/substr 慢 5–10 倍,且堆分配频繁。真要高性能,就别碰正则。
简易手写替代(支持多字符分隔符,如 "||"):
std::vector<int> split_and_parse(const std::string& s, const std::string& delim) {
std::vector<int> res;
size_t start = 0, end = 0;
while ((end = s.find(delim, start)) != std::string::npos) {
auto token = s.substr(start, end - start);
if (!token.empty()) res.push_back(std::stoi(token));
start = end + delim.length();
}
auto last = s.substr(start);
if (!last.empty()) res.push_back(std::stoi(last));
return res;
}
- 不支持正则语义(如“一个或多个空格”),但胜在确定、可预测、无依赖
-
std::string::find是O(N*M),若分隔符很长或字符串极长,考虑用 KMP 预处理 - 所有
substr都触发内存拷贝,若只读不改,可改用std::string_view(C++17)避免
实际用哪一种,取决于你的分隔符是否规则、数据来源是否可信、以及性能要求是否苛刻。正则看着省事,但一上线就容易在边界 case 上栽跟头。

















