C++提取字母代码报错:terminate called after throwing an instance of out_of_range
错误排查与修复方案
核心错误点
数组越界访问
循环for(int i = 0; i < str1.length()+1; i++)中,i的上限设为str1.length(),但C++字符串的索引范围是0到str1.length()-1,当i等于str1.length()时,str1[i]会访问超出字符串内存的区域,直接触发out_of_range异常。逻辑判断错误
条件if(checkstring < 97 && checkstring > 122)逻辑矛盾,一个数值不可能同时小于97且大于122,应该改为||(逻辑或),用来判断当前字符不是小写字母(tolower转换后,字母的ASCII范围是97-122)。substr参数错误
str1.substr(stringcut1, str1.length())存在两个问题:- 如果所有字符都是字母,
stringcut1会保持初始值-1,而substr的起始位置不能为负数,会触发异常; - substr的第二个参数是截取的长度,而非结束位置,原写法会导致截取长度超出字符串剩余长度。
- 如果所有字符都是字母,
修正后的代码
#include <iostream> #include <string> #include <algorithm> #include <ctype.h> using namespace std; int main() { string str1 = "Hello World!-"; sort(str1.begin(), str1.end()); int stringcut1 = 0; // 统一转小写 for(int z = 0; z < str1.size(); z++) { str1[z] = tolower(str1[z]); } // 统计开头的非字母字符数 for(int i = 0; i < str1.length(); i++) { int checkstring = str1[i]; // 判断是否为非小写字母 if(checkstring < 97 || checkstring > 122) { stringcut1++; } else { // 排序后非字母集中在开头,遇到第一个字母即可终止循环 break; } } // 从第一个字母位置截取到末尾 str1 = str1.substr(stringcut1); cout << str1 << endl; return 0; }
额外优化说明
- 由于已对字符串排序,非字母字符会集中在开头,遇到第一个字母时直接终止循环,提升执行效率;
- substr仅传入起始位置参数时,默认截取到字符串末尾,无需指定长度,写法更简洁安全。
内容的提问来源于stack exchange,提问作者Laeil Khan
相关产品推荐
相关产品推荐

