You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Visual Studio Code中r+模式下fputs执行后出现重复内容与NULL的原因

C文件读写异常问题分析与解决

问题复现

用户提供的代码如下:

#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);
        }
    }
}

运行后选择写入"Jenny",终端会重复原有内容并输出大量NULL,而非仅显示写入的字符串。

问题根源:代码逻辑错误(与临时内存无关)

出现异常的核心原因有三个:

  1. 错误的feof循环逻辑
    while(!feof(fp))是典型的错误用法——feof仅在读取操作失败后才会置位,所以循环会多执行一次:当文件指针到达末尾时,fgetc会返回EOF,但此时feof还未触发,代码依然会执行printf("%c", ch),把EOF(ASCII值为-1)当作字符输出,表现为NULL或乱码。

  2. 读写切换未做定位操作
    C标准明确规定:在以r+模式打开的文件中,从读取操作切换到写入操作时,必须先调用fseek、fsetpos或rewind进行定位,或者调用fflush刷新缓冲区。原代码读完文件后直接调用fputs,属于未定义行为,可能导致缓冲中的旧数据被意外写入,或文件指针位置混乱,后续读取时重复输出原有内容。

  3. 写入后读取的指针位置错误
    写入"Jenny"后,文件指针位于写入内容的末尾,此时直接调用fgetc会读取文件末尾之后的内容,连续返回EOF,循环while(ch1 != EOF)会不断输出EOF对应的NULL字符,直到程序异常终止。

VS Code对fputs的处理机制

VS Code只是代码编辑器,不参与fputs的执行逻辑。真正决定fputs行为的是你使用的C标准库(如GNU glibc、MSVC运行时库)和编译器(如GCC、Clang)。VS Code仅负责编辑代码、调用编译器编译程序、显示运行结果,对文件操作的底层逻辑没有任何特殊处理。

修复后的代码示例

#include <stdio.h>
#include <stdlib.h>
int main()
{
    FILE *fp;
    fp = fopen("lets.txt", "r+");
    if (fp == NULL)
    {
        printf("ERROR");
        exit(1);
    }

    char ch;
    // 正确的文件读取逻辑:先读再判断是否EOF
    while ((ch = fgetc(fp)) != EOF)
    {
        printf("%c", ch);
    }

    printf("\n\nYou want to write something? (1/0)");
    int n;
    // 处理scanf留下的换行符,避免干扰后续操作
    scanf("%d", &n);
    getchar();

    if (n == 1)
    {
        // 读切换到写前,调用fseek定位到文件末尾(符合标准要求)
        fseek(fp, 0, SEEK_END);
        fputs("Jenny", fp);
        // 刷新缓冲区,确保写入内容立即落盘
        fflush(fp);

        // 将指针移到刚写入内容的起始位置,准备读取
        fseek(fp, -5, SEEK_CUR);
        char ch1;
        while ((ch1 = fgetc(fp)) != EOF)
        {
            printf("%c", ch1);
        }
        fclose(fp);
    }
    else
    {
        printf("File Closed ");
        fclose(fp);
    }
    return 0;
}

内容的提问来源于stack exchange,提问作者Tar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 01:15:31