c++20推荐用std::remove_if+std::erase原地删除括号,需配对使用否则残留垃圾;只读场景用std::copy_if构造新串;手动循环慎用于utf-8;正则简洁但性能差且需异常处理。

用 std::remove_if + std::erase 删除所有括号(C++20 推荐)
最简洁安全的做法是组合使用 std::remove_if 和 std::erase,适用于 C++20 及以上。它原地修改字符串,不产生临时对象,性能好且语义清晰。
注意:std::remove_if 不真正删除元素,只是把要保留的元素前移,返回新逻辑结尾;std::erase 才真正截断——漏掉后者会导致残留垃圾字符。
std::string s = "a(b[c]d)e";
s.erase(std::remove_if(s.begin(), s.end(), [](char c) {
return c == '(' || c == ')' || c == '[' || c == ']' || c == '{' || c == '}';
}), s.end());
// s 变为 "abcde"
- 括号类型可按需增减,比如只删圆括号就只留
c == '(' || c == ')' - 若用 C++17 或更早,没有
std::erase,得写成s.erase(..., s.end())两步 - 不能对
const std::string&直接操作,必须有可修改副本
用 std::copy_if 构建新字符串(兼容老标准,适合只读场景)
当你不想/不能修改原字符串(比如输入是 const char* 或只读引用),或需要保留原串时,用 std::copy_if 复制非括号字符到新字符串更稳妥。
这个方法天然避免迭代器失效问题,也更容易调试——你可以先打印过滤条件是否符合预期。
std::string input = "x(y{z}w)[v]";
std::string output;
output.reserve(input.size()); // 预分配避免多次 realloc
std::copy_if(input.begin(), input.end(), std::back_inserter(output),
[](char c) { return !strchr("()[]{}", c); });
// output 为 "xyzwv"
-
strchr是 C 风格写法,也可改用std::string("()[]{}").find(c) == std::string::npos -
reserve()不是必须,但对长字符串能明显提升性能 - 如果输入是
const char*,先用std::string_view包一层再遍历,避免构造临时std::string
手写循环要注意的边界和编码陷阱
手动遍历看似简单,但容易在多字节字符、迭代器失效、空字符串等边缘 case 出错。尤其当字符串含 UTF-8 编码的中文或 emoji 时,按 char 删括号可能切开一个字符。
除非你明确处理的是纯 ASCII 字符串,否则不建议裸写 for (size_t i = 0; i 并在循环中调用 <code>s.erase(i, 1) ——这会移动后续字符,导致跳过下一个位置。
- 正确手写方式是倒序遍历:
for (int i = s.size()-1; i >= 0; --i),再删括号 - 或用索引+偏移量记录已删长度,正向遍历时调整下标
- 若字符串可能含 Unicode,应先用 ICU 或
std::utf8_codecvt_facet(C++11 起)做字符级而非字节级判断
正则表达式 std::regex_replace 的开销与限制
用 std::regex_replace(s, std::regex(R"([\(\)\[\]\{\}])"), "") 写法最直观,但实际项目中要谨慎:C++ 标准库的正则实现普遍较慢,编译期无法优化,且部分平台(如 MSVC 旧版本)对 Unicode 支持弱。
它适合一次性脚本或原型验证,不适合高频调用路径(比如每帧处理日志字符串)。
- 注意转义:圆括号在正则里有特殊含义,必须写成
\(和\),而方括号和花括号在字符组[...]内无需额外转义(但]必须放首位) - 正则引擎可能抛
std::regex_error,生产代码中应包裹try/catch - 若只是删固定字符集,正则比循环慢 3–10 倍,实测在 10KB 字符串上差异明显
std::erase 配合 std::remove_if,或者在 UTF-8 环境下当成单字节字符串处理。C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











