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

Windows C编程中文本文件字符串覆写异常原因咨询

文件覆写时字符丢失的原因解析

问题场景

初始file.txt内容(行号非实际内容):

1 |My name is Yugal Bishram Don
2 |

实际内容为:My name is Yugal Bishram Don\n

以"r+"模式打开文件后执行以下代码:

FILE *fp=fopen("file.txt", "r+");
fscanf(fp,"%[^\n]",buffer1);
// 对buffer1进行操作
rewind(fp);
fprintf(fp,"My name is Aswin Don\n");
fclose(fp);

执行后文件内容变为:

1 |My name is Aswin Don
2 |am Don
3 |

疑问:写入的字符串共21个字符,按预期应覆写前21个字符,剩余ram Don\n应保留,但实际剩余am Don,原字符串中的'r'为何消失?

核心原因

1. fscanf的缓冲区溢出问题

你使用的fscanf(fp, "%[^\n]", buffer1)存在严重安全隐患:这个格式说明符不会检查目标缓冲区的大小,会一直读取直到换行符的所有字符。如果buffer1的长度小于原行内容的长度(原行"My name is Yugal Bishram Don"共28个字符),就会发生缓冲区溢出——超出buffer1的字符会覆盖相邻内存区域的数据。

而FILE *fp结构体的内存可能就在buffer1附近,溢出的内容会破坏fp内部记录的文件指针位置、缓冲区状态等关键信息,导致后续的rewind操作没有真正将文件指针重置到文件开头,而是偏移了1个字节的位置。

这种情况下,后续的fprintf会从偏移1的位置开始写入21个字符:

  • 原文件偏移0的'M'被保留,偏移1-21被写入的内容覆盖,最终第一行呈现为"My name is Aswin Don";
  • 原文件偏移21的'r'被写入的最后一个字符(换行符\n)覆盖,后续的'a'开始的内容保留,于是第二行变成了'am Don'。

2. 读写切换的流同步问题

在C标准中,当文件流从读操作切换到写操作时(反之亦然),如果中间没有调用定位函数(fseek、rewind)或刷新函数(fflush),会导致未定义行为。虽然你调用了rewind,但如果之前的读操作导致输入缓冲区残留了未读取的字符(比如换行符\n),部分C库实现仍可能出现异常的指针定位行为,进一步加剧问题。

解决方法

  • 避免缓冲区溢出:使用fscanf时必须限制读取的字符数,比如fscanf(fp, "%27[^\n]", buffer1)(假设buffer1大小为28,留1个字节给终止符\0);或者更安全的做法是使用fgets读取整行,它会自动限制读取的字符数并保留换行符。
  • 确保流同步:在读写切换前,调用fflush(fp)刷新缓冲区,再执行rewind或fseek定位。示例代码:
FILE *fp=fopen("file.txt", "r+");
// 使用fgets更安全
fgets(buffer1, sizeof(buffer1), fp);
// 对buffer1进行操作
fflush(fp); // 刷新缓冲区,同步流状态
rewind(fp);
fprintf(fp,"My name is Aswin Don\n");
fclose(fp);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 18:05:37