目录
前言
文件存储版的通讯录 是在通讯录的基础上添加了文件操作等
在了解通讯录(文件存储版)之前,我们得好好学习一下 文件操作
只有掌握了操作文件,才能明白文件存储版的通讯录
一.基本思路
1.通讯录是由多人的信息组合,信息:姓名,年龄,性别,地址等。
2.通讯录的大小,存放的人数,此使用动态存储,更加方便存储和利用空间。
3.通讯录的基本功能:增加联系人、删除联系人、查找联系人,修改联系人
4.保存通讯录文档,方便下次使用。
注:通讯录分三种:静态、动态、文件三种。而此文章讲述的是动态存储的文件版通讯录。
静态:大小固定,存储的人数有明确限制,无法改变,使用数组实现。
动态:存储人数可以调节,可以随着人数的增加而增加,选择一个初始大小,之后可进行扩充操作, 可更好的利用空间。
文件:该通讯录是在以上两种通讯录之一上加上存储文件的操作,在程序执行结束后都无法保存,录入的信息在程序结束时就会消失。为了保存录入的信息,可以通过文件操作来实现。
二.代码的实现
2.1通讯录菜单
菜单能够实现和用户的交互。需要选择增、删、查、改的功能。
所以,通讯录需要一个菜单。
代码如下:
- void menu()
 - {
 - 	printf("*********************************\n");
 - 	printf("*******1.添加        2.删除*******\n");
 - 	printf("*******3.查找        4.修改*******\n");
 - 	printf("*******5.显示        6.保存*******\n");
 - 	printf("*******0.退出              *******\n");
 - 	printf("*********************************\n");
 - }
 - //使用函数指针数组
 - void (*(p[7]))(Contact*) = { Exit,AddContact,DeleteContact,SearchContact,ModifyContact,PrintContact,SaveContact };
 -  
 -  
 - int main()
 - { 
 -     //Contact cl;    这是下面代码结构体的
 -     //InitContact(&cl);
 -     int input;
 - 	do {
 - 		menu();
 - 		printf("请输入->");
 - 		scanf("%d", &input);
 - 		if (input <= 6)
 - 			p[input](&cl);  
 - 		else
 - 			printf("输入错误\n");
 -       
 - 	}while (input != 0);
 - }
 
 
为了方便,我们使用了函数指针数组,void (*(p[7]))(Contact*)
2.2通讯录的定义及功能
通讯录需要姓名、性别、年龄及电话,此时我们需要使用结构体来定义。还需要定义函数:增、删、查、改、打印学生信息、保存通讯录。
代码如下:
- #include<stdio.h>
 - #include<malloc.h>
 - #include<stdlib.h>
 - #include<string.h>
 - typedef struct PeoInfo
 - {
 - 	char name[10];//姓名
 - 	int age;      //年龄
 - 	char sex[3];  //性别
 - 	int phone[12];//电话
 - }PeoInfo;
 -  
 - typedef struct Contact
 - {	
 - 	int size;  //当前存储的人数
 - 	int capacity;  //通讯录容量大小
 - 	contact* data;  //结构体指针,访问个人信息
 -  
 - }Contact;
 - //初始化通讯录
 - void InitContact(Contact* pc);
 - //增加联系人
 - void AddContact(Contact* pc);
 - //删除联系人
 - void DeleteContact(Contact* pc);
 - //查找联系人
 - void SearchContact(Contact* pc);
 - //修改联系人
 - void ModifyContact(Contact* pc);
 - //显示通讯录
 - void PrintContact(Contact* pc);
 - //扩容通讯录
 - void CheckCapacity(Contact* pc);
 - //保存信息到文件
 - void SaveContact(Contact* pc);
 - //文件信息传递到通讯录
 - void LoadContact(Contact* pc);
 - //销毁空间,退出程序
 - void Exit(Contact* pc);
 -  
 -  
 
 
2.3函数实现
注:当通讯录退出的时候,把信息写到文件。
        当通讯录初始化后,加载文件的信息到通讯录中。
2.3.1初始化通讯录
通讯录是动态的,所以需要扩容,给一定空间。
-  
 - void InitContact(Contact* pc)
 - {
 - 	// 此时通讯录是空的,应先为通讯录分配空间
 - 	pc->data = (PeoInfo*)malloc(sizeof(PeoInfo) * 4);
 -  
 - 	// 如果分配成功,将通讯录的size设为0,capacity设为初识大小
 - 	pc->size = 0;
 - 	pc->capacity = 4;
 - 	//将文档的信息传递到动态内存里,函数实现在下方
 - 	LoadContact(pc);
 - }
 
 
2.3.2文件信息传递到通讯录里
将文件的信息加载到通讯录里
- void LoadContact(Contact* pc)
 - {
 - 	// 以读的形式打开文件
 - 	FILE* pf = fopen("contact.txt", "rb");
 - 	if (pf == NULL)
 - 	{
 - 		perror("fopen");
 - 		return;
 - 	}
 -  
 - 	// 将文件中的内容加载到通讯录中
 - 	// 这里用fread函数,当fread函数读取的联系人信息数为0时,说明读取结束
 - 	PeoInfo tmp = { 0 }; // 定义一个联系人信息的结构体,便于读取
 - 	int i = 0;
 - 	while (fread(&tmp, sizeof(PeoInfo), 1, pf))
 - 	{
 - 		CheckCapacity(pc); // 在这个函数中查看数组是否需要扩容,若需要,则扩容
 - 		pc->data[i] = tmp;
 - 		pc->size++;
 - 		i++;
 - 	}
 -  
 - 	// 关闭文件
 - 	fclose(pf);
 - 	pf = NULL;
 - 	return;
 - }
 
 
2.3.3扩容通讯录
添加联系人之前,需要判断通讯录是否满员,满员则需要扩容
- void CheckCapacity(Contact* pc)
 - {
 - 	// 判断通讯录是否已满,若满,进行扩容
 - 	if (pc->size == pc->capacity)
 - 	{
 - 		PeoInfo* tmp = (PeoInfo*)realloc(pc, sizeof(PeoInfo) * 4);
 - 		if (tmp == NULL)
 - 		{
 - 			printf("realloc fail\n");
 - 			return;
 - 		}
 - 		pc->data = tmp;
 -  
 - 		// 若扩容成功,增大capacity
 - 		pc->capacity *= 2;
 - 	}
 -  
 - }
 
 
2.3.4增加联系人
需要添加联系人的各项信息。
- void AddContact(Contact* pc)
 - {
 - 	int num = 0;
 - 	printf("添加人数:");
 - 	scanf("%d", &num);
 - 	// 输入要添加的联系人的信息
 - 	// 这里pc->data为结构体数组,pc->data[pc->size]为其中的元素,也就是某一个联系人的信息
 - 	for (int i = 0; i < num; i++)
 - 	{
 - 		//判断通讯录是否满人
 - 		CheckCapacity(pc);
 - 		printf("请输入名字\n");
 - 		scanf("%s", pc->data[pc->size].name);
 - 		printf("请输入性别\n");
 - 		scanf("%s", pc->data[pc->size].sex);
 - 		printf("请输入年龄\n");
 - 		scanf("%d", &pc->data[pc->size].age);
 - 		printf("请输入电话\n");
 - 		scanf("%s", pc->data[pc->size].phone);
 - 		
 -  
 - 		pc->size++; // 将存入的联系人的数量加1
 - 	}
 - }
 
 
2.3.5删除联系人
需要找到该联系人的下标值,然后进行删除。
-  
 - void DeleteContact(Contact* pc)
 - {
 - 	int ret = 0;//记录寻找的下标值
 - 	printf("请输入要删除的联系人的名字\n");
 - 	char name[20];
 - 	scanf("%s", name);
 - 	// 定义一个新函数find,用来查找是否有这个联系人
 - 	// 如果有,返回联系人的下标,如果没有,返回-1
 - 	for (int i = 0; i < pc->size; i++)
 - 	{
 - 		if (strcmp(pc->data[i].name, name) == 0)
 - 		{
 - 			ret = i; break;
 - 		}
 - 	}
 - 	if (ret)
 - 	{
 - 		printf("不存在");
 - 	}
 - 	else {
 -  
 - 		for (int i = ret; i < pc->size - 1; i++)
 - 		{
 - 			pc->data[i] = pc->data[i + 1];
 - 		}
 - 		pc->size--;
 - 	}
 -  
 -  
 - }
 
 
2.3.6查询联系人
找到下标值,从而得到联系人的信息
- void SearchContact(Contact* pc)
 - {
 - 	int ret = 0;
 - 	printf("请输入要查找的联系人的名字\n");
 - 	char name[20];
 - 	scanf("%s", name);
 - 	// 利用已经定义的find函数进行查找
 - 	for (int i = 0; i < pc->size; i++)
 - 	{
 - 		if (strcmp(pc->data[i].name, name) == 0)
 - 		{
 - 			ret = i; break;
 - 		}
 - 	}
 -  
 - 	if (ret)
 - 	{
 - 		printf("没有找到该联系人\n");
 - 	}
 - 	else
 - 	{
 - 		// 如果找到,打印该联系人的信息,首先打印五个标题
 - 		printf("%-10s\t%-10s\t%-5s\t%-15s\n", "姓名", "性别", "年龄", "电话");
 - 		printf("%-10s\t%-10s\t%-5d\t%-15s%\n",
 - 			pc->data[ret].name,
 - 			pc->data[ret].sex,
 - 			pc->data[ret].age,
 - 			pc->data[ret].phone
 - 			);
 - 	}
 -  
 -  
 - }
 
 
2.3.7修改联系人
找到下标值,从而进行各项数据的修改
- void ModifyContact(Contact* pc)
 - {
 - 	int ret = 0;
 - 	printf("请输入要查找的联系人的名字\n");
 - 	char name[20];
 - 	scanf("%s", name);
 - 	for (int i = 0; i < pc->size; i++)
 - 	{
 - 		if (strcmp(pc->data[i].name, name) == 0)
 - 		{
 - 			ret = i; break;
 - 		}
 - 	}
 -  
 - 	if (ret)
 - 	{
 - 		printf("没有找到该联系人\n");
 - 	}
 - 	else
 - 	{
 - 		printf("请输入名字\n");
 - 		scanf("%s", pc->data[ret].name);
 - 		printf("请输入性别\n");
 - 		scanf("%s", pc->data[ret].sex);
 - 		printf("请输入年龄\n");
 - 		scanf("%d", &pc->data[ret].age);
 - 		printf("请输入电话\n");
 - 		scanf("%s", pc->data[ret].phone);
 - 	
 - 	}
 -  
 -  
 - }
 
 
2.3.8打印通讯录
打印每个人的具体数据
- // 在这个函数内打印所有联系人的信息
 - void PrintContact(Contact* pc)
 - {
 - 	// 首先打印五个标题
 - 	printf("%-10s\t%-10s\t%-5s\t%-15s\n", "姓名", "性别", "年龄", "电话");
 - 	// 然后用for循环打印所有联系人的信息
 - 	for (int i = 0; i < pc->size; i++)
 - 	{
 - 		printf("%-10s\t%-10s\t%-5d\t%-15s\n",
 - 			pc->data[i].name,
 - 			pc->data[i].sex,
 - 			pc->data[i].age,
 - 			pc->data[i].phone	
 - 		);
 - 	}
 - }
 
 
2.3.9信息保留在文件中
程序退出时,要将销毁空间,并且把数据存入文件里,方便下次调用
- void SaveContact(Contact* pc)
 - {
 - 	FILE* p = fopen("contact.txt", "wb");
 - 	if (p == NULL)
 - 	{
 - 		perror("SaveContact");
 - 	}
 - 	else {
 - 		int i = 0;
 - 		for (i; i < pc->size; i++)
 - 		{
 - 			fwrite(pc->data + i, sizeof(PeoInfo), 1, p);
 - 		}
 -  
 - 		fclose(p);
 - 		p = NULL;
 - 		printf("保存成功");
 - 	}
 - 	
 - }
 
 
2.3.10销毁空间退出程序
- void Exit(Contact* pc)
 - {
 - 	//销毁空间
 - 	free(pc->data);
 - 	pc->data = NULL;
 - 	pc->size = 0;
 - 	pc->capacity = 0;
 - }
 
 
三.完整代码
和上面的代码比起来,连贯了Contact.c的各个函数实现。
3.1Text.c文件
- #include"Contact.h"
 - void menu()
 - {
 - 	printf("*********************************\n");
 - 	printf("*******1.添加        2.删除*******\n");
 - 	printf("*******3.查找        4.修改*******\n");
 - 	printf("*******5.显示        6.保存*******\n");
 - 	printf("*******0.退出              *******\n");
 - 	printf("*********************************\n");
 - }
 - //使用函数指针数组
 - void (*(p[7]))(Contact*) = { Exit,AddContact,DeleteContact,SearchContact,ModifyContact,PrintContact,SaveContact };
 -  
 - int main()
 - {
 - 	//定义结构体
 - 	Contact cl;
 - 	InitContact(&cl);
 - 	int input;
 - 	do {
 - 		menu();
 - 		printf("请输入->");
 - 		scanf("%d", &input);
 - 		if (input <= 6)
 - 			p[input](&cl);
 - 		else
 - 			printf("输入错误\n");
 -  
 - 	} while (input != 0);
 - }
 
 
3.2Contact.h文件
- #include<stdio.h>
 - #include<malloc.h>
 - #include<stdlib.h>
 - #include<string.h>
 - typedef struct PeoInfo
 - {
 - 	char name[10];//姓名
 - 	int age;      //年龄
 - 	char sex[3];  //性别
 - 	int phone[12];//电话
 - }PeoInfo;
 -  
 - typedef struct Contact
 - {
 - 	int size;  //当前存储的人数
 - 	int capacity;  //通讯录容量大小
 - 	PeoInfo* data;  //结构体指针,访问个人信息
 -  
 - }Contact;
 - //初始化通讯录
 - void InitContact(Contact* pc);
 - //增加联系人
 - void AddContact(Contact* pc);
 - //删除联系人
 - void DeleteContact(Contact* pc);
 - //查找联系人
 - void SearchContact(Contact* pc);
 - //修改联系人
 - void ModifyContact(Contact* pc);
 - //显示通讯录
 - void PrintContact(Contact* pc);
 - //扩容通讯录
 - void CheckCapacity(Contact* pc);
 - //销毁并且保存通讯录
 - void SaveContact(Contact* pc);
 - void LoadContact(Contact* pc);
 - void Exit(Contact* pc);
 
 
3.3Contact.c文件
- #include"Contact.h"
 -  
 - void InitContact(Contact* pc)
 - {
 - 	// 此时通讯录是空的,应先为通讯录分配空间
 - 	pc->data = (PeoInfo*)malloc(sizeof(PeoInfo) * 4);
 -  
 - 	// 如果分配成功,将通讯录的size设为0,capacity设为初识大小
 - 	pc->size = 0;
 - 	pc->capacity = 4;
 - 	//将文档的信息传递到动态内存里,函数实现在下方
 - 	LoadContact(pc);
 - }
 - void LoadContact(Contact* pc)
 - {
 - 	// 以读的形式打开文件
 - 	FILE* pf = fopen("contact.txt", "rb");
 - 	if (pf == NULL)
 - 	{
 - 		perror("fopen");
 - 		return;
 - 	}
 -  
 - 	// 将文件中的内容加载到通讯录中
 - 	// 这里用fread函数,当fread函数读取的联系人信息数为0时,说明读取结束
 - 	PeoInfo tmp = { 0 }; // 定义一个联系人信息的结构体,便于读取
 - 	int i = 0;
 - 	while (fread(&tmp, sizeof(PeoInfo), 1, pf))
 - 	{
 - 		CheckCapacity(pc); // 在这个函数中查看数组是否需要扩容,若需要,则扩容
 - 		pc->data[i] = tmp;
 - 		pc->size++;
 - 		i++;
 - 	}
 -  
 - 	// 关闭文件
 - 	fclose(pf);
 - 	pf = NULL;
 - 	return;
 - }
 - void CheckCapacity(Contact* pc)
 - {
 - 	// 判断通讯录是否已满,若满,进行扩容
 - 	if (pc->size == pc->capacity)
 - 	{
 - 		PeoInfo* tmp = (PeoInfo*)realloc(pc, sizeof(PeoInfo) * 4);
 - 		if (tmp == NULL)
 - 		{
 - 			printf("realloc fail\n");
 - 			return;
 - 		}
 - 		pc->data = tmp;
 -  
 - 		// 若扩容成功,增大capacity
 - 		pc->capacity *= 2;
 - 	}
 -  
 - }
 - void AddContact(Contact* pc)
 - {
 - 	int num = 0;
 - 	printf("添加人数:");
 - 	scanf("%d", &num);
 - 	// 输入要添加的联系人的信息
 - 	// 这里pc->data为结构体数组,pc->data[pc->size]为其中的元素,也就是某一个联系人的信息
 - 	for (int i = 0; i < num; i++)
 - 	{
 - 		//判断通讯录是否满人
 - 		CheckCapacity(pc);
 - 		printf("请输入名字\n");
 - 		scanf("%s", pc->data[pc->size].name);
 - 		printf("请输入性别\n");
 - 		scanf("%s", pc->data[pc->size].sex);
 - 		printf("请输入年龄\n");
 - 		scanf("%d", &pc->data[pc->size].age);
 - 		printf("请输入电话\n");
 - 		scanf("%s", pc->data[pc->size].phone);
 - 		
 -  
 - 		pc->size++; // 将存入的联系人的数量加1
 - 	}
 - }
 - void DeleteContact(Contact* pc)
 - {
 - 	int ret = 0;//记录寻找的下标值
 - 	printf("请输入要删除的联系人的名字\n");
 - 	char name[20];
 - 	scanf("%s", name);
 - 	// 定义一个新函数find,用来查找是否有这个联系人
 - 	// 如果有,返回联系人的下标,如果没有,返回-1
 - 	for (int i = 0; i < pc->size; i++)
 - 	{
 - 		if (strcmp(pc->data[i].name, name) == 0)
 - 		{
 - 			ret = i; break;
 - 		}
 - 	}
 - 	if (ret)
 - 	{
 - 		printf("不存在");
 - 	}
 - 	else {
 -  
 - 		for (int i = ret; i < pc->size - 1; i++)
 - 		{
 - 			pc->data[i] = pc->data[i + 1];
 - 		}
 - 		pc->size--;
 - 	}
 -  
 -  
 - }
 - void SearchContact(Contact* pc)
 - {
 - 	int ret = 0;
 - 	printf("请输入要查找的联系人的名字\n");
 - 	char name[20];
 - 	scanf("%s", name);
 - 	// 利用已经定义的find函数进行查找
 - 	for (int i = 0; i < pc->size; i++)
 - 	{
 - 		if (strcmp(pc->data[i].name, name) == 0)
 - 		{
 - 			ret = i; break;
 - 		}
 - 	}
 -  
 - 	if (ret)
 - 	{
 - 		printf("没有找到该联系人\n");
 - 	}
 - 	else
 - 	{
 - 		// 如果找到,打印该联系人的信息,首先打印五个标题
 - 		printf("%-10s\t%-10s\t%-5s\t%-15s\n", "姓名", "性别", "年龄", "电话");
 - 		printf("%-10s\t%-10s\t%-5d\t%-15s%\n",
 - 			pc->data[ret].name,
 - 			pc->data[ret].sex,
 - 			pc->data[ret].age,
 - 			pc->data[ret].phone
 - 			);
 - 	}
 -  
 -  
 - }
 - void ModifyContact(Contact* pc)
 - {
 - 	int ret = 0;
 - 	printf("请输入要查找的联系人的名字\n");
 - 	char name[20];
 - 	scanf("%s", name);
 - 	// 利用已经定义的find函数进行查找
 - 	for (int i = 0; i < pc->size; i++)
 - 	{
 - 		if (strcmp(pc->data[i].name, name) == 0)
 - 		{
 - 			ret = i; break;
 - 		}
 - 	}
 -  
 - 	if (ret)
 - 	{
 - 		printf("没有找到该联系人\n");
 - 	}
 - 	else
 - 	{
 - 		printf("请输入名字\n");
 - 		scanf("%s", pc->data[ret].name);
 - 		printf("请输入性别\n");
 - 		scanf("%s", pc->data[ret].sex);
 - 		printf("请输入年龄\n");
 - 		scanf("%d", &pc->data[ret].age);
 - 		printf("请输入电话\n");
 - 		scanf("%s", pc->data[ret].phone);
 - 	
 - 	}
 -  
 -  
 - }
 - // 在这个函数内打印所有联系人的信息
 - void PrintContact(Contact* pc)
 - {
 - 	// 首先打印五个标题
 - 	printf("%-10s\t%-10s\t%-5s\t%-15s\n", "姓名", "性别", "年龄", "电话");
 - 	// 然后用for循环打印所有联系人的信息
 - 	for (int i = 0; i < pc->size; i++)
 - 	{
 - 		printf("%-10s\t%-10s\t%-5d\t%-15s\n",
 - 			pc->data[i].name,
 - 			pc->data[i].sex,
 - 			pc->data[i].age,
 - 			pc->data[i].phone	
 - 		);
 - 	}
 - }
 - void SaveContact(Contact* pc)
 - {
 - 	FILE* p = fopen("contact.txt", "wb");
 - 	if (p == NULL)
 - 	{
 - 		perror("SaveContact");
 - 	}
 - 	else {
 - 		int i = 0;
 - 		for (i; i < pc->size; i++)
 - 		{
 - 			fwrite(pc->data + i, sizeof(PeoInfo), 1, p);
 - 		}
 -  
 - 		fclose(p);
 - 		p = NULL;
 - 		printf("保存成功");
 - 	}
 - 	
 - }
 - void Exit(Contact* pc)
 - {
 - 	//销毁空间
 - 	free(pc->data);
 - 	pc->data = NULL;
 - 	pc->size = 0;
 - 	pc->capacity = 0;
 - }
 
 
总结
只有不断的掌握知识,我们才能敲代码得心应手,在不断的学习里,逐渐进步。
-------------小菜TQ02

                

















