C++字符串删除子串函数抛出std::out_of_range异常问题求助
问题分析与修复
错误原因
你的代码核心问题在于初始字符串长度slen未同步更新:
- 你一开始把
slen设为字符串的初始长度,但后续调用s.erase()修改字符串后,slen始终保持初始值,完全脱离了字符串的实际长度。 - 以测试用例
s="eemckxmckx"、part="emckx"为例:- 初始
slen=10,lenPart=5,循环条件允许i最大到10-5=5。 - 第一次在
i=1位置匹配到子串,删除后s变为"emckx"(长度5),但slen仍为10,i被设为max(0,1-5)=0。 - 再次进入循环,
0 <= 10-5成立,调用s.substr(0,5)匹配成功,删除后s变为空字符串(长度0),i仍为0。 - 循环条件
0 <=5依然成立,此时调用s.substr(0,5),由于s长度为0远小于5,触发std::out_of_range异常。
- 初始
修复方案
有两种可行的修复方式,核心都是让循环条件基于字符串的实时长度判断:
方式1:直接使用实时长度判断循环条件
string removeOccurrences(string &s, const string &part) { int lenPart = part.length(); int i = 0; // 强制转换为int,避免size_t无符号数的溢出问题 while (i <= (int)s.length() - lenPart) { if (s.substr(i, lenPart) == part) { s.erase(i, lenPart); i = max(0, i - lenPart); } else { i++; } } return s; }
方式2:删除后同步更新slen
string removeOccurrences(string &s, const string &part) { int lenPart = part.length(); int slen = s.length(); int i = 0; while (i <= slen - lenPart) { if (s.substr(i, lenPart) == part) { s.erase(i, lenPart); slen = s.length(); // 同步更新为当前字符串长度 i = max(0, i - lenPart); } else { i++; } } return s; }
补充说明
- 注意
(int)s.length()的转换:string::length()返回的是无符号类型size_t,如果直接计算s.length() - lenPart,当字符串长度小于lenPart时会得到一个极大的无符号数,导致循环错误执行,所以强制转换为int规避该问题。 i = max(0, i - lenPart)的逻辑是合理的,用于处理删除子串后,前面的字符可能形成新匹配的场景(比如s="aaaaa"、part="aa",删除后需要回退检查)。
内容的提问来源于stack exchange,提问作者user20273569
相关产品推荐
相关产品推荐

