通讯录成员的改变
之前我们定义了date[100]的数组用来存放100个人的信息,但是当需要存储的人数超过100时,内存不够,存储人数较少时,又有些浪费,并且数组空间在创建时就已经确立,无法随需求改变,因此我们希望让它可以动态变化。
这里我默认初始为3,每次不够了就增容2。(为了方便测试)
#define once_sz 2
#define init_sz 3
第一个参数为每次增容2,第二个参数为初始化为3.
typedef struct contact
{
peopleinfo *date;
int sz;
int capacity;
}contact;
将date[n]改为一个peopleinfo类型的指针,便于接收我们调用内存分配函数后返回的void*起始地址
sz仍然表示现在已经有的人员信息数
新增capacity成员,用来表示现有的通讯录容量。
通讯录初始化
void contact_init(contact* pc)
{
assert(pc);
pc->sz = 0;
pc->capacity = init_sz;
peopleinfo* ptr = (peopleinfo*)calloc(init_sz,sizeof(peopleinfo));
if (NULL == ptr)//中间变量str判断是否成功开辟了一块空间
{
perror("contact_init:calloc");
return;
}
pc->date = str;
str=NULL:
}
sz初始化为0,capacity初始化为init_sz
然后利用calloc函数进行动态内存开辟,第一个参数为块数,第二个为每块空间的大小,因为每个元素都是人员信息peopleinfo,所以强制转换为peopleinfo。
然后创建一个中间变量ptr用来判断返回值是否为NULL,即是否成功开辟一块空间,判断完后,将ptr赋给date,用date指针来维护这一块空间,然后str可以置为空。
增加功能的升级
在增删查改、排序、显示功能中,仅增加和删除两个会改变当前的人员信息数,因此我们也要相应的增加/减少通讯录容量。
增加功能此前是判断sz是否达到最大元素sz,然后进行增加信息。
现在为了实现动态通讯录,我们增加增容功能,使其内存慢慢增加,按需增加,不再需要一个数组大小去限制它。
//增加人员信息
void contact_add(contact* pc)
{
assert(pc);
check_capacity(pc);
//通讯录没满,添加信息
printf("请输入姓名\n");
scanf("%s", pc->date[pc->sz].name);
printf("请输入年龄\n");
scanf("%d", &pc->date[pc->sz].age);
printf("请输入性别\n");
scanf("%s", pc->date[pc->sz].sex);
printf("请输入电话\n");
scanf("%s", pc->date[pc->sz].tel);
printf("请输入地址\n");
scanf("%s", pc->date[pc->sz].dres);
pc->sz++;
}
增容函数的实现
在增加人员信息前,先判断是否需要增容,如果需要,就进行增容。
当已有人员sz和capacity容量相同是需要增容。
增容过程利用realloc重新确定开辟空间的大小。
realloc第一个参数是重新开辟空间的起始地址,第二个是更新后的空间大小。
返回值用中间变量ptr接收,判断不为空指针后,用date指针来维护。
然后将ptr置空,相应的,容量capacity也要加上增量。
void check_capacity(contact* pc)
{
if (pc->capacity == pc->sz)
{
//相等时进行增容
peopleinfo* ptr = (peopleinfo*)realloc(pc->date, (pc->capacity + once_sz) * sizeof(peopleinfo));
if (NULL == ptr)
{
perror("check_capacity:realloc");
return;
}
pc->date = ptr;
ptr = NULL;
pc->capacity += once_sz;
printf("增容成功\n");
}
}
当我们已有3个人员信息,再次添加后,显示增容成功。
减容函数的实现
当删除人员信息较多时,影响sz的量较大时,我们可以考虑减容以节省空间。
初始时,sz=0,capacity=3,差值为3,且相同时增量为2,因此我们可以在sz和capacity的差值大于3时进行减容。
#define d_value 3
这里我们定义一个减容的差值3,以后还可以改成其他数。
添加6个元素后,此时capacity为7,sz为6,现在开始删除元素
删除至3个,此时sz=3,capacity=7,差大于3,成功减容。
退出时释放空间
前面我们多次使用malloc、calloc、realloc等内存开辟函数,但却没有释放,可能会导致内存泄漏问题,因此我们在退出通讯录时,一并进行释放操作。
//销毁通讯录
void contact_destroy(contact* pc)
{
free(pc->date);
pc->date = NULL;
}
将date指针指向的空间free,并将date置空即可。
动态内存开辟函数头文件是stdlib.h,返回地址要判断是否为空,还要进行free和置空操作。
目录
通讯录成员的改变
通讯录初始化
增加功能的升级
增容函数的实现
减容函数的实现
退出时释放空间