【问题标题】:Different output content file copy in CC中不同的输出内容文件副本
【发布时间】:2012-01-13 22:13:52
【问题描述】:

您好,我在 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 并且仍然相同。我是不是忘记了什么?

【问题讨论】:

  • feof() 不会像您认为的那样做。阅读文档。它不会测试下一次读取是否会尝试读取文件末尾;它检查最后一次失败读取尝试是否因为已经到达文件结尾而失败。
  • @pmg 是对的; feof 应该在循环之后使用以检查是否发生 EOF而不是错误

标签: c file-copying fgetc getc


【解决方案1】:

什么

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

确实,是:

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

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

正确的循环是

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

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

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

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

【讨论】:

  • 谢谢。我认为 (!feof(src) 与 ((ch = fgetc(src)) != EOF) 相同
  • @GeoPapas:没有。您必须在读取和写入之间进行检查,然后还必须检查ferror
  • 如果我想在第一次复制后重新复制文件,必须使用 ungetc?
  • @GeoPapas:没有。您应该 fseek 到文件的开头。 ungetc 只保证一个字符可以被推回;它用于在标记器中实现预读。
【解决方案2】:

第一个循环获取字符(可能检测到 EOF),然后检查该值是否未检测到 EOF,并可能执行写入字符的块(直到读取所有字符)。

第二个循环检查是否检测到 EOF,获取字符(可能检测到 EOF),写入字符(不考虑它可能是什么),并可能继续到下一个字符(如果 EOF '未检测到)。

在第二个循环中,在检查它是否为 EOF 之前写入字符。

【讨论】:

    【解决方案3】:

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

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

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

    【讨论】:

      【解决方案4】:

      您的while 循环有一个非一错误。它读/写一个额外的字符,这是奖金 的来源 - 您将fgetc() 返回的 EOF 值写入输出文件!

      【讨论】:

        【解决方案5】:

        编辑

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


        我唯一注意到的是:

        char ch;
        

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

        改用int 试试看。

        【讨论】:

          猜你喜欢
          • 2017-04-25
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-02-23
          • 2010-11-21
          • 2012-08-16
          相关资源
          最近更新 更多