用C语言实现文件版的通讯录

1.为什么要进行文件操作

在往期,我们使用C语言构造过通讯录,但是无论是一次性开辟好空间的通讯录,还是动态版的通讯录,都无法做到退出通讯录后将信息保存下来。但是通过文件操作,我们可以在退出通讯录时将信息保存到文件中,并且在再次打开时读取信息到程序中,以达到每次打开时能信息的功能。

2.如何保存通讯录

在C语言里,有文件操作函数帮助我们将程序中的信息保存到文件中。为了保存通讯录,我们将会用到fopen,fclose,fwrite以及fread函数。通过这四个函数,我们可以在关闭程序时将信息写入到文件中,并且在打开程序时将文件中的信息读取到程序中,已达到保存通讯录信息的目的。

接下来,我们先对这四个函数进行介绍。

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

fopen函数可以让我们打开一个文件,其第一个参数为包含文件名的字符串,它可以是文件的名字,比如"data.txt",只写文件名时程序只会在当前目录下查找该文件。也可包含文件的路径,比如""C:\Users\Administrator\Desktop\data.txt",这样就能对其他目录下的文件进行操作了。

第二个参数则是包含文件访问模式的字符串。比如"r"则意为以读取的方式打开文件,若该文件不存在则会打开失败。而"w"则表示以写入的方式打开一个文件,如果没有同名文件则会创建一个空文件,若有同名文件则会清空该文件。

其返回值会返回一个FILE*类型的指针,这个指针指向了被打开的文件,若打开失败则会返回NULL。

int fclose(FILE *stream)

fclose函数可以帮助我们关闭一个已经打开的文件。其参数为要关闭的文件,其返回值在关闭文件成功时会返回0,如果失败则会返回EOF。

size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream)

fwrite函数可以将所指向空间的数据写入到文件中。参数ptr指向了被写入数据的空间。参数size指每个被写入数据的大小。参数nmemb指写入的数据总数,每个数据大小为size。参数stream是要被写入的文件的指针。fwrite函数的返回值为写入的数据总数。

size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream)

fread函数则是将文件内的数据读取到内存空间处,其中ptr指针指向了该内存空间,size参数意为每个数据需要读取的空间大小,nmemb则是读取的数据总数。stream指针指向了需要被读取的文件。fread函数的返回值为读取的数据总数。

3.修改通讯录

在选择退出后,我们创建一个SaveCon函数以保存通讯录,再将通讯录销毁。

case EXIT:
			SaveCon(&con);//保存通讯录到文件中
			DestroyCon(&con);
			printf("退出通讯录。");
			break;

SaveCon函数内部实现

void SaveCon(struct contact* con)
{
	assert(con);//断言
	FILE* pf = fopen("C:\\Users\\Administrator\\Desktop\\data.txt", "wb");//打开文件
	if (pf == NULL)
	{
		perror("SaveContact");
		return;
	}
	fwrite(con->data, sizeof(struct peoinfo), con->size, pf);//写入信息
	fclose(pf);//关闭文件
	pf = NULL;//指针置为空指针
}

这样,我们就能在关闭通讯录时,将信息自动保存到文件中。

我们再构建一个LoadCon函数以在打开通讯录时读取文件中的信息。

int main()
{
	struct contact con;
	InitCon(&con);
	LoadCon(&con);//将文件中的信息读取到通讯录中
    //循
    //环
    //部
    //分
    return 0;
}

LoadCon函数的内部实现

void LoadCon(struct contact* con)
{
	assert(con);//断言
	FILE* pf = fopen("C:\\Users\\Administrator\\Desktop\\data.txt", "rb");//打开文件
	if (pf == NULL)
	{
		perror("LoadContact");
		return;
	}
	struct peoinfo tmp = { 0 };//创建临时空间保存信息
	while (fread(&tmp, sizeof(struct peoinfo), 1, pf))//当没有信息可读取就跳出循环
	{
		if (con->size == con->capacity)//判断容量是否足够,若不够则需要增容
		{
			struct peoinfo* p = realloc(con->data, 
            (con->capacity + COM_CAP) * sizeof(struct peoinfo));
			if (p == NULL)
			{
				printf("增容失败\n");
				return;
			}
			con->data = p;
			con->capacity += COM_CAP;
		}
		con->data[con->size] = tmp;//将信息从临时空间内放入通讯录中
		con->size++;
	}
	fclose(pf);
	pf = NULL;
}

与写入不同,读取信息时我们的size为0,所以无法直接读取size个信息到通讯录内,所以我们先使用一个tmp结构体接收一个人的信息,再判断fread函数的返回值是否为0,若为0则说明该次读取已经无法读取到信息了。若不为0则将该信息写入到通讯录中,再读取下一个人的信息。这里还要注意,通讯录初始化后的容量可能放不下所有人的信息,所以我们在每读取一个人的信息后,就要对通讯录的容量进行判断,若容量不够则需要进行扩容。

这样,一个可以将信息保存到文件中的通讯录就改造完成了。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值