5

信じられないほど単純なコードであるべきものに問題があります。エラーチェックで1から3までの整数を取り込みたい。大きすぎたり小さすぎたりする数値のチェックには問題なく機能しますが、アルファと数値の組み合わせが入力されると、無限ループに陥ります。提案?

#include <iostream>
using namespace std;

int main(int argc, char *argv[]){
    int input;

    cout << "\nPlease enter a number from 1 to 3:" << endl;
    cout << "-> ";
    cin >> input;

    while(input< 1 || input> 3){
        cout << "\n---------------------------------------" << endl;
        cout << "\n[!] The number you entered was invalid." << endl;
        cout << "\nPlease re-enter a number from 1 to 3" << endl;
        cout << "-> ";
        cin >> input;
    }

    cout << "You chose " << input << endl;
}
4

4 に答える 4

8

問題はそれです:

cin >> input;

数値以外の値を読み取ろうとすると、不良ビットが設定されます。その後、 を使用しようとしてもoperator>>黙って無視されます。

したがって、これを修正する方法は、ストリームが良好な状態にあるかどうかをテストし、そうでない場合は状態フラグをリセットして、もう一度読み取りを試みることです。ただし、(問題の原因となった) 不良な入力がまだ入力にあることに注意してください。

if (cin >> input)
{
    // It worked (input is now in a good state)
}
else
{
    // input is in a bad state.
    // So first clear the state.
    cin.clear();

    // Now you must get rid of the bad input.
    // Personally I would just ignore the rest of the line
    cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

    // now that you have reset the stream you can go back and try and read again.
}

(不良ビットが設定されていることが原因で) スタックするのを防ぐには、文字列に読み取ってから、文字列ストリームを使用してユーザー入力を解析します。また、さまざまなスタイルの読み取りを簡単に組み合わせることができるため (つまり、組み合わせて、文字列ストリームでこれらを使用できるため)、この方法 (ユーザーの対話型入力用) を好みoperator>>ますstd::getline()

#include <iostream>
#include <sstream>
#include <string>
// using namespace std;
// Try to stop using this.
// For anything other than a toy program it becomes a problem.

int main(int argc, char *argv[])
{
    int          input;

    std::string  line;
    while(std::getline(std::cin, line))   // read a line at a time for parsing.
    {
        std::stringstream linestream(line);
        if (!(linestream >> input))
        {
             // input was not a number
             // Error message and try again
             continue;
        }
        if ((input < 1) || (input > 3))
        {
             // Error out of range
             // Message and try again
             continue;
        }
        char errorTest;
        if (linestream >> errorTest)
        {
             // There was extra stuff on the same line.
             // ie sobody typed 2x<enter>
             // Error Message;
             continue;
        }

        // it worked perfectly.
        // The value is now in input.
        // So break out of the loop. 
        break;
    }
}
于 2012-11-03T18:28:55.003 に答える
2
#include <iostream>
#include <string>

using namespace std;

int validatedInput(int min = 1, int max = 3)
{
    while(true)
    {
        cout << "Enter a number: ";
        string s;
        getline(cin,s);
        char *endp = 0;
        int ret = strtol(s.c_str(),&endp,10);
        if(endp!=s.c_str() && !*endp && ret >= min && ret <= max)
            return ret;
        cout << "Invalid input. Allowed range: " << min << "-" << max <<endl;
    }
}

int main(int argc, char *argv[])
{
    int val = validatedInput();
    cout << "You entered " << val <<endl;
    return 0;
}
于 2012-11-03T18:35:58.493 に答える
0

入力を int として宣言しましたが、英数字を入力に書き込むと、暗黙的に整数に変換しようとします。しかし、エラーチェックはこれを考慮していません。

この問題は、while ループを変更することで簡単に解決できます。これをチェックする代わりに、チェックしてみませんか

while(input!=1 || input!=2 || input!=3)
于 2012-11-03T18:28:22.213 に答える