2

您好,我在 C 语言中有一个简单的复制文件程序,但我无法解释为什么当我使用第二种方法时我在目标文件中得到不同的输出。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

什么

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

确实,是:

  1. 检查EOF
  2. 读取一个字符,可能导致 EOF
  3. 输出刚刚读取的字符,而不检查 EOF。

当 EOF 发生时,(3) 仍然会在下一次迭代中的 (1) 签入之前执行。特殊值EOF转换为 achar并输出。

正确的循环是

while ((ch = fgetc(src)) != EOF)
    fputc(ch, dst);

假设你给出ch类型int,因为 achar不能代表EOF。注意检查中的分配;一些程序员会告诉你这很难看,但有很多人使用它,你不妨习惯它。您的变体for循环也是正确的。

(旁白 1:fputc等价于putcand fgetcto getc,只要您不尝试在函数指针上下文中使用它们。)

(旁白 2:您的while循环也不会检查流错误,同时检查EOF返回也会捕获。)

于 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

while 循环为您提供了一个随机字符,因为在读取失败之前实际上并未标记 EOF。因此,您的 while 循环中发生的事情是您进行读取,fgetc失败,设置 EOF,然后将 duff 值返回给您,然后您将其打印出来。

构建 while 循环的更好方法是:

ch=fgetc(src);
while (!feof(src)) {
   fputc(ch,dst);
   ch=fgetc(src);
}
于 2012-01-13T22:22:19.420 回答
0

编辑

看起来这不是实际问题,但我会保留答案作为建议。


我唯一注意到的是:

char ch;

根据您的系统,char可以签名或未签名,足以容纳 EOF 或不够。您的while循环可能表明您的操作系统适合后一种情况。

改用int并试一试。

于 2012-01-13T22:19:13.083 回答