繁体   English   中英

Visual Studio Code 如何处理“r+”模式下文件 I/O 的 fputs 语句?

[英]How does Visual Studio Code handle the fputs statement for File I/O in "r+" mode?

我写了一段代码

#include <stdio.h>
#include <stdlib.h>
int main()
{
    FILE *fp;
    fp=fopen("lets.txt","r+");
    if(fp==NULL)
    {
        printf("ERROR");
        exit(1);
    }
    else
    {
        char ch,ch1;
        while(!feof(fp))
        {
           ch= fgetc(fp);
           printf("%c",ch);
        }
        printf("\n\nYou want to write something? (1/0)");
        int n;
        scanf("%d",&n);
        if(n==1)
        {
            fputs("Jenny",fp);
            ch1 = fgetc(fp);
            printf("%c\n", ch1);
            while(ch1 != EOF)
            {
                ch1=fgetc(fp);
                printf("%c",ch1);
            }
            fclose(fp);
        }
        else{
            printf("File Closed ");
            fclose(fp);
        }
    }
}

我试图在一个已经存在的文件“lets.txt”中插入一个字符串原始文本文件

但是当我运行这段代码时,它显示在终端中运行代码的终端照片

我原以为这只是将 Jenny 放入最终文件,但它也添加了之前存在的其他文本和大量 NULL。这是因为临时 memory 存储或类似的东西还是代码中的一些错误? [![不知道](https://i.stack.imgur.com/GQmpK.png)](https://i.stack.imgur.com/GQmpK.png)

回复:“我将 while 循环的条件更改为这个简单的形式 - ch = fgetc(fp); while(ch.= EOF) 但它仍然显示相同的结果。


getchar()返回的值必须存储在int中:

ch= fgetc(fp);

ch已声明为char 将值存储在char中会使EOF测试变得不可靠。 C17 声明EOF具有负 int 值。 在某些实现中, charunsigned ,因此它不能表示负值。

在对类型char进行签名的实现中,假设EOF定义为-1 (大多数实现都是这种情况),不可能将EOF与字符代码255 (将作为值-1存储在char中,但在int中为255 )。

从手册页:

fgetc()、getc() 和 getchar() 在文件末尾或错误时将读取的字符返回为 unsigned char 转换为int或 EOF。

它进一步指出:

如果将 getchar() 返回的 integer 值存储到 char 类型的变量中,然后与 integer 常量 EOF 进行比较,比较可能永远不会成功,因为 char 类型变量的符号扩展扩展到 integer 是实现定义的.

这也与fgetc相关。


可能的修复:

ch声明为int

首先,线条

char ch,ch1;
while(!feof(fp))
{
    ch= fgetc(fp);
    printf("%c",ch);
}

错了。

如果您希望ch保证能够表示值EOF并且还希望能够将它与每个可能的字符代码区分开来,那么您必须将fgetc的返回值存储在int中,而不是char中。 请注意fgetc返回一个int ,而不是一个char 有关此问题的更多信息,请参阅此其他答案

此外,function feof仅在先前的读取操作因文件结束而失败时才返回非零值(即 true)。 它不提供下一次读取操作是否失败的任何指示。 这意味着如果fgetc返回EOF ,您将打印该值,就好像fgetc成功一样,这是错误的。 有关此问题的更多信息,请参阅以下问题:

为什么“while(?feof(file) )”总是错误的?

由于上述原因,我建议您将这些行更改为以下内容:

int ch, ch1;

while ( ( ch = fgetc(fp) ) != EOF )
{
    printf( "%c", ch );
}

另一个问题是,当文件以更新模式打开时(即在模式字符串中使用+打开,例如您正在执行的"r+" ),您无法在读写之间自由切换。 根据ISO C11 标准的§7.21.5.3¶7

  • 在没有对fflush function 或文件定位 function( fseekfsetposrewind )的干预调用的情况下,不应直接在 output 之后输入,并且

  • 在没有对文件定位 function 的中间调用的情况下,输入不得直接跟在 output 之后,除非输入操作遇到文件结尾。

如果您违反任何这些规则,那么您的程序将调用未定义的行为,这意味着任何事情都可能发生,其中包括您获得无效 output 的可能性。

因此,我建议您更改行

fputs("Jenny",fp);
ch1 = fgetc(fp);

到:

fseek( fp, 0, SEEK_CUR );
fputs("Jenny",fp);
fflush( fp );
ch1 = fgetc(fp);

对比行fflush( fp ); ,这是绝对必要的,行fseek( fp, 0, SEEK_CUR ); 根据上述规则实际上没有必要,因为您遇到了文件结尾。 但无论如何保留该行可能是个好主意,例如,以防万一您以后更改程序以出于文件结束之外的其他原因停止读取。 在这种情况下,将需要该行。

在读写之间切换时,您还没有设置文件指针。 MSVC 手册页介绍了fopen

但是,当你从读切换到写时,输入操作一定会遇到EOF标记。 如果没有EOF ,则必须使用对文件定位 function 的干预调用。文件定位函数是fsetposfseekrewind 当您从写入切换到读取时,您必须使用对fflush或文件定位 function 的干预调用。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM