W
William Payne
Hello, when I was writing a user-driven test program for a data structure I
wrote, I encountered an annoying problem. The test program is laid out as a
menu with several numbered options. The user selects one option by typing in
its corresponding number (int). Depending on the choice he made, he may be
asked to provide another integer (or no input at all). So all the user does
is entering integers. I don't want the user to be able to cause problems or
crashes by providing invalid input, but he is despite my error checking.
Here follows output from my program here boiled down to a "minimum":
$ ./test
1 - choice one
2 - choice two
3 - exit program
What is your choice? 1
Enter integer to be doubled: 2+2
2 doubled is 4
1 - choice one
2 - choice two
3 - exit program
What is your choice? Enter integer to be squared:
In this test run the user presses 1 when asked for which choice he wants in
the menu. But when asked to input an integer he enters 2+2, and cin does not
go into an error state but leaves the last '2' plus a newline in the stream,
triggering a new menu option (the '+' was eaten by a call to cin.get() which
is supposed to get rid of the newline. Now how can I fix my code so it
doesn't allow this? And why doesn't cin choke on 2+2 when asked to enter an
integer?
#include <iostream>
#include <limits>
#include <string>
int enter_integer(const std::string& prompt);
int main()
{
std::string prompt;
while(true)
{
std::cout << "1 - choice one" << std::endl;
std::cout << "2 - choice two" << std::endl;
std::cout << "3 - exit program" << std::endl;
int n = enter_integer("What is your choice? ");
switch(n)
{
case 1:
n = enter_integer("Enter integer to be doubled: ");
std::cout << n << " doubled is " << n * 2 << std::endl;
break;
case 2:
n = enter_integer("Enter integer to be squared: ");
std::cout << n << " squared is " << n * n << std::endl;
break;
case 3:
return 0;
default:
std::cout << n << " is an invalid menu choice." << std::endl;
}
}
}
int enter_integer(const std::string& prompt)
{
while(true)
{
std::cout << prompt << std::flush;
int n;
std::cin >> n;
if(!std::cin)
{
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(),
'\n');
std::cout << "You must enter an integer!" << std::endl;
}
else
{
std::cin.get(); /* Get rid of newline in the stream. */
return n;
}
}
return -1; /* Should never be reached. */
}
/ William Payne
wrote, I encountered an annoying problem. The test program is laid out as a
menu with several numbered options. The user selects one option by typing in
its corresponding number (int). Depending on the choice he made, he may be
asked to provide another integer (or no input at all). So all the user does
is entering integers. I don't want the user to be able to cause problems or
crashes by providing invalid input, but he is despite my error checking.
Here follows output from my program here boiled down to a "minimum":
$ ./test
1 - choice one
2 - choice two
3 - exit program
What is your choice? 1
Enter integer to be doubled: 2+2
2 doubled is 4
1 - choice one
2 - choice two
3 - exit program
What is your choice? Enter integer to be squared:
In this test run the user presses 1 when asked for which choice he wants in
the menu. But when asked to input an integer he enters 2+2, and cin does not
go into an error state but leaves the last '2' plus a newline in the stream,
triggering a new menu option (the '+' was eaten by a call to cin.get() which
is supposed to get rid of the newline. Now how can I fix my code so it
doesn't allow this? And why doesn't cin choke on 2+2 when asked to enter an
integer?
#include <iostream>
#include <limits>
#include <string>
int enter_integer(const std::string& prompt);
int main()
{
std::string prompt;
while(true)
{
std::cout << "1 - choice one" << std::endl;
std::cout << "2 - choice two" << std::endl;
std::cout << "3 - exit program" << std::endl;
int n = enter_integer("What is your choice? ");
switch(n)
{
case 1:
n = enter_integer("Enter integer to be doubled: ");
std::cout << n << " doubled is " << n * 2 << std::endl;
break;
case 2:
n = enter_integer("Enter integer to be squared: ");
std::cout << n << " squared is " << n * n << std::endl;
break;
case 3:
return 0;
default:
std::cout << n << " is an invalid menu choice." << std::endl;
}
}
}
int enter_integer(const std::string& prompt)
{
while(true)
{
std::cout << prompt << std::flush;
int n;
std::cin >> n;
if(!std::cin)
{
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(),
'\n');
std::cout << "You must enter an integer!" << std::endl;
}
else
{
std::cin.get(); /* Get rid of newline in the stream. */
return n;
}
}
return -1; /* Should never be reached. */
}
/ William Payne