写入txt文件时,Ctrl+d与Ctrl+c终止程序的差异解析
问题:Ctrl+C终止程序时文件无内容,Ctrl+D却正常?
测试代码
#include <stdio.h> int main(void) { FILE *cfPtr = NULL; if ( (cfPtr = fopen("clients.txt","w")) == NULL ){ puts("File could not be opened"); }else{ puts("Enter the account, name, and balance"); puts("Enter EOF to end input."); printf("%s", "? "); int account = 0; char name[30] = ""; double balance = 0.0; scanf("%d%29s%lf",&account,name,&balance); while (!feof(stdin)){ fprintf(cfPtr,"%d %s %.2f\n",account,name,balance); printf("%s", "? "); scanf("%d%29s%lf",&account,name,&balance); } fclose(cfPtr); } }
测试输入
Enter the account, name, and balance Enter EOF to end input. ? 100 Jones 24.98 ? 200 Doe 345.67 ? 300 White 0.00 ? 400 Stone -42.16 ? 500 Rich 224.62
原因与解释
核心问题:标准库的缓冲区机制
C语言标准库的文件I/O默认使用缓冲模式,fprintf写入的数据并不会直接写到磁盘文件,而是先暂存到内存中的缓冲区里。只有满足以下条件之一时,缓冲区的内容才会同步到磁盘:
- 缓冲区被写满;
- 调用
fflush()函数强制刷新缓冲区; - 调用
fclose()关闭文件(关闭时会自动触发缓冲区刷新)。
两种终止方式的差异
- Ctrl+D终止:Ctrl+D是向标准输入(
stdin)发送EOF信号,程序会正常执行完while循环,最后走到fclose(cfPtr)语句。fclose会自动把缓冲区里的所有数据写入磁盘,所以clients.txt里能看到完整的输入内容。 - Ctrl+C终止:Ctrl+C是向进程发送
SIGINT中断信号,程序会被立即终止,根本没机会执行fclose,缓冲区里暂存的数据还没来得及同步到磁盘,最终文件就是空的。
可选解决办法
如果需要在异常终止时也保留写入的数据,可以试试这两种方案:
- 每次调用
fprintf后,立刻调用fflush(cfPtr)强制刷新缓冲区,这样数据会实时写入磁盘,但频繁刷新会降低程序性能; - 给
SIGINT信号注册一个处理函数,在收到中断信号时先执行fclose(cfPtr)再退出程序,确保缓冲区数据被写入。示例代码片段:
#include <signal.h> FILE *cfPtr; // 把文件指针设为全局变量,方便信号处理函数访问 void sigint_handler(int sig) { if (cfPtr != NULL) { fclose(cfPtr); } exit(0); } // 在main函数开头注册信号处理函数 signal(SIGINT, sigint_handler);
内容的提问来源于stack exchange,提问作者CroCo
相关产品推荐
相关产品推荐

