欢迎来到 Claffic 的博客 💞💞💞
前言:
上期博客写了静态通讯录并且答应给大家写一个动态版,这不,它来了:
1.动态版与静态版的区别
静态版的内存空间开辟大小是固定的,放了预期的最大值,并不会根据实际存放的数据而变化;
当需要存放的数据较少时,难免会出现内存的浪费,所以我们考虑申请动态内存开辟;
2.相关函数的介绍
2.1 malloc
开辟动态内存,最经典的就是 malloc 函数了:
函数的作用是向内存申请一块连续可用的空间,并返回指向这块空间的指针;
用它需要传递一个无符号整型的参数:需要开辟的动态内存的大小,单位是字节;
如果开辟成功,函数返回指向开辟好空间的指针;
如果开辟失败,函数返回NULL指针;
因此 malloc 的返回值要做检查。
但是,动态内存嘛,向内存申请了还是要还的;
还内存也方便,用一个 free 函数就可以:
free 函数用来释放动态内存开辟的空间;
如果 ptr 指向的空间不是动态内存开辟的,free 函数的行为未定义;
如果 ptr 是 NULL,函数不作为;
另外注意,指针释放后小心变野哦,释放的指针要赋个 NULL;
开辟动态内存,养成好习惯:
free(ptr);
ptr = NULL;
2.2 calloc
calloc 函数的作用也是申请动态内存,只不过比 malloc 更灵活些;
它为 num 个大小为 size 的元素开辟一块空间,
并且把空间的每个字节初始化为 0。
2.3 realloc
realloc 函数的出现让动态内存管理更加灵活;
realloc 函数的作用是调整动态开辟内存的大小;
函数返回调整之后的内存起始位置;
ptr 是要调整的内存地址;
size 是调整之后的新大小。
3.实现过程
做了以上铺垫,就可以开始正题了:
静态通讯录到动态通讯录,需要在哪动刀子呢?
多是在添加联系人信息时开辟动态内存:
我们先给存放联系人一个初始空间,再定义一个扩容空间,按需扩容。
给通讯录结构体改一 加一:
typedef struct Contact
{
PeoInform data[MAX];//存放的联系人
PeoInform* data;//指向存放人的信息空间
int sz;//当前已经存放的联系人个数
int capacity;//当前通讯录的容量
}Contact;
然后在原来的添加联系人的基础上加入检查是否扩容的函数:
void* check_capacity(Contact* pc)
{
assert(pc);
if (pc->sz == pc->capacity)
{
printf("通讯录已满,无法添加\n");
return;
}
//扩容
PeoInform* ptr = (PeoInform*)realloc(pc->data, (pc->capacity + INC_SZ) * sizeof(PeoInform));
if (ptr == NULL)
{
perror("check_capacity");
return;
}
pc->data = ptr;
pc->capacity += INC_SZ;
printf("扩容成功\n");
}
初始化也要相应改变:
void Init_Contact(Contact* pc)
{
assert(pc);
pc->sz = 0;
PeoInform* ptr = (PeoInform*)calloc(DEFAULT_SZ, sizeof(PeoInform));
if (ptr == NULL)
{
perror("Init_Contact");
return;
}
pc->data = ptr;
pc->capacity = DEFAULT_SZ;
}
退出时要销毁通讯录:
void Dtroy_Contact(Contact* pc)
{
free(pc->data);
pc->data = NULL;
pc->capacity = 0;
pc->sz = 0;
pc = NULL;
}
到这里基本上就可以了,已经化为动态版。
源码已上传至 我的 gitee,
拿走不谢 ~
总结:
静态版升级为动态版,实际上只是在申请内存上做了改动,重点是学会如何使用动态内存开辟。
如果你觉得这篇文章还不错并且对你有帮助,不妨支持一波哦 💗💗💗
关注我 不迷路!!!