题目
编写一个高效的全局子串替换函数 replaceAll(std::string& str, const std::string& from, const std::string& to)。将字符串中所有匹配的 from 替换为 to。重点处理经典死循环陷阱:当新子串 to 中包含原旧子串 from 时(例如将 "a" 替换为 "aa"),必须通过精确计算替换后的指针偏移量跳过新插入的内容。
输入格式:第一行输入原文本;第二行输入待替换的目标旧子串;第三行输入替换后的新子串。
输出格式:输出完全替换后的最终字符串。
数据范围与约定:字符串长度 <code>≤ 10^5</code>。
思路与算法
1. 死循环陷阱
如果每次替换完成后仍从当前 pos 重新 find(from, pos),当 to 包含 from 时,程序会陷入死循环直到内存耗尽崩溃。
2. 精确位移步进
使用 str.replace(pos, from.length(), to) 完成替换后,下次查找的起始位置必须设置为 pos + to.length(),直接跃过刚刚注入的新内容。
3. 空子串防御
若 from.empty(),必须直接短路返回,否则 find("", pos) 将永远返回当前 pos 导致致命死循环。
完整程序
#include <iostream>
#include <string>
void replaceAll(std::string& str, const std::string& from, const std::string& to) {
if (from.empty()) {
return; // 防御空串匹配死循环
}
std::string::size_type startPos = 0;
while ((startPos = str.find(from, startPos)) != std::string::npos) {
str.replace(startPos, from.length(), to);
// 关键:跳过刚刚替换插入的新子串整体长度
startPos += to.length();
}
}
int main() {
std::string text, from, to;
if (!std::getline(std::cin, text) || !std::getline(std::cin, from) || !std::getline(std::cin, to)) {
return 0;
}
std::cout << "替换前原串: " << text << "\n";
replaceAll(text, from, to);
std::cout << "替换后结果: " << text << "\n";
return 0;
}运行示例
示例 1:
输入:
user_id = %id%, user_name = %id%_name
%id%
admin输出:
替换前原串: user_id = %id%, user_name = %id%_name
替换后结果: user_id = admin, user_name = admin_name
示例 2:
输入:
banana
a
aa输出:
替换前原串: banana
替换后结果: baanaanaa