ifstream getline() problem

Discussion in 'C++' started by John, Jul 11, 2003.

  1. John

    John Guest

    Hello all,

    I am trying to read in lines into a buffer from a file. Normally I would do
    this very low-level,
    but I have come to the conclusion I must stop doing everything the hard way.
    So, I thought I would try
    <fstream>. The code below causes an infinite loop in the while() statement.
    Debugging, I see that the buffer just has a 0 in
    the first position, and nothing else.

    ifstream listfile;

    listfile.open("data\\modellist.txt", ios::in);

    if(listfile.bad()) return 0;

    char buffer[100];

    while(!listfile.getline(buffer, 100).eof())

    {

    //Do stuff with buffer

    }

    Anyone know why? The file is ok, and works fine with fread and the like.



    Thanks in advance!
     
    John, Jul 11, 2003
    #1
    1. Advertising

  2. "John" <> wrote in message news:3f0e780e@shknews01...
    | I am trying to read in lines into a buffer from a file. Normally I would
    do
    | this very low-level,
    | but I have come to the conclusion I must stop doing everything the hard
    way.
    | So, I thought I would try
    | <fstream>. The code below causes an infinite loop in the while()
    statement.
    | Debugging, I see that the buffer just has a 0 in
    | the first position, and nothing else.
    ....
    | ifstream listfile;

    Note that the easiest way to do things safely and correctly is:
    std::string line;
    while( std::getline( listfile, line ) )
    { ... }

    | char buffer[100];
    |
    | while(!listfile.getline(buffer, 100).eof())

    If getline() fails for any other reason than eof, this will
    get into an infinite loop. Also, the last non-empty but valid
    line could be neglected (IIRC, eof is set if the line was
    extracted successfully up to the end of the file instead
    of a newline).

    A better test for the exit condition would be:
    while( !listfile.getline(buffer, 100).fail() )
    or simply (relying on a cast operator):
    while( listfile.getline(buffer, 100) )
    or my personally preferred style:
    while( !! listfile.getline(buffer, 100) )

    hth,
    --
    Ivan Vecerina, Dr. med. <> http://www.post1.com/~ivec
    Brainbench MVP for C++ <> http://www.brainbench.com
     
    Ivan Vecerina, Jul 11, 2003
    #2
    1. Advertising

  3. Ivan Vecerina wrote:
    > or my personally preferred style:
    > while( !! listfile.getline(buffer, 100) )


    What's the difference between that and

    while (listfile.getline(buffer, 100))

    ? Why the need for the double '!'?

    --
    "Codito ergo sum"
    Roel Schroeven
     
    Roel Schroeven, Jul 11, 2003
    #3
  4. John wrote:
    > Hello all,
    >
    > I am trying to read in lines into a buffer from a file. Normally I would do
    > this very low-level,
    > but I have come to the conclusion I must stop doing everything the hard way.
    > So, I thought I would try
    > <fstream>. The code below causes an infinite loop in the while() statement.
    > Debugging, I see that the buffer just has a 0 in
    > the first position, and nothing else.
    >
    > ifstream listfile;
    >
    > listfile.open("data\\modellist.txt", ios::in);
    >
    > if(listfile.bad()) return 0;
    >
    > char buffer[100];
    >
    > while(!listfile.getline(buffer, 100).eof())
    >
    > {
    >
    > //Do stuff with buffer
    >
    > }


    Try

    std::ifstream listfile (filename, std::ios_base::in);

    if (stream)
    {
    std::string s;
    while (std::getline (listfile, s))
    {
    // do stuff
    }
    }

    Are you running from the right directory?

    >
    > Anyone know why? The file is ok, and works fine with fread and the like.
    >


    bad () is not the opposite of good ().

    >
    > Thanks in advance!
    >
    >
     
    Buster Copley, Jul 11, 2003
    #4
  5. John

    Jim Fischer Guest

    John wrote:
    > I changed it to your suggestion:
    >
    > string line;
    >
    > while(getline(listfile, line))
    >
    > { }
    >
    > But now it does not even enter the loop at all. So, something must be wrong
    > with the file stream, but
    > listfile.bad() doesn't show this.


    The 'ios_base::badbit' state flag usually indicates some sort of unusual
    malfunction -- e.g., a sector on the floppy disk is bad (cannot be read)
    and so the OS aborted the read attempt. IOW, you shouldn't use the
    ..bad() member function to detect "normal" I/O failures (e.g., end of
    file, unexpected data value, etc.).

    > Is there anything obvious that I have
    > missed? The code can be broken down to:
    > ifstream listfile("data\\modellist.txt");
    >
    > getline(listfile, line) //line is a std::string
    >
    > and this compiles, but does not work. What am I missing? Is there a way to
    > actually find out what failed?


    Consider the following code sample.

    <example>

    <code>
    #include <iostream>
    #include <sstream>

    class show_iostate {
    protected:
    std::ios_base::iostate state_;
    public:
    show_iostate (std::ios & stream) : state_(stream.rdstate()) { }
    virtual ~show_iostate () { }
    virtual std::eek:stream & print (std::eek:stream &) const;
    };

    std::eek:stream &
    show_iostate:: print (std::eek:stream & out) const
    {
    out
    << (std::ios_base::badbit & state_ ? 'B' : '-')
    << (std::ios_base::eofbit & state_ ? 'E' : '-')
    << (std::ios_base::failbit & state_ ? 'F' : '-')
    << (std::ios_base::goodbit == state_ ? 'G' : '-')
    ;
    return out;
    }

    std::eek:stream &
    operator << (std::eek:stream & out, const show_iostate & s)
    {
    return s.print(out);
    }

    int main()
    {
    std::string s;
    std::istringstream iss("Hello\nworld!");
    std::cout << "Before : " << show_iostate(iss) << '\n';
    while ( std::getline(iss, s) ) {
    std::cout << "Loop : " << show_iostate(iss)
    << " [" << s << "]\n";
    }
    std::cout << "After : " << show_iostate(iss) << '\n';
    }
    </code>

    <output>
    Before : ---G
    Loop : ---G [Hello]
    Loop : -E-- [world!]
    After : -EF-
    </output>

    </example>


    For debugging purposes you could write,

    ifstream listfile("data\\modellist.txt");
    std::cout << "listfile : " << show_iostate(listfile) << '\n';

    This would show the 'listfile' object's iostate status after the file
    open attempt is made. If listfile's status is displayed as '---G' (i.e.,
    listfile's iostate is "ios::goodbit"), then the open attempt was
    successful and you can turn your attention to the getline() call, and so on.

    --
    Jim

    To reply by email, remove "link" and change "now.here" to "yahoo"
    jfischer_link5809{at}now.here.com
     
    Jim Fischer, Jul 11, 2003
    #5
  6. John

    Duane Hebert Guest

    > Try
    >
    > std::ifstream listfile (filename, std::ios_base::in);
    >
    > if (stream)
    > {
    > std::string s;
    > while (std::getline (listfile, s))
    > {
    > // do stuff
    > }
    > }
    >
    > Are you running from the right directory?
    >
    > >
    > > Anyone know why? The file is ok, and works fine with fread and the like.
    > >

    >
    > bad () is not the opposite of good ().


    What is stream? Do you mean if(listfile) or if (listfile.is_open()) ?
     
    Duane Hebert, Jul 11, 2003
    #6
  7. "Roel Schroeven" <> wrote in message
    news:kxwPa.368$-ops.be...
    > Ivan Vecerina wrote:
    > > or my personally preferred style:
    > > while( !! listfile.getline(buffer, 100) )

    >
    > What's the difference between that and
    >
    > while (listfile.getline(buffer, 100))


    In this case, there is no actual difference.
    But the latter line relies on an *implicit* conversion
    to bool. Actually, if you look into it, this is not just
    a conversion to bool, but a conversion to void* -- that's
    because there are some tricky issues related to such an
    implicit conversion operator, so the standard library
    provides the latter conversion to mimic a bool() operator.

    Even as it is, one could still get in trouble:
    void Verify(bool testThatMustBeTrue);
    void Verify(void* pointerThatMustBeValid);
    If you were to write:
    Verify( listfile.getline(buffer,100) );
    It is the second overload of Verify that would be called.
    (and the non-zero pointer that is returned by the void*
    conversion could be some invalid or illegal address ).

    These implicit conversion issues do not apply when
    using the operator !() overloaded by the stream classes
    (which returns a bool, but with the opposite logical value).


    Now, as I said, using the " !! " operator is a
    style convention. I have adopted it since I've seen
    it used a couple years ago, and never needed to go back.
    (though, as for other style issues, I remain flexible).


    Because implicit conversions to bool have some caveats,
    you will see that several coding standards require
    the use of:
    if( myPtr != NULL ) and if( myPtr == NULL )
    instead of:
    if( myPtr ) and if( ! myPtr )
    To avoid a common mistake: if( myPtr = NULL )
    some even advise the following style:
    if( NULL != myPtr ) and if( NULL == myPtr )


    Instead of that, I just like the symmetry
    and simplicity of writing:
    if( !! myPtr ) and if( ! myPtr )


    In all circumstances I know, " !! " can be considered
    and used as a built-in "convert-to-bool" operator.
    It also works nicely with stream-classes and the like
    that provide a conversion to bool to check validity.
    And in our own classes, when a similar validity test
    is needed, we only provide an operator!(), and do not
    mess with implicit conversion operators.


    So it is just a style convention we adopted,
    and we think it has real benefits compared to
    other approaches.


    Best regards,
    --
    Ivan Vecerina, Dr. med. <> http://www.post1.com/~ivec
    Soft Dev Manager, XiTact <> http://www.xitact.com
    Brainbench MVP for C++ <> http://www.brainbench.com
     
    Ivan Vecerina, Jul 12, 2003
    #7
  8. Ivan Vecerina wrote:
    > "Roel Schroeven" <> wrote in message
    > news:kxwPa.368$-ops.be...
    >> Ivan Vecerina wrote:
    >> > or my personally preferred style:
    >> > while( !! listfile.getline(buffer, 100) )

    >>
    >> What's the difference between that and
    >>
    >> while (listfile.getline(buffer, 100))

    >


    [...]

    > In all circumstances I know, " !! " can be considered
    > and used as a built-in "convert-to-bool" operator.
    > It also works nicely with stream-classes and the like
    > that provide a conversion to bool to check validity.
    >
    > So it is just a style convention we adopted,
    > and we think it has real benefits compared to
    > other approaches.


    Thanks for the elaborate explanation. I've used !! myself in the past
    for converting from int to bool, not knowing it is actually recommended
    practice.

    --
    "Codito ergo sum"
    Roel Schroeven
     
    Roel Schroeven, Jul 12, 2003
    #8
  9. "Roel Schroeven" <> wrote in message
    news:Ib_Pa.3799$-ops.be...
    > Ivan Vecerina wrote:
    > > In all circumstances I know, " !! " can be considered
    > > and used as a built-in "convert-to-bool" operator.
    > > It also works nicely with stream-classes and the like
    > > that provide a conversion to bool to check validity.
    > >
    > > So it is just a style convention we adopted,
    > > and we think it has real benefits compared to
    > > other approaches.

    >
    > Thanks for the elaborate explanation. I've used !! myself in the past
    > for converting from int to bool, not knowing it is actually recommended
    > practice.


    I wouldn't dare call !! "recommended practice" just because I
    like and recommend its use ;)
    (when I say 'we', I just speak for myself and the team
    I work with on various development projects).

    I haven't invented the approach, but I have found it to be
    convenient, and haven't seen a situation yet where it
    creates problems.

    Maybe someone here will voice a different opinion...


    Cheers,
    Ivan
    --
    Ivan Vecerina, Dr. med. <> http://www.post1.com/~ivec
    Soft Dev Manager, XiTact <> http://www.xitact.com
    Brainbench MVP for C++ <> http://www.brainbench.com
     
    Ivan Vecerina, Jul 12, 2003
    #9
  10. Ivan Vecerina wrote:
    >
    > "Roel Schroeven" <> wrote in message
    > news:Ib_Pa.3799$-ops.be...
    > > Ivan Vecerina wrote:
    > > > In all circumstances I know, " !! " can be considered
    > > > and used as a built-in "convert-to-bool" operator.
    > > > It also works nicely with stream-classes and the like
    > > > that provide a conversion to bool to check validity.
    > > >
    > > > So it is just a style convention we adopted,
    > > > and we think it has real benefits compared to
    > > > other approaches.

    > >
    > > Thanks for the elaborate explanation. I've used !! myself in the past
    > > for converting from int to bool, not knowing it is actually recommended
    > > practice.

    >
    > I wouldn't dare call !! "recommended practice" just because I
    > like and recommend its use ;)
    > (when I say 'we', I just speak for myself and the team
    > I work with on various development projects).
    >
    > I haven't invented the approach, but I have found it to be
    > convenient, and haven't seen a situation yet where it
    > creates problems.
    >
    > Maybe someone here will voice a different opinion...


    "!!" sucks. http://google.com/groups?selm=

    regards,
    alexander.
     
    Alexander Terekhov, Jul 12, 2003
    #10
  11. Duane Hebert wrote:
    >>Try
    >>
    >> std::ifstream listfile (filename, std::ios_base::in);
    >>
    >> if (stream)
    >> {
    >> std::string s;
    >>while (std::getline (listfile, s))
    >> {
    >> // do stuff
    >> }
    >> }
    >>
    >>Are you running from the right directory?
    >>
    >>
    >>>Anyone know why? The file is ok, and works fine with fread and the like.
    >>>

    >>
    >>bad () is not the opposite of good ().

    >
    >
    > What is stream? Do you mean if(listfile) or if (listfile.is_open()) ?
    >
    >


    Ah, yes. Thanks. I meant `if (listfile)'.
     
    Buster Copley, Jul 14, 2003
    #11
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Joe
    Replies:
    4
    Views:
    7,789
    Chris Theis
    Jan 22, 2004
  2. Jim Phelps
    Replies:
    1
    Views:
    1,763
    Karl Heinz Buchegger
    Jan 21, 2004
  3. Christopher Benson-Manica

    ifstream/getline

    Christopher Benson-Manica, Apr 1, 2004, in forum: C++
    Replies:
    15
    Views:
    28,614
    Leor Zolman
    Apr 1, 2004
  4. tinks
    Replies:
    1
    Views:
    642
  5. Assertor
    Replies:
    2
    Views:
    2,603
    Assertor
    Feb 26, 2006
Loading...

Share This Page