可存储通讯录

前面我们已经学过了静态通讯录,动态通讯录,但这两种通讯录储存的信息在程序运行结束后就会自动消失,那么如何能够将信息储存起来呢?

今天我们来介绍可储存通讯录

 

接上次动态通讯录,我们需要增加的功能有两个:

1. 每一次打开通讯录要加载文件里储存的通讯录信息

2.每一次关闭通讯录要将本次通讯录信息的更改传入文件中

我们来看看具体的实现方式:

1.我们在初始化的同时加载出文件信息

//初始化通讯录​
void InitContact(struct contact* con)
{
	assert(con);
	con->num = 0;
	con->data = (struct pepinfo*)calloc(DEFAULT_SZ, sizeof(struct pepinfo)); //分配默认大小并清空
	if (con->data == NULL) //检查分配是否成功
	{
		printf("%s\n", strerror());
		return;
	}
	con->capacity = DEFAULT_SZ;
	//加载联系人信息
	LoadContact(con);
}
//加载联系人信息
void LoadContact(struct contact*pc)
{
	//打开文件
	FILE*pf=fopen("contact.txt","rb");
	if (NULL == pf)
	{
		perror("LoadContact::fopen");
		return;
	}
	//读文件
	struct pepinfo tmp = { 0 };
	while (fread(&tmp,sizeof(struct pepinfo),1,pf))
	{ 
		CheckCapacity(pc);
		pc->data[pc->num] = tmp;
		pc->num++;
	}
	//关闭文件
	fclose(pf);
	pf = NULL;
}

 2.我们在退出通讯录之前要将信息保存

//保存联系人信息
void SaveContact(struct contact* pc)
{
	//打开文件
	FILE*pf =fopen("contact.txt", "wb");
	//写入
	if (NULL == pf)
	{
		perror("SaveContact::fopen");
		return;
	}
	for (int i = 0; i < pc->num; i++)
	{
		//fwrite(&(pc->data[i]),sizeof(struct pepinfo),1,pf);
		 fwrite(pc->data + i, sizeof(struct pepinfo), 1, pf);
	}
	//关闭文件
	fclose(pf);
	pf = NULL;
}

  下面是具体代码

test.c

#define _CRT_SECURE_NO_WARNINGS 
#include<stdio.h>
#include"contact.h"

void menu()
{
	printf("****************************************************\n");
	printf("*****    1.添加联系人      2.删除联系人      *******\n");
	printf("*****    3.查找联系人      4.修改联系人      *******\n");
	printf("*****    5.展示联系人      6.排序联系人      *******\n");
	printf("*****    7.清空联系人      0.退出            *******\n");
	printf("****************************************************\n");
}
enum option
{
	exit,
	add,
	del,
	search,
	modify,
	show,
	sort,
	clear
};
int main()
{
	int input = 0;
	struct contact con;//创建一个通讯录
	InitContact(&con);//初始化通讯录
	do
	{
		menu();//打印菜单
		printf("请选择》》");
		scanf("%d", &input);
		switch (input)
		{
		case exit:
			//保存联系人信息
			SaveContact(&con);
			DestroyContact(&con); //退出时销毁
				printf("退出\n");
				break;
		case add:
			tianjia(&con);
			break;
		case del:
			shanchu(&con);
			break;
		case search:
			chazhao(&con);
			break;
		case modify:
			xiugai(&con);
			break;
		case show:
			dayin(&con);
			break;
		case sort:
			paixu(&con);
			break;
		case clear:
			qingkong(&con);
			break;
		default:
			printf("选择错误\n");
			break;
		}

	} while (input);
	return 0;
}

contact.c

#define _CRT_SECURE_NO_WARNINGS 
#include"contact.h"
#include<stdio.h>

#define DEFAULT_SZ 3
//先对函数进行声明
void InitContact(struct contact* con);
void tianjia(struct contact* con);
void shanchu(struct contact* con);
void chazhao(const struct contact* con);
void dayin(struct contact* con);
void xiugai(struct contact* con);
void paixu(struct contact* con);
void CheckCapacity(struct contact* con);


//添加联系人
void tianjia(struct contact *con)
{
	CheckCapacity(con);
	if (con->num == max)
	{
		printf("\n通讯录已满,添加失败\n");
	}
	else
	{
		printf("\n请输入联系人姓名》");
		scanf("%s", con->data[con->num].name);
		printf("\n请输入联系人性别》");
		scanf("%s", con->data[con->num].sex);
		printf("\n请输入联系人年龄》");
		scanf("%d", &con->data[con->num].age);//age是变量 需要取地址&
		printf("\n请输入联系人电话》");
		scanf("%s", con->data[con->num].tel);
		printf("\n请输入联系人住址》");
		scanf("%s", con->data[con->num].ads);
		con->num++;
		printf("\n添加成功\n");
	}
}


//删除联系人
void shanchu(struct contact* con)
{
	int n = 0;
	printf("\n请输入要删除联系人的序列号");
	scanf("%d", &n);
	if (n<1 || n>con->num)
	{
		printf("不存在的序列号,删除失败\n");
	}
	else
	{
		for (int i = 0; i <= con->num - n; i++)
		{
			*(con->data[n-1 + i].name) = *(con->data[n + i ].name);
			*(con->data[n-1 + i].sex) = *(con->data[n + i ].sex);
			con->data[n-1 + i].age = con->data[n + i ].age;
			*(con->data[n-1 + i].tel) = *(con->data[n + i ].tel);
			*(con->data[n-1 + i].ads) = *(con->data[n + i ].ads);
		}
		con->num--;//不要忘了把联系人数量减1
		printf("删除成功\n");
	}
}


//查找联系人
void chazhao(const struct contact*con)
{
	printf("请输入需要查找的序号>");
	int  n = 0;
	scanf("%d", &n);
	if (n > con->num)
	{
		printf("该序号联系人不存在\n");
	}
	else
	{
		printf("%15s\t%5s\t%8s\t%15s\t%30s\n\n", "name", "age", "sex", "tel", "ads");
		printf("%15s\t%5d\t%8s\t%15s\t%30s\n",
			con->data[n - 1].name,
			con->data[n - 1].age,
			con->data[n - 1].sex,
			con->data[n - 1].tel,
			con->data[n - 1].ads);
	}
}


//打印联系人
void dayin(struct contact *con)
{
	int n = 0;
	printf("%15s\t%5s\t%8s\t%15s\t%30s\n\n", "name", "age", "sex", "tel", "ads");
	for( n=0;n< con->num;n++)
	{
		printf("%15s\t%5d\t%8s\t%15s\t%30s\n",
		con->data[n].name,
		con->data[n].age,
		con->data[n].sex,
		con->data[n].tel,
		con->data[n].ads);
	}
}


//修改联系人信息
void xiugai(struct contact* con)
{
	int n = 0;
	printf("请输入需要修改联系人的序号");
	scanf("%d", &n);
	if (n > con->num)
	{
		printf("该序号联系人不存在\n");
	}
	else
	{
		printf("\n请输入联系人姓名》");
		scanf("%s", con->data[n-1].name);
		printf("\n请输入联系人性别》");
		scanf("%s", con->data[n-1].sex);
		printf("\n请输入联系人年龄》");
		scanf("%d", &con->data[n-1].age);//age是变量 需要取地址&
		printf("\n请输入联系人电话》");
		scanf("%s", con->data[n-1].tel);
		printf("\n请输入联系人住址》");
		scanf("%s", con->data[n-1].ads);
		printf("\n修改成功\n");
	}
}

//按照名字排序
void paixu(struct contact* con)
{
	int i, j;
	struct pepinfo tmp;
	for (i = 0; i < con->num - 1; i++)
	{
		for (j = 0; j < con->num - 1 - i; j++)
		{
			if (0 < strcmp(con->data[j].name, con->data[j + 1].name))
			{
				tmp = con->data[j];
				con->data[j] = con->data[j + 1];
				con->data[j + 1] = tmp;
			}
		}
	}
		printf("完成排序\n");
}


//清空联系人
void qingkong(struct contact* con)
{
	assert(con);
	con->num = 0;
	con->data = (struct pepinfo*)calloc(DEFAULT_SZ, sizeof(struct pepinfo)); //分配默认大小并清空
	if (con->data == NULL) //检查分配是否成功
	{
		printf("%s\n", strerror());
		return;
	}
	con->capacity = DEFAULT_SZ;
	printf("清空成功\n");
}
//检查容量
void CheckCapacity(struct contact* con)
{
	if (con->num == con->capacity)
	{
		//每次扩容两个
		struct pepinfo* ptr = (struct pepinfo*)realloc(con->data, (con->capacity + 2) * sizeof(struct pepinfo));
		if (ptr != NULL)
		{
			con->data = ptr;
			con->capacity += 2;
			printf("增容成功\n");
		}
		else
		{
			perror("通讯录增容失败");
			exit(1);
		}
	}
}


//加载联系人信息
void LoadContact(struct contact*pc)
{
	//打开文件
	FILE*pf=fopen("contact.txt","rb");
	if (NULL == pf)
	{
		perror("LoadContact::fopen");
		return;
	}
	//读文件
	struct pepinfo tmp = { 0 };
	while (fread(&tmp,sizeof(struct pepinfo),1,pf))
	{ 
		CheckCapacity(pc);
		pc->data[pc->num] = tmp;
		pc->num++;
	}
	//关闭文件
	fclose(pf);
	pf = NULL;
}

//初始化通讯录​
void InitContact(struct contact* con)
{
	assert(con);
	con->num = 0;
	con->data = (struct pepinfo*)calloc(DEFAULT_SZ, sizeof(struct pepinfo)); //分配默认大小并清空
	if (con->data == NULL) //检查分配是否成功
	{
		printf("%s\n", strerror());
		return;
	}
	con->capacity = DEFAULT_SZ;
	//加载联系人信息
	LoadContact(con);
}


//保存联系人信息
void SaveContact(struct contact* pc)
{
	//打开文件
	FILE*pf =fopen("contact.txt", "wb");
	//写入
	if (NULL == pf)
	{
		perror("SaveContact::fopen");
		return;
	}
	for (int i = 0; i < pc->num; i++)
	{
		//fwrite(&(pc->data[i]),sizeof(struct pepinfo),1,pf);
		 fwrite(pc->data + i, sizeof(struct pepinfo), 1, pf);
	}
	//关闭文件
	fclose(pf);
	pf = NULL;

}


//​销毁通讯录
void DestroyContact(contact* con)
{
	free(con->data);
	con->data = NULL;
	con->capacity = 0;
	con->num = 0;
}

contact.h

#pragma once
#define max 1000
#define name_max  20
#define sex_max   5
#define  tel_max  15
#define ads_max  30
#include<stdio.h>
#include<assert.h>
struct pepinfo//描述一个人的信息
{
	    char name[name_max];//姓名
		char sex[sex_max];//性别
		int age;//年龄
		char tel[tel_max];//电话号码
		char ads[ads_max];//家庭住址
};

typedef struct contact
{
	 struct pepinfo* data;
	int num;//有效元素的个数
	int capacity;//容量
}contact;

上一篇:实验2 数组、指针与C++标准库


下一篇:动态开辟内存的通讯录C语言实现