-2

I have a function that parses some input from std::cin and returns an integer value on success. I need to detect, based on the return value, if something went wrong when parsing input. Zero is a valid return. What can I use to differentiate between valid zero and "bad input"?

If I need to post code as an example, just let me know. Thanks!

[EDIT]

int parseInput(){
    int calculatedValue = 0;
    bool parseOk = true;
    /* Parse cin for valid input.*/
    if (parseOk) {
        /* Perform calculation. Can be zero */
    }
    return calculatedValue; // Any integer is valid
}
dustinnoe
  • 675
  • 5
  • 7
  • Often errors are returned as negative values, it's a widely used de-facto convention. You could use an enum to describe the various possible errors. – tux3 Mar 01 '15 at 12:26
  • 1
    _"If I need to post code as an example, just let me know"_ Yes, you should. As for your question, you can throw an exception for example or have a separate output parameter and return `bool` – πάντα ῥεῖ Mar 01 '15 at 12:26
  • You need to reserve a special integer for bad input – Thiyagu Mar 01 '15 at 12:26
  • @tux3 And what if negative values are in range of allowed inputs as well? – πάντα ῥεῖ Mar 01 '15 at 12:27
  • You can probably test if (std::cin) – Captain Giraffe Mar 01 '15 at 12:27
  • have you considered throwing an exception? – David Haim Mar 01 '15 at 12:31
  • return -1 for error, >=0 for success – thang Mar 01 '15 at 12:31
  • @thang What if negative values are valid return as already suggested – Thiyagu Mar 01 '15 at 12:32
  • @πάνταῥεῖ then I misunderstood the question. – tux3 Mar 01 '15 at 12:34
  • @tux3 Well, the OP left that point unclear. In general `-1` is a valid input for `std::cin >> int_var;` – πάντα ῥεῖ Mar 01 '15 at 12:36
  • Using a sentinel value usually winds up being a bad idea. A negative value might not be valid today, but functionality tends to change over time. Someday it might become a perfectly valid value and, all of a sudden, some things don't seem to work anymore. Also, programmers tend to be lazy, if a function returns a value, they will tend to just use the value and not bother to check if it's in a valid range. At least by using `std::optional` or an exception, they are forced to acknowledge that there could have been an error. They may still ignore it, but they are aware of it. – Ferruccio Mar 01 '15 at 14:32

4 Answers4

7

This would be the perfect job for std::optional. Your best alternative, with regards to notify at return value, is to implement a similar class.

Alternatively, you should really use an exception. Exceptions are made exactly to notify the user of your function that something went wrong.

Shoe
  • 74,840
  • 36
  • 166
  • 272
2

You can use an boolean flag for checking if something went wrong, it is common practice (for instance, Qt library uses it) to do something like:

int getIntegerStuffFromInput(bool & ok); 

or

bool getIntegerStuffFromInput(int & value);
Яois
  • 3,838
  • 4
  • 28
  • 50
1

When you read numbers from std::cin, the most important thing is not to read directly into an int. Instead, you use std::getline to read a whole line of input into an std::string. This way you can detect wrong input much more easily.

Once the line has been entered, you convert the resulting std::string to an int.

std::string input_line;
std::getline(std::cin, input_line);
// input_line now contains a whole line of input

In C++11, you just use std::stoi for the conversion:

int const input = std::stoi(input_line);

This function will throw an exception if the string cannot be converted to an integer number.

In pre-C++11, you use std::istringstream:

std::istringstream is(input_line);
int input = 0;
is >> input;

The following code then checks if the line could be correctly converted to an integer number or not:

if (!is)
{
    // error
}
Christian Hackl
  • 27,051
  • 3
  • 32
  • 62
  • 1
    What's wrong with `if(!(std::cin >> input)) { /* handle bad input*/ }` totally depends on (not further given) context IMHO. – πάντα ῥεῖ Mar 01 '15 at 13:07
  • @πάνταῥεῖ: Reading a whole line will make it easier to catch wrong input like "1 22" when "122" was intended. Granted, my examples do not show such sophisticated error handling, but reading whole lines is just better practice in general IMHO. – Christian Hackl Mar 01 '15 at 13:18
  • Well, I have to agree it gives a better possibility to check what exactly is going on: http://stackoverflow.com/a/26027067/1413395 – πάντα ῥεῖ Mar 01 '15 at 13:22
0

"What can I use to differentiate between valid zero and "bad input"?"

You have basically three choices

If you need to handle all integers as a valid return value:

  1. Throw an exception, that can be handled outside from your function call
  2. Have a dedicated output parameter passed by reference, and return bool from your function, false indicates bad input.

If negative integers aren't a valid return value:

Just return a negative value and test for result < 0.

πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190