File EOF with empty last line of file

Hello,
I'm getting back into C++ using Eclipse and MinGW. My question is this. I am reading a text file. Some lines of the file have no data other can crlf. Following is the code I'm using:
1
2
3
4
5
6
string tempStr;
string strText;
while(!fileStream.eof()) {
   fileStream >> tempStr;
   strText += tempStr;
   } // end while 


The code works fine as long as the last line of the file has data. However, if the last line of the file is just a crlf, the program goes off into never-never land as EOF never gets set to TRUE (confirmed with cout statements in the loop.

Now I can make the problem go away if I use getline() instead of the >> extraction operator.

So my question is why isn't the extraction operator able to deal with an empty last line?

Thanks.

Jim
This is because the ">>" operator doesn't remove whitespace from the buffer, so technically "fileStream" never hits .eof(). Try this instead:

1
2
while(fileStream >> tempStr)
   {strText += tempStr;}
Last edited on
Hi Thanks for the answer.

So if I'm getting this right, the extraction operator is looking for data to send to the string. It sees and ignores the crlf but because those are the last data in the file, extraction never finds anything to send back before hitting eof and then just stalls there.

Whereas in the middle of the file it sees and ignores the "empty" crlf but finds data just beyond and reads until it hits the next crlf. Seeing that it has data, it then sends that data to the string and everything moves along.

Now if my logic above is correct, your example shouldn't work either because >> will have nothing to send. If it did, then why wouldn't it (or something) set eof to true?

Just tried out your code and get the following error:

This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.
terminate called after throwing an instance of 'std::ios_base::failure'
  what():  basic_ios::clear

Don't loop on EOF. The eof() status only gets signalled after you try (and fail) to read past the end of file.

Instead, use the good() status, as Computergeek01 correctly showed you.

The error message you are getting indicates that something other than what you showed us is happening. Please post your exact code and we can help you fix it.
@computergeek01
the answer you posted for OP sorted out a bug with a program i've been working on, now its bug-free! haha thanks for the words of wisdom =P
Hi Duoas,
Regarding your comment about good() status by Computergeek0, he made no such statement.

Regarding your comment about the error message, I did a straight substitution replacing
1
2
3
4
while(!fileStream.eof()) {
   fileStream >> tempStr;
   strText += tempStr;
   } // end while  

with
1
2
while(fileStream >> tempStr)
   {strText += tempStr;}


For me the objective is to understand why
fileStream >> tempStr;
fails but
getline(fileStream,tempStr);
works when the last line of the file is just a crlf. It seems to me that both should work, as they both do if the last line of the file contains data.

@ OP: C++ is what I like to call fun. I technically did say to test on good() because good() returns false if any of the internal ifstream error flags are set to true, operations such as 'while' and 'if' check good() implicitly. The ">>" or extraction operator sets the failbit flag when there is nothing left to read between the current position and the end of file which would cause good() to return false. But you are correct in the sense that I did not literally say to test on ifstreamobj.good().

To answer you question; where as the extraction operator ">>" ignores whitespace, the getline() command delimits itself on the newline character (when it is given two arguments). So with getline() you will eventually hit the end of the file with the "crif" extracted.

EDIT: By the way, you usually use the term "crif" when you are refering to the last blank line in a page of code. Your persistence in using this term for the file you are reading did catch my attention but until now I've been dismissing it. But now I'm curious, what is it that you're doing exactly?
Last edited on
Hi Computergeek,
Understood regarding comment on "good".

Still having trouble with it. Using the following code:
1
2
3
4
while(!fileStream.eof()) {
  getline(fileStream,tempStr);
   strText += tempStr;
   } // end while  


I thought I had a working program but it started failing on the last line of the input file when running it against a real file vs the test file.

I'm unclear on your comment re my use of crlf. I never used it to refer to the file - only to data lines within the file, particularly the last line.

What I'm trying to do is to read an html file created by MS Word and strip out all the crud leaving only unstyled standard tags. That code is all working. The problem is now that I'm working with a MS Word created file the program dies when it hits the last line of the file. I've tried testing for eof, testing for good, using extraction, using getline. All these methods fail. I don't understand why C++ falls on its face on the last line of the file.

I guess that I must assume that I am incorrectly reading the file. So how do I read a file into a single string defined as string tempStr? Everything I've tried so far works just fine - right up until the last line of the file and then it dies.





Well this is bizarre.

I went back to the getline code but added a try catch to see what was going on:
1
2
3
4
5
6
7
8
9
      while(fileStream.good()) {
       lineNumber++;
       cout << "Reading Line " << lineNumber << endl;
       try { getline(fileStream,tempStr); }
       catch(exception& e) {
          cout << "getline Error: " << e.what() << endl;
         }
       strText += tempStr;
        } // end while 


Darned if it didn't correctly read the file and not mysteriously stop working inside the while loop.

Just for grins, I removed the try-catch block and recompiled the program. Sure enough it goes belly-up when it hits the last line of the input file.

Adding the try-catch back in and recompiling - and the program works.

So why does getline work when it is placed inside a try {} but fail when the try{} is absent????????




I don't really get why you are being so obtuse.

If all you want is to read lines from file into a string, use something like:

1
2
while (getline( fileStream, tempStr ))
  strText += tempStr;

Unless you have set the ios::exceptions flag, or you got the stream from a user (as in -- your code is library code), you don't need the try..catch stuff, as it will not change the way your code behaves.

Keep in mind that debuggers do modify the behavior of your program...

So if things don't work right then either there is something wrong with your compiler or there is some code affecting it we don't know about.
Topic archived. No new replies allowed.