By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
446,194 Members | 889 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 446,194 IT Pros & Developers. It's quick & easy.

EOF problem

P: 8
I have a function that is suppose to read a list of records from a text file into a linked list. But if the file doesn't exist it is suppose to create one. I tried a while (!file.eof()) but it still seems to run through the loop once even if is an already existing or newly created empty file. By running through the loop it is filling my linked list with garbage values and results in later crashing when trying to access the linked list.

Expand|Select|Wrap|Line Numbers
  1. void read_file(acnt *rec_temp, int &total_rec)
  2. {
  3.     fstream file;
  4.     char string[100];
  5.     acnt *head = rec_temp;
  6.  
  7.     file.open("banks.txt", ios::in | ios::app);                            //open file
  8.  
  9.     if(!file)                                                            // if file could not be opened
  10.     {
  11.     cerr << "Error: File could not be opened!" << endl;
  12.     exit(1);
  13.     }
  14.  
  15.  
  16.     if (!file.eof())                                                    //if file is not empty
  17.     {
  18.         while (!file.eof())                                                //read until end of file
  19.         {
  20.             file >> rec_temp->number;
  21.  
  22.             file >> string;
  23.             rec_temp->fname = new name;
  24.             rec_temp->fname->new_name(string);
  25.  
  26.             file >> string;
  27.             rec_temp->lname = new name;
  28.             rec_temp->lname->new_name(string);
  29.  
  30.             file >> rec_temp->balance;
  31.  
  32.             rec_temp->next = new acnt;
  33.             rec_temp->next->prev = rec_temp;
  34.             rec_temp = rec_temp->next;
  35.  
  36.             total_rec++;
  37.         }
  38.  
  39.         file.close();
  40.  
  41.         rec_temp->prev->next = NULL;
  42.         delete rec_temp;
  43.         head->prev = NULL;
  44.     }
  45.     else                                                                //File is empty, set list to NULL
  46.     {
  47.         rec_temp = NULL;
  48.         rec_temp->number = NULL;
  49.         rec_temp->fname = NULL;
  50.         rec_temp->lname = NULL;
  51.         rec_temp->balance = NULL;
  52.         rec_temp->next = NULL;
  53.         rec_temp->prev = NULL;
  54.     }
  55. }
  56.  
Feb 18 '07 #1
Share this Question
Share on Google+
11 Replies


AdrianH
Expert 100+
P: 1,251
I have a function that is suppose to read a list of records from a text file into a linked list. But if the file doesn't exist it is suppose to create one. I tried a while (!file.eof()) but it still seems to run through the loop once even if is an already existing or newly created empty file. By running through the loop it is filling my linked list with garbage values and results in later crashing when trying to access the linked list.

Expand|Select|Wrap|Line Numbers
  1. void read_file(acnt *rec_temp, int &total_rec)
  2. {
  3.     fstream file;
  4.     char string[100];
  5.     acnt *head = rec_temp;
  6.  
  7.     file.open("banks.txt", ios::in | ios::app);                            //open file
  8.  
  9.     if(!file)                                                            // if file could not be opened
  10.     {
  11.     cerr << "Error: File could not be opened!" << endl;
  12.     exit(1);
  13.     }
  14.  
  15.  
  16.     if (!file.eof())                                                    //if file is not empty
  17.     {
  18.         while (!file.eof())                                                //read until end of file
  19.         {
  20.             file >> rec_temp->number;
  21.  
  22.             file >> string;
  23.             rec_temp->fname = new name;
  24.             rec_temp->fname->new_name(string);
  25.  
  26.             file >> string;
  27.             rec_temp->lname = new name;
  28.             rec_temp->lname->new_name(string);
  29.  
  30.             file >> rec_temp->balance;
  31.  
  32.             rec_temp->next = new acnt;
  33.             rec_temp->next->prev = rec_temp;
  34.             rec_temp = rec_temp->next;
  35.  
  36.             total_rec++;
  37.         }
  38.  
  39.         file.close();
  40.  
  41.         rec_temp->prev->next = NULL;
  42.         delete rec_temp;
  43.         head->prev = NULL;
  44.     }
  45.     else                                                                //File is empty, set list to NULL
  46.     {
  47.         rec_temp = NULL;
  48.         rec_temp->number = NULL;
  49.         rec_temp->fname = NULL;
  50.         rec_temp->lname = NULL;
  51.         rec_temp->balance = NULL;
  52.         rec_temp->next = NULL;
  53.         rec_temp->prev = NULL;
  54.     }
  55. }
  56.  
Sorry, there is not enough here to compile.

However, one pointer I have is that you make your class acnt do the filling of the class/struct acnt.

A class should do operations on itself for itself. This is because it knows itself best and it localises the code affecting acnt objects in one location. This allows you transfer or to do those operations elsewhere in your system without having to copy code.

To allow for doing an operation like this:
Expand|Select|Wrap|Line Numbers
  1. cin >> *rec_temp;
add the following member to you acnt class(or struct as they are almost equivilant)
Expand|Select|Wrap|Line Numbers
  1. class acnt
  2. {
  3. ...
  4. public:
  5.   std::istream& operator>>(std::istream& lhs) // lhs = left hand side of operator
  6.   {
  7.     // Fill this object with data such as:
  8.     lhs >> number;  // replaces file >> rec_temp->number
  9.  
  10.     return lhs;
  11.   }
  12. ...
  13. };
  14.  
Hope this helps,


Adrian
Feb 18 '07 #2

RRick
Expert 100+
P: 463
I can not get this code to create a non-existent file with ios::in and ios:app open modes. I'm using gnu 3.4.5. The following link (http://rafb.net/efnet_cpp/tutorials/..._openmode.html) says that gnu is using the correct behavior. You should be able to create a new file only with trunc. I really don't know which compiler is right.

There is another option you can try: ios::ate. This sets the pointer to the end of the file at creation. This might work with your system. I suspect that eof is not set on creation of the file with ios:app because ios::app is meant to be used with writing, not reading. You might need to do a read before eof is set. Maybe the ios::ate open will fix this.

Why are you opening a data file with read/write permissions? Generally, data files are read only and opening them with write permission is a bug waiting to happen.
Feb 18 '07 #3

P: 8
AdrianH:

It's been a while since I did c++ programming and I couldn't remember how to do overloaded operators. This is just a homework assignment (one where I have already gone way beyond what was required) but if I get this problem figured out, I will might try to go back and clean up the code some (like what you suggested). I will also post the code in it's entirety so you can compile it.

RRick:

I will try some of the different methods you suggested. I'm not worries about the security of the program (like I said this is just a homework assignment), but the reason for having ios::in and ios:app is because I didn't know how else to create a file if it didn't exist.



Here's the code for the entire program:
***Code moved to next post becuase it was too long***


It seems to work fine if a file already exist and has at least one account stored in it. But with no stored data the program crashes. If you want to make a file to test it with, just call it "banks.txt" and put one record in it like this:

500 Mary Jane 789.79

Make sure there is no newline after "789.79"
Feb 18 '07 #4

AdrianH
Expert 100+
P: 1,251
It seems to work fine if a file already exist and has at least one account stored in it. But with no stored data the program crashes.
Sorry for deleting your code, but posting the entire thing is a bad idea due to copiers (bad students) on the forums.

However, your last statement tells me what you are doing wrong:
Expand|Select|Wrap|Line Numbers
  1.     }
  2.     else                                                                //File is empty, set list to NULL
  3.     {
  4.         rec_temp = NULL;
  5.         rec_temp->number = NULL;
  6.         rec_temp->fname = NULL;
  7.         rec_temp->lname = NULL;
  8.         rec_temp->balance = NULL;
  9.         rec_temp->next = NULL;
  10.         rec_temp->prev = NULL;
  11.     }
  12.  
If you notice, you are setting rec_temp to NULL. Just after it you then set everything in it to NULL. Now if you point at something, you can set anything in it to whatever you like. But if you point at nothing, is there anything in it to set?

Tell me if you get what I am saying.


Adrian
Feb 19 '07 #5

P: 8
AdrianH:

Yeah that makes sense. So I should just set rec_temp to NULL (I thought about that but wasn't sure when I wrote it). But actually that whole if statement (and the else) was added after the fact that I was having problems with my loop, to try and fix my problem.
For some reason, it will always never execute the else statement (the part where everything was set to NULL). my code had this statement written in it:

Expand|Select|Wrap|Line Numbers
  1. if (! file.eof)
  2. {
  3.         while(! file.eof)
  4.         {
  5.         .....
  6.         }
  7. }
  8. else
  9. {        
  10.         rec_temp = NULL;
  11.         .....
  12. }
  13.  
I will always

Regardless of the fact that file may be empty or had just been created (and therefore empty), it always executes the if and while loop....never the else. and if it is an empty file it runs the while loop only once. Why doesn't the "! file.eof" statement work?


P.S.
No worries about deleting the code, I understand.
Feb 19 '07 #6

AdrianH
Expert 100+
P: 1,251
AdrianH:

Yeah that makes sense. So I should just set rec_temp to NULL (I thought about that but wasn't sure when I wrote it). But actually that whole if statement (and the else) was added after the fact that I was having problems with my loop, to try and fix my problem.
For some reason, it will always never execute the else statement (the part where everything was set to NULL). my code had this statement written in it:

Expand|Select|Wrap|Line Numbers
  1. if (! file.eof)
  2. {
  3.         while(! file.eof)
  4.         {
  5.         .....
  6.         }
  7. }
  8. else
  9. {        
  10.         rec_temp = NULL;
  11.         .....
  12. }
  13.  
I will always

Regardless of the fact that file may be empty or had just been created (and therefore empty), it always executes the if and while loop....never the else. and if it is an empty file it runs the while loop only once. Why doesn't the "! file.eof" statement work?


P.S.
No worries about deleting the code, I understand.
Oh, I see. The reason why the ! file.eof statement doesn't work... mmmm, no wait, your code within the if and within the loop should never execute. The reason is that the eof member is not a member variable but a member function. Your statement is getting the pointer to the function. An ! in front of it should make it 0. I don't know why your code is executing the way it is, but try putting an empty set of parenthesis after the eof. This will then execute the member function and not get its address.

Try that and let me know the results. If it works like I think it should, you can remove the exterior if around the while loop as the while loop will not execute when it reaches the end of the file.


Adrian
Feb 19 '07 #7

P: 8
Oops, when i typed that last bit of code I forgot the "()" after the eof. But it actually is there is there in my code. So, no that still doesn't work for some reason.
Feb 19 '07 #8

AdrianH
Expert 100+
P: 1,251
Oh, sorry, didnít reread your first post. Ignore my last one. The problem is not the eof. You are using that correctly

I wrote a small programme to test this eof problem. Here it is:
Expand|Select|Wrap|Line Numbers
  1. #include <fstream>
  2. #include <iostream>
  3.  
  4. using namespace std;
  5. int main()
  6. {
  7.     fstream file;
  8.     file.open("banks.txt", ios::in | ios::app);
  9.     if (!file) {
  10.         cout << "File not opened" << endl;
  11.         exit(1);
  12.     }
  13.     while (!file.eof()) {
  14.         cout << "reading line: '";
  15.         char buffer[2000];
  16.         file.getline(buffer, 2000);
  17.         cout << buffer << "'" << endl;
  18.     }
  19. }
  20.  
I found that if the file exists, ios::app will cause it not to open. Probably because ios:app is an output flag, and you are opening an input stream. If you get rid of ios::app, it opens the file if it is there.

Now as to why the !file.eof() doesnít work... well, actually it does. You just havenít reached the end of the file since you havenít read from it yet. Try using file.peek() prior to the loop. This will cause the file to be read and if there is nothing in it, it will set the eof bit.

Hope this helps.


Adrian
Feb 19 '07 #9

DeMan
100+
P: 1,806
Hi,

I'm not entirely sure whether this applies here, but occasionally you see strange behaviour of eof in different languages because some check eof as "The next read will fail because there is nothing left" and others read it as "the previous read failed because there were no characters". Not being 100% familiar with the eof() method I can't be sure this is the problem, but I suspect you may need to attempt at least one read before you call file.eof().
Feb 19 '07 #10

AdrianH
Expert 100+
P: 1,251
Hi,

I'm not entirely sure whether this applies here, but occasionally you see strange behaviour of eof in different languages because some check eof as "The next read will fail because there is nothing left" and others read it as "the previous read failed because there were no characters". Not being 100% familiar with the eof() method I can't be sure this is the problem, but I suspect you may need to attempt at least one read before you call file.eof().
You are correct. Hence the need to call peek().


Adrian
Feb 19 '07 #11

DeMan
100+
P: 1,806
I have a habit of typing slowly, so I actually submitted before I saw your post (oops!!)
Feb 19 '07 #12

Post your reply

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