So, fewdie's "
the code is complete and perfect" not so much attempt.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
|
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
#if 0
With an 'int' for the number, >> just barfs on numeric overflow and never gets
past the first record.
Read firstName=Jason=
Read lastName=Matthews=
Read birthYear=1997=
Read number=2147483647=
Read username==
Read password==
#endif
struct UserData {
UserData() :birthYear(-1), number(-1) {}
string firstName;
string lastName;
int birthYear;
long int number; //!! int is too short
string username;
string password;
};
UserData GetData(string username, const char* file)
{
ifstream infile;
UserData tmp;
infile.open(file);
if (infile.fail())
return UserData(); // failed to open file return an 'invalid' user
while (!infile.eof())
{
infile >> tmp.firstName
>> tmp.lastName
>> tmp.birthYear
>> tmp.number
>> tmp.username
>> tmp.password;
cout << "Read firstName=" << tmp.firstName << "=" << endl;
cout << "Read lastName=" << tmp.lastName << "=" << endl;
cout << "Read birthYear=" << tmp.birthYear << "=" << endl;
cout << "Read number=" << tmp.number << "=" << endl;
cout << "Read username=" << tmp.username << "=" << endl;
cout << "Read password=" << tmp.password << "=" << endl;
if (tmp.username == username)
return tmp; // user found
}
infile.close();
return UserData(); // user not found return an 'invalid' user
}
int main()
{
UserData user = GetData("nobody", "foo.txt");
}
| |
With this input
$ cat foo.txt
Jason Matthews 1997 6782349567 user1997 pass1997
Kelsey James 1980 2484560234 user1980 pass1980
John Doe 1990 4567890231 user1990 pass1990
|
Wait for it.....
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
|
$ ./a.out
Read firstName=Jason=
Read lastName=Matthews=
Read birthYear=1997=
Read number=6782349567=
Read username=user1997=
Read password=pass1997=
Read firstName=Kelsey=
Read lastName=James=
Read birthYear=1980=
Read number=2484560234=
Read username=user1980=
Read password=pass1980=
Read firstName=John=
Read lastName=Doe=
Read birthYear=1990=
Read number=4567890231=
Read username=user1990=
Read password=pass1990=
Read firstName=John=
Read lastName=Doe=
Read birthYear=1990=
Read number=4567890231=
Read username=user1990=
Read password=pass1990=
| |
Yep, that's right.
Failing to check for end of file properly, and failing to check the result of the >> operators means effectively processing the last record twice.
Nothing was actually read on the 4th pass, it's just whatever happened to be lying around in memory at that time. The eof() wasn't going to stop the 4th pass because eof() was still false. Had the code being doing what it should have, and checking the actual status of >>, it would have known there was nothing to do on the 4th pass.
What's in the variables?
Maybe it's the last data, maybe it's a completely new object, maybe it's a pile of garbage.
Regardless, it was there and the code tried to do something with it.
If you're lucky, the garbage doesn't result in a crash or a false match.
Try copying say a BMP file with a poorly written eof() loop and then wonder why all your graphics programs spit it back as a malformed image.
> eof() leads to errors maybe yes but not in my code
Today's half-assed hack is tomorrow's obscure bug.