Streams eof() and good()

Discussion in 'C++' started by Adrian, Apr 19, 2007.

  1. Adrian

    Adrian Guest

    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;
    }
     
    Adrian, Apr 19, 2007
    #1
    1. Advertisements

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

    HTH,
    - J.
     
    Jacek Dziedzic, Apr 19, 2007
    #2
    1. Advertisements

  3. Adrian

    Adrian Guest

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



    Adrian
     
    Adrian, Apr 19, 2007
    #3
  4. Adrian

    Zeppe Guest

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

    Zeppe
     
    Zeppe, Apr 19, 2007
    #4
  5. Adrian

    Adrian Guest

    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
     
    Adrian, Apr 19, 2007
    #5
  6. Adrian

    anon Guest

    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
    Not sure about these
     
    anon, Apr 19, 2007
    #6
  7. Adrian

    Adrian Guest

    These two are old compilers. Why dont you try gcc 4.x.x and see the results?
    Wish I could - anything greater then 2.95.2 wont compile on unixware!
     
    Adrian, Apr 19, 2007
    #7
  8. Adrian

    Salt_Peter Guest

    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
    */
     
    Salt_Peter, Apr 19, 2007
    #8
  9. Adrian

    Zeppe Guest

    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
     
    Zeppe, Apr 19, 2007
    #9
  10. Adrian

    Adrian Guest

    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
    }
    }
     
    Adrian, Apr 19, 2007
    #10
  11. Adrian

    James Kanze Guest

    Implementation defined, but in practice, I find it difficult to
    believe that a correct implementation would not set 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.
     
    James Kanze, Apr 19, 2007
    #11
  12. Adrian

    Zeppe Guest

    is not, look at my other post. The standard requires eof.
    I would have expected good() if the last operation was successful, but I
    was wrong. there is fail() for that ^^
    oh well, that one seemed a toy problem created to make a question,
    didn't it?

    Regards,

    Zeppe
     
    Zeppe, Apr 19, 2007
    #12
  13. Adrian

    James Kanze Guest

    In every implementation I've seen, yes.
    But the << operator probably did. Otherwise, how did it know to
    stop.
    And it's not 100% reliable even for that.
    You don't need the strm.good() here (and it's not very idiomatic
    to use it).
    And also failbit or badbit.
    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 ;
    }
     
    James Kanze, Apr 19, 2007
    #13
    1. Advertisements

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 (here). After that, you can post your question and our members will help you out.