ifstream getline() problem

J

John

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!
 
I

Ivan Vecerina

| 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,
 
R

Roel Schroeven

Ivan said:
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 '!'?
 
B

Buster Copley

John said:
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 ().
 
J

Jim Fischer

John said:
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.
 
D

Duane Hebert

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?


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

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

Ivan Vecerina

Roel Schroeven said:
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,
 
R

Roel Schroeven

Ivan said:
Roel Schroeven said:
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.
 
I

Ivan Vecerina

Roel Schroeven said:
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
 
A

Alexander Terekhov

Ivan said:
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/[email protected]

regards,
alexander.
 

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

Similar Threads

ifstream::getline() synatx 18
ifstream 5
ifstream 1
Problem with ifstream::getline 1
Error with ifstream and exceptions 71
ifstream problem? 13
multi-thread and ifstream 1
getline problem 10

Members online

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,904
Latest member
HealthyVisionsCBDPrice

Latest Threads

Top