C语言文件操作【进阶--6--】

发布于:2024-12-18 ⋅ 阅读:(69) ⋅ 点赞:(0)



C语言文件操作

一、文件的概念

  1. 程序文件
    • 程序文件是包含计算机程序指令的文件,这些指令可以被计算机的处理器执行
    • 它们通常由程序员编写,并且可以是源代码(如CJavaPython等)或编译后的二进制文件(如.exe.dll.so等)
    • 程序文件定义了程序的逻辑和行为,是软件运行的基础
  2. 数据文件
    • 数据文件包含程序在运行时需要读取或写入的数据
    • 这些数据可以是文本、数字、图像、视频等任何形式的信息
    • 数据文件通常由用户或其他程序生成,并被程序用来执行特定的任务,如存储配置信息、用户数据、临时文件等
    • 数据文件的格式可以是结构化的(如CSVXMLJSON等)或非结构化的(如TXTDOCXPNG等)

二、文件标识

  • 一个文件需要有一个唯一的文件标识,以便用户识别和引用
  • 文件标识 = 文件路径 + 文件名主干 + 文件后缀 文件标识=文件路径+文件名主干+文件后缀 文件标识=文件路径+文件名主干+文件后缀
  1. 文件路径
    • 文件路径指明了文件在文件系统中的位置。它从根目录开始,通过一系列目录名来定位文件所在的具体位置
    • 在Windows系统中,路径使用反斜杠(\)作为分隔符,而在Unix/Linux和macOS系统中,路径使用正斜杠(/)作为分隔符
      • 例如,在c:\code\test.txt中,c:\code\是文件路径,表示文件位于C盘的code目录下
  2. 文件名主干
    • 文件名主干是文件标识中除去路径和后缀的部分,它描述了文件的内容或用途
      • c:\code\test.txt中,test是文件名主干
  3. 文件后缀
    • 文件后缀是文件名主干后面的点(.)和一系列字母的组合,用于表示文件的类型或格式
    • 文件后缀有助于操作系统和程序识别文件的格式,并关联到相应的应用程序
      • c:\code\test.txt中,.txt是文件后缀,表示这是一个文本文件

三、文件指针

  • FILE 结构体定义在 <stdio.h> 头文件中,是标准库中用于文件操作的核心类型

  • 每个被使用的文件都在内存中开辟了一个相应的文件信息区,用来存放文件的相关信息(如文件的名字,文件状态及文件当前的位置等)。这些信息保存结构体变量FILE

早期VS编译环境提供的<stdio.h>头文件中有以下的文件类型申明:

struct _iobuf {
  char *_ptr;
  int _cnt;
  char *_base;
  int _flag;
  int _file;
  int _charbuf;
  int _bufsiz;
  char *_tmpfname;
};
typedef struct _iobuf FILE;
成员名称 类型 说明
_ptr char* 指向缓冲区中下一个要读取或写入的位置
_cnt int 表示缓冲区中剩余的字符数
_base char* 指向缓冲区的起始地址
_flag int 表示文件的状态和模式 例如 是否为读模式 写模式 二进制模式等
_file int 存储文件描述符 用于系统调用
_charbuf int 用于标记是否使用缓冲区
_bufsiz int 缓冲区的大小
_tmpfname char* 指向一个临时文件名的指针 通常用于临时文件

请添加图片描述

四、文件的打开与关闭

Ⅰ、文件的打开fopen()

fopen() 函数用于打开一个文件,并返回一个指向 FILE 结构体的指针,这个指针可以用于后续的文件操作

函数原型:

FILE *fopen(const char *filename, const char *mode);

参数:

  • filename:要打开的文件的名称
  • mode:文件打开的模式,决定了文件是用于读取、写入还是追加数据

返回值:

  • 成功时返回一个 FILE 文件指针
  • 失败时返回 NULL空指针

常用模式字符串:

文件使用方式 操作模式 含义 文件不存在时的行为
"r" 只读 打开已存在的文本文件以供读取 出错
"w" 只写 创建文本文件以供写入,若文件存在则覆盖 创建新文件
"a" 追加 在文本文件末尾添加数据,若文件不存在则创建 创建新文件
"rb" 只读 打开已存在的二进制文件以供读取 出错
"wb" 只写 创建二进制文件以供写入,若文件存在则覆盖 创建新文件
"ab" 追加 二进制文件末尾添加数据,若文件不存在则创建 创建新文件
"r+" 读写 打开已存在的文本文件以供读写 出错
"w+" 读写 创建文本文件以供读写,若文件存在则覆盖 创建新文件
"a+" 读写 打开文件以供在文件末尾读写,若文件不存在则创建 创建新文件
"rb+" 读写 打开已存在的二进制文件以供读写 出错
"wb+" 读写 创建二进制文件以供读写,若文件存在则覆盖 创建新文件
"ab+" 读写 打开二进制文件以供在文件末尾读写,若文件不存在则创建 创建新文件
  • 引用同一目录下的文件时,可以使用相对路径

    • ./data.txt指的是当前目录下的data.txt文件,而../docs/report.txt指的是上一级目录docs下的report.txt文件

    •   FILE* pf = fopen("./test.txt", "r");
      
  • 引用不同目录下的文件,应使用绝对路径

    •   FILE* pf = fopen("D:\\User\\YiAn\\C_Code_1\\test.txt", "r");
      
    • 须多使用一道\用来转义

Ⅱ、文件的关闭fclose()

fclose() 函数用于关闭一个通过 fopen() 打开的文件流,并释放所有与该文件流相关的资源

函数原型:

int fclose(FILE *stream);

参数:

  • stream:指向 FILE 结构体的指针,该结构体代表要关闭的文件流

返回值:

  • 成功时返回 0
  • 失败时返回 EOF(通常是 -1

Ⅲ、示例程序

#include<stdio.h>
#include<string.h>
#include<errno.h>

int main()
{
	//打开文件
	FILE* pf = fopen("./Data/test.txt", "r");//相对路径
	//FILE* pf = fopen("D:\\User\\YiAn\\C_Code_1\\test.txt", "r");//绝对路径
	if (pf == NULL)
	{
		printf("%s\n", strerror(errno));
		return -1;
	}
	//操作文件

	//关闭文件
	fclose(pf);
	pf = NULL;
	return 0;
}

五、文件的顺序读写

功能 函数名 适用于
字符输入函数 fgetc 所有输入流
字符输出函数 fputc 所有输出流
文本行输入函数 fgets 所有输入流
文本行输出函数 fputs 所有输出流
格式化输入函数 fscanf 所有输入流
格式化输出函数 fprintf 所有输出流
二进制输入 fread 文件
二进制输出 fwrite 文件

Ⅰ、字符输入输出函数

① fputc()

fputc():向文件写入一个字符

int fputc(int c, FILE *stream);
  • c:要写入的字符
  • stream:指向FILE对象的指针

返回值:

  • 成功时,返回被写入字符
  • 失败时,返回 EOF

使用示例:

fputc('A', pf);
  • 将字符A写入文件指针pf所指向的文件信息区
② fgetc()

fgetc():从文件读取一个字符

int fgetc(FILE *stream);
  • stream:指向FILE对象的指针

返回值:

  • 成功时,返回文件中的第一个字符
  • 失败时,返回 EOF

Ⅱ、文本行输入输出函数

① fputs()

fputs():向文件写入一个字符串

int fputs(const char *s, FILE *stream);
  • s:要写入的字符串
  • stream:指向FILE对象的指针

返回值:

  • 成功时,返回非负值
  • 失败时,返回 EOF

使用示例:

int main(void)
{
    int rc = fputs("Hello World", pf);

    if (rc == EOF)
       //...写入失败处理
       return 1;
}
② fgets()

fgets():从文件读取一行

char *fgets(char *str, int n, FILE *stream);
  • str:存储读取数据的缓冲区(指向char数组元素的指针)
  • n:最大读取字符数
  • stream:指向FILE对象的指针

返回值:

  • 成功时,返回str
  • 失败时,返回 NULL

使用示例:

	//读一行文字
	char str[20] = { 0 };
	char* gs = fgets(str, 4, pf);
	if (gs == NULL)
	{
		//...读取失败处理
    perror("fgets");
		return 1;
	}
	printf("%s\n", str);

  • 读出的字节会存放在创建的数组str
  • n作为最大读取的字符数,其最后需要留一个字节存放\n,因此实际能够读出的字节为n-1

Ⅲ、格式化输入输出函数

这里的格式化的数据表示结构体数据

① fprintf()

fprintf():向文件写入格式化的字符串

int fprintf(FILE *stream, const char *format, ...);
  • stream:指向FILE对象的指针
  • format:格式化字符串
  • ...:可变参数列表

返回值:

  • 正整数:表示成功写入的输出项的数量。这通常与格式字符串中指定的输出项数量相匹配
  • 负值:表示在写入过程中发生了错误。错误可能包括但不限于:
    • 文件流未正确打开或已经关闭
    • 磁盘空间不足,无法写入更多数据
    • 没有足够的权限写入指定的文件
    • 输出被流控制(如终端的流控制)阻止

使用示例:

	struct S
{
	char name[10];
	int age;
	float score;
};

int main()
{
	struct S Stu = { "MoJang",20,98.5f };
	FILE* pstu = fopen("./Score.txt", "w");//打开文件
	if (pstu == NULL)
	{
		perror("fopen");//打印错误信息
		return 1;
	}
	//写入信息
	fprintf(pstu, "%s %d %.2f", Stu.name, Stu.age, Stu.score);

	//关闭文件
	fclose(pstu);
	pstu = NULL;
	return 0;
}
  • Score.txt

    •   MoJang 20 98.50
      
② fscanf()

fscanf():从文件读取格式化的输入

int fscanf(FILE *stream, const char *format, ...);
  • stream:指向FILE对象的指针
  • format:格式化字符串
  • ...:可变参数列表

返回值:

  • 正整数:成功匹配并赋值的输入项的数量。
  • EOF:如果在第一次匹配失败之前输入结束,或者发生错误,函数返回 EOFEOF 也可以通过 feof 函数检测,以确定是否到达文件末尾,或者通过 ferror 函数检测是否发生错误

使用示例:

struct S
{
	char name[10];
	int age;
	float score;
};

int main()
{
	struct S stu;//创建结构体变量存储读出的信息
	FILE* pstu = fopen("./Score.txt", "r");//打开文件
	if (pstu == NULL)
	{
		perror("fopen");//打印错误信息
		return 1;
	}
	//读文件信息
	int flag = fscanf(pstu, "%s %d %f", stu.name, &(stu.age), &(stu.score));

	//打印
	printf("%d\n\n", flag);
	printf("%s\n", stu.name);
	printf("%d\n", stu.age);
	printf("%.2f\n", stu.score);


	//关闭文件
	fclose(pstu);
	pstu = NULL;
	return 0;
}
  • 打印结果:

    •   3
        
        MoJang
        20
        98.50
      
    • 返回值flag表示读取项的数量

Ⅳ、二进制输入输出函数

① fwrite()

fwrite():将数据以二进制写入文件

size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
  • 参数:

    • ptr:指向要写入的数据的指针
    • size:每个数据项的大小,以字节为单位
    • nmemb:要写入的数据项的数量
    • stream:指向FILE对象的指针,该对象标识了要写入的文件流
  • 返回值:

    • 写入成功:返回值是一个size_t类型,表示成功写入的数据项的数量
    • 写入失败:如果返回值小于nmemb,可能是由于错误或到达文件末尾
  • 使用示例:

    •   struct S
        {
        	char name[10];
        	int age;
        	float score;
        };
        
        int main()
        {
        	//初始化需写入的数据
        	struct S dat = { "张三",21,98.5 };
        	//打开文件(wb--以二进制的形式写入)
        	FILE* pf = fopen("./Score.txt", "wb");
        	//判断是否成功打开
        	if (pf == NULL)
        	{
        		perror("fopen");
        		return 1;
        	}
        	//以二进制的形式写入数据
        	fwrite(&dat, sizeof(struct S), 1, pf);
        
        	//关闭文件
        	fclose(pf);
        	pf = NULL;
        	return 0;
        }
      
    • wb---->以二进制的形式写入

② fread()

fread():从文件中以二进制读取数据

size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
  • 参数:

    • ptr:指向用于存储读取数据的内存区域的指针。
    • size:每个数据项的大小,以字节为单位。
    • nmemb:要读取的数据项的数量。
    • stream:指向FILE对象的指针,该对象标识了要读取的文件流。
  • 返回值:

    • 读取成功:返回值是一个size_t类型,表示成功读取的数据项的数量
    • 读取失败:如果返回值小于nmemb,可能是由于错误、到达文件末尾或数据不足
  • 使用示例:

    •   struct S
        {
        	char name[10];
        	int age;
        	float score;
        };
        
        int main()
        {
        	//初始化结构体,存入读出的数据
        	struct S dat = { 0 };
        	//打开文件(wb--以二进制的形式写入)
        	FILE* pf = fopen("./Score.txt", "rb");
        	//判断是否成功打开
        	if (pf == NULL)
        	{
        		perror("fopen");
        		return 1;
        	}
        	//以二进制的形式读
        	fread(&dat, sizeof(struct S), 1, pf);
        
        	//将dat中读出的内容打印至stdout
        	printf("%s %d %.2f\n", dat.name, dat.age, dat.score);
        
        	//关闭文件
        	fclose(pf);
        	pf = NULL;
        	return 0;
        }
      
    • rb---->以二进制的形式写入

    • 输出结果:

      •   张三 21 98.50
        

Ⅴ、“流” (Stream)的简单介绍

  1. 标准输入流 (stdin)

    • 通常用于从键盘或标准输入设备接收数据
  2. 标准输出流 (stdout)

    • 通常用于将数据输出到屏幕或标准输出设备

    •   fprintf(stdout, "%s %d %.2f", Stu.name, Stu.age, Stu.score);
      
      • 可以使用fprintf将信息打印至标准输出流stdout(屏幕)上
  3. 标准错误流 (stderr)

    • 用于将错误信息输出到屏幕或标准错误输出设备
  4. 文件流:

    • 用于从文件读取数据或向文件写入数据。在C语言中,使用FILE指针来操作文件流
  5. 网络流:

    • 用于通过网络套接字(socket)进行数据传输
  6. 管道流 (Pipe)

    • 在Unix-like系统中,管道是一种特殊类型的文件,用于在进程间传递数据
  7. 串行通信流:

    • 用于通过串行端口(如RS-232)进行数据传输
  8. 内存流:

    • 数据在内存中的缓冲区之间流动,例如在C语言中使用fmemopen函数创建的流
  • 流通常与I/O (输入/输出) 操作相关联。流可以是文本模式的,其中数据以字符为单位进行处理,或者是二进制模式的,其中数据以字节为单位进行处理。

Ⅵ、三组输入输出语句

① 表格 1: scanf 和 rintf
函数名称 功能描述 读取/写入来源 返回值
scanf 针对标准输入的【格式化输入语句】 标准输入(键盘) 成功读取的项目数
printf 针对标准输出的【格式化输出语句】 标准输出(屏幕) 成功写入的项目数
② 表格 2: fscanf 和 fprintf
函数名称 功能描述 读取/写入来源 返回值
fscanf 针对所有输入流的【格式化输入语句】 文件或输入流 成功读取的项目数
fprintf 针对所有输出流的【格式化输出语句】 文件或输出流 成功写入的项目数
③ 表格 3: sscanf 和 sprintf
函数名称 功能描述 读取/写入来源 返回值
sscanf 从一个字符串中转换出一个格式化的数据 字符串 成功读取的项目数
sprintf 把一个【格式化的数据转换成字符串 字符串缓冲区 成功写入的项目数

sprintf( )

格式化的数据——>字符串

struct S
{
	char name[10];
	int age;
	float score;
};

//将一个格式化的数据转换成字符串
int main()
{
	//创建一个格式化的数据
	struct S ss = { "李四",22,90.5 };
	char buf[40] = { 0 };//用于存储转换而来的字符串

	sprintf(buf, "%s %d %.2f", ss.name, ss.age, ss.score);
	printf("%s\n", buf);//打印字符串

	return 0;
}
  • 输出:

    •   李四 22 90.50
      

sscanf( )

字符串——>格式化的数据

struct S
{
	char name[10];
	int age;
	float score;
};

//将一个字符串转换成一个格式化的数据
int main()
{
	//创建一个源字符串数据
	char buf[40] = { "李四 22 90.50" };
	//创建一个结构体数据,以接收
	struct S ss = { 0 };

	sscanf(buf, "%s %d %f", ss.name, &(ss.age), &(ss.score));
	//%f不能写成%.2f,须保证转换数据的完整性
	//李四	-->	ss.name
	//22	-->	ss.age
	//90.50	-->	ss.score

	//打印测试
	printf("%s\n%d\n%.2f\n", ss.name, ss.age, ss.score);

	return 0;
}
  • 输出:

    •   李四
        22
        90.50
      

六、文件的随机读写

Ⅰ、fseek()函数

用于移动文件流中的文件指针(FILE*)的位置

① 函数原型

int fseek(FILE *stream, long int offset, int whence);

② 参数

  • stream:指向FILE对象的指针,该对象标识了要操作的文件流

  • offset偏移量,指定从whence参数指定的位置开始的字节数。可以是正数或负数

  • whence起始点,指定offset参数相对于哪个位置。可能的值包括:

      • SEEK_SET:文件的开头(通常为文件的起始位置)
      • SEEK_CUR:当前文件位置指针的位置
      • SEEK_END:文件的末尾

③ 返回值

  • 成功时:返回 0
  • 失败时:返回非零值

④ 使用示例

	FILE* pf = fopen("./Data/test.txt", "r");
	//文件中存储的信息为:ABCDEF
	if (pf == NULL) {
		perror("fopen");
		return 1;
	}
//.......
//.......
	fclose(pf);
	pf = NULL;

	return 0;
}

  • 文件test.txt中存放的是:

    •   ABCDEF
      
  •   	fseek(pf, 2, SEEK_SET);
      	int ch = fgetc(pf);//使用一次指针+1,由C-->D
      	printf("%c\n", ch);//C
    
    • 设置文件指针从起始位置向后偏移2
    • 指针指向A ----> 指针指向C
    • 使用fgetc函数后,当前指针的位置会向后偏移一个单位
  •   	fseek(pf, 2, SEEK_CUR);
      	ch = fgetc(pf);
      	printf("%c\n", ch);//F
    
    • 设置文件指针从当前位置向后偏移2
    • 指针指向D ----> 指针指向F
  •   fseek(pf, -2, SEEK_END);
      ch = fgetc(pf);
      printf("%c\n", ch);//E
    
    • 设置文件指针从末尾位置向前偏移2
    • 指针指向文件末尾 ----> 指针指向E

Ⅱ、ftell()函数

用于返回文件指针相对于起始位置的偏移量

① 函数原型

long int ftell(FILE *stream);

② 参数

  • stream:指向 FILE 对象的指针,该对象标识了要操作的文件流

③ 返回值

  • 如果成功,返回当前位置相对于起始位置的偏移量offset
  • 如果失败,返回 -1L(在 errno 被设置为 EBADF 时,表示无效的文件流

Ⅲ、rewind()函数

重置文件指针,使其回到起始位置

① 函数原型

void rewind(FILE *stream);

② 参数

  • stream:指向 FILE 对象的指针,该对象标识了要操作的文件流

七、文本文件和二进制文件

文本文件和二进制文件是两种主要的文件类型,它们在存储和处理数据的方式上有所不同

文本文件 (Text Files)

  • 若要求在外存上以ASCII的形式存储,则需要在存储前转换。这样以ASCII的形式存储的文件就是 文本文件

  1. 字符编码: 文本文件包含以字符编码(如ASCII、UTF-8等)形式存储的文本数据
  2. 可读性: 文本文件的内容可以用文本编辑器直接打开和阅读,因为它们是由人类可读的字符组成
  3. 换行符: 文本文件中的换行符在不同的操作系统中可能有所不同(如Windows中的\r\n和Unix/Linux中的\n
  4. 处理方式: 文本文件通常用于存储需要人类阅读的数据,如代码、文档、配置文件等
  5. I/O操作: 在C语言中,可以使用fgetcfgetsfputcfputs等函数进行字符或字符串级别的读写操作

二进制文件 (Binary Files)

  • 数据在内存中以二进制的形式存储,如果不加转换的输出到外存,就是二进制文件

  1. 数据存储: 二进制文件包含以二进制形式存储的数据,这可以是任何类型的数据,如图像、音频、视频或程序的编译代码
  2. 不可读性: 二进制文件的内容不能直接用文本编辑器阅读,因为它们包含非文本数据或编码方式不适合文本显示
  3. 跨平台性: 二进制文件在不同的操作系统中具有一致性,因为它们不依赖于特定的换行符或其他文本格式
  4. 处理方式: 二进制文件通常用于存储需要由程序处理的数据,如数据库文件、可执行文件、图像文件等
  5. I/O操作: 在C语言中,可以使用freadfwritefseek等函数进行数据块的读写操作,这些操作不涉及字符编码转换
  • 字符一律以ASCII形式存储
  • 数值型数据既可以用ASCII形式存储,也可以二进制形式存储

举例:

若要存储整数10000

  1. ASCII形式存储:

    • 磁盘中占用5byte,一个字符占用一个字节

    • ASCII形式存储数字10000,则会将其每一位数字转换为对应的ASCII字符:

      •   '1' -> 49
          '0' -> 48
          '0' -> 48
          '0' -> 48
          '0' -> 48
        
      • 因此,数字10000ASCII字符序列存储为:49 48 48 48 48

  2. 二进制形式存储:

    • 磁盘中占用4byte,即一个整型的大小(int
    • 00000000      00000000      00011011      00010000 = 10      27      00      00 00000000\;\; 00000000\;\; 00011011\;\; 00010000=10\;\;27\;\;00\;\;00 00000000000000000001101100010000=10270000小端存储

八、文件读取结束的判定

feof()函数:

  • 在文件读取过程中,不能直接用feof()函数的返回值作为判断文件是否结束的依据
  • 当文件读取结束的时候,该函数可以判断是读取失败结束,还是遇到文件尾结束

feof 函数在可用于检查文件流是否已经到达文件末尾End Of File,EOF

函数原型:

int feof(FILE *stream);

参数: stream:指向 FILE 对象的指针,该对象标识了要检查的文件流

返回值:

  • 如果文件位置指针已经到达文件末尾,返回非零值(通常是1)
  • 如果文件位置指针没有到达文件末尾,返回0
  • 如果在读取过程中发生错误,feof 也会返回非零值,但此时 ferror 函数将返回一个非零值以指示错误发生

Ⅰ、文本文件读取结束的判断

  • 文本文件读取是否结束,判断返回值是否为EOF (fgetc),或者NULL(fgets)
  • 例如:
    • fgetc判断是否为EOF
    • fgets判断返回值是否为NULL

示例

FILE *file = fopen("example.txt", "r");
char c;
if (file == NULL) 
{
    perror("fopen");
    return -1;
}
while ((c = fgetc(file)) != EOF) 
{
    // 处理字符 c
}
if (feof(file)) 
{
    printf("End of file reached.\n");
}
fclose(file);
file = NULL;

Ⅱ、二进制文件读取结束的判断

  • 使用 fread 函数从二进制文件中读取数据时,应该检查返回值是否小于请求读取的数据项的数量
    • 如果 fread 返回的项数小于请求的项数,这可能意味着已经到达文件末尾或者发生了读取错误

示例

FILE *file = fopen("example.bin", "rb");
int data[10];
size_t items_read = fread(data, sizeof(int), 10, file);
if (items_read < 10) 
{
  if (feof(file)) 
    {
        printf("在提取所有文件之前达到末尾\n");
    } 
  else if (ferror(file)) 
    {
        perror("读取文件错误");
    }
}
fclose(file);
file = NULL;

九、文件缓冲区

请添加图片描述

  • 文件缓冲区(File Buffer)是操作系统为每个打开的文件自动分配的一块内存区域,用于暂存即将写入文件的数据(输出缓冲区)或从文件中读取的数据(输入缓冲区)

  • 文件缓冲区的主要目的是减少实际的磁盘I/O操作次数,因为直接与磁盘进行数据交换通常比与内存交换要慢得多

#include <stdio.h>
#include <windows.h>

int main() {
    FILE* pf = fopen("test.txt", "w");
    if (pf == NULL) {
        perror("Error opening file");
        return -1;
    }
    fputs("abcdef", pf); // 先将数据放入输出缓冲区

    printf("睡眠10秒-已经写入数据了,打开test.txt文件,此时文件还没有写入内容\n");
    Sleep(10000);

    printf("刷新缓冲区\n");
    fflush(pf); // 刷新缓冲区,将数据写入文件

    printf("再睡眠10秒-此时,再次打开test.txt文件,文件有内容了\n");
    Sleep(10000);

    fclose(pf); // 关闭文件,fclose也会刷新缓冲区
    pf = NULL;
    return 0;
}
  • 因此,使用fputs等函数向文件写入数据时,并不会立马就将数据存入文件中,只有当缓冲区刷新时,数据才会写入文件中

网站公告

今日签到

点亮在社区的每一天
去签到