0

Possible Duplicate:
End of File in C++

I wrote a function to read data from a .txt file, but when I call it, it keeps crashing. Here's the code:

void beolvas(vector<int> &charge, vector<int> &deliver, vector<Robot*> &robots) { string s; ifstream f; do { cout << "Add meg a filenevet" << endl; cin >> s; f.open(s.c_str()); } while (!f.good()); cout << "adatok beolvasasa..." << endl; int napok; if (!(f >> napok)) throw 1; charge.resize(napok); deliver.resize(napok); for (int i = 0; i<napok; i++) { if (!(f>>charge[i])) throw 1; if (!(f>>deliver[i])) throw 1; } string type, name; int battery; while (!f.eof()) { cout << " a "; if (f>>type && f>>name && f>>battery) { if (type=="Mac") { Mac r = Mac(name,battery); robots.push_back(&r); }; if (type=="Eco") { Eco r = Eco(name,battery); robots.push_back(&r); }; if (type=="Pro") { Pro r = Pro(name,battery); robots.push_back(&r); }; }; }; } 

It seems the problem occurs in the while loop. If I want to read from a 3 row long text, I get 4 letter a-s on the screen (I have the program print one before reading every row).

Is f.eof() not the function I need to use here?

1
  • eof() is always wrong. There are hundreds of duplicates on SO. Commented Dec 20, 2012 at 14:10

2 Answers 2

1

This is one of the most common problems with reading from files. Checking f.eof() will only tell if you the previous read hit the end of the file. Hence, after the last successful read (where you got your third "a" printed), eof() returns false and your loop executes one more time, outputting an extra "a".

Instead, use your extraction line as the condition for your while loop:

while (f>>type && f>>name && f>>battery) { if (type=="Mac") { Mac r = Mac(name,battery); robots.push_back(&r); } if (type=="Eco") { Eco r = Eco(name,battery); robots.push_back(&r); } if (type=="Pro") { Pro r = Pro(name,battery); robots.push_back(&r); } } 

This works because as soon as one of your extractions hits the end of the file, the while condition will be false and the loop won't execute.

If you want to continue after badly formatted lines, I recommend that you use std::getline instead:

std::string line; while (std::getline(f, line)) { std::stringstream ss(line); if (ss >> type && ss >> name && ss >> battery) { // ... } } 

The reason for using this std::getline approach is because you would have had a problem if half of a line had been correctly formatted. Your approach would have read in perhaps type and name then failed on battery and the next iteration of the loop would have started from the same place.

You're also going to have a problem with the fact you're pushing pointers to objects that have automatic storage duration into some vectors. When the block in which the objects are created ends, the pointers will be pointing to an invalid object.

Sign up to request clarification or add additional context in comments.

2 Comments

thank you :) but wont this result in the program quitting the loop if it finds a "wrong" line? i would want to read in all lines given in a correct form
The function f.eof() may or may not return true if the previous input succeeded. It's only useful after you know that an input has failed; if it returns true, there's a good chance that the previous input failed because of end of file (but even that is not guaranteed).
0

This is a FAQ. In C/C++, the end-of-file condition is triggered only after you have tried to read past the end. So, you can't assume from feof() == false that input is available (because you could be exactly at the end of the file, but not yet past it). You should always test for valid input after a read operation.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.