std::cin doesn't throw an exception on bad input
C++ iostreams don't use exceptions unless you tell them to, with cin.exceptions( /* conditions for exception */ )
.
But your code flow is more natural without the exception. Just do if (!(cin >> input))
, etc.
Also remember to clear the failure bit before trying again.
The whole thing can be:
int main()
{
int input;
do {
cout << "Please enter an integral value \n";
cin.clear();
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
} while(!(cin >> input));
cout << input;
return 0;
}
While loop with try catch fails at bad cin input
You should think carefully what you want to do if user gives invalid input in this case. Usually in these cases the best solution is to read one line from the input and throw it away.
Try putting cin.clear()
and std::cin.ignore(std::numeric_limits<streamsize>::max(),'\n');
in your catch clause. cin.clear()
clears the failure state in cin, and cin.ignore()
throws away rest of the line waiting in the input buffer.
(And yes, you probably should rethink your use of exceptions).
How to handle wrong data type input
The reason the program goes into an infinite loop is because std::cin
's bad input flag is set due to the input failing. The thing to do is to clear that flag and discard the bad input from the input buffer.
//executes loop if the input fails (e.g., no characters were read)
while (std::cout << "Enter a number" && !(std::cin >> num)) {
std::cin.clear(); //clear bad input flag
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); //discard input
std::cout << "Invalid input; please re-enter.\n";
}
See the C++ FAQ for this, and other examples, including adding a minimum and/or maximum into the condition.
Another way would be to get the input as a string and convert it to an integer with std::stoi
or some other method that allows checking the conversion.
standard input stream cin failing to prompt for input
12e is interpreted as the begin of a floating point number like 12e03. But the end is missing, so your stream is put on error (failbit). This state causes all subsequent input to fail until the failstate is cleared.
You could have an inner loop that checks such formatting errors:
while (...) {
...
while ( (cin >> x >> currency).fail() && !cin.eof()) { // loops as long as there's input and it's invalid
cout << "invalid format";
cin.clear();
}
if (cin.eof()) // if there's no longer input stop looping
break;
...
}
live demo
Note that you should initialize currency
to something different than 'q' if you want to make sure that your loop is executed in every circumstance.
By the way, if you enter 12 e (with a space), 12 will be interpreted as the number and put to x and e to currency, as you expect.
Exception doesn't continue loop correctly
Bad input sets the failbit
but doesn't throw exception by default.
you might use basic_ios::exceptions to have exception:
std::cin.exceptions(std::ifstream::failbit);
int numItems;
try
{
std::cout << "How many items to store?" << std::endl;
std::cin >> numItems;
if(numItems<0)
throw "Invalid Number.";
}
catch (const std::exception& e)
{
std::cin.clear();
std::string line;
std::getline(std::cin, line);
std::cerr << "'" << line << "' is not a number\n";
// ...
}
catch (const char* negativeValue)
{
std::cout << negativeValue << std::endl;
return 1;
}
C++ advice on exception handling
You say "10 positive inputs", but you have int number;
. If your number
is going to be an integer, then it can't take fractions like 33.44
for instance, and it also can't be NaN
(so you wouldn't need to check for that). If you want to allow fractions, do double number
instead. That aside, the check could look like this:
for (int i = 0; i < 10; i++) {
std::cin >> number;
if (std::cin.fail()) {
std::cin.clear();
std::string input;
std::cin >> input;
std::cout << "input failed! Invalid input: " << input << std::endl;
return -1;
}
After every inputted number, you do the std::cin.fail()
check. If it failed, you can just return. In this example, I also made it print the invalid input. For that you need to call std::cin.clear();
to reset that error flag, and then you can put that invalid input into an std::string
(which should work, unlike with the number
). You need to include <string>
for that. If you don't need to print anything, you can just return
and forget about the clearing, the string and the output. Also, in this example, since the mess made by the invalid input is neatly cleaned up, you could take more (valid) inputs again if you don't return
instead.
Next, checking for negative numbers:
if (number < 0) {
std::cout << "Error: Negative number!" << std::endl;
return -1;
}
Finally, the NaN
check (for double
):
if (isnan(number)) {
std::cout << "Error: number is NaN!" << std::endl;
return -1;
}
You need to include <math.h>
for the isnan
.
Putting it all together, it could look like this:
#include <iostream>
#include <string> // std::istream >> std::string
#include <math.h> // isnan
int main() {
double number;
for (int i = 0; i < 10; i++) {
std::cin >> number;
if (std::cin.fail()) {
std::cin.clear();
std::string input;
std::cin >> input;
std::cout << "input failed! Invalid input: " << input << std::endl;
return -1;
}
if (number < 0) {
std::cout << "Error: Negative number!" << std::endl;
return -1;
}
if (isnan(number)) {
std::cout << "Error: number is NaN!" << std::endl;
return -1;
}
}
return 0;
}
How to catch invalid input in c++?
You will need to #include <limits>
int x;
std::cout << "Enter a number: ";
std::cin >> x;
while(std::cin.fail()) {
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(),'\n');
std::cout << "Bad entry. Enter a NUMBER: ";
std::cin >> x;
}
std::cout << "x = " << x << std::endl;
There's a template for you.
Related Topics
How to Alter Qt Widgets in Winapi Threads
Why Is There No Piecewise Tuple Construction
How to Iterate Through Every Possible Combination of N Playing Cards
How to Keep My Topmost Window on Top
Initializing a Vector of Vectors Having a Fixed Size with Boost Assign
How Are Exceptions Implemented Under the Hood
How Does Intel Tbb's Scalable_Allocator Work
How to #Include When There Is a Circular Dependency
Do You Know Tool Building Tree of Include Files in Project\File
Project Euler Problem 12 - C++
How to Treat a Specific Warning as an Error
Wait for Input for a Certain Time