This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

A problem with cin or strtod?


Hi.

        I ran into a problem where (cin >> x) for double x reads in
NaN as a double, even though this seems not to be in accordance with
the C++ standard.  It seems to me that the problem is either with cin
(in g++) or strtod(3) (in glibc), and since I don't have the C and C++
standards in front of me, I'm not quite sure which of them is the
problematic element.  Therefore, I am sending this to the bug streams
for both g++ and glibc.

I began with the following code to read names and student grades and
just print them out again:

-------------------------------------------------------
dkatz@magellan:~/ac++/ch05/5-2$ cat data
Smith 93 91 47 90 92 73 100 87
Carpenter 75 90 87 92 93 60 0 98
nand 78 66 65 69 64 68 63 61
Foo 33 45 66 67 43 42 31 16
Nancy 12 23 34 34 45 14 23 12
-------------------------------------------------------


-------------------------------------------------------
#include <iostream>
#include <string>

using std::cin;
using std::cout;
using std::endl;
using std::string;

int main()
{
    string name;
    while (cin >> name) {
	cout << name << " ";	// print the student's name
	if (cin) {
	    double x;
	    while (cin >> x)	// print out all the doubles as grades
		cout << x << " ";
	    
	    cin.clear();        /* reset the stream (should be in an
				   error state from trying to read a
				   non-double) */
	}
	cout << endl;
    }
    return 0;
}
-------------------------------------------------------

Upon compilation and running, I get:

-------------------------------------------------------
dkatz@magellan:~/ac++/ch05/5-2$ g++ -Wall -ansi -pedantic \
> -o error.out error_harness.cpp 
dkatz@magellan:~/ac++/ch05/5-2$ ./error.out < data
Smith 93 91 47 90 92 73 100 87 
Carpenter 75 90 87 92 93 60 0 98 nan 
d 78 66 65 69 64 68 63 61 
Foo 33 45 66 67 43 42 31 16 nan 
cy 12 23 34 34 45 14 23 12 
-------------------------------------------------------

Clearly, the cin istream is reading "Nan" as an acceptable value for a
double.


        I corresponded with Andrew Koenig about this example (the code
above was derived from some of the sample code in his book
_Accelerated C++_) and his response led me to look at strtod(3):

        So what I think is happening is that the Linux implementation
        (I think that g++ uses that native C libraries for I/O
        conversions) is treating "Nan" as a number as an
        ``extension.''  I put ``extension'' as quotes, because when I
        searched through the C++ standard, I came to the conclusion
        that a conforming implementation is not permitted to extend
        the language in this way.

        In particular, conforming implementations are expect to accept
        all valid input, and reject all invalid input.  In this case,
        valid input is actually defined by the strtod function in the
        C library, which requires that the input contain at least one
        digit and begin with a digit, +, -, or decimal point.

        C++ does offer a mechanism for extending the definition of
        input to accept strings such as "NaN".  One does so by
        defining a data structure called a locale, and the telling cin
        to use that locale instead of the standard one.  But for it to
        accept this particular input without an explicitly defined
        locale is, as far as I know, an unauthorized change to the
        specification.

As far as I can tell, I am using the default "C" locale.  

        Based on this, it is not clear to me whether the issue is with
the conformance of strtod(3) to the C standard, or the usage of
strtod(3) by g++ in the implementation of cin.  I would hope, however,
that compiling with the -ansi and -pedantic flags would be enough to
get the correct, standard behavior.  (I admit that I don't have the
C++ standard in front of me, but if Dr. Koenig says that this behivior
doesn't conform then I'm inclined to take his word for it! :-))

        I hope this helps lead either glibc or g++ closer to standard
behavior.  Thanks.

Dan Katz



P.S.  System info:  Debian testing/woody

dkatz@magellan:~$ uname -a
Linux magellan 2.2.18 #1 Thu Dec 21 21:13:10 EST 2000 i686 unknown

dkatz@magellan:~$ g++ --version
2.95.2

dkatz@magellan:~$ strings /lib/libc.so.6 | grep version
[...]
GNU C Library stable release version 2.2.1, by Roland McGrath et al.
Compiled by GNU CC version 2.95.2 20000220 (Debian GNU/Linux).



Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]