-
sequential access file
ok, heres the problem, whenever i run this function it displays the proper results from the file, but the prints out a empty set of record fields :( i know its running through the while loop one extra time, but i dont know how to stop it! anyone have any suggestions??
Code:
void Displayallcustomers()
{
string LASTNAME, FIRSTNAME, STREETADDRESS, CITY, PROV, POSTALCODE;
ifstream infile;
infile.open("customers.dat", ios::in);
if (infile.is_open())
{
while (!infile.eof())
{
getline(infile, LASTNAME, '#');
getline(infile, FIRSTNAME, '#');
getline(infile, STREETADDRESS, '#');
getline(infile, CITY, '#');
getline(infile, PROV, '#');
getline(infile, POSTALCODE, '#');
cout <<"Last Name:" << LASTNAME << "" <<endl;
cout <<"First Name:" << FIRSTNAME << "" <<endl;
cout <<"Street Address:" << STREETADDRESS << ""<<endl;
cout <<"City:" << CITY << "" <<endl;
cout <<"Province:" << PROV << "" <<endl;
cout <<"Postal Code:" << POSTALCODE << ""<<endl;
}
infile.close();
}
else
cout<<"YOU HAVE SELECTED AN INVALID OPTION"<<endl;
}
Tagged by Salem
-
You could start off by using code tags so I can read you code. THen you could change your while into a do while.
-
I think it has to do with how streams work. It is my understanding that every time you call a method from a class derived from the ios class (ifstream is derived from istream wchich is derived from ios) it sets one or more bits in the stream "state". The "state" of the stream can then be evaluated by using other methods. In this case, the eof() method is called to evaluate the state of the stream to see if the last input resulted inputting EOF. If it did then eof() returns a non-zero value, otherwise it returns 0.
The problem you are running into is that eof() checks the state of the stream but isn't a call for input per se.
Let's use an example to try to clarify this. Say the file has two ints in it like this:
1
2
and you want to read the file like this--mimicking what you do:
while(!infile.eof())
{
infile >> num;
cout << num;
}
What happens is that when the condition for while is checked before the first input is done, the EOF hasn't been found yet, so calling eof() returns 0, and !0 is evaluated to true. The program then reads in the first int and prints it to the screen. The first call to >> didn't result in finding EOF so when the conditional of while is checked again eof() still returns 0 and !0 is still true so the second int is read in and printed to the screen. So far so good. But now pay attention because here is the crux of the problem. The program has read in the last int from the file, but EOF still hasn't been found, so when the conditional of the while is checked again eof() still returns 0 and !0 is still true so there is a third passage through the body of the while loop, but there's nothing for infile to read in! You happen to get blanks as infile tries to read something in, other times you may get a double entry of the last piece of data, or some other wierd stuff, it's hard to say. The point is that EOF hasn't been found which means eof() still is going to return 0 which means !0 is true and you've got a problem.
Now check this out. Same file, same code, with slight modification.
infile >> num;
while(!infile.eof())
{
cout << num;
infile >> num;
}
Now the first call to infile occurs before the while loop. It doesn't result in reading in EOF so !eof() returns true and the value of num is printed to the screen. This time the call to infile in the loop comes after the call to cout << rather than before. And this is the crucial move, infile is called just before the call to while() a second time, and it works. Now at the end of the second run through the while loop infile >> num is called a third time. This time it does find EOF and the condition of the while turns positive and the loop stops without running a third time resulting in reading in just two values of num like you intended it to.
IMO this is the proper way to do it. The other "fixes" already posted, do/while instead of while and while(getline()) will probably work okay as long as the file isn't empty to begin with, but they are likely to lead to problems if the file is empty to begin with, whereas this method won't. (I'll leave it up to you to work this out.)
Therefore my suggestion to fix your code is as follows:
Code:
if (infile.is_open())
{
getline(infile, LASTNAME, '#')
while (!infile.eof())
{
getline(infile, FIRSTNAME, '#');
getline(infile, STREETADDRESS, '#');
getline(infile, CITY, '#');
getline(infile, PROV, '#');
getline(infile, POSTALCODE, '#');
cout <<"Last Name:" << LASTNAME << "" <<endl;
cout <<"First Name:" << FIRSTNAME << "" <<endl;
cout <<"Street Address:" << STREETADDRESS
<< ""<<endl;
cout <<"City:" << CITY << "" <<endl;
cout <<"Province:" << PROV << "" <<endl;
cout <<"Postal Code:" << POSTALCODE << ""<<endl;
getline(infile, LASTNAME, '#');
}
Sorry for such a long winded answer, but it's not an easy concept to write about.