How can I detect whether the istream extraction failed like this?
string s("x");
stringstream ss(s);
int i;
ss >> std::ios::hex >> i;
EDIT -- Though the question title covers this, I forgot to mention in the body: I really want to detect whether the failure is due to bad formatting, i.e. parsing, or due to any other IO-related issue, in order to provide proper feedback (an malformed_exception("x") or whatever).
if(! (ss >> std::ios::hex >> i) )
{
std::cerr << "stream extraction failed!" << std::endl;
}
It's just that easy.
ETA: Here's an example of how this test interacts with the end of a stream.
int i;
std::stringstream sstr("1 2 3 4");
while(sstr >> i)
{
std::cout << i << std::endl;
if(sstr.eof())
{
std::cout << "eof" << std::endl;
}
}
will print
1
2
3
4
eof
If you were to check sstr.eof()
or sstr.good()
in the while loop condition, 4 would not be printed.
Failure to extract the value will set the stream's "fail" bit, which can be detected by if (ss.fail())
, or just if (!ss)
. Equivalently, you can test the result of the >>
operation, since that returns a reference to the stream.
These will also detect other errors, which set the "bad" bit; you can distinguish these with ss.bad()
.
If you want to continue reading from the stream, you'll need to clear the state flags (ss.clear()
).
Errors during extraction are signaled by the internal state flags.
You can check them by the good()
member function.
See also here: http://www.cplusplus.com/reference/iostream/stringstream
Or just using the if()
-construction as suggested above.
This works due to the bool cast operator of stream classes
First off: thanks for the useful answers. However, after some investigation (cfr. cppreference) and verification, it seems that the one way to check for parse-failure only is by checking for the ios::failbit
flag, as in
const bool parsing_failed = (ss >> ios::hex >> i).rdstate() & ios::failbit ;
While both the suggested istream::operator!
and istream::operator bool
mingle failbit
and badbit
(cfr here and there on cplusplusreference).