Raffaele Rossi
Raffaele Rossi

Reputation: 3127

Catching exception without having to throw

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

Answers (2)

tambre
tambre

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

Slava
Slava

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;
}

live example

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

Related Questions