-1

I've this example:

int main() {

    int val{};
    bool stop = false;
    char c;

    while (!stop) {
        std::cout << "val: ";
        try {
            if (!(std::cin >> val)) {               
                throw std::runtime_error("bad input");
            }
            std::cout << val << " : " << val * val << std::endl;
        }
        catch (std::exception& e) {
            std::cout << e.what() << std::endl;
            std::cin.clear();
            std::cin.ignore(numeric_limits<std::streamsize>::max(), '\n');
            std::cout << "retry\?\n>>" << std::endl;
            std::cin >> c;
            if (c != 'y' && c != 'Y')
                stop = true;
        }

    }
}

The code works fine but I want to know should I use this in a real world program? Because I've seen some alternatives: getting the input as a string then using conversion to integral types.

  • My question: is Should I use exception handling for invalid input like characters where it should be integers.. or Just sue string and conversion?
Maestro
  • 2,512
  • 9
  • 24
  • 4
    IMHO, there is nothing exceptional about bad input so exceptions should not be used. – NathanOliver Aug 07 '19 at 12:38
  • 2
    There's nothing exceptional here, and a non-exception implementation would actually be shorter and clearer. –  Aug 07 '19 at 12:39
  • 2
    Well, it's a design choice, and in those cases, the answer depends on several factors in the real context. Anyway, why do you expect failure from `!std::cin`? – BiagioF Aug 07 '19 at 12:39
  • @BiagioFesta `std::cin` evaluates to true if the stream is in a good state. So `!std::cin` will be true when the stream is in a bad state – NathanOliver Aug 07 '19 at 12:40
  • 1
    Exceptions are very overused, and in cases such as this are mostly a goto that makes you feel good for not writing "goto". You can rewrite that as a straightforward `if-else`. – molbdnilo Aug 07 '19 at 12:42
  • @NathanOliver yeah I know it, I am just curious to know why to expect failure in `std::cin`. I said so because I don't think it is a good way to implement a *"input parser validator"* if that what it meant to be here – BiagioF Aug 07 '19 at 12:42
  • 1
    @Biagio It's not (directly) expecting failure on `std::cin`, it's expecting failure on the `>>` operation –  Aug 07 '19 at 12:44
  • FWIW, [this](https://stackoverflow.com/a/10829091/4342498) is how I would handle checking for bad numeric input. – NathanOliver Aug 07 '19 at 12:45
  • Thank you guys! But what if the error in input stream is other than invalid input like a system-level error? Doesn't this also need E.H? – Maestro Aug 07 '19 at 12:47
  • If you are writing serious input code (which you are probably not doing if you are using operator >>) then you should be looking at the individual stream status bits, such as `badbit` and in that case you might throw an exception, but it would be caught at the highest level of your code. Catching exceptions immediately after they are thrown is almost always wrong. –  Aug 07 '19 at 12:52
  • Alright, it the choice of the design. To me personally, I like to use the exception handling approach. In real-world programming, you might have tons of code and exception handling will benefit you. You can use this approach to throw your meaning full exception as necessary and centralize the logic in one place to handle those exception to communicate the message clearly to the user. In practical you might need to create your custom exception as well. For example ObjectNotFoundException, IllegalStateException, BadRequestException, .... – Sereysopheak Eap Aug 07 '19 at 16:55
  • @NathanOliver So you mean in a real program I can use this: `while(!(std::cin >> x)){ std::cin.clear(); std::cin.ignore(std::numeric_limits::max(), '\n');} std::cout << "x: " << x << std::endl;`? – Maestro Aug 07 '19 at 20:41
  • 1
    @Maestro Yes. Although that approach can potentially leave garbage in the buffer. If you input `5a` for instance then `while(!std::cin >> x)` will store the `5` in `x`, `cin` will be good so the condition will be false and the loop wont execute. That leaves `a` in the buffer and it will dirty the next input operation. If you use [this approach](https://stackoverflow.com/questions/10828937/how-to-make-cin-take-only-numbers/10829091#10829091) that can't happen. – NathanOliver Aug 07 '19 at 20:44
  • @NathanOliver: Thank you very much! – Maestro Aug 07 '19 at 20:45

1 Answers1

3

Snipped of your code showing the try/throw/catch in question:

    try {
        if (!(std::cin >> val)) {               
            throw std::runtime_error("bad input");
        }
        std::cout << val << " : " << val * val << std::endl;
    }
    catch (std::exception& e) {

For the provided example, you would not use a try/throw/catch in real world code. Usually, you would prefer the simplest code to read and understand and for this case it is much simpler to avoid exception handling alltogether and use if/else instead:

      if ((std::cin >> val)) {                  
        std::cout << val << " : " << val * val << std::endl;
      }
      else {
darune
  • 10,480
  • 2
  • 24
  • 62