C++20起可用std::erase删除指定字符(如空格),std::erase_if配合isspace可删所有空白符;旧标准用remove_if+erase实现;trim需手动编写,注意isspace参数须转unsigned char及reverse_iterator::base()用法。

用 std::erase 删除所有空格(C++20 及以上)
C++20 引入了 std::erase 和 std::erase_if,对 std::string 做原地删除非常直观。它直接修改原字符串,不需手动管理迭代器,也不用担心失效问题。
-
std::erase用于删除指定值的所有匹配项,比如空格字符' ' -
std::erase_if更灵活,支持任意谓词,可同时删掉' '、'\t'、'\n'等空白符
std::string s = " hello \t world\n";
std::erase(s, ' '); // 只删 ASCII 空格
// s 变成 "helloworld\n"(注意:\t 和 \n 还在)
<p>std::erase_if(s, [](char c) { return std::isspace(static_cast<unsigned char>(c)); });
// s 变成 "helloworld"</unsigned></p>
⚠️ 注意:std::isspace 必须传 unsigned char,否则遇到负值(如某些 locale 下的扩展字符)会 UB。
用 std::remove_if + erase(C++11–C++17 兼容方案)
这是最通用、兼容性最好的写法,适用于所有标准版本。本质是“移除-擦除”惯用法(erase–remove idiom),不会改变未被删除字符的相对顺序。
-
std::remove_if把所有满足条件的字符“挪到末尾”,返回新逻辑结尾的迭代器 - 后续用
string::erase删除从该位置到末尾的冗余部分
std::string s = " a b\tc\n ";
s.erase(std::remove_if(s.begin(), s.end(), [](char c) {
return std::isspace(static_cast<unsigned char>(c));
}), s.end());
</unsigned>
常见踩坑点:
- 忘记
static_cast→std::isspace对负值行为未定义 - 混用
std::remove(只匹配字面值)和std::remove_if(需谓词)→ 想删所有空白却写了std::remove(s.begin(), s.end(), ' '),漏掉制表符和换行 - 在循环中边遍历边
erase→ 迭代器失效,结果错乱或崩溃
只删首尾空格(trim),不碰中间
很多场景其实只需要 trim,比如解析配置、用户输入清理。C++ 标准库没提供 trim,但可以手写简洁实现:
auto trim = [](std::string& s) {
auto start = s.begin();
while (start != s.end() && std::isspace(static_cast<unsigned char>(*start))) ++start;
auto end = s.end();
while (end != start && std::isspace(static_cast<unsigned char>(*(end - 1)))) --end;
s = std::string(start, end);
};
</unsigned></unsigned>
或者更高效地原地截断(避免构造新 string):
s.erase(s.begin(), std::find_if_not(s.begin(), s.end(), [](char c) {
return std::isspace(static_cast<unsigned char>(c));
}));
s.erase(std::find_if_not(s.rbegin(), s.rend(), [](char c) {
return std::isspace(static_cast<unsigned char>(c));
}).base(), s.end());
</unsigned></unsigned>
注意:第二个 erase 的参数是 reverse_iterator::base(),不是 s.rbegin().base() —— 后者永远等于 s.end(),会清空整个字符串。
性能与编码细节提醒
删空格看着简单,但实际容易忽略边界情况:
- 多字节空格(如 Unicode NBSP
'\u00A0')不会被std::isspace识别,除非当前 locale 支持且已设置(例如std::setlocale(LC_ALL, ""))。纯 ASCII 场景没问题,国际化文本需额外处理 - 频繁修改长字符串时,
std::erase_if内部仍是移动操作,时间复杂度 O(n),无法避免;若需高频编辑,考虑改用std::vector或构建新字符串(reserve + push_back) -
std::string_view不能删空格(只读),只能复制为std::string后处理
真正动手时,先确认你要删的是“所有空白”“仅空格”还是“仅首尾”,再选对应工具——选错 API 比写错逻辑更容易引入隐藏 bug。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











