深度解析C语言文件操作以及常见问题

作者:~小明学编程

文章专栏:C语言基础知识

目之所及皆为回忆,心之所向皆为过往
在这里插入图片描述

目录

为什么我们要使用文件

文件的打开和关闭

文件指针

文件的打开和关闭

文件的打开方式

文件的顺序读写 

fgetc

fputc

fputs

fgets

fscanf

fprintf

fwrite

fread

文件的随机读取

fseek

 ftell

rewind 

文件读取结束的判定

大怨种feof


为什么我们要使用文件

在我们写程序的时候,大家一定发现了一个问题就是我们的程序在运行完了之后就啥也没有了就如我们的通讯录小程序我们在运行程序的时候会对其输入很多的人物信息然后我们可以对其进行修改查询等操作,但是当我们结束该程序的时候我们所输入的数据会随着我们的程序的结束而被程序给释放掉,那么我们如何解决该问题呢?这时我们会想到要是我们能有一个文件存储这些信息,当我们下次再次打开该程序的时候接着读取上一次的信息就好了,这便是我们本次要介绍的内容,我们通过一些函数直接操作文件的读写。

文件的打开和关闭

文件指针

缓冲文件系统中,关键的概念是“文件类型指针”,简称“文件指针”。
每个被使用的文件都在内存中开辟了一个相应的文件信息区,用来存放文件的相关信息(如文件的名 字,文件状态及文件当前的位置等)。这些信息是保存在一个结构体变量中的。该结构体类型是有系统 声明的,取名FILE.
使用方式
FILE* pf;//文件指针变量
定义 pf 是一个指向 FILE 类型数据的指针变量。可以使 pf 指向某个文件的文件信息区(是一个结构体变
量)。通过该文件信息区中的信息就能够访问该文件。也就是说, 通过文件指针变量能够找到与它关联 的文件。

文件的打开和关闭

文件在读写之前应该先 打开文件 ,在使用结束之后应该 关闭文件
在编写程序的时候,在打开文件的同时,都会返回一个 FILE* 的指针变量指向该文件,也相当于建立了指 针和文件的关系, ANSIC 规定使用 fopen 函数来打开文件, fclose 来关闭文件。
int main()
{
	int a = 10000;
	FILE* pf = fopen("test.txt", "wb");//打开文件
	fwrite(&a, 4, 1, pf);//二进制的形式写到文件中
	fclose(pf);//关闭文件
	pf = NULL;
	return 0;
}

文件的打开方式

深度解析C语言文件操作以及常见问题_第1张图片

文件的顺序读写 

深度解析C语言文件操作以及常见问题_第2张图片

下面给大家具体介绍几个文件常用函数

fgetc

深度解析C语言文件操作以及常见问题_第3张图片

 函数的功能主要就是从标准流中读取一个字符然后写入文件中

int main()
{
	FILE* pw = fopen("test.txt", "w");
	if (pw == NULL)
	{
		printf("%s\n", strerror(errno));
	}
	fputc('h', pw);
	fputc('a', pw);
	fputc('h', pw);
	fputc('a', pw);
	fclose(pw);
	pw = NULL;
	printf("读取完毕!\n");
	return 0;
}

深度解析C语言文件操作以及常见问题_第4张图片

fputc

深度解析C语言文件操作以及常见问题_第5张图片

函数的主要功能就是从文件中读出一个字符
int main()
{
	FILE* pw = fopen("test.txt", "r");
	if (pw == NULL)
	{
		printf("%s\n", strerror(errno));
	}
	printf("%c", fgetc(pw));
	printf("%c", fgetc(pw));
	printf("%c", fgetc(pw));
	printf("%c", fgetc(pw));
	fclose(pw);
	pw = NULL;
	printf("读取完毕!");
	return 0;
}

通过fgetc函数我们将刚刚读入的字符再次的读出来。

深度解析C语言文件操作以及常见问题_第6张图片

这里说明一下,大家可能会觉得我们四个相同的输出语句为什么却读的不同的内容
这是因为无论我们是读入还是读出,当我们读完第一个字符的时候我们的内部文件指针会自动的指向下一个字符所以我们才会读出不同的内容。

fputs

深度解析C语言文件操作以及常见问题_第7张图片

 函数的功能主要是写入一个字符串进入我们的文件之中,其中有两个参数,一个是我们的字符串地址,还有一个是文件指针

int main()
{
	char str[10]={0};
	FILE* pw = fopen("test.txt", "w");
	if (pw == NULL)
	{
		printf("%s\n", strerror(errno));
	}
	//fgets(str, 10, pw);
	//printf("%s", str);
	//fgets(str, 10, pw);
	//printf("%s", str);
	fputs("hello\n", pw);
	fputs("world", pw);
	fclose(pw);
	pw = NULL;
	return 0;
}

深度解析C语言文件操作以及常见问题_第8张图片

fgets

深度解析C语言文件操作以及常见问题_第9张图片

函数的主要功能就是 从我们的流也就是文件中读取字符串,我们可以看到该函数一共有三个参数,分别是把我们读取的字符串要放入的地址,读取的个数,以及我们的文件指针。

int main()
{
	char str[10]={0};
	FILE* pw = fopen("test.txt", "r");
	if (pw == NULL)
	{
		printf("%s\n", strerror(errno));
	}
	fgets(str, 10, pw);
	printf("%s", str);
	fgets(str, 10, pw);
	printf("%s", str);
	//fputs("hello\n", pw);
	//fputs("world", pw);
	fclose(pw);
	pw = NULL;
	return 0;
}

深度解析C语言文件操作以及常见问题_第10张图片

fscanf

深度解析C语言文件操作以及常见问题_第11张图片

 函数的主要功能就是格式化的从文件中输入想要的数据

struct S
{
	char name[20];
	int age;
	double score;
};

int main()
{
	struct S s = { 0 };
	FILE* p = fopen("text.txt", "r");
	if (p == NULL)
	{
		printf("%s", strerror(errno));
	}
	if (p == 0)
	{
		return 1;
	}
	fscanf(p, "%s %d %f", s.name, &(s.age), &(s.score));
	printf("%s %d %f", s.name, s.age, s.score);
	fclose(p);
	p == NULL;
	return 0;
}

深度解析C语言文件操作以及常见问题_第12张图片

fprintf

深度解析C语言文件操作以及常见问题_第13张图片

 函数的主要功能就是格式化的将数据输出到文件之中

struct S
{
	char name[20];
	int age;
	double score;
};
int main()
{
	struct S s = { "张三",20,100.0 };
	FILE* p = fopen("text.txt", "w");
	if (p == NULL)
	{
		printf("%s", strerror(errno));
	}
	if (p == 0)
	{
		return 1;
	}
	fprintf(p,"%s %d %f", s.name, s.age, s.score);
	fclose(p);
	p == NULL;
	return 0;
}
深度解析C语言文件操作以及常见问题_第14张图片

fwrite

深度解析C语言文件操作以及常见问题_第15张图片

 函数主要功能是以二进制的形式写入文件数据

其中的参数分别是要写入的项目地址,字节的大小,要写入的最大项目数和文件指针

struct S
{
	char name[20];
	int age;
	double score;
};
int main()
{
	struct S s = { "张三",20,60 };
	FILE* pf = fopen("test.txt", "wb");
	if (pf == NULL)
	{
		return 1;
	}
	fwrite(&s, sizeof(struct S), 1, pf);
	return 0;
}

深度解析C语言文件操作以及常见问题_第16张图片

fread

深度解析C语言文件操作以及常见问题_第17张图片

 函数的主要功能是从流中以二进制形式读入数据,参数和fwrite一样。

struct S
{
	char name[20];
	int age;
	double score;
};

int main()
{
	struct S s = { 0 };
	FILE* pf = fopen("test.txt", "rb");
	if (pf == NULL)
	{
		return 1;
	}
	fread(&s, sizeof(struct S), 1, pf);
	printf("%s %d %.1lf", s.name, s.age, s.score);
	return 0;
}

深度解析C语言文件操作以及常见问题_第18张图片

文件的随机读取

fseek

深度解析C语言文件操作以及常见问题_第19张图片

 该函数可以让我们从指定的位置读取文件的内容,传参以此是文件指针,偏移量和读取的位置

int main()
{
	FILE* p = fopen("test.txt", "r");
	if (p == NULL)
	{
		return 1;
	}
	fseek(p, 2, SEEK_CUR);
	printf("%c", fgetc(p));
	fclose(p);
	p = NULL;
	return 0;
}

我们可以看到我们的偏移量是2,读取位置是当前文件指针的位置

深度解析C语言文件操作以及常见问题_第20张图片

 ftell

函数的主要作用是返回一个文件指针相对于起始位置的偏移量

int main()
{
	FILE* p = fopen("test.txt", "r");
	if (p == NULL)
	{
		return 1;
	}
	fseek(p, 2, SEEK_CUR);
	printf("%c\n", fgetc(p));
	int ret = ftell(p);
	printf("%d", ret);
	fclose(p);
	p = NULL;
	return 0;
}

深度解析C语言文件操作以及常见问题_第21张图片

我们可以看到返回的是3。

rewind 

此函数的目的是让文件指针重新回到起始的位置。

文件读取结束的判定

大怨种feof

对feof函数最大的误解就是觉得它是用来判断判断文件是否结束的,然而它的作用并不是如此,用它的时候文件一定是读取结束只是它可以告诉我们文件读取结束是因为什么是文件读完了还是文件读取失败了。

1. 文本文件读取是否结束,判断返回值是否为 EOF fgetc ),或者 NULL fgets
例如:
fgetc 判断是否为 EOF .
fgets 判断返回值是否为 NULL .
2. 二进制文件的读取结束判断,判断返回值是否小于实际要读的个数。
例如:
fread 判断返回值是否小于实际要读的个数。
int main() 
{
	int c; // 注意:int,非char,要求处理EOF
	FILE* fp = fopen("test.txt", "r");
	if (!fp) {
		perror("File opening failed");
		return EXIT_FAILURE;
	}
	//fgetc 当读取失败的时候或者遇到文件结束的时候,都会返回EOF
	while ((c = fgetc(fp)) != EOF) // 标准C I/O读取文件循环
	{
		putchar(c);
	}
	//判断是什么原因结束的
	if (ferror(fp))
		puts("I/O error when reading");
	else if (feof(fp))
		puts("End of file reached successfully");
	fclose(fp);
	return 0;
}

深度解析C语言文件操作以及常见问题_第22张图片

你可能感兴趣的:(C语言基础知识,c语言,开发语言)