问题
Hello i had a simple copy file program in C but i cant explain why i get different output in the destination file when i use the 2nd method. The correct output with for loop:
I am the worst programmer in the world!
:D
And this is bla bla bla bla
more bla bla bla...
BUT with while loop a random char is generated in EOF:
I am the worst programmer in the world!
:D
And this is bla bla bla bla
more bla bla bla...
The code is
int main()
{
int i;
char ch;
create_files();
FILE *src = fopen("best.txt", "r");
FILE *dst = fopen("copied.txt", "w");
for(i=getc(src); i!=EOF; i=getc(src)) //correct copy
{
putc(i, dst);
}
/* while(!feof(src)) //woot?
{
ch=fgetc(src);
fputc(ch,dst);
}*/
fclose(dst);
fclose(src);
return 0;
}
void create_files()
{
FILE *fp;
fp = fopen("best.txt","w");
fprintf(fp,"I am the worst programmer in the world!\n:D\n And this is bla bla bla bla\n more bla bla bla...\n");
fclose(fp);
}
i ve used both fputc or putc and fgetc or getc and still the same. Did i forget something?
回答1:
What
while (!feof(src)) {
ch=fgetc(src);
fputc(ch,dst);
}
does, is:
- check for EOF
- read a character, possibly causing EOF
- output the character just read, without checking for EOF.
When EOF occurs, (3) is still executed before the check in (1) in the next iteration. The special value EOF
is converted to a char
and output.
The correct loop is
while ((ch = fgetc(src)) != EOF)
fputc(ch, dst);
assuming you give ch
the type int
, because a char
cannot represent EOF
. Note the assignment within the check; some programmers will tell you that's ugly, but so many use it that you might as well get used to it. Your variant for
loop is correct as well.
(Aside 1: fputc
is equivalent to putc
and fgetc
to getc
, as long as you don't try to use them in a function pointer context.)
(Aside 2: your while
loop also doesn't check for stream errors, while checking for EOF
returns catches that as well.)
回答2:
The first loop fetches the character (possibly detecting the EOF) and then checks the value didn't detect an EOF and possibly executes the block writing the character (until all characters have been read).
The second loop checks to see if an EOF was detected, fetches the character (possibly detecting an EOF), writes the character (without regard as to what it might be), and possibly continues onto the next character (if EOF wasn't detected).
In the second loop, you write the character before checking if it is a EOF.
回答3:
The while loop gives you a random character because EOF isn't actually flagged until a read fails. So what's happening in your while loop isyou do a read, fgetc
fails, sets EOF, and returns a duff value back to you, which you then print.
A better way to structure the while loop would be:
ch=fgetc(src);
while (!feof(src)) {
fputc(ch,dst);
ch=fgetc(src);
}
回答4:
Your while
loop has an off-by-one error. It reads/writes an extra character, which is where that bonus
is coming from - you wrote the EOF value returned by fgetc()
into the output file!
回答5:
Edit
Looks like this isn't the actual problem, but I'll keep the answer as an advice.
The only thing I noticed is:
char ch;
Depending on your system, char
can be signed or unsigned, enough to hold a EOF or not enough. Your while
loop is probably demonstrating that your OS fits in the latter case.
Use int
instead and give it a try.
来源:https://stackoverflow.com/questions/8857963/different-output-content-file-copy-in-c