首页 文章

更长的获取线cin输入的问题

提问于
浏览
2

我正在编写一个C程序,要求用户输入一个单词或句子,通过单词/句子,用'aoa'或'AoA'替换'a'或'A'的所有实例,然后输出结果 . 但是,如果我尝试输入更长的句子,我就会遇到问题 . 例如,如果我输入“为什么程序不会运行”,程序会输出奇怪的字母而不是预期的结果 . 这是我的代码:

#include <iostream>
#include <string>

using namespace std;

int main(int argc, const char * argv[])
{
string mening, temp; //The mening string is the word/sentence the user will input.
int play = 1, add;

while (play == 1) {
cout<<"Type in the sentence: ";

getline(cin, mening); //The input is saved in the string variable mening.

unsigned long y = mening.size(); //Grabs the amount of characters in input; this number is saved in the unsigned long variable y.
add = 0; //Makes sure the int variable add is reset to 0 if the loop restarts.

for (int k = 0, n = 1;n<=y;k++, n++) {
    if (mening[k] == 'a' || mening[k] == 'A') {
        k++;


        for (int i = k, m = 1;m<=y - n;i++, m++) {
            temp[i] = mening[i];
        } //The characters after the one that has been checked are stored in temp array indexes, if the character that has been checked is an a or A.

        for (int i = k, m = 1, j = k + 2;m<=y - n;i++, m++, j++) {
            mening[j] = temp[i];
        } //The characters after the one that has been checked move two steps to the right, to allow the two extra letters.

        mening[k] = 'o';
        mening[k + 1] = mening[k - 1];

        k++;

        add = add + 2; //The int variable add is increased by 2 during each aoa/AoA to avoid strange characters being outputted at the very end.

    }
    else { }

}

for (int k = 0;k<=y + add - 1;k++) {
    cout<<mening[k];
}

cout<<endl<<"Do you want to do it again? (yes/no): ";

getline(cin, mening);

    cin.clear();
    cout << flush;
    cout.flush();
    cout.clear();

if (mening == "Yes" || mening == "yes" || mening == "YES") {

}
else {
    play = 2;
}
}


cout<<endl<<"The program will now close.";

return 0;
}

可能导致问题的原因是什么?

4 回答

  • 0

    一个直接的问题是你从 [1,n] 索引,而C( std::stringstd::vector ,但也是C样式数组)使用 [0,n) . 这意味着'll access beyond the end of the string. And you'将字符存储到带有 temp[x]temp 中,尽管 temp 的大小始终为0.这两种都是未定义的行为,这可能会产生任何影响(包括崩溃程序) .

    在开发代码时应该使用标准库的调试模式 . 在Visual Studios中,我认为这是默认值;使用g,您需要将 -D_GLIBCXX_CONCEPT_CHECKS -D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_PEDANTIC 添加到命令行 .

    处理此问题的最简单方法是复制到新字符串中,随时进行更改:

    std::string results;
    for ( auto current = mening.cbegin(); current != mening.cend(); ++ current ) {
        switch ( *current ) {
        case 'a':
            results += "aoa";
            break;
    
        case 'A':
            results += "AoA";
            break;
    
        default:
            results += *current;
            break;
        }
    }
    

    如果你确实想要进行替换,那就太棘手了 . 当您插入的文本多于开头时,迭代器将失效 . 所以你需要这样的东西:

    static std::string const Ao( "Ao" );
    static std::string const ao( "ao" );
    for ( auto current = mening.begin(); current != mening.end(); ++ current ) {
        switch ( *current ) {
        case 'a':
            current = mening.insert( current, ao.begin(), ao.end() ) + 2;
            break;
    
        case 'A':
            current = mening.insert( current, Ao.begin(), Ao.end() ) + 2;
            break;
        }
    }
    

    就个人而言,我赞成复制到一个新的字符串 .

  • 0

    我建议你应该使用标准函数 std::string::insert 来插入字符 'oA''oa' . 它将使您的代码更易于处理和调试 .

    或者你可以这样做:

    #include <iostream>
    #include <string>
    
    using namespace std;
    
    int main(int argc, const char * argv[])
    {
    string mening, temp; //The mening string is the word/sentence the user will input.
    int play = 1, add;
    
    while (play == 1) {
    cout<<"Type in the sentence: ";
    
    getline(cin, mening); //The input is saved in the string variable mening.
    
    unsigned long y = mening.size(); //Grabs the amount of characters in input; this number is saved in the unsigned long variable y.
    add = 0; //Makes sure the int variable add is reset to 0 if the loop restarts.
    
    for (int n = 0; n<y; n++ ) {
        cout << mening[n];
        if (mening[n] == 'a' || mening[n] == 'A') 
            cout << "o" << mening[n];
    }
    
    cout<<endl<<"Do you want to do it again? (yes/no): ";
    
    getline(cin, mening);
    
        cin.clear();
        cout << flush;
        cout.flush();
        cout.clear();
    
    if (mening == "Yes" || mening == "yes" || mening == "YES") {
    
    }
    else {
        play = 2;
    }
    }
    
    
    cout<<endl<<"The program will now close.";
    
    return 0;
    }
    
  • 0
    #include <iostream>
    #include <string>
    
    
    std::string ReplaceA(std::string s) {
        std::string temp = "";
        for (unsigned int k = 0; k < s.size(); k++) {
            if (s[k] == 'a' || s[k] == 'A') {
                temp = temp + s[k];
                temp = temp + "o";
                temp = temp + s[k];
                }
                else { 
                    temp = temp + s[k];
                }
    
            }
        return temp;
    }
    
    int main(int argc, const char * argv[])
    {
        std::string mening; //The mening string is the word/sentence the user will input.
        int play = 1;
    
        while (play == 1) {
            std::cout<<"Type in the sentence: ";
    
            getline(std::cin, mening); //The input is saved in the string variable mening.
    
            std::cout << ReplaceA(mening) << std::endl;
    
            std::cout << "Do you want to do it again? (yes/no): ";
    
            std::cin >> mening;
            if( std::cin.fail() || ( mening != "yes" && mening != "no" ) ) {
                std::cout << "Bad Input\nDo you want to do it again? (yes/no): ";
                std::cin.clear();
                std::cin.ignore('256','\n');
                std::cin >> mening;
            }else{
                if(mening == "no") break;
            }
            std::cin.clear();
            std::cin.ignore('256','\n');
    
        }
    
    
        std::cout << "The program will now close.";
    
        return 0;
    }
    

    更有条理,具有处理返回字符串的转换的函数 .

    你也可以尝试这个功能,两个都工作,一个似乎有点漂亮 .

    std::string ReplaceA(std::string s) {
        std::string temp = "";
        for(std::string::iterator k = s.begin(); k != s.end(); k++) {
            switch(*k) {
            case 'a': temp += "aoa"; break;
            case 'A': temp += "AoA"; break;
            default: temp += *k; break;
            }
        }
        return temp;
    }
    
  • 1

    实际上有一个尾随字符'\ n'来自最后一个cin >>,所以getline取这个'\ n'字符并被终止;在getline之前忽略缓冲区的内容......

    cin.ignore();
    getling(cin,string_name)

相关问题