通讯录进阶,支持动态内存与数据存储的通讯录

如果你没有看过通讯录初级,请先移步到那。
在前面我们写了一个静态的通讯录,通讯录的大小都是固定的,同时每次启动通讯录都需要重新输入数据。这用起来肯定是不人性化的。
进阶通讯录与原版的不同点就在于,通讯录的大小是会随着数据的添加而增大的,也就是动态内存管理,以及会对通讯录的数据进行存储,一旦通讯录被关闭数据就会自动存放在相应的文件。同时在下一次打开通讯录时,会自动将文件中的数据导入通讯录中。

1.对结构体contact的修改

//静态
//typedef struct contact
//{
   
   
//	buddies data[MAX];
//	int size;
//}contact;
//动态
typedef struct contact
{
   
   
	buddies* data;
	int size;
	int capacity;
}contact;

capacity的添加是为了可以清楚的知道目前我们为通讯录开放的多大的空间。

2.对通讯录初始化的修改

//静态
//void InitContact(contact* pc)
//{
   
   
//	memset(pc->data, 0, sizeof(pc->data));
//	pc->size = 0;
//}
//动态
void InitContact(contact* pc)
{
   
   
	pc->data = (buddies*)malloc(sizeof(buddies) * 2);
	pc->size = 0;
	pc->capacity = 2;
}

动态内存开辟,这里我们的规定是初始给2个联系人的空间,你可以自行修改。然后将malloc开辟空间是地址给pc->data

3.对通讯录添加数据的修改

//静态
//void AddContact(contact* pc)
//{
   
   
//	if (pc->size > MAX)
//	{
   
   
//		printf("通讯录已满\n");
//		return;
//	}
//	printf("请输入姓名:>");
//	scanf("%s", pc->data[pc->size].name);
//	printf("请输入年龄:>");
//	scanf("%d", &pc->data[pc->size].age);
//	printf("请输入性别:>");
//	scanf("%s", pc->data[pc->size].sex);
//	printf("请输入电话:>");
//	scanf("%s", pc->data[pc->size].tel);
//	printf("请输入地址:>");
//	scanf("%s", pc->data[pc->size].add);
//	printf("联系人添加完成\n");
//	//添加成功,size要加1
//	pc->size += 1;
//}

int check_capacity(contact* pc)//检查当前容量是否需要进行扩容
{
   
   
	if (pc->size == pc->capacity)//扩容了
	{
   
   
		buddies* tmp = (buddies*)realloc(pc->data, sizeof(buddies) * (pc->capacity + 2));//利用realloc进行扩容,每次添加2个空间的大小,最佳扩容方法应该是每次扩大1.5倍~2倍。因为频繁的扩容容易造成内存碎片增多
		if (tmp == NULL)
		{
   
   
			//扩容失败
			perror("realloc");
			return 0;
		}
		pc->data = tmp;
		pc->capacity += 2;
		printf("扩容成功\n");
		return 1;
	}
	else//还没满
	{
   
   
		return 1;
	}
}

//动态
void AddContact(contact* pc)
{
   
   
	if (check_capacity(pc) == 0)
	{
   
   
		return;
	}
	printf("请输入姓名:>");
	scanf("%s", pc->data[pc->size].name);
	printf("请输入年龄:>");
	scanf("%d", &pc->data[pc->size].age);
	printf("请输入性别:>");
	scanf("%s", pc->data[pc->size].sex);
	printf("请输入电话:>");
	scanf("%s", pc->data[pc->size].tel);
	printf("请输入地址:>");
	scanf("%s", pc->data[pc->size].add);
	printf("联系人添加完成\n");
	//添加成功,size要加1
	pc->size += 1;
}

因为原版通讯录的大小是固定的,只需要检查空间是否满了就可以了。而动态的通讯录在检查后还需要进行扩容,扩容失败返回-1,没满返回1,扩容成功也返回1。AddContact函数再根据返回值来做下一步大操作。

3.通讯录的销毁

因为通讯录的空间是动态内存开辟的,所以再最后是需要还给存储系统的,我们需要释放空间。
至于什么时候释放,当用户退出程序时释放空间。

void DestoryContact(contact* pc)
{
   
   
	free(pc->data);
	pc->data = NULL;
	pc->size = 0;
	pc->capacity = 0;
}

int main()
{
   
   
	int input = 0;
	contact ct;
	InitContact(&ct);
	do
	{
   
   
		menu();//菜单
		printf("请选择:>");
		scanf("%d", &input);
		switch (input)
		{
   
   
		case ADD:
			AddContact(&
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Yui_

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

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

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

打赏作者

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

抵扣说明:

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

余额充值