0

I know that function "eof" (cpp) return "True" only after wrong try to read from file (and not when i arrived to the end of file)

Because of that if we want to move all the file from 1 to another we must do

infile.get(c);
while ( !infile.eof() )
{
   outfile << c;
   infile.get(c);
}

and not

while ( !infile.eof() )
{
   infile.get(c);
   outfile <<c;
}

because if we do the seconde way the last char will copy 2 time

But on another program it not work like that

I create file grades.txt and write on it "dani"

Code like this:

ifstream inGrade("grades.txt");
ofstream outRoster("roster.txt");

int tmpGrade;
inGrade >> tmpGrade;

while (!inGrade.eof() ) 
{

    outRoster << tmpGrade <<endl ;
    inGrade >> tmpGrade;
}

It creates 'roster.txt" but copies nothing into it.

But if I use this code:

ifstream inGrade("grades.txt");
ofstream outRoster("roster.txt");

int tmpGrade;


while (!inGrade.eof() ) 
{
    inGrade >> tmpGrade;
    outRoster << tmpGrade <<endl ;

}

It will create the roster.txt and copy the "dani" to there

Why??? Why on this example eof return false when we arrive to the end of file, and not after wrong try to read from file.

Leo
  • 1,034
  • 9
  • 23
dani1999
  • 93
  • 1
  • 9

2 Answers2

1

I create file grades.txt and write on this "dani"

All your read operations should fail, because "dani" cannot be extracted as an integer. This sets the failbit of the stream but does not consume any characters and therefore doesn't set eofbit. Both your programs should be stuck in an infinite loop.

fix i not put dani i put "100"

Ok, then you won't get the infinite loop :) I've written a program to demonstrate the problem:

istringstream input("100");
int foo;

cout << "Reading int succesfully" << endl;
input >> foo;
cout << "!input:\t" << boolalpha << !input << endl;
cout << "input.eof():\t" << boolalpha << input.eof() << " << pay attention" << endl << endl;
cout << "Attempting to read eof" << endl;
input >> foo;
cout << "!input:\t" << boolalpha << !input << endl;
cout << "input.eof():\t" << boolalpha << input.eof() << endl << endl;

input.clear();
input.str("c");
char c;

cout << "Reading char succesfully" << endl;
input >> c;
cout << "!input:\t" << boolalpha << !input << endl;
cout << "input.eof():\t" << boolalpha << input.eof() << " << pay attention"  << endl << endl;
cout << "Attempting to read eof" << endl;
input >> c;
cout << "!input:\t" << boolalpha << !input << endl;
cout << "input.eof():\t" << boolalpha << input.eof() << endl << endl;

And the output:

Reading int succesfully
!input:      false
input.eof(): true << pay attention

Attempting to read eof
!input:      true
input.eof(): true

Reading char succesfully
!input:      false
input.eof(): false << pay attention

Attempting to read eof
!input:      true
input.eof(): true

So, the behaviour of eofbit is different when reading a single character compared to when reading a formatted input such as numbers.

Therefore if you want to modify your version of the loop such that it behaves the same way for numbers and characters, you'll need to check the streams status using the bool conversion instead of eof(). Additionally, that would prevent infinite loop on invalid input. You could use fail() instead but that doesn't check for badbit so it won't have desired behaviour when you get i/o error.

infile.get(c);
while (infile) // or !infile.fail() if you have infallible hardware
{
   // use c
   infile.get(c);
}

Should work as well as

int tmpGrade;
inGrade >> tmpGrade;
while (inGrade) 
{
    // use tmpGrade
    inGrade >> tmpGrade;
}

However, your approach duplicates the input call. You can avoid that by getting the input in the loop condition:

while (inGrade >> tmpGrade)
{
    // use tmpGrade
}
eerorika
  • 181,943
  • 10
  • 144
  • 256
  • fix i not put dani i put "100" – dani1999 Feb 20 '15 at 12:17
  • @dani1999 ah, I'll expand my answer. – eerorika Feb 20 '15 at 13:01
  • what do you mean please? – dani1999 Feb 20 '15 at 13:04
  • @dani1999 I meant that I was going to add more information to my answer. It's updated now. – eerorika Feb 20 '15 at 13:22
  • yeh int tmpGrade; inGrade >> tmpGrade; while (inGrade) { // use tmpGrade inGrade >> tmpGrade; } work well so use like that and not eof? i will happy if you can explian me again with simpli why fstream inGrade("grades.txt"); ofstream outRoster("roster.txt"); int tmpGrade; inGrade >> tmpGrade; while (!inGrade.eof() ) { outRoster << tmpGrade <> tmpGrade; } not work – dani1999 Feb 20 '15 at 14:45
0

Formatted input will trigger the end-of-file condition if the end of the file is reached while reading a value. This means that your "corrected" loop will fail to output the final value, if there's nothing after it in the input file. In particular, if there's only one value in the input file, there won't be any output.

Instead of checking for the end of the file, you need to keep trying to read until the read fails. The last value won't fail (but might set eof); the next attempt after that will fail, indicating that you should stop.

As a bonus, the code to do this is rather less confusing than your back-to-front loop:

while (inGrade >> tmpGrade) {
    outRoster << tmpGrade << endl;
}
Mike Seymour
  • 235,407
  • 25
  • 414
  • 617