动态内存管理改造简易通讯录

动态通讯录

本章内容基于上章内容实现,具体情况若有不清楚,请先查看上一篇文章。
动态通讯录实现了,动态开辟,如果存放满了,再开辟空间进行存储,相对静态更方便一些。

动态通讯录需要改造的地方

我们基于静态通讯录之上,来改造一下实现动态通讯录
需要改造的地方有:
结构体的改造
初始化函数
添加函数
退出通讯录

结构体的改造

静态的结构体是data是max也就是100。

typedef struct PeoInfo
{
	char name[NAME_MAX];
	int age;
	char sex[SEX_MAX];
	char tele[TELE_MAX];
	char addr[ADDR_MAX];
}PeoInfo;

typedef struct Contact
{
	PeoInfo data[MAX];//存放成员数据
	int sz;//记录当前通讯录人数
}Contact;

Contact结构体中data数组是限定的,也就是100个。

动态通讯录的结构体代码如下:

typedef struct PeoInfo
{
	char name[NAME_MAX];
	int age;
	char sex[SEX_MAX];
	char tele[TELE_MAX];
	char addr[ADDR_MAX];
}PeoInfo;
typedef struct Contact
{
	PeoInfo* data;//存放成员数据
	int sz;//记录当前通讯录人数
	int capacity;//记录当前通讯录容量
}Contact;

在静态的基础之上,我们改动了data从数组改编成了指针指向的是动态内存开辟的PeoInfo,以及多了一个参数capacity来记录当前通讯录容量。

改造初始化函数

静态的初始化函数是这样的

void InitContact(Contact* pc)
{
	assert(pc);

	pc->sz = 0;
	memset(pc->data, 0, sizeof(pc->data));
}

直接把data成员里面全部赋值为0。

void InitContact(Contact* pc)
{
	assert(pc);

	pc->sz = 0;
	pc->capacity = DEFAULT_SZ;
	pc->data = calloc(pc->capacity,sizeof(PeoInfo));
	if (pc->data == NULL)
	{
		perror("InitContact->calloc");
		return;
	}
}

动态我们开辟一块内存用来存放PeoInfo的信息,而他的地址则让data指针指向即可,我们用if语句查看是否data指针为空,为空则提示一下calloc函数出错。

改造添加函数

添加函数与静态的不同则是通讯录不会再满了,因为我们满了我们会动态在开辟空间即可。

void ADDContact(Contact* pc)
{
	assert(pc);
	if (pc->sz == MAX)
	{
		printf("通讯录已满,无法增加\n");
		return;
	}
	//增加信息
	printf("请输入姓名:");
	scanf("%s", pc->data[pc->sz].name);
	printf("请输入年龄:");
	scanf("%d", &(pc->data[pc->sz].age));
	printf("请输入性别:");
	scanf("%s", pc->data[pc->sz].sex);
	printf("请输入电话号码:");
	scanf("%s", pc->data[pc->sz].tele);
	printf("请输入住址:");
	scanf("%s", pc->data[pc->sz].addr);

	//
	pc->sz++;
	printf("添加联系人成功!\n");
}

上面是静态的添加函数,接下来看一下动态的添加函数。

void ADDContact(Contact* pc)
{
	assert(pc);
	if (pc->sz == pc->capacity)
	{
		PeoInfo* ptr = realloc(pc->data, (pc->capacity + DEFAULT_INC) * sizeof(PeoInfo));
		if (ptr != NULL)
		{
			pc->data = ptr;
			pc->capacity += DEFAULT_INC;
			printf("增加联系人空间成功\n");
		}
		else
		{
			perror("ADDContact->realloc");
		}
	}
	//增加信息
	printf("请输入姓名:");
	scanf("%s", pc->data[pc->sz].name);
	printf("请输入年龄:");
	scanf("%d", &(pc->data[pc->sz].age));
	printf("请输入性别:");
	scanf("%s", pc->data[pc->sz].sex);
	printf("请输入电话号码:");
	scanf("%s", pc->data[pc->sz].tele);
	printf("请输入住址:");
	scanf("%s", pc->data[pc->sz].addr);

	//
	pc->sz++;
	printf("添加联系人成功!\n");
}

我们首先判断通讯录由动态开辟的空间是否已满,满了则开辟新的空间,用realloc函数开辟即可,之后赋给PeoInfo类型的ptr指针。如果该指针不为空,那么再把ptr指针赋给data指针,之后让通讯录容量+2,在这里是为了方便测试,所以只加2,最后用printf函数提醒一下增加联系人空间成功,否则则提醒一下realloc函数出错。之后就可以正常添加信息。增加通讯录容量也可以单独封装成一个函数,感兴趣的话可以尝试一下。

改造退出通讯录

动态开辟空间在程序结束时都要释放出去,防止有不可预料的结果产生,所以退出通讯录也要稍微 改造一下,静态直接退出即可不需要函数,所以我们直接看动态的退出通讯录。

void DestoryContact(Contact* pc)
{
	free(pc->data);//释放动态内存空间
	pc->data = NULL;//赋为空指针
	pc->sz = 0;//释放完人数当然为0
	pc->capacity = 0;//释放完,通讯录容量也自然为0
}

这个十分简单,释放掉动态空间的地址,然后把该指针赋值为空指针,然后sz为零,capacity为零即可。

改造后的全部代码

为大家奉上完整的代码,方便参考调试。

test.c

#define  _CRT_SECURE_NO_WARNINGS
#include"contact.h"
enum Option
{
	EXIT,
	ADD,
	DEL,
	SEARCH,
	MODIFY,
	SHOW,
	SORT,
	EMPTY
};
void menu();
int main()
{
	int input = 0;
	Contact con;
	InitContact(&con);
	do
	{
		menu();
		printf("请输入你想选择的操作:");
		scanf("%d", &input);
		switch (input)
		{
		case EXIT:
			DestoryContact(&con);
			printf("退出通讯录成功");
			break;
		case ADD:
			ADDContact(&con);
			break;
		case DEL:
			DELContact(&con);
			break;
		case SEARCH:
			SearchContact(&con);;
			break;
		case MODIFY:
			ModifyContact(&con);
			break;
		case SHOW:
			SHOWContact(&con);
			break;
		case SORT:
			SortContact(&con);
			break;
		case EMPTY:
			InitContact(&con);
			printf("清空通讯录成功\n");
			break;
		default:
			printf("输入错误\n");
			break;
		}


	} while (input);
	return 0;
}

contact.c

#define  _CRT_SECURE_NO_WARNINGS
#include "contact.h"
void menu()
{
	printf("*****************************\n");
	printf("*****0.EXIT****1.ADD*********\n");
	printf("*****2.DEL*****3.SEARCH******\n");
	printf("*****4.MODIFY**5.SHOW********\n");
	printf("*****6.SORT****7.EMPTY*******\n");
}
void InitContact(Contact* pc)
{
	assert(pc);

	pc->sz = 0;
	pc->capacity = DEFAULT_SZ;
	pc->data = calloc(pc->capacity,sizeof(PeoInfo));
	if (pc->data == NULL)
	{
		perror("InitContact->calloc");
		return;
	}
}
//void CheckCapacity(Contact* pc)
//{
//	if (pc->sz == pc->capacity)
//	{
//		PeoInfo* ptr = realloc(pc->data, (pc->capacity + DEFAULT_INC) * sizeof(PeoInfo));
//		if (ptr != NULL)
//		{
//			pc->sz = ptr;
//			pc->capacity += DEFAULT_INC;
//			printf("增加联系人空间成功\n");
//		}
//		else
//		{
//			perror("ADDContact->realloc");
//		}
//	}
//}
void ADDContact(Contact* pc)
{
	assert(pc);
	if (pc->sz == pc->capacity)
	{
		PeoInfo* ptr = realloc(pc->data, (pc->capacity + DEFAULT_INC) * sizeof(PeoInfo));
		if (ptr != NULL)
		{
			pc->data = ptr;
			pc->capacity += DEFAULT_INC;
			printf("增加联系人空间成功\n");
		}
		else
		{
			perror("ADDContact->realloc");
		}
	}
	//增加信息
	printf("请输入姓名:");
	scanf("%s", pc->data[pc->sz].name);
	printf("请输入年龄:");
	scanf("%d", &(pc->data[pc->sz].age));
	printf("请输入性别:");
	scanf("%s", pc->data[pc->sz].sex);
	printf("请输入电话号码:");
	scanf("%s", pc->data[pc->sz].tele);
	printf("请输入住址:");
	scanf("%s", pc->data[pc->sz].addr);

	//
	pc->sz++;
	printf("添加联系人成功!\n");
}

void SHOWContact(const Contact* pc)
{
	assert(pc);
	if (pc->sz == 0)
	{
		printf("通讯录为空,无需打印\n");
		return;
	}
	int i = 0;
	//名字  年龄  性别  电话    地址
	//xxx   xxx  xxx  xxx     xxx
	printf("%-20s%-10s%-10s%-12s%-30s\n", "名字", "年龄", "性别", "电话", "地址");
	for (i = 0; i < pc->sz; i++)
	{
		//打印每个人的信息
		printf("%-20s%-10d%-10s%-12s%-30s\n",
			pc->data[i].name, pc->data[i].age, pc->data[i].sex, pc->data[i].tele, pc->data[i].addr);
	}
}
int FindByName(Contact* pc, char* name)
{
	assert(pc);
	int i = 0;
	for (i = 0; i < pc->sz; i++)
	{
		if (strcmp(pc->data[i].name, name) == 0)
		{
			return i;
		}
	}
	return -1;
}
void DELContact(Contact* pc)
{
	char name[NAME_MAX];
	assert(pc);
	if (pc->sz == 0)
	{
		printf("通讯录为空,不可删除\n");
		return;
	}
	printf("请输入你想删除的联系人:");
	scanf("%s", name);
	int ret = FindByName(pc, name);
	if (ret == -1)
	{
		printf("该联系人不存在,无法删除!\n");
		return;
	}
	int i = 0;
	for (i = ret; i < pc->sz - 1; i++)
	{
		pc->data[i] = pc->data[i + 1];
	}
	pc->sz--;
	printf("删除该联系人成功!\n");
}
void SearchContact(Contact* pc)
{
	assert(pc);
	char name[NAME_MAX];
	printf("请输入想查找的联系人");
	scanf("%s", &name);
	int ret = FindByName(pc, name);
	if (ret == -1)
	{
		printf("该联系人不存在!\n");
		return;
	}
	printf("%-20s%-10s%-10s%-12s%-30s\n", "名字", "年龄", "性别", "电话", "地址");
	printf("%-20s%-10d%-10s%-12s%-30s\n",
		pc->data[ret].name, pc->data[ret].age, pc->data[ret].sex, pc->data[ret].tele, pc->data[ret].addr);
}
void ModifyContact(Contact* pc)
{
	assert(pc);
	char name[NAME_MAX];
	printf("请输入想修改的联系人");
	scanf("%s", &name);
	int ret = FindByName(pc, name);
	if (ret == -1)
	{
		printf("该联系人不存在!\n");
		return;
	}
	printf("请输入姓名:");
	scanf("%s", pc->data[ret].name);
	printf("请输入年龄:");
	scanf("%d", &(pc->data[ret].age));
	printf("请输入性别:");
	scanf("%s", pc->data[ret].sex);
	printf("请输入电话号码:");
	scanf("%s", pc->data[ret].tele);
	printf("请输入住址:");
	scanf("%s", pc->data[ret].addr);
	printf("修改联系人成功!\n");
}
int compare_name(const void* base, const void* src)
{
	return strcmp(((PeoInfo*)base)->name, ((PeoInfo*)src)->name);
}
int compare_age(const void* base, const void* src)
{
	return (((PeoInfo*)base)->age - ((PeoInfo*)src)->age);
}
void SortContact(Contact* pc)
{
	int ret = 0;
	printf("1按名字排序,2按年龄排序\n");
	scanf("%d", &ret);
	if (ret == 1)
	{
		qsort(pc->data, pc->sz, sizeof(PeoInfo), compare_name);
		SHOWContact(pc);
		printf("名字排序成功\n");
	}
	else if (ret == 2)
	{
		qsort(pc->data, pc->sz, sizeof(PeoInfo), compare_age);
		SHOWContact(pc);
		printf("年龄排序成功\n");
	}
	else
	{
		printf("选择错误,返回操作");
	}

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

contact.h

#define  _CRT_SECURE_NO_WARNINGS
#pragma once
#include<stdio.h>
#include<assert.h>
#include<string.h>
#include<stdlib.h>
#define NAME_MAX 20
#define SEX_MAX 10
#define TELE_MAX 12
#define ADDR_MAX 30

#define MAX 100
#define DEFAULT_SZ 3
#define DEFAULT_INC 2

typedef struct PeoInfo
{
	char name[NAME_MAX];
	int age;
	char sex[SEX_MAX];
	char tele[TELE_MAX];
	char addr[ADDR_MAX];
}PeoInfo;

//typedef struct Contact
//{
//	PeoInfo data[MAX];//存放成员数据
//	int sz;//记录当前通讯录人数
//}Contact;
typedef struct Contact
{
	PeoInfo* data;//存放成员数据
	int sz;//记录当前通讯录人数
	int capacity;//记录当前通讯录容量
}Contact;
void menu();
void InitContact(Contact* pc);
void ADDContact(Contact* pc);
void SHOWContact(const Contact* pc);
void DELContact(Contact* pc);
void SearchContact(Contact* pc);
void ModifyContact(Contact* pc);
void SortContact(Contact* pc);
void DestoryContact(Contact* pc);

最后各位看客老爷万福金安。
在这里插入图片描述

  • 7
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值