在C中解决ÿ文件结尾

时间:2016-05-04 23:28:18

标签: c eof

当我在输出文件末尾的C中将文件内容复制到另一个文件时,我有这个字符ÿ。我理解感谢这个论坛它是EOF指标,但我不明白该怎么做才能在输出文件中摆脱它。

这是我的代码:

second_file = fopen(argv[2], "w+");
while (curr_char != EOF)
{
    curr_char = fgetc(original_file);
    fputc(curr_char, second_file);
}
printf("Your file has been successfully copy\n");
fclose(second_file);
fclose(original_file);

1 个答案:

答案 0 :(得分:4)

对于您阅读的每个角色,您有两件事要做:

  1. 检查是否是EOF。
  2. 如果没有,请将其写入输出。
  3. 你的问题是你正在以错误的顺序做这两件事。

    可能有几种不同的解决方法。你选择哪一个取决于你关心你的程序看起来好多少,而不仅仅是工作。

    一。从您编写的代码开始,我们可以将其更改为:

    while (curr_char != EOF)
        {
        curr_char = getc(original_file);
        if(curr_char == EOF) break;
        putc(curr_char, second_file);
        }
    

    在这里,我们在写入之前,在阅读之后立即测试该角色是否为EOF。如果它是EOF,我们会提前摆脱循环。这样可行,但很难看:有两个不同的地方我们测试EOF,其中一个从不“开火”。 (另外,正如评论员提醒我的那样,第一次通过循环问题,我们在设置它之前测试curr_char。)

    两个。你可以像这样重新安排它:

    curr_char = getc(original_file);
    while (curr_char != EOF)
        {
        putc(curr_char, second_file);
        curr_char = getc(original_file);
        }
    

    在这里,我们读了一个初始角色,只要它不是EOF,我们就会写它并读另一个。这样做会很好,但是它仍然有点难看,因为这次有两个不同的地方我们读这个角色。

    三。你可以像这样重新安排它:

    while ((curr_char = getc(original_file)) != EOF)
        {
        putc(curr_char, second_file);
        }
    

    这是在C中编写字符复制循环的传统方法。对getc的调用和curr_char的赋值都隐藏在while循环的控制表达式中。这取决于在C中,赋值表达式具有与任何其他表达式一样的值。也就是说,表达式a = b的值是我们刚刚分配给a的任何值(即b的值)。所以表达式curr_char = getc(original_file)的值是我们刚读过的字符。因此,当我们说while ((curr_char = getc(original_file)) != EOF)时,我们实际上说的是,“致电getc,将结果分配给curr_char,如果不等于EOF,请选择另一个围绕循环旅行。“

    (如果您仍然遇到此问题,我已在these notesthis writeup中撰写了其他解释。)

    这段代码既好又坏。这很好,因为我们只有一个地方我们读过字符,一个地方我们测试字符,一个地方我们写字符。但它有点不好因为,让我们承认,起初它有点神秘。很难想到这个任务 - 埋藏在 - while - 条件中。像这样的代码给C带来了充满晦涩的gobbledegook的声誉。

    但是,至少在这种情况下,真的值得学习这个成语,并且对它感到满意,因为减少到只有一个读取和一个测试,一个写入真正 美德。在这样一个微不足道的案例中,这并不重要,但在其他原因复杂的实际程序中,如果在两个不同的地方发生了一些关键的功能,那么很容易忽视这个事实,并且改变其中一个,但忘了把它交给另一个。

    (事实上,这只发生在我上周的工作中。我试图修复别人的代码中的错误。我终于弄清楚当代码执行X时,它无意中清除了Y.我找到了这个地方在哪里做了X,我添加了一些新的代码来正确地重新创建Y.但是当我测试我的修复时,它没有用!原来有两个单独的地方,代码做X,我找到并修复了错了。)

    最后,这是编写循环的等效最小但非常规的方式:

    while (1)
        {
        curr_char = getc(original_file);
        if(curr_char == EOF) break;
        putc(curr_char, second_file);
        }
    

    这有点像数字1,但它摆脱了while循环中的冗余条件,并将其替换为常量1,在C中为“true”。这将工作也很好,并且它具有一次读取,一次测试和一次写入的优点。它实际上最终完成了与3号完全相同的操作和完全相同的顺序,但是通过线性布局它可能更容易理解。

    4号唯一的问题是它是一个非常规的“中间突破”循环。就我个人而言,我没有中间突破循环的问题,我发现它们不时出现,但如果我写了一个而且有人说“史蒂夫,这很难看,这不是任何人认可的成语,它会让人迷惑“,我必须同意。

    P.S。我已将fgetcfputc的来电替换为更传统的getcputc。我不确定是谁告诉你使用fgetcfputc,并且有一些模糊的情况你需要它们,但它们是如此罕见,以至于我认为人们可能会忘记“ f“变体存在,并始终使用getcputc