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,而非仅显示写入的字符串。
问题根源:代码逻辑错误(与临时内存无关)
出现异常的核心原因有三个:
错误的
feof循环逻辑while(!feof(fp))是典型的错误用法——feof仅在读取操作失败后才会置位,所以循环会多执行一次:当文件指针到达末尾时,fgetc会返回EOF,但此时feof还未触发,代码依然会执行printf("%c", ch),把EOF(ASCII值为-1)当作字符输出,表现为NULL或乱码。读写切换未做定位操作
C标准明确规定:在以r+模式打开的文件中,从读取操作切换到写入操作时,必须先调用fseek、fsetpos或rewind进行定位,或者调用fflush刷新缓冲区。原代码读完文件后直接调用fputs,属于未定义行为,可能导致缓冲中的旧数据被意外写入,或文件指针位置混乱,后续读取时重复输出原有内容。写入后读取的指针位置错误
写入"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
相关产品推荐
相关产品推荐

