From Bugzilla Helper: User-Agent: Mozilla/4.0 (compatible; MSIE 6.0b; Windows 98) Description of problem: Extraction of a double variable from a istrstream consisting of a single char should set fail() and ios::failbit. The string "i" and "s" give different results! How reproducible: Always Steps to Reproduce: 1.See program below in additional information 2. 3. Actual Results: if string = "i", result = 2 0; if string = "s", result = 2 2; Additional info: istrstream a("i"); double b; a>>b; cout<<ios::failbit<<" "<<a.fail()<<endl; (Run, look at the result, then change to a("s")).
It is not that surprising, 'i' is prefix of inf, so in that case it failed on the EOF condition (eofbit is set), while with "s" it failed already on 's' character. Anyway, istream::operator>> should check whether it did not actually scan the number and set failbit too. Following patch should do the job: 2001-08-07 Jakub Jelinek <jakub> * iostream.cc (do_scan): New. (istream::operator>>(long double &)): Use it. (istream::operator>>(double &)): Likewise. (istream::operator>>(float &)): Likewise. * g++.old-deja/g++.other/failbit1.C: New test. --- gcc/testsuite/g++.old-deja/g++.other/failbit1.C.jj Wed Aug 8 14:52:09 2001 +++ gcc/testsuite/g++.old-deja/g++.other/failbit1.C Wed Aug 8 14:51:12 2001 @@ -0,0 +1,21 @@ +#include <strstream> +#include <iostream> + +extern "C" void abort (void); + +using namespace std; + +int main(void) +{ + istrstream a ("i"); + istrstream b ("s"); + double c; + + a >> c; + b >> c; + if (! a.fail ()) + abort (); + if (! b.fail ()) + abort (); + return 0; +} --- libio/iostream.cc.jj Tue Jul 24 20:40:52 2001 +++ libio/iostream.cc Wed Aug 8 14:37:14 2001 @@ -361,6 +361,19 @@ READ_INT(unsigned long long) READ_INT(bool) #endif +static void do_scan(istream *istr, const char *format, ...) +{ + streambuf *_strbuf = istr->_strbuf; + va_list ap; + va_start(ap, format); + int errcode = 0; + int count = _IO_vfscanf(_strbuf, format, ap, &errcode); + if ((errcode & (_IOS_EOF|_IOS_FAIL)) == _IOS_EOF && count != 1) + errcode |= _IOS_FAIL; + istr->setstate((ios::iostate)errcode); + va_end(ap); +} + istream& istream::operator>>(long double& x) { if (ipfx0()) @@ -368,10 +381,10 @@ istream& istream::operator>>(long double _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, _strbuf); #if _G_HAVE_LONG_DOUBLE_IO - scan("%Lg", &x); + do_scan(this, "%Lg", &x); #else double y; - scan("%lg", &y); + do_scan(this, "%lg", &y); x = y; #endif isfx(); @@ -386,7 +399,7 @@ istream& istream::operator>>(double& x) { _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, _strbuf); - scan("%lg", &x); + do_scan(this, "%lg", &x); isfx(); _IO_cleanup_region_end (0); } @@ -399,7 +412,7 @@ istream& istream::operator>>(float& x) { _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, _strbuf); - scan("%g", &x); + do_scan(this, "%g", &x); isfx(); _IO_cleanup_region_end (0); }
I've added that patch into libstdc++-2.96-96.
Fixed.