mobile wallpaper 1mobile wallpaper 2mobile wallpaper 3mobile wallpaper 4mobile wallpaper 5mobile wallpaper 6mobile wallpaper 7
2353 字
6 分钟
文件操作代码详解
2026-06-12

本篇整理了 C 语言文件操作的课堂代码,涵盖文件打开与关闭、文件读写操作,以及一道填空题的题目与答案对比解析。

目录#


一、文件打开与关闭:读取文件内容#

题目说明#

阅读并理解一个最基本的文件读取程序:打开文件 1.txt,逐字符读取其中的内容并输出到屏幕,最后关闭文件。

解题思路#

  1. 定义文件指针 FILE *fp,所有文件操作都通过该指针进行。
  2. fopen(filename, "r") 以”只读”方式打开文件,若打开失败返回 NULL
  3. 检查打开是否成功:if ((fp = fopen(...)) == NULL),失败则提示并退出。
  4. fgetc(fp) 逐字符读取,直到返回 EOF(文件结束标志)。
  5. putchar(ch) 将读取的字符输出到屏幕。
  6. 最后用 fclose(fp) 关闭文件,释放资源。

完整代码#

#include <stdio.h>
int main()
{
FILE *fp; /* 定义文件指针 */
char ch, *filename = "1.txt"; /* 文件名 */
/* 以只读方式打开文件,并检查是否成功 */
if ((fp = fopen(filename, "r")) == NULL)
{
printf("cannot open file\n");
exit(0); /* 打开失败,退出程序 */
}
/* 逐字符读取文件内容直到EOF(文件结束) */
while ((ch = fgetc(fp)) != EOF)
putchar(ch); /* 输出读取的字符到屏幕 */
fclose(fp); /* 关闭文件 */
return 0;
}

关键知识点#

  • FILE 类型:C 标准库定义的文件结构体类型,FILE * 是文件指针,所有文件 I/O 函数都需它作为参数。
  • fopen 函数FILE *fopen(const char *filename, const char *mode);
    • 模式 "r":只读,文件必须存在,否则返回 NULL
    • 模式 "w":只写,文件不存在则创建,存在则清空内容。
    • 模式 "a":追加,文件不存在则创建,存在则在其末尾追加。
    • 还有 "r+""w+""a+" 等读写组合模式。
  • fgetc 函数int fgetc(FILE *fp); 从文件读取一个字符,返回 int(不是 char),读到文件末尾返回 EOF(通常为 -1)。
  • EOF:End Of File,文件结束标志宏,定义为 -1。这也是为什么 fgetc 返回 int 而非 char——若返回 char,则 0xFF 会被误判为 EOF
  • fclose 函数:关闭文件,刷新缓冲区,释放系统资源。打开的文件务必关闭,否则可能导致数据丢失或资源泄漏。
  • 打开失败检查的必要性:文件可能不存在、无权限或路径错误,必须检查 fopen 返回值是否为 NULL

小贴士:本程序使用了 exit(0) 但未包含 <stdlib.h>,严格来说应包含该头文件。exit 函数声明在 <stdlib.h> 中。


二、文件读写操作:从键盘写入文件#

题目说明#

从键盘输入字符,逐个存到磁盘文件中,直到输入 # 为止。同时将输入的字符回显到屏幕上。

解题思路#

  1. 定义文件指针 FILE *fp 和字符变量 ch、文件名数组 filename[20]
  2. 提示用户输入文件名,用 scanf("%s", filename) 读入。
  3. getchar() 吸收 scanf 留下的回车符,避免它被当作第一个输入字符。
  4. "w"(只写)方式打开文件,检查是否成功。
  5. 循环读取键盘输入 ch = getchar(),当 ch != '#' 时:
    • fputc(ch, fp) 将字符写入文件。
    • putchar(ch) 将字符回显到屏幕。
  6. 输入 # 后结束循环,fclose(fp) 关闭文件。

完整代码#

/*
从键盘输入字符,逐个存到磁盘文件2.txt中,直到输入'#'为止
*/
#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE* fp; /* 步骤1:定义文件指针 */
char ch, filename[20];
printf("Please input(file name):"); /* 输入写入数据的文件名 */
scanf("%s", filename);
getchar(); /* 接收执行scanf函数时,最后的回车 */
if ((fp = fopen(filename, "w")) == NULL) /* 步骤2:文件打开(只写模式) */
{
printf("Can not open file.\n");
exit(0);
}
printf("Please input(end of #):");
ch = getchar(); /* 接收输入的第一个字符 */
while (ch != '#')
{
fputc(ch, fp); /* 步骤3:文件写操作,将字符ch输出到fp所指向的文件中 */
putchar(ch); /* 将字符ch输出在显示屏上 */
ch = getchar(); /* 逐个接收从键盘输入的字符 */
}
putchar('\n');
fclose(fp); /* 步骤4:文件关闭 */
return 0;
}

关键知识点#

  • fputc 函数int fputc(int ch, FILE *fp); 将字符 ch 写入文件 fp,写入成功返回该字符,失败返回 EOF
  • getchar 吸收回车scanf("%s", ...) 读取字符串后会留下回车符在缓冲区,若不吸收,下一次 getchar() 会读到回车而非实际输入。这是 C 语言输入常见的”坑”。
  • 文件写模式 "w":若文件已存在,会清空原内容;若不存在,则创建新文件。要保留原内容应在末尾追加,使用 "a" 模式。
  • 键盘输入与文件写入的同步:用户输入的字符既写入文件又显示在屏幕上,便于用户确认输入内容。
  • 结束标志:用 # 作为输入结束标志,是 C 语言入门程序常见的约定。

三、填空题解析:文件写入完整流程#

本节是一道文件操作填空题,给出了题目版本(含空待填)答案版本(完整代码),通过对比帮助理解填空点。

题目版本(含空待填)#

/*
从键盘输入字符,逐个存到磁盘文件2.txt中,直到输入'#'为止
*/
#include <stdio.h>
#include <stdlib.h>
int main( )
{
FILE* fp ; /* 步骤1:定义文件指针 */
char ch , filename[20] ;
printf( "Please input(file name):" ) ; /* 输入写入数据的文件名 */
scanf( "%s" , filename ) ;
getchar( ) ; /* 接收执行scanf函数时,最后的回车 */
if( fp == NULL) /* 步骤2:文件打开 */ <--- 此处需填空
{
printf( "Can not open file.\n" ) ;
exit( 0 ) ;
}
printf( "Please input(end of #):" ) ;
ch = getchar( ) ; /* 接收输入的第一个字符 */
while( ch != '#' )
{
fputc(ch, fp); /* 步骤3:文件写操作,将字符ch输出到fp所指向的文件中 */
putchar( ch ) ; /* 将字符ch输出在显示屏上 */
ch = getchar( ) ; /* 逐个接收从键盘输入的字符 */
}
putchar( '\n' ) ;
fclose(fp); /* 步骤4.文件关闭 */
return 0 ;
}

题目分析#

题目要求实现”从键盘输入字符写入文件”的功能,但 if 语句的条件部分被挖空了:if( fp == NULL)。注意这里 fp 是文件指针,尚未通过 fopen 赋值,直接与 NULL 比较是错误的——fp 此刻是未初始化的野指针,比较结果无意义。

需要填入的是 fopen 调用,并让整个表达式与 NULL 比较,以判断打开是否失败。

答案版本(完整代码)#

/*
从键盘输入字符,逐个存到磁盘文件2.txt中,直到输入'#'为止
*/
#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE* fp; /* 步骤1:定义文件指针 */
char ch, filename[20];
printf("Please input(file name):"); /* 输入写入数据的文件名 */
scanf("%s", filename);
getchar(); /* 接收执行scanf函数时,最后的回车 */
if ((fp = fopen(filename, "w")) == NULL) /* 步骤2:文件打开(答案填空处) */
{
printf("Can not open file.\n");
exit(0);
}
printf("Please input(end of #):");
ch = getchar(); /* 接收输入的第一个字符 */
while (ch != '#')
{
fputc(ch, fp); /* 步骤3:文件写操作,将字符ch输出到fp所指向的文件中 */
putchar(ch); /* 将字符ch输出在显示屏上 */
ch = getchar(); /* 逐个接收从键盘输入的字符 */
}
putchar('\n');
fclose(fp); /* 步骤4.文件关闭 */
return 0;
}

题目与答案对比分析#

填空点定位#

位置题目版本答案版本说明
if 条件if( fp == NULL)if ((fp = fopen(filename, "w")) == NULL)核心填空点

填空内容详解#

填入的内容是 fp = fopen(filename, "w"),整个 if 条件变为:

if ((fp = fopen(filename, "w")) == NULL)

这一行完成了两件事:

  1. 赋值fp = fopen(filename, "w") 调用 fopen 打开文件,将返回的文件指针赋给 fp
  2. 判断:将赋值后的 fpNULL 比较,判断打开是否失败。

为什么要用”赋值 + 比较”的写法#

这是 C 语言中检查 fopen惯用写法,原因如下:

  • fopen 可能失败(文件不存在、无权限、磁盘满等),失败时返回 NULL
  • 若不检查直接使用 fp,程序会因解引用 NULL 指针而崩溃。
  • 把”赋值”和”判断”合并到一行,既简洁又不易遗漏检查。

等价的展开写法是:

fp = fopen(filename, "w");
if (fp == NULL)
{
printf("Can not open file.\n");
exit(0);
}

两种写法功能完全等价,但合并写法更紧凑,是 C 程序员的习惯写法。

注意运算符优先级#

  • 赋值运算符 = 的优先级低于关系运算符 ==,所以必须用括号把 fp = fopen(...) 括起来。
  • 若写成 if (fp = fopen(filename, "w") == NULL)(缺少外层括号),由于 == 优先级高,会先计算 fopen(...) == NULL 得到 0 或 1,再赋给 fp,导致 fp 变成 0 或 1 而非有效的文件指针——这是一个经典的优先级 bug。

易错点小结#

  1. 忘记 fopen:直接用未初始化的 fp 比较 NULL,逻辑错误。
  2. 括号缺失fp = fopen(...) == NULL 因优先级问题导致 fp 被赋为 0 或 1。
  3. 模式字符串错误:本题是”写入”文件,必须用 "w" 而非 "r"。若用 "r",文件不存在时会打开失败。
  4. 忘记 getchar() 吸收回车scanf 后回车残留在缓冲区,会导致第一个 getchar() 读到回车而非用户实际输入。
  5. 忘记 fclose:写入的数据可能还在缓冲区未刷盘,程序结束后数据丢失。

四、文件操作核心知识点总结#

文件操作的四个标准步骤#

所有文件 I/O 程序都遵循以下四步流程:

定义文件指针 → 打开文件 → 读写文件 → 关闭文件
FILE *fp fopen() fgetc/fputc fclose()
fgets/fputs
fread/fwrite
fprintf/fscanf

常用文件函数对照表#

函数功能函数原型说明
fopen打开文件FILE *fopen(const char *name, const char *mode);失败返回 NULL
fclose关闭文件int fclose(FILE *fp);成功返回 0,失败返回 EOF
fgetc读一个字符int fgetc(FILE *fp);返回 int,末尾返回 EOF
fputc写一个字符int fputc(int ch, FILE *fp);成功返回 ch,失败返回 EOF
fgets读一行字符串char *fgets(char *s, int n, FILE *fp);读 n-1 个字符或遇换行
fputs写字符串int fputs(const char *s, FILE *fp);不自动加换行
fscanf格式化读int fscanf(FILE *fp, const char *fmt, ...);类似 scanf
fprintf格式化写int fprintf(FILE *fp, const char *fmt, ...);类似 printf
fread读数据块size_t fread(void *buf, size_t size, size_t n, FILE *fp);二进制读
fwrite写数据块size_t fwrite(const void *buf, size_t size, size_t n, FILE *fp);二进制写
feof判断文件结束int feof(FILE *fp);结束返回非 0

文件打开模式对照表#

模式含义文件不存在时文件存在时
"r"只读失败从开头读
"w"只写创建清空内容
"a"追加创建在末尾追加
"r+"读写失败从开头读写
"w+"读写创建清空内容
"a+"读追加创建可读,写时追加
"rb"二进制只读失败从开头读
"wb"二进制只写创建清空内容

注意"w""w+" 模式会清空原文件内容,使用前务必确认!若想保留原内容,应使用 "a""a+"

文本文件 vs 二进制文件#

特性文本文件二进制文件
存储方式ASCII 字符内存原样存储
读写函数fgetc/fputc/fgets/fputs/fscanf/fprintffread/fwrite
模式后缀b(如 "r"b(如 "rb"
换行处理\n\r\n 转换不转换
可读性文本编辑器可读需专用程序
存储效率较低(数字占多个字符)较高(数字按类型定长)

编程规范建议#

  1. 始终检查 fopen 返回值if ((fp = fopen(...)) == NULL) 是标准写法。
  2. 打开的文件务必关闭:每个 fopen 对应一个 fclose,建议成对编写。
  3. 二进制文件用 "b" 模式:跨平台时避免换行符转换问题。
  4. 缓冲区刷新fflush(fp) 可手动刷新缓冲区;正常 fclose 也会刷新。
  5. 文件结束判断:用 feof 或检查 fgetc 是否返回 EOF,避免死循环。
  6. 错误处理ferror(fp) 可检测读写错误,clearerr(fp) 清除错误标志。

掌握以上文件操作基础后,可以进一步学习:文件指针定位(fseek/ftell/rewind)、临时文件(tmpfile)、文件删除重命名(remove/rename)等进阶内容。

分享

如果这篇文章对你有帮助,欢迎分享给更多人!

文件操作代码详解
https://blog.radarweb.top/posts/c/文件操作代码详解/
作者
Sherry
发布于
2026-06-12
许可协议
CC BY-NC-SA 4.0

部分信息可能已经过时

目录