Silently passing wrong input for good one

Hi there,
the program below, when compiled with GCC 4.0.2 and given the input "-3e-abcd", prints
input = `-3e-abcd' good f = -3 left = `abcd'
which means that:
- if you give "-3e-abcd" to a `cin >> f', the double -3.0 is read; - the characters "-3e-" are eaten; - the status of `cin' is set to "good".
I was unable to understand whether this behavior is conforming or even mandated by the standard. To me it does not look good, for the reason that "-3e-", the string eaten, would not seem to be a valid floating point numeral. Nonetheless, the status is set to good.
For comparison, wit Comeau C++ I get
$ como z.cc Comeau C/C++ 4.3.3 (Oct 24 2003 16:00:23) for RedHat_LINUX_INTEL_ELF Copyright 1988-2003 Comeau Computing. All rights reserved. MODE:non-strict warnings C++
$ a.out -3e-abcd input = `-3e-abcd' fail left = `abcd'
At least here the programmer has a way to know that the input was wrong, something that, with the behavior of libstdc++, would seem impossible (since an extra "e-" has been silently and undetectably eaten).
So the question is: are both behaviors conforming to the standard? It not, who is wrong? If yes, isn't the behavior of Comeau's library more robust and useful? All the best,
Roberto
#include <string> #include <iostream> #include <sstream>
using namespace std;
int main() { char input[200]; cin.getline(input, sizeof(input)); cout << "input = `" << input << "'" << endl; stringstream in(input); double f = -123.456; in >> f; string s = "initialized"; if (in.eof()) cout << "eof" << endl; if (in.fail()) cout << "fail" << endl; if (in.good()) cout << "good" << endl; if (in.bad()) cout << "bad" << endl;
char left[200]; if (in) { cout << "f = " << f << endl; in.getline(left, sizeof(left)); cout << "left = `" << left << "'" << endl; } else { in.clear(); in.getline(left, sizeof(left)); cout << "left = `" << left << "'" << endl; } }

Hi Roberto,
the program below, when compiled with GCC 4.0.2 and given the input "-3e-abcd", prints
input = `-3e-abcd' good f = -3 left = `abcd'
I changed this behavior during the 3.4.x development cycle (3.3.x did behave like Comeau), see testcase num_get/get/char/10.cc. Basically, my rationale was that of matching as closely as possible the usual usage of scanf in C: if '-3e-' is handed to scanf, it definitely assigns -3.0 and the user happily proceeds.
Then, we come to the detailed interpretation of C++ 22.2.2.1.2/11, where it says: "would have caused scanf to report an input failure". In my reading of the C standard (frankly, I have available only C99, which sometimes is subtly different from C90, the real reference), an input failure is a very specific kind of failure (see 7.19.6.2/4), which may lead to scanf returning EOF (7.19.6.2/16).
Anyway, more generally, if I read again the entire 7.19.6.2 (in particular /9 is important when it defines an input item as *a prefix* of a matching input sequence), I don't see how possibly a scanf of a single float can *fail* (either input failure or matching failure) when '-3e-' is passed. Indeed, in practice, it assigns the value and returns 1, nothing externally visible signals that something went wrong.
Paolo.
participants (2)
-
Paolo Carlini
-
Roberto Bagnara