string的修改操作:插入、删除与替换
困难2字符串的“修改手术”:插入、删除与替换
你有没有写过作文之后发现少了一个字,需要“插入”到句子中间?或者写错了几个字,想把它们“删除”掉?又或者想全文把“小明”改成“小红”——这就是“替换”。
在编程里,我们经常要对字符串做同样的操作。C++ 的 string 提供了 insert、erase 和 replace 这些“手术工具”,能直接修改原字符串。Python 的字符串虽然不能变(像一张写好的纸,不能擦改),但我们可以用“剪接”的方法——切片加拼接——来生成新字符串,达到同样的效果。
从生活中的例子引入(保留原有内容)
假设你在作业本上写了一段话,写到一半发现少了一个字,需要“插入”到某个位置;或者写错了几个字,要“删除”它们;又或者想把全文中的“小明”都改成“小红”,这就是“替换”。
在编程中,字符串也经常需要这样修改。C++ 的 string 提供了 insert、erase 和 replace 成员函数,Python 字符串虽然不可变,但可以通过切片和拼接实现类似效果。
STL 原理和使用方法
insert 插入:在任意位置“加塞”
insert 就像在排队时插队——你选择一个位置,把新内容塞进去,后面的人(字符)自动往后挪。
基本用法(保留原有内容):
insert(pos, str):在位置pos之前插入字符串str,pos可以是下标或迭代器。- 还可以指定插入次数或插入子串的一部分(重载版本)。
更多重载版本(新增补充):
insert(pos, n, ch):在位置pos前插入n个相同字符ch。insert(pos, str, subpos, sublen):插入str中从subpos开始的sublen个字符。insert(iterator, ch):在迭代器指向的位置前插入一个字符。insert(iterator, n, ch):在迭代器位置前插入n个字符。insert(iterator, first, last):插入另一个容器(如string、vector)中迭代器区间[first, last)的字符。
生活例子:
你想给朋友发一条消息:“我昨天去了公园”,但突然想起昨天还去了超市,想改成“我昨天去了公园和超市”。你可以在“公园”后面插入“和超市”。在代码里就是 s.insert(6, "和超市")(假设下标6是“公”字前面的位置)。
Python 实现技巧(新增):
- 因为 Python 字符串不可变,所以用切片拼接:
s = "我昨天去了公园" pos = s.find("公园") # 找到"公园"起始位置,假设为5 s = s[:pos] + "和超市" + s[pos:] # 在"公园"前插入 - 如果想插入多个相同字符,可以用
"*" * n生成字符串再拼接。
erase 删除:任意范围“擦除”
erase 就像用橡皮擦掉一段文字,后面的字符会自动往前补齐。
基本用法(保留原有内容):
erase(pos, len):从pos开始删除len个字符。如果省略len,则删除从pos到末尾。erase(iterator):删除迭代器指向的单个字符。erase(first, last):删除迭代器区间的字符。
更多重载版本(新增):
- C++11 之后,
erase返回一个迭代器,指向被删除元素的下一个位置(方便连续删除)。
生活例子:
你写了一行字“我今天吃了苹果和香蕉”,但发现“苹果和”三个字是多余的,想删掉。假设“苹果”在位置6(从0开始),长度为3,只需要 s.erase(6, 3) 即可。
常见误区(新增):
- C++ 中调用
erase(pos, len)时,如果pos越界(大于等于字符串长度),会导致程序崩溃(未定义行为)。 - 如果
len很大(超过从pos到末尾的长度),不会报错,只会删到末尾。 - 使用迭代器删除后,原来的迭代器会失效(不能再使用),必须重新获取。
Python 实现(新增):
- 删除固定位置:
s = s[:pos] + s[pos+len:] - 删除单个字符:
s = s[:i] + s[i+1:]
replace 替换:精确“改写”
replace 就像用修正带覆盖一段文字,再写上新的内容。
基本用法(保留原有内容):
replace(pos, len, str):将从pos开始的len个字符替换为str。- 也可以用迭代器指定范围进行替换。
更多重载版本(新增):
replace(pos, len, str, subpos, sublen):用str的子串来替换。replace(iterator_first, iterator_last, str):用迭代器区间指定范围。replace(pos, len, n, ch):将区间替换为n个字符ch。
生活例子:
你的作文里把“小明”写成了“小红”,现在要改回来。先用 find 找到“小红”的位置,然后替换成“小明”。或者更简单:如果知道位置,直接替换。
C++ 与 Python 差异(新增):
- C++ 的
replace只替换一次(你指定的位置和长度),要全部替换需要自己写循环或用算法std::replace(但那是替换字符,不是子串)。 - Python 的
replace默认替换所有匹配的子串,也可以指定替换次数:s.replace("old", "new", count)。
常见陷阱(新增):
- 替换的字符串长度可以和原区间不同,字符串会自动调整长度。
- 如果替换后字符串变长,后面的字符会往后移;变短则往前移。
新手容易犯的错误(新增详细列表)
- 下标越界
- C++:
pos必须小于等于size()(对于 insert 可以等于 size,表示末尾插入),否则程序崩溃。 - Python:切片不会报错,但拼接时如果下标写错,可能得到错误结果。
- C++:
- 迭代器失效
- 在 C++ 中,插入或删除字符后,之前保存的迭代器(例如
it = s.begin())会失效,不能再使用。需要重新获取。
- 在 C++ 中,插入或删除字符后,之前保存的迭代器(例如
- 认为 Python 字符串可以修改
- 新手容易写
s.replace(...)之后以为s变了,其实要重新赋值:s = s.replace(...)。
- 新手容易写
- C++ 中 replace 只替换一次
- 如果想替换所有“abc”,需要自己写循环,不能直接
s.replace(...)完成全部替换。
- 如果想替换所有“abc”,需要自己写循环,不能直接
- erase 省略 len 时的行为
- 如果调用
s.erase(pos)而没有给出len,会从pos删除到末尾,不是只删一个字符。要删一个字符用s.erase(pos, 1)或迭代器版。
- 如果调用
完整示例(保留原有代码并增加一个综合案例)
原有 C++ 代码(带详细注释)
#include <iostream>
#include <string>
using namespace std;
int main() {
string s = "I love coding";
// 1. insert:在 "love" 前面插入 "really "
s.insert(2, "really "); // 下标2是'l'的位置,插入后变成 "I really love coding"
cout << "insert后: " << s << endl;
// 2. erase:删除从下标0开始的2个字符("I "),剩下 "really love coding"
s.erase(0, 2);
cout << "erase后: " << s << endl;
// 删除最后一个字符 'g'
s.erase(s.size() - 1);
cout << "删除最后一个字符: " << s << endl;
// 3. replace:将 "coding" 替换为 "programming"
// 先用 find 找到 "coding" 的位置
size_t pos = s.find("coding");
if (pos != string::npos) {
s.replace(pos, 6, "programming"); // "coding" 长度为6
cout << "replace后: " << s << endl;
}
// 使用迭代器版本插入(在开头插入一个字符)
s.insert(s.begin(), 'A');
cout << "开头插入 'A': " << s << endl;
// erase 第二个字符(现在A在位置0,第二个字符是空格?我们删掉那个空格)
s.erase(s.begin() + 1); // 删除下标1的字符
cout << "删除第二个字符: " << s << endl;
return 0;
}
原有 Python 代码(带详细注释)
# Python字符串不可变,每次修改都会创建新字符串
s = "I love coding"
# 1. insert:在 "love" 前面插入 "really "
# 先找到 "love" 的位置
pos = s.find("love")
if pos != -1:
s = s[:pos] + "really " + s[pos:]
print(f"insert后: {s}")
# 2. erase:删除从下标0开始的2个字符
s = s[2:] # 切片,跳过前两个字符
print(f"erase后: {s}")
# 删除最后一个字符
s = s[:-1]
print(f"删除最后一个字符: {s}")
# 3. replace:将 "coding" 替换为 "programming"
# Python 有直接的 replace 方法(返回新字符串)
s = s.replace("coding", "programming")
print(f"replace后: {s}")
# 若要在开头插入字符
s = 'A' + s
print(f"开头插入 'A': {s}")
# 删除第二个字符
if len(s) > 1:
s = s[:1] + s[2:] # 保留第一个字符,跳过第二个,再连上剩余
print(f"删除第二个字符: {s}")
新增综合示例:模拟修改朋友圈文案(C++ 和 Python 对照)
场景:
你发了一条朋友圈:“今天和同桌去图书馆,然后去吃了火锅(超辣)”。
后来你发现:“同桌”改成“好朋友”更准确;删掉括号里的“超辣”;在“图书馆”后面插入“和网吧”?不,改成“然后去公园散步”。
C++ 实现:
#include <iostream>
#include <string>
using namespace std;
int main() {
string s = "今天和同桌去图书馆,然后去吃了火锅(超辣)";
// 1. 将"同桌"替换为"好朋友"
size_t pos = s.find("同桌");
if(pos != string::npos) {
s.replace(pos, 6, "好朋友"); // "同桌" 两个字占用6字节(UTF-8,假设)
}
cout << "替换后: " << s << endl; // 注意:中文字符在UTF-8中每个占3字节,这里简化
// 2. 删除括号及里面的"超辣"(包括括号)
pos = s.find("(超辣)"); // 全角括号
if(pos != string::npos) {
s.erase(pos, 9); // 假设删除9字节
}
cout << "删除后: " << s << endl;
// 3. 在"图书馆"后面插入",然后去公园散步"
pos = s.find("图书馆");
if(pos != string::npos) {
s.insert(pos + 9, ",然后去公园散步"); // 找到"图书馆"结束位置
}
cout << "最终: " << s << endl;
return 0;
}
Python 实现(需要处理编码,这里简化为普通字符串):
s = "今天和同桌去图书馆,然后去吃了火锅(超辣)"
# 1. 替换"同桌"为"好朋友"
s = s.replace("同桌", "好朋友")
print(f"替换后: {s}")
# 2. 删除"(超辣)"
s = s.replace("(超辣)", "") # 直接替换为空字符
print(f"删除后: {s}")
# 3. 在"图书馆"后插入",然后去公园散步"
pos = s.find("图书馆")
if pos != -1:
s = s[:pos + 3] + ",然后去公园散步" + s[pos + 3:] # 每个汉字占1个位置(Python中按字符)
print(f"最终: {s}")
注意:中文字符在 C++ 中可能占用多个字节(如 UTF-8 下每个汉字 3 字节),使用下标时要小心。实际开发中建议使用 wstring 或 string 配合长度计算。Python 的字符串以 Unicode 字符为单位,处理中文更方便。
总结要点和注意事项(保留原有内容并补充)
- C++ 的
insert、erase、replace会直接修改原字符串,效率较高。 - Python 字符串不可变,每次修改都生成新字符串,大量修改时建议先转为
list再操作,最后用''.join转回来。 - 注意下标范围,越界会导致未定义行为(C++)或错误(Python)。
replace在 C++ 中只替换指定位置的一次,而 Python 的replace默认替换所有匹配项(可指定次数)。- 使用迭代器时注意迭代器失效问题(插入删除后后续迭代器可能无效)。
新增提醒:
- 在 C++ 中,如果要插入或删除多个字符,优先考虑重载版本(如
insert(pos, n, ch))而非循环操作,效率更高。 - 对大量字符串修改(如拼接大量片段),C++ 可用
string::reserve提前分配内存,Python 用list+join。
相关指引(新增)
学会插入、删除和替换之后,你可以继续探索这些知识:
- 字符串查找:
find、rfind、find_first_of等,能帮你准确找到要修改的位置。 - 子串提取:
substr(C++)/切片(Python)可以取出字符串的一部分。 - 字符串比较:
compare(C++)/比较运算符(Python)判断两个字符串是否相等。 - 字符串流处理:C++ 的
stringstream可以把字符串当做输入输出流,方便格式化;Python 的StringIO类似。 - 正则表达式:当需要复杂模式匹配和替换时(比如把所有数字替换成*),正则表达式是最强工具(C++
<regex>,Pythonre模块)。 - Python 的
str与bytes:了解编码转换,避免中文乱码。
把字符串的修改操作练熟,你就掌握了处理文本的基本功。现在去试试修改你的“作文”吧!
例题精讲
在C++中,已知string s = "HelloWorld"; 执行 s.insert(5, " "); 后,s的值是什么?
执行以下代码后,字符串s的值是什么?\nstring s = "abcdefg";\ns.erase(2, 3);
在C++中,string的replace函数只能替换指定长度的字符,不能插入或删除字符。
完善代码,实现在字符串s的末尾插入一个感叹号。\nstring s = "Hello";\ns.____(s.____(), '!');补全代码,删除字符串s中从位置3开始的2个字符。\nstring s = "abcdef";\ns.____(3, ____);