2

こんにちは私はCで簡単なコピーファイルプログラムを持っていましたが、2番目の方法を使用したときに宛先ファイルで異なる出力が得られる理由を説明できません。forループを使用した正しい出力:

I am the worst programmer in the world!
:D
 And this is bla bla bla bla
 more bla bla bla...

ただし、whileループを使用すると、EOFでランダムな文字が生成されます。

I am the worst programmer in the world!
:D
 And this is bla bla bla bla
 more bla bla bla...


コードは

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);
}

私はfputcまたはputcとfgetcまたはgetcの両方を使用しましたが、それでも同じです。何か忘れましたか?

4

5 に答える 5

2

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.)

于 2012-01-13T22:25:07.893 に答える
1
于 2012-01-13T22:19:18.733 に答える
1

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.

于 2012-01-13T22:21:13.463 に答える
1

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);
}
于 2012-01-13T22:22:19.420 に答える
0

編集

これは実際の問題ではないようですが、アドバイスとして答えを残しておきます。


私が気付いた唯一のことは:

char ch;

システムに応じてchar、EOFを保持するのに十分な場合もあれば、十分でない場合もあります。あなたのwhileループはおそらくあなたのOSが後者の場合に適合することを示しています。

int代わりに使用して、試してみてください。

于 2012-01-13T22:19:13.083 に答える