C语言——文件相关操作补充

一、文件读取结束的判定

当我们使用例如fgetc、fgets、fscanf、fread等函数来读取文件内容时,我们可能遇到需要判断文件读取的结束,一般情况下都是通过这些函数的返回值来判断文件读取是否结束。

1、fgetc

返回读取的字符的ASCII值,如果读到文件末尾或发生错误,则返回EOF(通常定义为-1)。

所以在使用fgetc函数读取文件内容时,要判断文件读取的结束则判断fgetc函数的返回值是否是EOF,如果fgetc函数的返回值为EOF,则可能是达到文件结尾,也就是文件读取结束。

例如使用fgetc以一个个字符读取文件的所有内容并打印出来:

cpp 复制代码
#include <stdio.h>

int main()
{
	FILE* pf = fopen("test.txt", "r");
	if (pf == NULL)
	{
		perror("fopen");
		return -1;
	}

	char ch = 0;
	while ((ch = fgetc(pf)) != EOF)//使用fgetc函数的返回值作为判断,如果是EOF,则可能是读取结束
	{
		printf("%c ", ch);
	}
	printf("\n");

	fclose(pf);
	pf = NULL;
	return 0;
}

文件内容为:

运行结果:

2、fgets

返回指向读取字符串的指针,如果读到文件末尾或发生错误,则返回NULL

如果fgets函数的返回值为NULL,则可能是达到文件结尾,也就是文件读取结束。

例如尝试使用fgets函数将文件的内容一行行读取并打印:

cpp 复制代码
#include <stdio.h>

int main()
{
	FILE* pf = fopen("test.txt", "r");
	if (pf == NULL)
	{
		perror("fopen");
		return -1;
	}

	char str[100] = { 0 };
	while (fgets(str,100,pf) != NULL)//使用fgets函数的返回值作为判断,如果是NULL,则可能是读取结束
	{
		printf("%s", str);
	}

	fclose(pf);
	pf = NULL;
	return 0;
}

文件内容:

运行结果:

3、fscanf

返回成功匹配和赋值的输入项数,如果读到文件末尾或发生错误,则返回EOF

如果fscanf函数的返回值为EOF,则可能是达到文件结尾,也就是文件读取结束。

使用fscanf函数格式化读取文件中所有数据:

cpp 复制代码
#include <stdio.h>

int main()
{
	FILE* pf = fopen("test.txt", "r");
	if (pf == NULL)
	{
		perror("fopen");
		return -1;
	}

	int id = 0;
	char name[10] = { 0 };
	int age = 0;
	while (fscanf(pf, "%d %s %d", &id, name, &age) == 3)//使用fscanf的返回值作为判定条件,如果返回值不等于期望匹配项,则可能是文件读取完成
	{
		printf("%d %s %d\n", id, name, age);
	}

	fclose(pf);
	pf = NULL;
	return 0;
}

文件内容:

运行结果:

4、fread

函数原型:

cpp 复制代码
size_t fread(void *ptr, size_t size, size_t count, FILE *stream);

返回成功读取的元素个数,如果读到文件末尾或发生错误,则返回值可能小于count

文件内容,使用下面的程序写入test.bin文件中:

cpp 复制代码
#include <stdio.h>

int main()
{
	FILE* pf = fopen("test.bin", "wb");
	if (pf == NULL)
	{
		perror("fopen");
		return -1;
	}

	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	fwrite(arr, sizeof(int), sizeof(arr) / sizeof(int), pf);

	fclose(pf);
	pf = NULL;
	return 0;
}

使用二进制编辑器打开查看(这里是小端字节序):

使用fread读取十个整形数据:

cpp 复制代码
#include <stdio.h>

int main()
{
	FILE* pf = fopen("test.bin", "rb");
	if (pf == NULL)
	{
		perror("fopen");
		return -1;
	}

	int temp = 0;
	while (fread(&temp, sizeof(int), 1, pf) == 1)//以fread函数的返回值为判定,因为这里读取元素个数为1,正确读取应当返回1,如果返回值不是1,则可能是文件结尾,也就是文件读取完成
	{
		printf("%d ", temp);
	}
	printf("\n");

	fclose(pf);
	pf = NULL;
	return 0;
}

运行结果:

5、总结

  • 对于fgetc,当返回值为EOF时,可能表示文件读取结束。
  • 对于fgets,当返回值为NULL时,可能表示文件读取结束。
  • 对于fscanf,当返回值为EOF时,可能表示文件读取结束。
  • 对于fread,当返回值小于请求的元素个数count时,可能表示文件读取结束。

二、feof和ferror

在上面的文件读取结束的判定中,只是初步的判定,因为对于那些读取文件的函数的特殊返回值不一定是代表文件到了结尾(文件读取结束),也可能是代表文件读取错误。所以我们需要判断是哪一种情况,到底是文件读取结束还是文件读取错误,就需要下面的两个函数。

1、feof

feof函数用于检测文件的结束标志(End-Of-File)。

函数原型:

函数参数和返回值:

参数 stream 是文件流指针,当文件指针到达文件末尾时,feof函数返回非零值(通常是1),否则返回0。

2、ferror

ferror函数用于检测文件操作是否发生错误。

函数原型:

函数参数和返回值:

参数 stream 是文件流指针,如果在文件操作过程中发生错误,ferror函数返回非零值(通常是1),否则返回0。

3、使用示例:

如果需要区分文件结束和读取错误,可以使用feofferror函数。

test.txt文件内容:

下面的代码尝试以一个个字符读取此文件的全部内容,并且打印出来:

cpp 复制代码
#include <stdio.h>

int main() {
	FILE* pf = fopen("test.txt", "r");
	if (pf == NULL) {
		perror("fopen");
		return 0;
	}

	char ch = 0;
	while ((ch = fgetc(pf)) != EOF) {
		printf("%c ", ch);
	}
	printf("\n");
	if (feof(pf)) {
		printf("文件读取结束\n");
	}
	else if (ferror(pf)) {
		printf("文件读取错误\n");
	}

	fclose(pf);
	pf = NULL;
	return 0;
}

运行结果:

在上述代码中,feof(file)用于检查是否到达文件末尾,而ferror(file)用于检查是否发生了读取错误。这里的结果是文件读取结束。

相关推荐
结衣结衣.11 分钟前
python中的函数介绍
java·c语言·开发语言·前端·笔记·python·学习
茫茫人海一粒沙14 分钟前
Python 代码编写规范
开发语言·python
原野心存14 分钟前
java基础进阶知识点汇总(1)
java·开发语言
程序猿阿伟17 分钟前
《C++高效图形用户界面(GUI)开发:探索与实践》
开发语言·c++
暗恋 懒羊羊25 分钟前
Linux 生产者消费者模型
linux·开发语言·ubuntu
五味香41 分钟前
C++学习,信号处理
android·c语言·开发语言·c++·学习·算法·信号处理
梓䈑1 小时前
【C语言】自定义类型:结构体
c语言·开发语言·windows
PYSpring1 小时前
数据结构-LRU缓存(C语言实现)
c语言·数据结构·缓存
鱼跃鹰飞1 小时前
Leecode热题100-295.数据流中的中位数
java·服务器·开发语言·前端·算法·leetcode·面试