整数输入验证,怎么样?

Ric*_*Sch 5 c++ error-handling integer infinite-loop

我遇到了一个非常简单的代码问题.我想接受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;
}
Run Code Online (Sandbox Code Playgroud)

Mar*_*ork 8

问题是:

cin >> input;
Run Code Online (Sandbox Code Playgroud)

当您尝试读取非数字值时,将导致设置坏位.在那之后,任何使用它的尝试都会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.
}
Run Code Online (Sandbox Code Playgroud)

为了防止它被卡住(这是由设置的坏位引起)读入字符串然后使用字符串流来解析用户输入.我也更喜欢这种方法(用于用户交互式输入),因为它允许更容易地组合不同类型的阅读(即组合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;
    }
}
Run Code Online (Sandbox Code Playgroud)

  • @MikaelMello:谢谢.固定. (2认同)