文件操作和此基础之上的通讯录修改


本章会讲述到大量的函数,函数的详细在www.cplusplus.com中都有

1.为什么使用文件

从我们之前完成的通讯录来看我们的数据都是存储在内存中的,每次运行我们的程序我们都要重新录入一边我们之前的信息,程序执行结束后我们的信息就不存在了,这时我们就需要将数据存入我们的文件中,也就是磁盘中.

2.什么是文件

文件分为两类:程序文件和数据文件

2.1程序文件:

程序文件就是我们常常写的源文件(.c),目标文件(.obj),执行文件(.exe)这一类型的文件。

2.2数据文件

数据文件的内容不一定是程序,而是我们在使用时对其文件进行读写时运用到的数据,比如说我们在进行程序运行时会输入文件的数据用来完成我们的需求,或者是输出文件的内容。

3.文件的打开和关闭

文件的打开和关闭运用到了两个函数分别是:
打开->fopen()
第一个参数 filename是我们的文件名
第二个参数是我们需要打开的模式(这个打开模式待会儿会有图)
如果我们打开失败了这个函数会返回一个空指针
在这里插入图片描述

关闭->fclose()
其参数是我们的数据存放在那个文件流中,这里的文件流就是我们在访问文件时会自动产生一个文件信息区,而这个文件信息区就是一个结构体其名称是FILE 我们要以一个FILE* 的指针去维护我们整个文件
在这里插入图片描述
我们在此细讲如何去维护我们的文件:每当我们打开一个文件的时候文件中默认打开了一个文件信息区,这个文件信息区是一个FILE类型的结构体,我们一般不会直接去访问文件里面的内容,我们一般利用的就是一个文件指针去维护我们整个文件
在这里插入图片描述
大致就是这样的一个过程,我们通过文件指针去维护我们的文件信息区再进一步访问到我们的文件,文件信息区就存储了我们的文件内容的各项数据,这个是通过操作系统完成的我们也不需要深入了解.

打开文件时的模式

这个是我们在打开文件时可能选择的模式:
在这里插入图片描述
"r"的实例
在这里插入图片描述
"w"的实例
在这里插入图片描述
在这里插入图片描述
当我们运行程序完毕的时候我们确实发现了在我们的这个当前文件中确实出现了一个名为test.data的文件也就是说明我运用w的模式在没有源文件的时候我们会自动新建一个
可以自己尝试使用各种模式

4.文件的顺序读写和随机读写

当我们掌握如何去打开和关闭一个文件的时候我们就可以往文件中进行读写了.

4.1文件的顺序读写

在这里插入图片描述
1.fgetc()
它是从一个流中输入数据到这个流所指向的空间中,如果是文件流就输入到该文件中如果输入失败则会返回一个EOF值,下图我们可以看见如何使用fgetc去访问到我们文件中的第一个字符
在这里插入图片描述
2.fputc()
它是从一个流中输出我们的一个字符,如果是文件流就从该文件中写入一个字符,如果输出失败则会返回一个EOF值,下图我们可以看见如何使用fputc去输出我们文件中的第一个字符
在这里插入图片描述

3.fgets()
它和fgetc()的不同点就是它是输入一整行的字符串,它的参数中有个num,它实际访问到的个数是这个num-1的个数,就是说如果我们要访问abcde这五个字符但是我们这里的num如果写5它就只能访问到4个字符,是因为它需要一个结束标志如果实际的字符长度比这里的num大,这个num就会在最后补上一个’\0’如果没有比num大则会在末尾添加一个’\n’的换行符,如果输入不成功的话就会返回一个NULL
如图我们可以看见确实只读取了num-1个字符后面的x并没有输出出来
在这里插入图片描述
4. fputs()
它和fputc的不同点就是它是输出一整行的字符串,它是将一整行字符串输出到一个流中,如果是文件,就输到文件中,如果输出失败则返回EOF
如图所示确实将hello world 存储到了文件中
在这里插入图片描述
5.fscanf()
之前我们的操作都是基于我们所选中的数据都是字符或者字符串类型,但是我们的数据类型还有整形,浮点型等类型,我们应该以格式化的形式去访问到这些数据才不会导致数据的异常或者导致类型不同的问题
如图,当我们的文件中已经有了不同类型的数据的时候我们使用格式化的输入函数fscanf()就发现我们将数据确实读取到了两个变量中,一个是i一个是f,而如果没有读取成功fscanf则会返回EOF
在这里插入图片描述
6.fprintf()
我们能读取到不同格式的内容,也应该能写入不同种类型的数据,利用fprintf()可以完成对待格式化的数据如何存入我们的流中
如图我们也确实能看见将这两种类型的数据输出到了我们的文件流中
在这里插入图片描述
7.fwrite()
有时候我们的数据不需要让别人直接观察到我们就采用二进制的形式去写入数据
如图我们发现我们存入的数据却看不明白是因我们没有进行转化而是直接存储了我们的二进制数,在不进行转化的时候我们在文件中的值都是以ASCLL码值存储的而每个字符都有其对应的ASCLL码值所以就导致造成我们看不懂的现象,我们存入的值是99但是在文件中却是c(c的ASCLL码值是99)
在这里插入图片描述

8.fread()
当我们想要读取二进制的文件的时候我们就可以用采用二进制读取文件数据的函数fread()
我们也确实是把之前用fwrite()写进的99读取了出来,fread的返回值一定是小于实际要读的个数

在这里插入图片描述

4.1.1通讯录的改造之前的通讯录点击这里

改造的方向就是:
1.可以从文件中导入数据
2.在程序结束时将数据导入文件中
我们既然是在结束时将数据导入文件中那么我们封装的函数就应该在程序结束之前
在这里插入图片描述

void savecontent(content* pc)
{
	//打开文件
	FILE* pf = fopen("content.data", "wb");
	if (pf == NULL)
	{
		perror("fopen");
		return;
	}
	//写入文件
	int i = 0;
	for (i = 0; i < pc->pepnum; i++)
		fwrite(pc->date + i, sizeof(PePInfo), 1, pf);
	//关闭文件
	fclose(pf);
	pf = NULL;
}

这是我们导入数据的代码。
当我们打开程序时,我们需要导入文件中的信息来方便我们对数据进行各种的增删改查等功能
我们封装一个函数叫Download()

void Download_content(content* pc)
{
	//打开文件
	FILE* pf = fopen("content.data", "rb");
	if (pf == NULL)
	{
		perror("Down_lode_fopen");
		return;
	}
	//读入数据
	PePInfo tmp = { 0 };
	while (fread(&tmp, sizeof(PePInfo), 1, pf))
	{
		if (Checkcapacity(pc) == 0)
		{
			perror("Checkcapacity");
			return;
		}
		pc->date[pc->pepnum] = tmp;
		pc->pepnum++;
	}
	//关闭文件
	fclose(pf);
	pf = NULL;
}

全部代码
点击这里

4.1.2 printf,fprintf.sprintf-scanf,fscanf,sscanf的区别

这里的…代表可变参数即参数不固定
在这里插入图片描述
在这里插入图片描述
这里我们确实将字符串arr中的10转化成了整形10.
概括一下就是:
在这里插入图片描述

4.2文件的随机读写

刚刚我们的读写都是在起始位置依次向后进行读写,现在我们要学习如何在自己想要读写的位置进行读写
1.fseek()
该函数会根据文件的偏移量和文件指针来定位当前文件指针的指向
在这里插入图片描述
2.ftell()
该函数用于返回当前文件指针的偏移量
在这里插入图片描述
我们也可以发现当fgetc()取出一个字符的时候其文件指针就会向后走一格,所以这里的偏移量是3和4

3.rewind()
该函数用于回到文件指针的起始位置
在这里插入图片描述
可以看见恢复起始位置的偏移量是0.

5.文本文件和二进制文件

根据数据的组织形式我们将数据分为了文本文件和二进制文件
二进制文件:就是不通过任何的转化直接将二进制数据存储到我们的硬盘中就叫做二进制文件
文本文件:如果要求以ASCLL码值的形式存储到我们的硬盘中就要在二进制的基础上加以转换,翻译成我们能直观看到的文件信息就叫做文本文件
字符一律以ASCLL码值的形式存储而数值既可以以ASCLL码值的形式存储也可以通过二进制存储
我们来测试一下:

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

老幺*

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值