Streams eof() and good()

A

Adrian

All,

This code below produces "GOOD" on one platform and "EOF" on the
other.

I expect it to produce "EOF" as the second read would hit the end of
the stream.

Which result is correct?

Adrian

#include <iostream>
#include <sstream>

int main(int argc, char *argv[])
{
std::stringstream strm("5 4");

int x;

strm >> x;
strm >> x;
if(strm.good())
{
std::cout << "GOOD\n";
}
if(strm.eof())
{
std::cout << "EOF\n";
}

return 0;
}
 
J

Jacek Dziedzic

Adrian said:
All,

This code below produces "GOOD" on one platform and "EOF" on the
other.

I expect it to produce "EOF" as the second read would hit the end of
the stream.

Which result is correct?

Adrian

#include <iostream>
#include <sstream>

int main(int argc, char *argv[])
{
std::stringstream strm("5 4");

int x;

strm >> x;
strm >> x;
if(strm.good())
{
std::cout << "GOOD\n";
}
if(strm.eof())
{
std::cout << "EOF\n";
}

return 0;
}

You expect wrong. You can only tell EOF reliably _after_
you have tried to read _past_ the end of stream and failed.

HTH,
- J.
 
A

Adrian

You expect wrong. You can only tell EOF reliably _after_
you have tried to read _past_ the end of stream and failed.

But doesnt strm >> x try and read past the eof as it keep extracting
chars



Adrian
 
Z

Zeppe

Adrian said:
All,

This code below produces "GOOD" on one platform and "EOF" on the
other.

I expect it to produce "EOF" as the second read would hit the end of
the stream.

Which result is correct?

Adrian

#include <iostream>
#include <sstream>

int main(int argc, char *argv[])
{
std::stringstream strm("5 4");

int x;

strm >> x;
strm >> x;
if(strm.good())
{
std::cout << "GOOD\n";
}
if(strm.eof())
{
std::cout << "EOF\n";
}

return 0;
}

It should be GOOD. What is the platform in which you are obtaining EOF?

Zeppe
 
A

Adrian

Adrian said:
This code below produces "GOOD" on one platform and "EOF" on the
other.
I expect it to produce "EOF" as the second read would hit the end of
the stream.
Which result is correct?

#include <iostream>
#include <sstream>
int main(int argc, char *argv[])
{
std::stringstream strm("5 4");
strm >> x;
strm >> x;
if(strm.good())
{
std::cout << "GOOD\n";
}
if(strm.eof())
{
std::cout << "EOF\n";
}
return 0;
}

It should be GOOD. What is the platform in which you are obtaining EOF?

FreeBSD 5.4 gcc 3.4.2 Reports EOF
Unixware 7.1.1 gcc 2.95.2 Reports GOOD
XP VS2005 Reports EOF (not that I trust ms c++)
SunOs 5.6 native REPORTS EOF
 
A

anon

Adrian said:
Adrian said:
All,
This code below produces "GOOD" on one platform and "EOF" on the
other.
I expect it to produce "EOF" as the second read would hit the end of
the stream.
Which result is correct?
Adrian
#include <iostream>
#include <sstream>
int main(int argc, char *argv[])
{
std::stringstream strm("5 4");
int x;
strm >> x;
strm >> x;
if(strm.good())
{
std::cout << "GOOD\n";
}
if(strm.eof())
{
std::cout << "EOF\n";
}
return 0;
}
It should be GOOD. What is the platform in which you are obtaining EOF?

FreeBSD 5.4 gcc 3.4.2 Reports EOF
Unixware 7.1.1 gcc 2.95.2 Reports GOOD

These two are old compilers. Why dont you try gcc 4.x.x and see the results?
The later versions of gcc follow c++ standards more then old versions
XP VS2005 Reports EOF (not that I trust ms c++)
SunOs 5.6 native REPORTS EOF
Not sure about these
 
A

Adrian

These two are old compilers. Why dont you try gcc 4.x.x and see the results?
The later versions of gcc follow c++ standards more then old versions
Wish I could - anything greater then 2.95.2 wont compile on unixware!
 
S

Salt_Peter

But doesnt strm >> x try and read past the eof as it keep extracting
chars

indeed, but you did not keep extracting characters.
So the result your getting is probably implementation defined.
In other words, good() will eventually fail, the question is "why?".
The typical use for eof() is to verify if the extraction failed for a
reason _other_ than the end marker was found.

#include <iostream>
#include <sstream>

int main()
{
std::istringstream strm("5 4 3 2 1");

int x;
while( strm.good() && (strm >> x) )
{
std::cout << "x = " << x;
std::cout << std::endl;
}
if( !strm.eof() )
{
std::cout << "stream's failbit or badbit flag set\n";
} else {
std::cout << "stream's eof flag set\n";
}
}

/*
x = 5
x = 4
x = 3
x = 2
x = 1
stream's eof flag set
*/
 
Z

Zeppe

Adrian said:
FreeBSD 5.4 gcc 3.4.2 Reports EOF
Unixware 7.1.1 gcc 2.95.2 Reports GOOD
XP VS2005 Reports EOF (not that I trust ms c++)
SunOs 5.6 native REPORTS EOF

Dear Adrian,

my bad.

Actually it seems that the standard requires to set the eof bit if the
end of input is reached why reading a number. I got confused because I
recalled that in the Stroustrup said that if an operation succeeds
good() should return true. Now, the stroustrup is a wonderful book and
it hardly contains errors: in fact, it briefly says:

"If the state is good() the previous input operation succeeded."

which is actually true, but the opposite is not! That means that you
have to check fail() to know if the last operation failed.

That's it. Remember to check the state anyway, because for example if
you'd have taken the input from the command line there would have been a
last \n at the end of the line that would have prevented the stream to
return the eof after the last read number.

A last note: you can generally trust visual c++ 8, the new version of
the microsoft compiler is very compliant with the standard. gcc 2.95 is
very likely to be not compliant, on the other hand, being absolutely
obsolete.

Regards,

Zeppe
 
A

Adrian

indeed, but you did not keep extracting characters.
This is what I was looking for - to see if the standard says eof
should be set or not

Your code produces "stream's eof flag set" on unixware and FreeBSD
which is in line with my tests that if you try and read at then end of
the stream eof is set (as it should be)

The reason for the question is that I have something like the
following code. Now with BSD the stream can be !good() but still have
a valid record.

Or should I change SomeClass to reset eof bit if it read a whole
record. I want to follow the way the standard implents operator>> for
builtin types.

----------------------------

class SomeClass;

std::ifstream in("some file");
std::string line;

while(getline(in, line))
{
std::stringstream strm(line);

SomeClass a;
strm >> a;
if(strm.good() || strm.eof())
{
// do something good
}
else
{
// report error
}
}
 
J

James Kanze

Implementation defined, but in practice, I find it difficult to
believe that a correct implementation would not set eof.
#include <iostream>
#include <sstream>
int main(int argc, char *argv[])
{
std::stringstream strm("5 4");
int x;
strm >> x;
strm >> x;
if(strm.good())
{
std::cout << "GOOD\n";
}
if(strm.eof())
{
std::cout << "EOF\n";
}
return 0;
}
It should be GOOD. What is the platform in which you are obtaining EOF?

According to what? I would expect EOF, but I don't think the
standard guarantees it.

The real question is what he is actually trying to do. In
practice, ios::good() is of no use what so ever, and ios::eof()
only after input has failed.
 
Z

Zeppe

James said:
Implementation defined, but in practice, I find it difficult to
believe that a correct implementation would not set eof.

is not, look at my other post. The standard requires eof.
According to what? I would expect EOF, but I don't think the
standard guarantees it.

I would have expected good() if the last operation was successful, but I
was wrong. there is fail() for that ^^
The real question is what he is actually trying to do. In
practice, ios::good() is of no use what so ever, and ios::eof()
only after input has failed.

oh well, that one seemed a toy problem created to make a question,
didn't it?

Regards,

Zeppe
 
J

James Kanze

In every implementation I've seen, yes.
indeed, but you did not keep extracting characters.

But the << operator probably did. Otherwise, how did it know to
stop.
So the result your getting is probably implementation defined.
In other words, good() will eventually fail, the question is "why?".
The typical use for eof() is to verify if the extraction failed for a
reason _other_ than the end marker was found.

And it's not 100% reliable even for that.
#include <iostream>
#include <sstream>
int main()
{
std::istringstream strm("5 4 3 2 1");

int x;
while( strm.good() && (strm >> x) )

You don't need the strm.good() here (and it's not very idiomatic
to use it).
{
std::cout << "x = " << x;
std::cout << std::endl;
}
if( !strm.eof() )
{
std::cout << "stream's failbit or badbit flag set\n";
} else {
std::cout << "stream's eof flag set\n";

And also failbit or badbit.
/*
x = 5
x = 4
x = 3
x = 2
x = 1
stream's eof flag set
*/

The usual idiom is:

while ( strm >> x ) {
std::cout << "x = " << x << std::endl ;
}
if ( strm.bad() ) {
std::cout << "Hard read error encountered" << std::endl ;
} else if ( ! strm.eof() ) {
std::cout << "Format error encountered" << std::endl ;
} else {
std::cout << "No error (probably)" << std::endl ;
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top