简体   繁体   中英

C++ input validation: how to accept only certain ints

I wanted the user to input 1, 2, 3, or 4, and ONLY those numbers. I do not want: 5, 79, 4rf, 1XXXXX, 2!, abc 1234, etc.

If I use 'cin >> ', then it would cut off the input to something like '2!' to the 2 and leave the '!' in for the next input, so getline() is preferable. The code I have listed technically works, but leaves an extra line of input when I ask again for another input after the user put in a invalid one.

Thank you for the help.

bool check = true;
string input;
int choice;

cout << "Please enter 1, 2, 3, or 4:" << endl;
getline(cin, input);

do
{
  check = true;
  if (input.length() != 1 || !isdigit(input[0]))
  {
     cout << "error, enter a valid input" << endl;
     check = false;
     cin.clear();
     cin.ignore(INT_MAX, '\n');
     getline(cin, input);
  }
  else
  {
     choice = stoi(input);
     if (!(choice == 1 || choice == 2 || choice == 3 || choice == 4))
     {
        cout << "error, enter a valid input" << endl;
        check = false;
        cin.clear();
        cin.ignore(INT_MAX, '\n');
        getline(cin, input);
     }
     else
     {
        check = true;
     }
  }

} while (check == false);

getline(cin, input); consumes an entire line or fails, and failure for getline on cin is pretty much the end of cin . If you got data at all, you got the whole line. There is nothing for cin.ignore(INT_MAX, '\\n'); to ignore, so the user winds up having to hit enter again before they can get to the getline(cin, input); retry.

Keeping your basic stricture, I'd clean it up to something more like

bool check = false; // assume failure
string input;
int choice;

cout << "Please enter 1, 2, 3, or 4:" << endl;

while (!check)
{
    if (getline(cin, input)) // test that we got something
    {
        if (input.length() != 1 || !isdigit(input[0]))
        {
            cout << "error, enter a valid input" << endl;
            // don't need to do anything else here
        }
        else
        {
            choice = input[0] - '0'; // easier conversion
            if (!(choice == 1 || choice == 2 || choice == 3 || choice == 4))
            {
                cout << "error, enter a valid input" << endl;
                // don't need to do anything else here
            }
            else
            {
                check = true; // all done
            }
        }
    }
    else
    {
        // to be honest there isn't much you can do here. You can clear and 
        // ignore, but it's hard to make unformatted input fail and still 
        // have a viable console. Maybe you should throw an exception, but 
        // for a simple program I'm all for giving up. 
        cerr << "Aaaaaaahhhhrrrg!\n";
        exit(-1);
    }

} 

I'm assuming failure because I only have one place I need to set the check flag: On success! This makes it a bit easier to pick this code up and put it in a function so you can reuse it more easily. Make the loop go forever and replace check = true; with return choice; .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM