substr 是最可控的字符串切分方法;需检查 i 是否越界,substr(i, len) 的 len 表示最多取字符数,不足时自动截断,i 每次递增 len 但须满足 i < str.size()。

用 std::string::substr 手动切分最直接
没有标准库函数能一键按固定长度切分字符串,substr 是最可控、最不易出错的选择。关键不是“能不能”,而是“怎么避免越界和空段”。
常见错误是循环中直接用 i + len 当右边界,没检查是否超出 str.size(),导致 std::out_of_range 异常。
- 每次调用
substr(i, len),第二个参数是“最多取多少个”,不是“必须取满”,所以即使剩余字符不足len也不会报错 - 起始位置
i每次递增len,但要确保i 才进入循环 - 空字符串或
len 需提前处理,否则陷入死循环或未定义行为
std::vector<std::string> split_by_length(const std::string& s, size_t len) {
if (len == 0 || s.empty()) return {};
std::vector<std::string> res;
for (size_t i = 0; i < s.size(); i += len) {
res.push_back(s.substr(i, len));
}
return res;
}
用 std::copy_n + std::back_inserter 更适合只读场景
如果你只是想把每段拷贝进 std::string,且不介意多一次内存分配(因为 std::string 构造仍需复制),std::copy_n 可以绕过 substr 的内部长度判断逻辑,性能略高——但差异极小,仅在超长字符串高频调用时值得考虑。
-
std::copy_n要求目标容器已预留空间或使用std::back_inserter,不能直接往空std::string写 - 必须确保源迭代器范围有效:
s.begin() + i到s.begin() + std::min(i + len, s.size()) - 不如
substr直观,调试时更难一眼看出切分逻辑
别踩 std::string_view 的生命周期坑
如果原字符串生命周期短,又想避免拷贝,可用 std::string_view 存引用。但必须保证它所指向的 std::string 在所有 string_view 使用完毕前不被销毁。
立即学习“C++免费学习笔记(深入)”;
- 返回
std::vector<std::string_view>是可行的,但调用方必须清楚所有权责任 - 不能把临时字符串(如
split_by_length("hello", 2)中的字面量)传进去再返回string_view,那会悬垂 -
string_view的substr和std::string行为一致,同样安全,但不会隐式转成std::string
Python 用户容易误用 std::regex
有人试图用正则(比如 R"((.{1,5}))")强行匹配固定长度,这完全没必要。正则引擎开销大,且 . 无法正确处理 UTF-8 多字节字符(C++ 标准库 regex 默认按字节匹配),还容易漏掉末尾不足长度的部分。
-
std::regex在此场景下既慢又不可靠,纯属过度设计 - 如果真需要模式化切分(比如跳过空格、保留分隔符),再考虑正则;固定长度就是线性扫描的事
- MSVC 和 libstdc++ 对
std::regex实现质量不一,跨平台时尤其容易出问题
substr 版本就够了。最难把握的其实是:要不要允许最后一段“不满也保留”——这取决于业务语义,代码里默认保留,但得让调用方心里有数。


















