Reputation: 3127
I am new to C++ and I come from a Delphi scenario, in which I was able to catch exceptions even without having to declare an explicit throw
. Look at here:
#include<iostream>
#include<exception>
int main() {
try {
int c;
std::cin >> c;
} catch(...) {
std::cerr << "Warning!" << std::endl;
char xz; std::cin >> xz;
return 1;
}
char z; std::cin >> z;
return 0;
}
//I return 1 because UNIX OS cares about this, a return != 0 means that Huston we have a problem
I have seen around that some exception (such as division by zero) aren't automatically caught, so I have to create a throw
by myself that will be caught for sure in my try-block.
If you look at the code above, when I first input 6.7
or test
I should be able to see on the output warning!
, but nothing. I am running on a Windows 10 machine.
I know that the catch(...)
is the general one and gives me for sure the protection, but why isn't it catching the wrong input?
Note. I have mentioned Delphi above because if you look at the code below, I am able to catch the error.
try
a := StrToInt('6.78'); //conversion error [string->double], a is int
ShowMessage('a is ' + a.ToString);
except
on E: Exception do
ShowMessage('Warning! > ' + e.Message);
//^ raises "Warning! > '6.78' is not a valid integer value."
end;
Why cannot I produce the same effect with C++? I know that they are two different languages, but at first I'd say that delphi "treats" exceptions better. For example it catches automatically the division by zero (see below) while c++ doesnt.
//this raises the "Division by zero" error.
a := 8 div StrToInt('0');
Conclusion. So the questions are: am I declaring the C++ try-catch
correctly? Do I always have to use the throw
to be sure that the error will be caught or I can omit it some times?
Upvotes: 1
Views: 2700
Reputation: 4853
std::cin
won't throw when the user inputs an invalid type.
Assuming C++11 and higher, the behaviour is as follows:
If extraction fails, zero is written to value and failbit is set. If extraction results in the value too large or too small to fit in value, std::numeric_limits::max() or std::numeric_limits::min() is written and failbit flag is set.
from std::basic_istream::operator>>
.
To check if the input is invalid you should do as follows:
#include <cstdint>
#include <iostream>
std::int32_t main()
{
std::int32_t example;
std::cin >> example;
if (std::cin.fail())
{
std::cout << "Invalid input" << std::endl;
}
}
Or you can also do it like this:
#include <cstdint>
#include <iostream>
std::int32_t main()
{
std::int32_t example;
if (!(std::cin >> example))
{
std::cout << "Invalid input" << std::endl;
}
}
Upvotes: 8
Reputation: 44258
As stated in documentation you need to set exception mask on std::cin
to make it throw std::ios_base::failure
:
#include <iostream>
int main() {
std::cin.exceptions( std::ios::failbit );
try {
int i = 0;
std::cin >> i;
std::cout << "i=" << i << std::endl;
}
catch(...) {
std::cerr << "error!" << std::endl;
}
return 0;
}
Do I always have to use the throw to be sure that the error will be caught or I can omit it some times?
Yes for exception to be thrown you need to call throw
. Though libraries may call throw for you for error conditions (including standard one), what exception it may throw and when should be stated in the documentation.
Upvotes: 9