This simple code:
#include <iostream>
#include <sstream>
int main()
{
float x = 0.0;
std::stringstream ss("NA");
ss >> x;
std::cout << ( ss.eof() ? "is" : "is not") << " at eof; x is " << x << std::endl;
}
returns different results, depending on which library I choose (I'm running clang from xcode 5 on OSX 10.9):
clang++ -std=c++11 -stdlib=libstdc++ -> not at eof
clang++ -stdlib=libstdc++ -> not at eof
/usr/bin/g++-4.2 -> not at eof
clang++ -std=c++11 -stdlib=libc++ -> at eof
clang++ -stdlib=libc+ -> at eof
It seems to me that if I try to read an alphabetic character into a float, the operation should fail, but it shouldn't eat the invalid characters - so I should get fail() but not eof(), so this looks like a bug in libc++.
Is there a c++ standard somewhere that describes what the behavior should be?
p.s. I've expanded the original test program like so:
#include <iostream>
#include <sstream>
int main()
{
float x = 0.0;
std::stringstream ss("NA");
ss >> x;
std::cout << "stream " << ( ss.eof() ? "is" : "is not") << " at eof and " << (ss.fail() ? "is" : "is not") << " in fail; x is " << x << std::endl;
if (ss.fail())
{
std::cout << "Clearing fail flag" << std::endl;
ss.clear();
}
char c = 'X';
ss >> c;
std::cout << "Read character: \'" << c << "\'" << std::endl;
}
and here's what I see:
With libc++:
stream is at eof and is in fail; x is 0
Clearing fail flag
Read character: 'X'
with stdlibc++:
stream is not at eof and is in fail; x is 0
Clearing fail flag
Read character: 'N'
p.p.s. As described in the issue that n.m. links to, the problem doesn't occur if the stringstream is set to "MA" instead of "NA". Apparently libc++ starts parsing the string, thinking it's going to get "NAN" and then when it doesn't, it gets all upset.
In this case, you should get fail, but not eof. Basically, if,
after failure, you can clear the error and successfully do
a get() of a character, you should not get eof. (If you
cannot successfully read a character after clear(), whether
you get eof or not may depend on the type you were trying to
read, and perhaps in some cases, even on the implementation.)
Related
I am fairly new to C++ and have been tinkering with some simple programs to teach myself the basics. I remember a little while ago installing MinGW on my desktop (I think for the C compiler). I decided to go for Cygwin for C++ and it seems to have been working a treat, up until I noticed that it seems to behave differently from the MinGW compiler for this program. I'm probably breaking some coding golden rule, but the reason for this is that Windows CMD uses the MinGW compiler, or I can open the Cygwin shell and use that instead. Variety!
For the program below, I am making notes on the ternary operator and switch statement. I initialize 'a' and 'b', ask for user input, and then use a function to check which is larger.
I then ask for user input again, to over-write the values in 'a' and 'b' to something else. When compiling from Windows CMD, this works fine and I can overwrite with new input, and the #define MAXIMUM and MINIMUM functions work fine on the new values. When I compile on Cygwin, however, after the first 'pause', the program launches past the two std::cin's and just runs MAXIMUM and MINIMUM on the old values of 'a' and 'b'.
Obviously I have tried just creating two new int variables, 'c' and 'd', and then there is no issue. The values are not immutable in any sense that I am aware of (although I don't know much, so I could be wrong).
I wasn't sure if this was something to do with the auto keyword, so I specified the type as int manually.
I also checked the version of both compilers with 'g++ -v' in Cygwin and at the CMD.
#include <iostream>
#include <cstdlib>
#define MAXIMUM(a,b) ((a > b) ? a : b)
#define MINIMUM(a,b) ((a < b) ? a : b)
int ternary_op(int a, int b)
{
char x = 'a';
char y = 'b';
auto result_var = 0;
result_var = a > b ? x : y; //Shorthand if statement with syntax (test_condition) ? (if_true) : (if_false)
return result_var;
}
int main()
{
auto a = 0;
auto b = 0;
auto larger = 0;
auto smaller = 0;
std::cout << "Enter an integer: " << "\n";
std::cin >> a;
std::cout << "Enter another integer: " << "\n";
std::cin >> b;
char greater_var = ternary_op(a,b); //Therefore if condition a > b is satisfied, greater_var is assigned x ('a')
std::cout << greater_var << std::endl;
switch(greater_var){
case 'a':
std::cout << "First integer " << a << " is larger than second, " << b << std::endl;
break;
case 'b':
std::cout << "Second integer " << b << " is larger than first integer, " << a << std::endl;
break;
}
std::cout << system("cmd /c pause") << std::endl;
std::cout << "We can also use defined functions to check equivalency and assign variables based upon the result." << "\n";
std::cout << "Enter an integer: " << std::endl;
std::cin >> a;
std::cout << "Enter another integer: " << std::endl;
std::cin >> b;
larger = MAXIMUM(a,b);
smaller = MINIMUM(a,b);
std::cout << "Larger and smaller numbers determined by defined function: " << larger << ", " << smaller << std::endl;
std::cout << system("cmd /c pause") << std::endl;
return 0;
}
Obviously if I make two new variables, 'c' and 'd', there is no issue. Changing the type to int myself did not change the way the program behaved using Cygwin. Unusually the MinGW version was 8.1.0, while Cygwin was 7.4.0. I'm not sure if this means that it is simply an older version of the same compiler.
Again, I'm very new to this so I'm just quite confused as to why they would behave so differently. I was also under the impression that different compilers were completely different beasts that simply read from the same standard hymn sheet, so to speak.
Just curious as to what is going on here!
Cheers!
I'm simply trying stringstream in UTF-8:
#include<iostream>
#include<string>
#include<sstream>
int main()
{
std::basic_stringstream<char8_t> ss(u8"hello");
char8_t c;
std::cout << (ss.rdstate() & std::ios_base::goodbit) << " " << (ss.rdstate() & std::ios_base::badbit) << " "
<< (ss.rdstate() & std::ios_base::failbit) << " " << (ss.rdstate() & std::ios_base::eofbit) << "\n";
ss >> c;
std::cout << (ss.rdstate() & std::ios_base::goodbit) << " " << (ss.rdstate() & std::ios_base::badbit) << " "
<< (ss.rdstate() & std::ios_base::failbit) << " " << (ss.rdstate() & std::ios_base::eofbit) << "\n";
std::cout << c;
return 0;
}
Compile using:
g++-9 -std=c++2a -g -o bin/test test/test.cpp
The result on screen is:
0 0 0 0
0 1 4 0
0
It seems that something goes wrong when reading c, but I don't know how to correct it. Please help me!
This is actually an old issue not specific to support for char8_t. The same issue occurs with char16_t or char32_t in C++11 and newer. The following gcc bug report has a similar test case.
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88508
The issue is also discussed at the following:
GCC 4.8 and char16_t streams - bug?
Why does `std::basic_ifstream<char16_t>` not work in c++11?
http://gcc.1065356.n8.nabble.com/UTF-16-streams-td1117792.html
The issue is that gcc does not implicitly imbue the global locale with facets for ctype<char8_t>, ctype<char16_t>, or ctype<char32_t>. When attempting to perform an operation that requires one of these facets, a std::bad_cast exception is thrown from std::__check_facet (which is subsequently silently swallowed by the IOS sentry object created for the character extraction operator and which then sets badbit and failbit).
The C++ standard only requires that ctype<char> and ctype<wchar_t> be provided. See [locale.category]p2.
Consider the following code snippet:
#include <iostream>
#include <sstream>
int main()
{
std::stringstream ss;
ss << "12345";
unsigned short s;
ss >> s;
ss << "foo";
std::cout << std::boolalpha
<< "\nss.eof() = " << ss.eof()
<< "\nss.good() = " << ss.good()
<< "\nss.bad() = " << ss.bad()
<< "\nss.fail() = " << ss.fail()
<< "\nss.str() = " << ss.str();
}
clang++ trunk prints the following result:
ss.eof() = true
ss.good() = false
ss.bad() = false
ss.fail() = false
ss.str() = 12345
on wandbox
g++ trunk prints the following result:
ss.eof() = true
ss.good() = false
ss.bad() = false
ss.fail() = true
ss.str() = 12345
on wandbox
As you can see, the value of ss.fail() is different between the two compilers. What does the Standard say regarding the behavior of std::stringstream in this case? Is it implementation-defined to set failbit/badbit when writing to a stream that has already been consumed?
Gcc is correct. std::stringstream inherits from std::basic_ostream, and according to the behavior of operator<<(std::basic_ostream) (which is invoked from ss << "foo";),
Effects: Behaves like a formatted inserter (as described in [ostream.formatted.reqmts]) of out.
And from §30.7.5.2.1/1 Common requirements [ostream.formatted.reqmts]:
(emphasis mine)
Each formatted output function begins execution by constructing an object of class sentry. If this object returns true when converted to a value of type bool, the function endeavors to generate the requested output. If the generation fails, then the formatted output function does setstate(ios_base::failbit), which might throw an exception.
And §30.7.5.1.3 Class basic_ostream::sentry [ostream::sentry]:
If os.good() is nonzero, prepares for formatted or unformatted output.
If os.tie() is not a null pointer, calls os.tie()->flush().
If, after any preparation is completed, os.good() is true, ok_ ==
true otherwise, ok_ == false. During preparation, the constructor may
call setstate(failbit) (which may throw ios_base::failure
([iostate.flags]))
And §30.5.5.4 basic_ios flags functions [iostate.flags]:
iostate rdstate() const;
Returns: The error state of the stream buffer.
bool good() const;
Returns: rdstate() == 0
bool eof() const;
Returns: true if eofbit is set in rdstate().
eofbit has been set in this case, then std::basic_ios::good returns nonzero and causes writing failed (as the result showed), then failbit should be set.
I am having trouble converting a string to a double. I am given a string with lat/long coordinates in the format of 33.9425/N 118.4081/W
I first call my function trimLastChar(std::string& input) twice, which will remove the the North, South, East, West characters and then the forward slash. This function correctly returns 33.9425 and 118.4081 respectfully as a std::string.
I am using the following code to convert my std::string to a double...however the problem is, the conversion losses precision -- I suspect it gets rounded?.
// Location In String is what trimLastChar returns
std::stringstream stream(locationInString);
std::cout << "DEBUG: before: " << locationInString << " ";
// output is a double* output = new double passed by reference to my function
stream >> output;
std::cout << output << std::endl;
The output in this case would produce:
33.9425
118.408
As you notice, the correct value should be 118.4081 but the 1 is missing...
Any ideas how to fix? Or more important, why is this happening?
The precision wasn't lost on input. It's being lost on output.
#include <iostream>
using std::cout;
using std::endl;
int main()
{
double v = 118.4081;
cout << v << endl;
cout.precision(10);
cout << v << endl;
}
outputs:
$ g++ -Wall x.cpp && ./a.out
118.408
118.4081
$
You probably have more digits than the output shows. By default, only a small number of digits is shown, you need to use std::setprecision to see more digits. Try
std::cout << std::setprecision(10) << output << std::endl;
The idiomatic loop to read from an istream is
while (thestream >> value)
{
// do something with value
}
Now this loop has one problem: It will not distinguish if the loop terminated due to end of file, or due to an error. For example, take the following test program:
#include <iostream>
#include <sstream>
void readbools(std::istream& is)
{
bool b;
while (is >> b)
{
std::cout << (b ? "T" : "F");
}
std::cout << " - " << is.good() << is.eof() << is.fail() << is.bad() << "\n";
}
void testread(std::string s)
{
std::istringstream is(s);
is >> std::boolalpha;
readbools(is);
}
int main()
{
testread("true false");
testread("true false tr");
}
The first call to testread contains two valid bools, and therefore is not an error. The second call ends with a third, incomplete bool, and therefore is an error. Nevertheless, the behaviour of both is the same. In the first case, reading the boolean value fails because there is none, while in the second case it fails because it is incomplete, and in both cases EOF is hit. Indeed, the program above outputs twice the same line:
TF - 0110
TF - 0110
To solve this problem, I thought of the following solution:
while (thestream >> std::ws && !thestream.eof() && thestream >> value)
{
// do something with value
}
The idea is to detect regular EOF before actually trying to extract the value. Because there might be whitespace at the end of the file (which would not be an error, but cause read of the last item to not hit EOF), I first discard any whitespace (which cannot fail) and then test for EOF. Only if I'm not at the end of file, I try to read the value.
For my example program, it indeed seems to work, and I get
TF - 0100
TF - 0110
So in the first case (correct input), fail() returns false.
Now my question: Is this solution guaranteed to work, or was I just (un-)lucky that it happened to give the desired result? Also: Is there a simpler (or, if my solution is wrong, a correct) way to get the desired result?
It is very easy to differentiate between EOF and other errors, as long as you don't configure the stream to use exceptions.
Simply check stream.eof() at the end.
Before that only check for failure/non-failure, e.g. stream.fail() or !stream. Note that good is not the opposite of fail. So in general never even look at the good, only at the fail.
Edit:
Some example code, namely your example modified to distinguish an ungood bool specification in the data:
#include <iostream>
#include <sstream>
#include <string>
#include <stdexcept>
using namespace std;
bool throwX( string const& s ) { throw runtime_error( s ); }
bool hopefully( bool v ) { return v; }
bool boolFrom( string const& s )
{
istringstream stream( s );
(stream >> boolalpha)
|| throwX( "boolFrom: failed to set boolalpha mode." );
bool result;
(stream >> result)
|| throwX( "boolFrom: failed to extract 'bool' value." );
char c; stream >> c;
hopefully( stream.eof() )
|| throwX( "boolFrom: found extra characters at end." );
return result;
}
void readbools( istream& is )
{
string word;
while( is >> word )
{
try
{
bool const b = boolFrom( word );
cout << (b ? "T" : "F") << endl;
}
catch( exception const& x )
{
cerr << "!" << x.what() << endl;
}
}
cout << "- " << is.good() << is.eof() << is.fail() << is.bad() << "\n";
}
void testread( string const& s )
{
istringstream is( s );
readbools( is );
}
int main()
{
cout << string( 60, '-' ) << endl;
testread( "true false" );
cout << string( 60, '-' ) << endl;
testread( "true false tr" );
cout << string( 60, '-' ) << endl;
testread( "true false truex" );
}
Example result:
------------------------------------------------------------
T
F
- 0110
------------------------------------------------------------
T
F
!boolFrom: failed to extract 'bool' value.
- 0110
------------------------------------------------------------
T
F
!boolFrom: found extra characters at end.
- 0110
Edit 2: in the posted code and results, added example of using eof() checking, which I forgot.
Edit 3:
The following corresponding example uses the OP’s proposed skip-whitespace-before-reading solution:
#include <iostream>
#include <sstream>
#include <string>
using namespace std;
void readbools( istream& is )
{
bool b;
while( is >> ws && !is.eof() && is >> b ) // <- Proposed scheme.
{
cout << (b ? "T" : "F") << endl;
}
if( is.fail() )
{
cerr << "!readbools: failed to extract 'bool' value." << endl;
}
cout << "- " << is.good() << is.eof() << is.fail() << is.bad() << "\n";
}
void testread( string const& s )
{
istringstream is( s );
is >> boolalpha;
readbools( is );
}
int main()
{
cout << string( 60, '-' ) << endl;
testread( "true false" );
cout << string( 60, '-' ) << endl;
testread( "true false tr" );
cout << string( 60, '-' ) << endl;
testread( "true false truex" );
}
Example result:
------------------------------------------------------------
T
F
- 0100
------------------------------------------------------------
T
F
!readbools: failed to extract 'bool' value.
- 0110
------------------------------------------------------------
T
F
T
!readbools: failed to extract 'bool' value.
- 0010
The main difference is that this approach produces 3 successfully read values in the third case, even though the third value is incorrectly specified (as "truex").
I.e. it fails to recognize an incorrect specification as such.
Of course, my ability to write Code That Does Not Work™ is no proof that it can not work. But I am fairly good at coding up things, and I could not see any way to detect the "truex" as incorrect, with this approach (while it was easy to do with the read-words exception based approach). So at least for me, the read-words exception based approach is simpler, in the sense that it is easy to make it behave correctly.