我们已经实现了静态版本的通讯录,可以实现增删查改等功能
https://mp.csdn.net/mp_blog/creation/editor/128825144
但是静态版本的通讯录存在局限性:一旦通讯录创建,其大小就固定了,我们需要存入通讯录中的人数是未知的,如果通讯录创建太大,可能造成空间的浪费;如果创建的太小,有可能造成空间不够存储的情况
改进:创建一个可以动态增长的通讯录
基本思路:默认通讯录的初始容量为存放3个联系人的空间,进行存储,一旦发现存满之后就进行通讯录扩容,每次增加2个联系人的空间
以下代码基于静态版本的通讯录进行修改
首先,我们需要在结构中添加一个变量,记录当前通讯录的容量
同时结构体数组需要修改为一个结构体指针
typedef struct Contact
{
PeoInfo* data;
int count;//当前通讯录的实际人数
int capacity;//通讯录的容量
}Contact;
初始化通讯录 :
我们需要开辟一块初始空间,这个大小我们可以使用#define定义,便于修改,每次扩容增加的人数也可以使用#define定义,这里DEFAULT_SZ是初始容量,INC_SZ是每次扩容的大小
//初始化通讯录
void InitContact(Contact* pc)
{
assert(pc);
pc->count = 0;
pc->data = (PeoInfo*)calloc(DEFAULT_SZ, sizeof(PeoInfo));//开辟指定的初始空间
if (pc->data == NULL)
{
printf("%s\n", strerror(errno));
return 1;
}
pc->capacity = DEFAULT_SZ;
return 0;
}
需要修改的代码块只有添加联系人部分:
静态版本的通讯录需要检查通讯录是否到达通讯录的最大容量,动态版本的通讯录需要在每次添加联系人后都检查通讯录的容量,一旦实际联系人的个数达到通讯录的容量,就应当进行扩容,我们可以把检查容量及扩容的操作封装成一个CheckCapacity函数
CheckCapacity(Contact* pc)
{
//当前空间已满,扩容
if (pc->count == pc->capacity)
{
PeoInfo* ptr = (PeoInfo*)realloc(pc->data, (pc->capacity + INC_SZ) * sizeof(PeoInfo));
if (ptr == NULL)
{
printf("AddContact::%s\n", strerror(errno));
return ;
}
else
{
pc->data = ptr;
pc->capacity = DEFAULT_SZ;
printf("增容成功!\n");
}
}
}
//添加联系人
void AddContact(Contact* pc)
{
assert(pc);
CheckCapacity(pc);//检查是否需要扩容
if (pc->count == MAX)
{
printf("通讯录已满\n");
return;//直接返回
}
else
{
printf("请输入姓名:");
scanf("%s", pc->data[pc->count].name);
printf("请输入年龄:");
scanf("%d", &pc->data[pc->count].age);
printf("请输入性别:");
scanf("%s", pc->data[pc->count].sex);
printf("请输入电话:");
scanf("%s", pc->data[pc->count].tele);
printf("请输入地址:");
scanf("%s", pc->data[pc->count].addr);
//添加成功
pc->count++;
printf("添加成功\n");
}
}
销毁通讯录:
动态开辟的内存使用完之后需要释放,否则会造成内存泄漏,所以我们应当补充一个函数销毁通讯录,实际上是销毁动态开辟的内存
//销毁通讯录
void DestroyContact(Contact* pc)
{
assert(pc);
free(pc->data);
pc->data = NULL;
}