views:

106

answers:

3

Doesn't C++ offer any guarantee about keeping variables intact on input failure? With older versions of gcc, a program like this one keeps the -1 value of i on failure (for instance if a letter is typed instead of a number on input). With Ubuntu 10.10 (gcc 4.4.5), i is reset to zero in case of input failure.

#include <iostream>

int main()
{
 int i = -1;
 std::cin >> i;
 std::cout << "i = " << i << '\n';
 return 0;
}

This behavior breaks a lot of my code. I suppose the gcc people know what they are doing, and it is likely to be my mistake. If anyone knows the standard, I'd like to know what it says about this situation.

Thanks.

+2  A: 

Don't rely on the variable. Rely on the state of the stream:

if (std::cin >> i) // "if (!std::cin.fail())" would also work
{
    // ok
}
else
{
    // error
}


As for why the behavior has changed, that's because the C++ standard has evolved:

From C++03:

If an error occurs, val is unchanged; otherwise it is set to the resulting value.

From C++0x (well.. from the last draft I have access to):

The numeric value to be stored can be one of:

  • zero, if the conversion function fails to convert the entire field.
  • the most positive (or negative) representable value, if the field to be converted to a signed integer type represents a value too large positive (or negative) to be represented in val.
  • the most positive representable value, if the field to be converted to an unsigned integer type represents a value that cannot be represented in val.
  • the converted value, otherwise.
Samuel_xL
Yes, thanks. My main question is does the C++ standard specify this behaviour, and where?
Rémi
@Rémi I understand. I've edited my answer
Samuel_xL
Thanks, that answers my question.
Rémi
+1  A: 

If you want a failed stream-in not to affect your variable and you don't want it to put the stream into a failed state, then stream in to a string, parse the string into a temporary and if all that succeeds, continue.

You can parse the string into a temporary using istringstream.

CashCow
+1  A: 

The C++ standard has changed in the required behaviour for this case. The requirements can be found in [lib.facet.num.get.virtuals] (22.2.2.1.2 in C++03, 22.4.2.1.2 in C++0x)

In C++03, the requirement is that the old value is unchanged in case of an error.
In C++0x, the requirement is that the value 0 is stored in case of a conversion error.

Bart van Ingen Schenau