使用相同的功能时意外收到“std :: out_of_range”错误

时间:2017-07-29 17:28:15

标签: c++ string function recursion char

我编写了一个递归回文函数,在第一个代码中只接收一个单词,在第二个代码中接收一个句子。然而,意外的第二个代码给了我“超出范围”的错误。

这两个代码中使用了这个功能(工作正常):

pygame.quit()

在第一个代码中,即使我输入了一个非常长的字符串,它也按预期工作:

bool palindrome( string str, int first, int last )
{
    if( first == str.size() - 1 ) //if string is a single alphabet.
        return true;
    if( str[ first ] == str[ last ] )
        return palindrome( str.substr( first + 1, last - 1 ), first, last - 2 );
}

在第二个代码中,我需要将输入句子转换为单词,同时使所有字符都为小写(我在其他函数中执行所有这些操作)。我在第二个代码中输入了相同的字符串但仍然在页面底部出现错误:

int main()
{
    string str = "madamhelloollehmadam";
    palindrome( str, 0, str.size() - 1 ) ? cout << "palindrome!" << '\n' : cout << "not palindrome." << '\n';
}

这是我得到的错误(我不会得到这个错误,第一个代码得到一个单词而不是一个句子,但两个“回文”函数是相同的。我猜测“normalString”函数有问题但我无法发现任何尺寸差异...)

int main()
{
    string str = "madam hello olleh madam"; //this becomes "madamhelloollehmadam" after going to "normalString" function.
    palindrome( normalString(str), 0, normalString(str).size() - 1 ) ? cout << "palindrome!" << '\n' : cout << "not palindrome." << '\n';
}

这也是normalString函数:

terminate called after throwing an instance of 'std::out_of_range'
  what():  basic_string::substr
Aborted

这是我的第二个代码:

string normalString( string str )
{
    vector<string> vec;
    for( int i = 0; i < str.size(); ++i )
        vec.push_back( charToString(str[ i ]) );

    for( int i = 0; i < vec.size(); ++i )
    {
        if( !isAlpha( vec[ i ] ) )
            vec[ i ].erase();
        if( isupper( stringToChar(vec[ i ]) ) ) 
            vec[ i ] = charToString( tolower( stringToChar( vec[ i ] ) ) );
    } 

    string str2 = vectorToString( vec );
    return str2;
}

2 个答案:

答案 0 :(得分:2)

此代码存在许多问题。

回文功能

首先,让我们重写一下签名。由于palindrome不需要字符串的副本,因此我们传入一个const引用。索引也应该更改为std::size_t,因为这是用于索引字符串的类型。

bool palindrome(const std::string &str, std::size_t first, std::size_t last) {

接下来,我们需要处理字符串只有一个字符的情况......但 也很重要,以处理字符串为零的情况。这是原始代码:

    // if (first == str.size() - 1) // Wrong!

首先,这并不是它所说的。我们正在处理的字符串的长度应该是从firstlast,而不是从firstsize() - 1(否则为什么last甚至存在? )其次,如果size()为0,这将无法工作。它会溢出!这是更正后的代码。

    // Empty string, or only one character
    std::size_t length = last - first;
    if (length <= 1)
        return true;

接下来,我们比较第一个和最后一个字符。但最后一个字符实际上并非str[last],而是str[last-1]

    if (str[first] == str[last - 1])

由于我们有方便的firstlast参数,因此我们使用它们而不是调用substr

        return palindrome(str, first + 1, last - 1);

但是如果条件失败,我们必须记得要回来......

    return false;
}

normalString函数

事实证明std::stringpush_back,因此您不需要向量,isAlpha可以更改为char而不是string {1}},这使它变得更加简单。

bool isAlpha(char c) {
    return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
}

std::string normalString(std::string str) {
    std::string result;
    for (char c : str) {
        if (isAlpha(c))
            result.push_back(std::tolower(c));
    }
    return result;
}

完整代码

同时删除了using namespace std;

#include <iostream>
#include <string>
#include <vector>
#include <locale>

bool palindrome(const std::string &, std::size_t, std::size_t);
std::string normalString(std::string);

int main() {
    while (true) {
        std::cout << "Enter a word or a sentence: ";
        std::string str;
        if (!(std::cin >> str))
            break;
        str = normalString(str);
        if (palindrome(str, 0, str.size())) {
            std::cout << str << " is palindrome!"
                << " (" << str << ")\n";
        } else {
            std::cout << str << " is not palindrome!"
                << " (" << normalString(str) << ") \n";
        }
    }
    return 0;
}

bool isAlpha(char c) {
    return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
}

std::string normalString(std::string str) {
    std::string result;
    for (char c : str) {
        if (isAlpha(c))
            result.push_back(std::tolower(c));
    }
    return result;
}

bool palindrome(const std::string &str, std::size_t first, std::size_t last) {
    // Empty string, or only one character
    std::size_t length = last - first;
    if (length <= 1)
        return true;
    if (str[first] == str[last - 1])
        return palindrome(str, first + 1, last - 1);
    return false;
}

答案 1 :(得分:0)

在Visual Studio中使用Windows调试,您可以查明特定行的问题。

所以这就是你的问题:在函数normalString(string)中你必须这样做:

for (int i = 0; i < vec.size(); ++i)
{
    if (!isAlpha(vec[i]))
        vec[i].erase();
    else if (isupper(stringToChar(vec[i])))  //this is where your error was. use visual studio to debug your application 
        vec[i] = charToString(tolower(stringToChar(vec[i])));
}

你想在一个让你的程序崩溃的奇怪角色上使用函数isupper。如果你使用else if语句,它会起作用,因为如果它不是alpha字符,它就不会尝试调用isupper()。

课程:使用Visual Studio调试模式

编辑:我相信你试图这样做isupper('{0}')。 isupper()显然不喜欢字符串终止符(它&#39; ll崩溃)