全文目录
- 前言
- 目标规划
- 结构变化
- 功能实现的不同点
- 添加功能 `AddContact`
- 扩容检查 `CheckCapacity`
- 销毁通讯录 `DestroyContact`
- 总结 + 源码
前言
前面我们写了一个静态数组版本的通讯录,再结合刚学习的动态内存管理的知识,我们现在来实现一个动态内存版本的通讯录。
目标规划
动态内存版本的通讯录,主要还是为了解决静态数组版本的通讯录空间太大导致的内存浪费和空间太小不够存放的问题。
扩容策略:
为通讯录设置一个初始容量大小
capacity
,如果size
跟capacity
一样的,capacity
扩大两个元素(如果觉得扩容操作太过频繁,可以实现二倍扩容)
结构变化
因为是动态内存版本,有扩容等操作,所以我们需要用capacity
来表示空间的大小,size
来表示使用了多少空间。其他的可以不用发生变化。
#define DEFAULT_CAPACITY 3// 默认容量大小typedef struct Contact {PeoInform* data;int size;int capacity;} Contact;
功能实现的不同点
既然结构变了,那么在实现功能的时候也会有点差异。
添加功能 AddContact
扩容检查 CheckCapacity
再添加联系人之前我们需要先检查容量够不够,为了方便维护,我们还是封装一个函数。
// 检查增容void CheckCapacity(Contact* con){assert(con);if (con->size == con->capacity){PeoInform* temp = (PeoInform*)realloc(con->data, (con->capacity + 2) * sizeof(PeoInform));if (temp == NULL){perror("CheckCapacity::realloc"); return;}else{con->data = temp;con->capacity += 2;puts("扩容成功\n");}}}
其他的还是老样子
// 添加联系人void AddContact(Contact* con){assert(con);puts("");CheckCapacity(con);printf("请输入姓名 ->");scanf("%s", con->data[con->size].name);printf("请输入性别 ->");scanf("%s", con->data[con->size].sex);printf("请输入年龄 ->");scanf("%s", con->data[con->size].age);printf("请输入电话号码 ->");scanf("%s", con->data[con->size].telephon);printf("请输入地址 ->");scanf("%s", con->data[con->size].addrs);puts("");con->size++;printf("添加成功!\n");}
销毁通讯录 DestroyContact
既然使用了动态内存,那么就需要注意内存泄漏问题,再退出之前需要将申请的空间释放。
// 销毁通讯录void DestroyContact(Contact* con);{assert(con);free(con->data);con->data = NULL;con->size = con->capacity = 0;}
总结 + 源码
相较于静态数组,动态内存写起来更麻烦,但是对内存有着更加严谨的控制,所以还是推荐动态内存。
源码地址:动态内存版本通讯录