c++oding="utf-8" ?>
最直接办法是用 std::regex_replace 匹配 r"(\.+)”并替换为空字符串,但需注意 libstdc++ 旧版本兼容性问题;高频调用应复用 regex 对象;对极大字符串或要求稳定性能的场景,推荐双指针遍历或 std::remove + erase(若需删除所有点)。

用 std::regex_replace 一次性清除连续点号
最直接的办法是正则匹配一个或多个连续的 .,替换成空字符串。C++11 起标准库支持 std::regex,但要注意:GCC 的 libstdc++ 在较老版本(如 GCC 4.9 之前)中正则实现不完整或有 bug,Clang 的 libc++ 相对稳定些。
实操建议:
- 使用
R"(\.+)"作为模式:原始字符串避免转义混乱,\.匹配字面量点,+表示“一个及以上” - 替换目标传空字符串
"",不是" "或"\0" - 若字符串极大(MB 级),正则可能比手写循环慢 2–3 倍,且构造
std::regex对象有开销;高频调用时建议复用编译好的regex对象
std::string s = "a...b....c"; s = std::regex_replace(s, std::regex(R"(\.+)"), ""); // 结果: "abc"
手写双指针遍历更可控、无依赖
不需要引入 <regex></regex>,兼容所有 C++11+ 编译器,逻辑清晰,性能稳定。核心思路是跳过所有连续的 .,只保留非点字符和第一个点(如果需要保留单个点)——但题目要求“删除所有连续点号”,即:只要出现两个及以上 . 就全删,而孤立的单个 . 应保留?不,题干是“删除所有的连续点号”,语义上指“所有由连续点号组成的子串”,也就是凡属“连续”者一律清空,不管长度是 2 还是 100;单个点不构成“连续”,所以不应删。但常见实际需求其实是“把所有点都删掉”,需确认意图。本方案按题干字面:只删“连续”的,即 ≥2 个连在一起的。
实操建议:
- 用两个索引:
write指向结果写入位置,read扫描原串 - 遇到非
.字符,直接复制并推进write - 遇到
.,先记下起始位置,往后跳过所有连续.;之后判断这段长度是否 ≥2 —— 是则跳过不复制,否则复制一个. - 注意边界:结尾可能是连续点号,别漏掉
std::string removeConsecutiveDots(std::string s) {
if (s.empty()) return s;
size_t write = 0;
for (size_t read = 0; read = 2:跳过,不写入
}
}
s.resize(write);
return s;
}
误用 std::string::erase 循环删除的坑
有人试图用 find + erase 反复删 "..",这是典型错误:删完一处后,原本不相邻的点可能拼成新的 "..",但循环没重新从头找,会漏删。例如 "...." → 删前两个变 "..",若继续从当前位置找,就跳过了新形成的 ".."。
常见错误现象:
- 输入
"a...b",输出"a.b"(只删了一处) - 代码里写
pos = s.find("..", pos + 2),导致越界或死循环 - 没处理空字符串或单点边界,
find返回std::string::npos后仍调用erase,触发未定义行为
正确做法:每次 erase 后,pos 应设为 0(重头找),或更高效地用 while 循环配合 find 并检查返回值:
size_t pos = 0;
while ((pos = s.find("..", pos)) != std::string::npos) {
s.erase(pos, 2);
// 不加 pos++,因为删掉两个后,新串在 pos 处可能又出现 ".."
}
但此法最坏时间复杂度 O(n²),不推荐用于长字符串。
要不要保留单个点?看场景再定
题干说“删除所有的连续点号”,逻辑上单个点不算“连续”,应保留。但实际中,比如清理文件名、URL 片段或日志字段时,往往希望“所有点都干掉”。这时候最简方案反而是:
s.erase(std::remove(s.begin(), s.end(), '.'), s.end());
它用 std::remove 把所有 . 挪到末尾,再用 erase 一并截断,O(n) 时间、零内存分配、无正则依赖。
选择依据:
- 要删“所有点” → 用
remove + erase - 只删“≥2 个连着的点”,留单个 → 用双指针或正则(带
\.{2,}模式) - 输入来自不可信源且含大量点 → 避免正则,防回溯爆炸(虽然
\.+不回溯,但若改成\.*x类就危险)
真正容易被忽略的是语义歧义:“连续点号”到底指“连续出现的点号构成的子串”还是“点号的连续重复形态”。前者是子串概念,后者易被理解成“只要重复就算”,但标准解释以子串为准。写代码前,先跟上下游确认输入样例和预期输出。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











