473,385 Members | 1,983 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,385 software developers and data experts.

Testing for End of File in I/O

I am experimenting with several ways to test for the end of file for an input file .txt
If, for example, I have a text (test.txt) file that had:

ab 5
fgd 3
fdfe 3
aasa 4
(intentionally blank line)
where the first input is a character array and the second is an integer value.

I could write
Expand|Select|Wrap|Line Numbers
  1.  
  2. #include<iostream>
  3. #include<fstream>
  4. using namespace std;
  5. int main(){
  6.     ifstream file;
  7.     char firstField[20];
  8.     int number;
  9.     bool endOfFile=false;
  10.     file.open("test.txt");
  11.     do{
  12.         if (file.eof()) endOfFile=true;
  13.         else{
  14.             file>>firstField>>number;
  15.             cout<<firstField<<number<<endl;
  16.         }
  17.         }while(!endOfFile);
  18.  
  19.     return 0;
  20. }
but then the last line is output twice becuase it(a pointer?) isn't to the end of the file when it is finished reading the last line of text.

Then I thought I could try this, to force it to read the final line which contained the eof indicator.
Expand|Select|Wrap|Line Numbers
  1. #include<iostream>
  2. #include<fstream>
  3. using namespace std;
  4. int main(){
  5.     ifstream file;
  6.     char firstField[20];
  7.     int number;
  8.     bool endOfFile=false;
  9.     file.open("test.txt");
  10.     do{
  11.         file.get();
  12.         file.get();
  13.         if (file.eof()){
  14.             endOfFile=true;
  15.         }
  16.         else{
  17.             file.unget();
  18.             file.unget();
  19.             file>>firstField>>number;
  20.             cout<<firstField<<number<<endl;
  21.         }
  22.         }while(!endOfFile);
  23.  
  24.     return 0;
  25. }
  26.  
This worked, but it just doesn't seem quite "standard"
Finally, I tried
Expand|Select|Wrap|Line Numbers
  1. #include<iostream>
  2. #include<fstream>
  3. using namespace std;
  4. int main(){
  5.     ifstream file;
  6.     char firstField[20];
  7.     int number;
  8.     file.open("test.txt");
  9.     while(file>>firstField){
  10.             file>>number;
  11.             cout<<firstField<<number<<endl;
  12.         }
  13.     return 0;
  14. }
  15.  
This method worked as well. Is there a format that professional programmers prefer? Is one more standard than the other? Is there a better, more efficient way to do this? Does one method have more flexibility than the other (i.e. there is no line left intentionally blank or there are several blank lines)?
Oct 15 '07 #1
2 4376
oler1s
671 Expert 512MB
If I had to make a list of top 10 things new programmers do wrong in C or C++, feof/eof would be on that list with certainty. Partly the trouble arises because many learning resources or other people's code is misleading or wrong. And partly because newcomers take a look at the function title (end of file) and jump to what seems to be a logical conclusion. They say: here's the logic I'm coding: (1) test if you're at the end of the file, and (2) if not, go ahead try to read in something.

Nice, but that's not what you coded. Take a very close look at eof. It never says eof returns true when you're at the end of the file. No, seriously, it doesn't. It says it returns true when the eofbit flag is set. Here's the big thing most newbies miss: eofbit is only set when there's a failed operation.

So let's say you read a bunch of times and reach the end of the file. How many failed operations have you had so far? None. Are you at the end of the file? Yes. Will eof return true? No, because there is no failed operation due to eof. See the impending doom? You're code assumes that if .eof() returns false, it's safe to go ahead and read from the file and do some operations on the input. But that file I/O operation will fail, and the last known input will be returned. Hence that last line repeating twice effect you see.

Which is why your second attempt that actually works is in reality an ugly, ugly, ugly hack. Your final piece of code comes across the right idea, although it isn't robust because of a mistake.

Everything has a return value. You as a programmer might not have the experience to code functions with meaningful error handling and return values, but the standard libraries most certainly have been designed in such a manner. File I/O, for example, has a return value, which you can use in a while loop, or in fact other test conditions. Worried about reaching the end of the file? Attempt to read, and check the return value. Actually, you should always check the return value regardless of whether you anticipate EOF or not. Anyway, if you do hit EOF, the return value will reflect the failure appropriately.

Your third example isn't quite robust because it assumes that if you can read in a firstfield, there is a number to read in as well. That's relying on well formed input file. Bad idea. A better idea is to use getline to take in a whole line and then parse appropriately with string streams.

As a side note, take a look at the C++ String class. It's preferable to using C-style character array strings, unless you have a good reason. Look at getline that's part of the string class, and also, look at string streams in C++.
Oct 15 '07 #2
Thanks for the very detailed response; it was very informative! I was considering using the getline function, but I wasn’t sure how I could parse the data inside of the string. Would it be correct to assume if I were to take in the entire line, and it happened to be an empty string, I could test for it and then end the loop?
Would you consider this code to be more robust?
Expand|Select|Wrap|Line Numbers
  1. #include<iostream>
  2. #include<fstream>
  3. #include<string>
  4. #include<cstring>
  5. using namespace std;
  6. int main(){
  7.     char a[4][5]={"ab", "fgd", "fdfe", "aasa"};
  8.     int value[4];
  9.     ifstream file;
  10.     string inputLine;
  11.     int number;
  12.     bool end=false;
  13.     file.open("test.txt");
  14.     do{
  15.         getline(file, inputLine);
  16.  
  17.         if (inputLine.length()!=0){
  18.             cout<<inputLine<<endl;
  19.         }
  20.         else{
  21.             end=true;
  22.             }
  23.     }while(!end);
  24.  
  25.     return 0;
  26. }
  27.  
Also, how would u recommend separating the elements in the string? Let’s say I wanted to compare the first part of each line with a predefined C-string to see if they were the same, and if they were, to store the integer value associated with it on the same line. For example if I had an integer array whose elements corresponded with the positions in C-string a.

Thanks for your time and insight!
Oct 15 '07 #3

Sign in to post your reply or Sign up for a free account.

Similar topics

2
by: Edvard Majakari | last post by:
Hi all ya unit-testing experts there :) Code I'm working on has to parse large and complex files and detect equally complex and large amount of errors before the contents of the file is fed to...
9
by: Peter Hansen | last post by:
The term "mock filesystem" refers to code allowing unit or acceptance tests to create, read and write, and manipulate in other ways "virtual" files, without any actual disk access. Everything is...
3
by: Brian van den Broek | last post by:
Hi all, I'm just starting to employ unit testing (I'm using doctest), and I am uncertain how to handle writing tests where the behaviour being tested is dependant on whether certain file paths...
3
by: Andrew | last post by:
Hi, I am thinking about ways for efficient techniques for isolation testing. Here is the problem as I see it: Complex OO systems are designed with massive number of dependencies between modules...
19
by: lihua | last post by:
Hi, Group! I got one question here: We all know that fclose() must be called after file operations to avoid unexpected errors.But there are really cases when you forget to do that!Just like...
72
by: Jacob | last post by:
I have compiled a set og unit testing recommendations based on my own experience on the concept. Feedback and suggestions for improvements are appreciated: ...
22
by: David Warner | last post by:
Greetings! I am working on a C app that needs to read print files generated by lp that contain HP LaserJet PCL codes. If the PCL contains binary data to define a bit map to be printed on the...
0
by: Matthew Fitzgibbons | last post by:
I'm by no means a testing expert, but I'll take a crack at it. Casey McGinty wrote: I've never run into this. Rule of thumb: always separate software from hardware. Write mock classes or...
3
by: CSharper | last post by:
In my solution, I seperate the code into one project and test into another project (NUnit). Now, in one of my test class, I need to reference a file. This file can not be created on the fly and it...
10
by: Brendan Miller | last post by:
What would heavy python unit testers say is the best framework? I've seen a few mentions that maybe the built in unittest framework isn't that great. I've heard a couple of good things about...
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.