求解ÿ;C语言中的文件结尾

求解ÿ;C语言中的文件结尾,c,eof,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 su

当我将一个文件的内容复制到输出文件末尾的另一个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);

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

  • 检查是否为EOF
  • 如果不是,则将其写入输出
  • 你的问题是你按错误的顺序做这两件事

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

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

    while (curr_char != EOF)
        {
        curr_char = getc(original_file);
        if(curr_char == EOF) break;
        putc(curr_char, second_file);
        }
    
    在这里,我们显式地测试字符是否是EOF,在读取它之后,在写入它之前。如果是EOF,我们会尽早脱离循环。这会起作用,但很难看:我们在两个不同的地方测试EOF,其中一个地方从不“点火”。(另外,正如一位评论员提醒我的那样,有一个问题是,第一次通过循环时,我们在设置之前就在测试
    curr\u char

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

    curr_char = getc(original_file);
    while (curr_char != EOF)
        {
        putc(curr_char, second_file);
        curr_char = getc(original_file);
        }
    
    while ((curr_char = getc(original_file)) != EOF)
        {
        putc(curr_char, second_file);
        }
    
    在这里,我们读一个初始字符,只要它不是EOF,我们就写它,然后读另一个。这很好,但还是有点难看,因为这一次我们在两个不同的地方阅读角色

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

    curr_char = getc(original_file);
    while (curr_char != EOF)
        {
        putc(curr_char, second_file);
        curr_char = getc(original_file);
        }
    
    while ((curr_char = getc(original_file)) != EOF)
        {
        putc(curr_char, second_file);
        }
    
    这是在C中编写字符复制循环的常规方法。对
    getc
    的调用和对
    curr\u char
    的赋值隐藏在
    while
    循环的控制表达式中。这取决于这样一个事实:在C语言中,赋值表达式和其他表达式一样有一个值。也就是说,表达式
    a=b
    的值是我们刚才分配给
    a
    的值(即
    b
    的值)。因此表达式
    curr\u char=getc(原始文件)
    的值就是我们刚才读取的字符。所以当我们说
    while((curr\u char=getc(original\u file))!=EOF)
    时,我们实际上说的是,“调用
    getc
    ,将结果分配给
    curr\u char
    ,如果它不等于
    EOF
    ,那么再绕一圈。”

    (如果您仍然看不到这一点,我已经在和中写了其他解释。)

    这段代码既好又坏。这很好,因为我们只有一个地方可以读字符,一个地方可以测试字符,还有一个地方可以写字符。但这有点糟糕,因为,让我们承认,一开始它有点神秘。很难想象隐藏在-
    while
    条件中的赋值。正是这样的代码给了C一个充满晦涩难懂的狼吞虎咽的名声

    但是,至少在这种情况下,它确实值得学习这个习语,并适应它,因为简化为一次读、一次测试和一次写确实是一种优点。在这样一个琐碎的例子中,这并不重要,但在由于其他原因而变得复杂的实际程序中,如果有一些关键功能发生在两个不同的地方,很容易忽略这一事实,对其中一个进行更改,但忘记对另一个进行更改

    (事实上,就在上周的工作中,这种情况发生在我身上。我正试图修复其他人代码中的一个错误。我最终发现,当代码执行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
    替换它,即“true”在C中,这也可以很好地工作,并且它具有一次读取、一次测试和一次写入的优点。它实际上以与数字3完全相同的顺序执行完全相同的操作,但通过线性布局,它可能更容易遵循

    数字4唯一的问题是它是一个非传统的“中间打断”循环。就个人而言,我对中间打断循环没有问题,我发现它们不时出现,但如果我写了一个,有人说“史蒂夫,这太难看了,这不是任何人都能识别的习惯用法,它会让人困惑”,我必须同意


    另外,我已经用更传统的
    getc
    putc
    取代了你对
    fgetc
    fputc
    的呼叫。我不知道是谁告诉你要使用
    fgetc
    fputc
    ,而且你需要它们的地方有一些模糊的情况,但它们是如此罕见,在我看来,人们可能会忘记它们t存在“f”变体,并且始终使用
    getc
    putc

    对于您读取的每个字符,您有两件事要做:

  • 检查是否为EOF
  • 如果不是,则将其写入输出
  • 你的问题是你按错误的顺序做这两件事

    解决这个问题可能有几种不同的方法。你选择哪种方法取决于你对程序外观的关注程度,而不仅仅是工作

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

    while (curr_char != EOF)
        {
        curr_char = getc(original_file);
        if(curr_char == EOF) break;
        putc(curr_char, second_file);
        }
    
    在这里,我们显式地测试字符是否是EOF,在读过它之后,在写它之前。如果它是EOF,我们会很早地跳出循环。这会起作用,但很难看:我们在两个不同的地方测试EOF,其中一个从来不会“触发”。(另外,正如一位评论员提醒我的,fir存在一个问题