C语言中的feof错误循环

4
我使用以下代码从文件中读取一个字符并替换它,但我遇到了一个错误。循环一直进行到文件结尾。
问题出在哪里?
我在Linux(NetBeans IDE)上测试了这段代码,它是正确的并且工作得很好,但当我尝试在Windows中使用VS 2008时,我发现出现了无限循环的情况。
//address = test.txt

FILE *fp;
fp=fopen(address,"r+");
if(fp == 0)
{
    printf("can not find!!");
}
else
{
    char w = '0';  /// EDIT : int w;
    while(1)
    {
        if((w = fgetc(fp)) != EOF)
        {
            if((w = fgetc(fp)) != EOF)
            {
                fseek(fp,-2,SEEK_CUR);
                fprintf(fp,"0");
            }
        }
        else
        {
            break;
        }
    }
} 
fclose(fp);

为什么不使用*feof()函数而是用while(1)*循环呢? - littleadv
有趣的是这在你的Linux系统上运行了。也许当w为char类型时,(w = fgetc(f))的类型定义不正确?我们会调查一下... - David Grayson
我测试过了,但它还是不起作用。 - user787084
如果我在while循环中使用feof(),那么如果我有7个字符,最终会有8个字符; 如果输入是“123456”,则输出为“0000000”,这意味着一个字符被添加到输入中。 - user787084
它是 int w ... 我知道......我用 int 测试过了,但它不起作用。 - user787084
2
你实际上想通过这个循环实现什么目标? - David Grayson
2个回答

6
你将 fgetc 的结果存储到 char 变量中,而不是 int 变量中。
char w = '0'; /* Wrong, should be int. */

顺带一提,这个问题在C语言常见问题解答中提到。
如果类型charunsigned,实际的EOF值将被截断(通过丢弃其高位比特,可能导致255或0xff),并且不会被识别为EOF,从而导致输入无限大。
编辑
重新阅读您的问题,您回退两个字符并写入一个字符的方式非常可疑。这很可能导致无限循环。
编辑2
你(可能)想要这样做(未经测试):
while ((w = getc(fp)) != EOF) {
    fseek(fp, -1, SEEK_CUR);
    fprintf(fp, "0");
    fflush(fp); /* Apparently necessary, see the answer of David Grayson. */
}

1
我测试了你的edit2,发现出现了一个无限循环,当我使用ctrl+c中断后,用记事本打开文件时看到了数百万个零。 - user787084
@mimad 你需要用我发布的代码替换掉你的整个while - cnicutar
1
在写和读之间切换时,您可能需要另一个 fseek。 - Bo Persson
当然,这是一个真正的问题,但是假设输入文件是ASCII并且在OP的编译器中char是有符号的,它不会导致无限循环。C FAQ说:“如果字符是有符号的并且输入全部是7位字符,则该错误可能长时间未被发现。” - David Grayson
1
@David Grayson 很好 :-) 我个人不太喜欢做太多的假设。 - cnicutar
显示剩余5条评论

3

在cplusplus.com上的fopen文档中写道:

对于允许读取和写入(或附加)的模式(包括“+”符号的模式),流应在读取操作后跟写入操作或写入操作后跟读取操作之间刷新(fflush)或重新定位(fseek,fsetpos,rewind)。

我们可以在fprintf之后添加fflush调用来满足该要求。

这是我的工作代码。它创建了一个名为example.txt的文件,在程序退出后,该文件的内容将为000000000000n

#include <stdio.h>

int main(int argc, char **argv)
{
    FILE * fp;
    int w;

    fp = fopen("example.txt","w");
    fprintf(fp, "David Grayson");
    fclose(fp);

    fp = fopen("example.txt","r+");
    while(1)
    {
        if((w = fgetc(fp)) != EOF)
        {
            if((w = fgetc(fp)) != EOF)
            {
                fseek(fp,-2,SEEK_CUR);
                fprintf(fp,"0");
                fflush(fp);  // Necessary!
            }
        }
        else
        {
            break;
        }
    }
    fclose(fp);
}

这是在Windows中使用MinGW测试的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接