This is covered in the isocpp.org faq. It recommends using a loop in the form of while (std::cin >> i)
so that the loop terminates if extraction fails. Extraction will continue to fail because std::cin
does not extract the invalid characters from the input stream. To discard these, you need to use std::cin.ignore
. Generally, you can put an arbitrarily large number as the first argument, but it is idiomatic to use std::numeric_limits<std::streamsize>::max()
(#include <limits>
) instead.
The loop can be succinctly written as:
while(!(std::cin >> choice) || (choice < 0) || (choice > 6)) {
cout << "Invalid choice." << endl;
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
Alternatively, you can put the prompt in the loop condition:
while((std::cout << "Selection: ")
&& (!(std::cin >> choice) || (choice < 0) || (choice > 6))) {
cout << "Invalid choice." << endl;
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
There is no need for an "invalid character" diagnostic because that is covered by !(std::cin >> choice)
. Example run:
Selection: a
Invalid choice.
Selection: b
Invalid choice.
Selection: c
Invalid choice.
Selection: d
Invalid choice.
Selection: 15
Invalid choice.
Selection: 10
Invalid choice.
Selection: 5