
本文详解如何使用 for 循环安全、高效地将输入文本中的英文句号(.)和感叹号(!)统一替换为两个感叹号(!!),指出原始代码因边遍历边修改字符串导致的逻辑错误,并提供基于 stringbuilder 的正确实现及正则替代方案。
原始代码的核心问题在于:在 for 循环中直接修改正在遍历的字符串 text,会导致索引错位与逻辑失控。由于 Java 中 String 是不可变对象,每次执行 text = front + "!!" + back 都会创建新字符串,而循环变量 i 仍按原字符串长度递增——但此时 text 已变长,后续字符位置偏移,且 i+1 可能越界(如末尾字符被替换后,substring(i+1) 抛出 StringIndexOutOfBoundsException),最终程序可能异常终止或输出为空。
✅ 正确做法是:分离“读取”与“构建”过程——遍历原字符串只读取字符,用可变容器(如 StringBuilder)累积结果。以下是符合题目要求(必须使用 for 循环)的推荐实现:
public static String replace(String text) {
StringBuilder sb = new StringBuilder(text.length()); // 预分配容量,提升性能
for (int i = 0; i < text.length(); i++) {
char c = text.charAt(i);
if (c == '.' || c == '!') {
sb.append("!!");
} else {
sb.append(c);
}
}
return sb.toString();
}? 关键改进说明:
- 使用 charAt(i) 替代 substring(i, i+1):更高效(避免新建子字符串对象),语义更清晰;
- StringBuilder 提供 O(1) 的追加操作,避免频繁字符串拼接带来的性能损耗;
- 循环全程不修改原字符串,索引 i 始终准确对应当前字符位置。
⚠️ 注意事项:
- 若输入为空字符串(""),该方法仍安全返回空字符串;
- 仅匹配 ASCII 中的 . 和 !;如需支持 Unicode 标点,需扩展判断逻辑;
- 题目强制要求 for 循环,故未采用 replaceAll("[.!]", "!!") 等简洁写法——虽一行可解,但不符合约束条件。
? 总结:字符串处理中,“遍历即修改”是典型反模式。牢记「只读原数据,另建新结果」原则,配合 StringBuilder,即可写出健壮、高效且符合教学要求的循环替换逻辑。










