Reputation: 203
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
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
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