“奇数索引”指字符串中索引值为1、3、5…的位置(从0开始计数),需删除这些位置的字符;正确做法是倒序遍历并erase,或用copy_if构建新串,同时注意size_t溢出和空串边界。

什么是“奇数索引”?先确认边界条件
字符串索引从 0 开始,所以索引 1、3、5… 是奇数索引。注意:不是“奇数字符”,而是“位置在奇数上的字符”。比如 "abcde" 中,索引 1 是 'b',索引 3 是 'd',这两个要删掉,结果是 "ace"。
常见错误是误以为要删 ASCII 值为奇数的字符,或者把索引从 1 开始算——这会导致结果错一位。
用 std::string::erase 从后往前删最安全
如果从前向后遍历并删除,每次 erase 都会让后续字符前移,索引关系立刻变化,容易跳过或越界。正确做法是倒序遍历索引,只删奇数位置,不干扰前面未处理的位置。
- 用
for (int i = s.size() - 1; i >= 0; --i)遍历 - 判断
i % 2 == 1(即奇数索引) - 调用
s.erase(i, 1)删除单个字符
示例:
立即学习“C++免费学习笔记(深入)”;
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
std::string s = "hello";
for (int i = s.size() - 1; i >= 0; --i) {
if (i % 2 == 1) s.erase(i, 1);
}
// 结果: "hlo"更高效:用 std::copy_if 构建新字符串
频繁 erase 会多次移动内存,O(n²) 时间;而一次遍历 + reserve + copy_if 是 O(n),且语义清晰、无迭代器失效风险。
- 先
s.reserve((s.size() + 1) / 2)预留空间(偶数索引最多占一半+1) - 用
std::copy_if把索引为偶数的字符拷贝过去 - 注意:需用带索引的 lambda,捕获一个计数器或用
std::distance计算位置
简洁写法(C++17 起):
std::string s = "hello";
std::string res;
res.reserve((s.size() + 1) / 2);
int idx = 0;
std::copy_if(s.begin(), s.end(), std::back_inserter(res),
[&idx](char) { return (idx++ % 2 == 0); });别忽略空字符串和单字符边界
空字符串 "" 或长度为 1 的字符串(如 "a")不会进入奇数索引范围,应原样返回。但用倒序循环时,i >= 0 在空串下会触发 s.size()-1 溢出(因为 size() 返回 size_t,减 1 变成极大正数),必须提前判空或改用有符号整型索引。
- 安全起见,循环前加
if (s.empty()) return; - 或统一用
int i = static_cast<int>(s.size()) - 1</int> - 用
copy_if方案天然规避该问题
真正容易被忽略的,是 size_t 与负数比较时的隐式转换陷阱——它不会报错,但会让循环跑几亿次。

















