c++oding="utf-8" ?>
最常用方案是用 std::string::find_first_not_of 和 find_last_not_of 配合 erase 或 substr,需显式传入空白字符集字符串,注意判空和越界;regex_replace 更灵活但性能差;手写循环兼容性最强且支持 locale。

std::string::erase 配合 find_first_not_of 和 find_last_not_of 最常用
直接用 std::string 自带成员函数组合,是 C++11 及以后最轻量、无额外依赖的方案。核心思路是先定位首尾第一个非空白字符位置,再截取中间子串或原地擦除。
注意:这里的“空白字符”默认指 ' '、'\t'、'\n'、'\r'、'\f'、'\v' —— 即 std::isspace 识别的字符,但 find_first_not_of 默认只认字面量,所以必须显式传入空白字符集字符串。
- 用
s.find_first_not_of(" \t\n\r\f\v")找开头第一个非空白位置;返回std::string::npos表示全空 - 用
s.find_last_not_of(" \t\n\r\f\v")找结尾最后一个非空白位置 - 若两者都有效(
first != std::string::npos),则s.erase(first, s.length() - last - 1)或更安全地s = s.substr(first, last - first + 1) - 别漏判空串:如果
first == std::string::npos,直接s.clear()
用 std::regex_replace 处理复杂空白模式(如连续多个制表符)
当需要把首尾的“任意空白序列”(包括 Unicode 空格、全角空格等)一并清理,或想复用正则逻辑时,std::regex_replace 更灵活,但开销明显更大,且各标准库对 std::regex 支持不一(MSVC 基本可用,libstdc++ 曾长期有 bug)。
典型写法:std::regex_replace(s, std::regex(R"(^\s+|\s+$)"), "") —— 注意 \s 在 C++ 正则中不一定匹配所有 Unicode 空格,且 R"(...)" 是为避免反斜杠转义混乱。
- 编译期需开启
-std=c++11或更高,并链接stdc++(某些旧环境要额外加-lstdc++) - 性能敏感场景慎用:一次构造 regex 对象 + 两次扫描,比纯迭代慢 3–5 倍
- 若只需 ASCII 空白,没必要上正则;真要 Unicode 支持,建议换
ICU或Boost.Regex
手写循环遍历 —— 兼容性最强、零依赖、可定制
嵌入式或受限环境(比如没 STL 的裸机 C++)只能自己扫。逻辑简单:两个指针分别从头/尾往中间走,跳过空白,最后用 substr 或 assign 截取。
关键点在于空白判断:别直接写 c == ' ',应调用 std::isspace(static_cast<unsigned char>(c))</unsigned>,否则遇到负值 char(如某些 locale 下的扩展 ASCII)会 UB。
- 头指针从
i = 0开始,满足std::isspace(static_cast<unsigned char>(s[i]))</unsigned>就 ++ - 尾指针从
j = s.size() ? s.size()-1 : 0开始,同样条件就 --,注意j >= i边界 - 最终有效区间是
[i, j](闭区间),若i > j则结果为空串 - 这种写法能无缝迁移到
std::string_view,且容易加日志或断点调试
为什么不能只用 trim_left / trim_right 分两步?
可以,但多数人忽略了一个细节:trim_left 后字符串变短,再调 trim_right 时若仍按原长度算,可能越界或漏删。更隐蔽的问题是——两次遍历不如一次双指针高效,尤其对长字符串。
常见错误写法:s.erase(0, s.find_first_not_of(" \t\n\r\f\v")); s.erase(s.find_last_not_of(" \t\n\r\f\v") + 1); —— 第二行的 find_last_not_of 若返回 npos(即全空),+1 会整数溢出,触发未定义行为。
- 正确做法:每次调用
find_*后必须检查是否等于std::string::npos - 或者统一用双指针法,只遍历一次
- 第三方库如
absl::StripTrailingAsciiWhitespace内部就是单次扫描,值得参考
实际项目里,90% 场景用第一种 find_first_not_of + find_last_not_of 组合就够了。真正容易被忽略的是:不同 locale 下 std::isspace 行为可能变化,而 find_first_not_of 用的是字面量比对,二者语义并不等价 —— 如果业务明确要求按当前 locale 判定空白,就得用手写循环 + std::isspace。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











