如何用str.erase()通过索引删除std::string元素?代码异常求解
关于std::string::erase的正确用法及你的代码问题解析
兄弟,你这代码明显是踩了std::string::erase的用法坑——首先明确说:绝对不能用str.erase(str[i])这种形式,这完全误解了erase的参数要求,也是你遇到乱码、删除异常的核心原因。我帮你一步步捋清楚问题:
你的代码里的两个致命错误
1. 用sizeof s获取字符串长度完全错误
sizeof是用来计算对象/类型在内存中占用的字节数的,对于std::string对象来说,不管它里面存了1个字符还是100个字符,sizeof的结果都是固定的(比如64位系统上通常是24字节)。你要获取字符串的实际字符长度,必须用s.size()或者s.length()。
2. erase的参数完全用错了
std::string::erase根本没有接受单个char类型的重载!当你写s.erase(s[x])时,s[x]是一个字符,会被隐式转换成int(也就是该字符的ASCII值),这相当于调用了erase(size_t pos)这个重载——把ASCII值当成了要删除的起始位置!
举个例子:如果s[x]是字符'a'(ASCII值97),而你的字符串长度只有5,那这个97的位置远远超出了字符串的范围,直接触发未定义行为,乱码就是这么来的。后面的s.erase(s[x-1], s[x])更离谱,两个字符都转成int,当成起始位置和删除长度,完全不是你想要的删除中间两个字符的逻辑。
正确的写法
想要删除字符串的指定位置字符,erase有几种正确的调用方式:
- 删除单个字符:用起始索引+删除长度,或者直接传指向该字符的迭代器
- 删除一段字符:用起始索引+删除长度,或者传迭代器范围(左闭右开)
下面是修正后的完整代码:
#include <iostream> #include <string> using namespace std; int main() { string s; cout << "Please input the desired string : \n"; cin >> s; int sz = s.size(); if (sz == 0) { // 空字符串判断,避免索引越界 cout << "Empty string can't be processed!" << endl; return 0; } int x = sz / 2; if (sz % 2 != 0) { // 方式1:用索引+长度删除单个字符 s.erase(x, 1); // 方式2:用迭代器删除单个字符 // s.erase(s.begin() + x); } else { // 方式1:用索引+长度删除两个字符 s.erase(x - 1, 2); // 方式2:用迭代器范围删除两个字符 // s.erase(s.begin() + x - 1, s.begin() + x + 1); } // 输出结果 cout << "Processed string: " << s << endl; return 0; }
关键修正点说明
- 用
s.size()替代sizeof s,正确获取字符串的实际字符长度 - 单个字符删除:
erase(x, 1)表示从索引x的位置开始删除1个字符;迭代器版本s.erase(s.begin() + x)直接指向要删除的字符 - 两个字符删除:
erase(x-1, 2)表示从x-1的位置开始删除2个字符,正好覆盖中间的两个字符;迭代器版本则传入左闭右开的范围,确保删除目标字符 - 增加了空字符串判断,避免用户输入空字符串时出现索引越界的问题
内容的提问来源于stack exchange,提问作者Mohamed El-Nazer
相关产品推荐
相关产品推荐

