Dustin Burns
Dustin Burns

Reputation: 203

Input validation conundrum

I just wrote a pretty simple input validation algorithm. I thought it was pretty good, but when I was testing it I saw something I didn't understand. Here is the code first.

#include <iostream>
#include <cstdlib>
#include <sstream>
#include <string>

using namespace std;

int main()
{
cout << "Simple Menu"
    << "\n\t\t1. Input"
    << "\n\t\t2. Exit" << endl;

string input = "";

int myNum = 0;

char myChar = {0};

do
{
    cout << "Please enter a valid menu option: ";
    getline(cin,input);

    if (!(stringstream(input) >> myNum))
    {
        cout << "Please enter a valid menu option: ";
        getline(cin,input);
    }           

}while(myNum < 1 || myNum > 5 || input.length() != 1);

cout << "\nThe menu option you entered is: " << myNum << endl << endl;

return 0;       
}

Turns out, if I put .1 in as a choice it asks me to enter a valid option, which is good. However, if I enter 2 (a valid option) immediately following entering .1, it still reacts as though I put in a bad value. Here is the console window for such an event:

Simple Menu
                1. Input
                2. Exit
Please enter a valid menu option: .1
Please enter a valid menu option: 2
Please enter a valid menu option: 2

The menu option you entered is: 2

Press any key to continue . . .

Any idea why this is?

Upvotes: 0

Views: 477

Answers (2)

Wug
Wug

Reputation: 13196

Your current code:

do
{
    cout << "Please enter a valid menu option: ";    // first prompt
    getline(cin,input);                              // you enter .1

    if (!(stringstream(input) >> myNum))
    {
        cout << "Please enter a valid menu option: ";// second prompt
        getline(cin,input);                          // this data is discarded
    }           

}while(myNum < 1 || myNum > 5 || input.length() != 1);

Change to:

do
{
    cout << "Please enter a valid menu option: "; // first prompt
    getline(cin,input);                           // .1

    if (!(stringstream(input) >> myNum)) continue;// if parsing fails loop back
} while(myNum < 1 || myNum > 5 || input.length() != 1);

Simplify further to:

myNum = -1;
do
{
    cout << "Please enter a valid menu option: "; // first prompt
    getline(cin,input);                           // .1

    stringstream(input) >> myNum;
} while(myNum < 1 || myNum > 5);

Upvotes: 3

dchhetri
dchhetri

Reputation: 7136

Trace out your logic, its doing what you told it todo. What you want is something like so

string input;
int myNum = -1;
while(myNum < 1 || myNum > 5 || input.length != 1){
    cout << "Please pick a valid menu options: ";
    getline(cin,input);
    stringstream parser(input);
    if(! (parser >> input )){
       input.clear();
       myNum = -1;
    }  
}

Upvotes: 1

Related Questions