应优先手写双指针遍历:用i读、j写,last_was_dot标记前字符是否为点,仅当非点后首次遇点才写入,最后s.resize(j)截断。

用 std::regex_replace 一次性清除连续点号
连续多个点号(如 "..."、"....")通常属于冗余,想全替换成单个点,正则最直接。但注意:std::regex 在部分旧编译器(如 GCC
实操建议:
- 匹配模式用
R"(\.{2,})"—— 至少两个点,避免误伤单点 - 替换为
".",不是空字符串,否则会把所有点都删光 - 若字符串极长(>100KB),优先考虑手写循环,regex 构建和匹配开销明显
std::string s = "a..b...c....d";
s = std::regex_replace(s, std::regex(R"(\.{2,})"), ".");
// 结果: "a.b.c.d"
手写双指针遍历,零依赖且可控
不引入正则、不分配额外内存、兼容 C++11 起所有标准,适合嵌入式或性能敏感场景。核心逻辑是跳过“非首点”的连续点号。
关键细节:
- 用两个索引
i(读位置)和j(写位置),原地覆盖 - 设标志
last_was_dot,只在前一个字符不是点时才写入当前点 - 遇到非点字符,直接写入并重置标志
- 最后用
s.resize(j)截断尾部冗余
std::string s = "a..b...c....d"; size_t j = 0; bool last_was_dot = false; for (size_t i = 0; i <h3>保留语义的点号不能乱删:比如域名、小数、路径</h3> <p>盲目“去冗余点”可能破坏数据含义。例如 <code>"192.168.0.1"</code> 中的点是分隔符,不是冗余;<code>"../dir/file"</code> 中的 <code>".."</code> 是上级目录标识,删成 <code>"./dir/file"</code> 就错了。</p><div class="aritcle_card flexRow artxards"> <div class="artcardd flexRow"> <a class="aritcle_card_img" rel="nofollow" href="/xiazai/skill5502" title="C++ Code Review Master"><img src="https://img.php.cn/upload/skill/000/000/081/179051228971575.jpg" alt="C++ Code Review Master" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a> <div class="aritcle_card_info flexColumn"> <a rel="nofollow" href="/xiazai/skill5502" title="C++ Code Review Master" class="overflowclass">C++ Code Review Master</a> <p class="overflowclass">组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。</p> </div> <a rel="nofollow" href="/xiazai/skill5502" title="C++ Code Review Master" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span> </a> </div> </div> <p>判断依据要看上下文:</p>
- 如果是文件路径,需识别
".."和"."这类特殊片段,不能只看字符重复 - 如果是数字字符串,先检查是否含
'e'或'E'(科学计数法)、是否只有数字+一个点(合法小数) - 如果明确是纯 ID 或标签(如
"user..name"),才适用前述两种方法
std::erase_if 不适合这个需求
C++20 的 std::erase_if 只能按单字符条件删除,无法感知“前面是不是点”,所以不能用来压缩连续点。有人试过这样写:
std::erase_if(s, [](char c) { return c == '.'; }); // ❌ 全删了
或者试图用 lambda 捕获状态,但 std::erase_if 不保证遍历顺序,也不传入索引,无法实现“跳过后续点”的逻辑。这类需求必须用显式循环或正则。
真正难的不是怎么删,而是怎么定义“冗余”——它取决于字段用途,而不是字符串本身。没上下文就上正则,容易修好一个 bug 引出三个新问题。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










