判断字符串变位词的C++代码触发std::out_of_range异常原因排查
std::out_of_range异常 我写了一个C++函数isAnagram,用来读取两个输入字符串并判断它们是否是变位词(长度相同、字符种类和数量一致)。用嵌套for循环实现时,运行触发错误:libc++abi: terminating due to uncaught exception of type std::out_of_range: basic_string。我怀疑是循环访问了不存在的索引,但找不到具体原因。
当前代码:
bool isAnagram(string firstString="", string secondString="") { //Initialize variables. cin >> firstString >> secondString; string copySecondString = secondString; int matchedChars = 0; //Check if string lengths are equal if (firstString.size() != secondString.size()) { return false; } // Outer for loop iterates through each character in firstString // Inner while loop iterates through each character in copySecondString for (int i = 0; i < firstString.size(); i++) { for (int copyIndex = 0; copyIndex < copySecondString.size(); copyIndex += 1) { //Check if index of copySecondString matches i if (firstString.at(i) == copySecondString.at(copyIndex)) { matchedChars += 1; copySecondString.erase(copySecondString.at(copyIndex)); cout << copySecondString.size(); break; } } } if (matchedChars == firstString.size()) { return true; } }
我知道代码不够高效,作为新手很正常,暂时不需要优化实现,只想排查当前运行失败的原因。我怀疑问题出在内层for循环,因为循环体里删除了copySecondString的字符,可能导致后续copyIndex超出长度,但理不清具体逻辑,希望有人指出错误原因。
erase函数参数错误是崩溃核心原因:你调用copySecondString.erase(copySecondString.at(copyIndex))时,传入的是字符的ASCII值,但std::string::erase没有接受单个字符作为参数的重载,实际会匹配到erase(size_t pos, size_t len = npos)版本,把字符值当成了索引位置。比如字符是'a'(ASCII值97),如果字符串长度远小于97,就会直接触发std::out_of_range异常,因为访问了超出字符串长度的索引。正确写法应该是传入要删除的位置索引:
copySecondString.erase(copyIndex, 1),或者用迭代器:copySecondString.erase(copySecondString.begin() + copyIndex)。函数缺少默认返回值:如果
matchedChars不等于firstString.size(),函数没有返回值,这会导致未定义行为,虽然不是当前崩溃的直接原因,但也是需要修复的问题。内层循环删除字符后
break的逻辑没问题,删除操作导致的字符串长度变化不会触发索引越界,因为循环条件是copyIndex < copySecondString.size(),每次循环都会重新判断当前长度。
内容的提问来源于stack exchange,提问作者EnOnline

