Jake
Jake

Reputation: 742

Why is the last line of my input file running twice?

INPUT FILE

Miller Andrew 65789.87 5
Green Sheila 75892.56 9
Sethi Amit 74900.50 6.1

ifstream inFile;
ofstream outFile;
string laastName;
string firstName;
double salary;
double percent;
double new Salary;
double increase;

inFile.open("Ch3_Ex6Data.txt");
outFile.open("Ch3_Ex6Output.dat");

while(!inFile.eof()) {

    inFile >> lastName;
    inFile >> firstName;
    inFile >> salary;
    inFile >> percent;

    percent /= 100;
    increase = salary * percent;
    newSalary = increase + salary;

    outFile << firstName << " " << lastName << " ";
    outFile << setprecision(2) << fixed << newSalary << endl;

}

inFile.close();
outFile.close();

return 0
}

Output File

Andrew Miller 69079.36
Sheila Green 82722.89
Amit Sethi 79469.43
Amit Sethi 74946.19

My question is why is the last line getting output twice and why is it different than the first one? I don't understand why the loop continues on. Is the end of file marker not hitting? I was able to hard code it by putting in an index variable and putting a second condition into the while loop by saying && less than index but i feel as if i shouldn't have to do that whatsoever.

Upvotes: 3

Views: 7844

Answers (4)

Raindrop7
Raindrop7

Reputation: 3911

  • You used lastName but you declared laastName so remove the a and be cautious.

  • double new Salary: What is this? - I think you meant: double NewSalary if so please read a useful book about naming variables in C++ because you are deliberately messing up.

  • while(!inFile.eof()) Is not recommended so give up using it.

  • Missing semicolon ; at the end of main.

  • Your code will look like:

    int main()
    {
        ifstream inFile;
        ofstream outFile;
        string lastName;
        string firstName;
        double salary;
        double percent;
        double newSalary;
        double increase;
    
        inFile.open("Ch3_Ex6Data.txt");
        outFile.open("Ch3_Ex6Output.dat");
    
        while(inFile >> lastName >> firstName >> salary >> percent){
            percent /= 100;
            increase = salary * percent;
            newSalary = increase + salary;
    
            outFile << firstName << " " << lastName << " ";
            outFile << setprecision(2) << fixed << newSalary << endl;
    
        }
    
        inFile.close();
        outFile.close();
    
        return 0;
    }
    

Upvotes: 0

Emilio Garavaglia
Emilio Garavaglia

Reputation: 20759

The problem is that eof does not do what you think it does.

Imagine you are walking on a floor, tile after tile, picking up what's on the floor, putting it in your pockets and show up (print) your pockets content.

When you put you feet on the last tile the floor is not yet "ended" and your nose is still safe. You have not (yet) smashed the wall. You fill-up the pockets and print them.

eof,then, tells you when your nose is broken, not when the tile is the last.

So, you are on the last tile, check your nose, find it ok, and go one step forward. Your nose is now bleeding, nothing is there to peek up to put in our pockets, and your pockets still contain ... what they had before.

You print the content of your pocket (once again) and than check your nose. It's broken: you exit.

The idiomatic way to solve that problem is this one:

while(inFile >> lastName
             >> firstName
             >> salary
             >> percent)
{
   //all your computation here
}

I think you should understand by yourself why.

Upvotes: 5

Striezel
Striezel

Reputation: 3758

The eofbit does not get set when an input operation reaches the end of the stream (as in: reading the last line), but when an input operation tries to read data after the end of the stream (as in: trying to read data when there is no more data left, because the end of the file stream has been reached).

This means that finishing to read the last line in the file does not set the end of file bit, and eof() will still be false. Therefore your program runs into the next loop iteration, and only after the next read in the line

inFile >> lastName;

is carried out, the eofbit gets set. The last line is printed twice, because all the read operations during the last loop iteration fail and the variables still have the values from the previous loop iteration.

Edit: To prevent that you could check whether the read operations were successful, e.g. by using inFile.good() in the loop:

while(!inFile.eof()) {
    inFile >> lastName;
    inFile >> firstName;
    inFile >> salary;
    inFile >> percent;

    //check whether no errors occurred during the input operations
    if (!inFile.good())
    {
      //input failure, leave the loop
      break;
    }

    percent /= 100;
    increase = salary * percent;
    newSalary = increase + salary;

    outFile << firstName << " " << lastName << " ";
    outFile << setprecision(2) << fixed << newSalary << endl;  
}

Upvotes: 3

David Schwartz
David Schwartz

Reputation: 182855

You don't check if any of the reads succeed. You output stuff whether or not the reads failed.

Your code appears to expect eof() to predict whether or not a future read will succeed. But it does not predict the future. A future read can still fail.

Your last time through the loop, all the read operations fail, so all the variables still have their original values. You then output the last line again. Then you finally check for errors (the call to eof() the time in the loop), but it's too late.

Instead, why not just check if your reads succeed? That's what you really want to know.

By the way, this is a very common mistake that appears in many different contexts. The crux of the mistake is you try to check all the conditions necessary for something to succeed and then assume that the thing will succeed because you checked every way it could fail. This is a bad idea for at least three reasons. First, it's usually wasted effort. Second, things can change between when you checked and when you attempt the operation. Third, you may have missed one of the ways it could fail.

Here, all three reasons apply.

Upvotes: 2

Related Questions