Search code examples
cfile-copyingfgetcgetc

Different output content file copy in C


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?


Solution

  • What

    while (!feof(src)) {
        ch=fgetc(src);
        fputc(ch,dst);
    }
    

    does, is:

    1. check for EOF
    2. read a character, possibly causing EOF
    3. 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.)