目录
前言
上篇博客我们已经用简单静态完成了通讯录,但是静态通讯录开辟的空间小了不够用,大了又占空间,机动性比较差。
因此,这里我们用动态开辟空间对通讯录进行一个升级。
前提操作
要改为动态通讯录,我们需要先对通讯录结构进行改进。
旧:
typedef struct Contact { PersonInfo cont[MAX_CONTACT_SIZE]; size_t capacity; size_t size; }Contact;
新:
typedef struct Contact { //PersonInfo cont[MAX_CONTACT_SIZE]; //静态开辟 PersonInfo *cont; //动态开辟 size_t capacity; size_t size; }Contact;
具体改进
1.初始化
既然我们采用动态开辟,那么我们初次开辟就不需要开辟那么大的空间了,开辟两个就够了,后面不够了依次翻倍开辟空间。
#define DEFAULT_CONTACT_SIZE 2
void InitContact(Contact *pcont) { assert(pcont != NULL); pcont->cont = (PersonInfo*)malloc(sizeof(PersonInfo)* DEFAULT_CONTACT_SIZE); memset(pcont->cont, 0, sizeof(PersonInfo)* DEFAULT_CONTACT_SIZE); pcont->capacity = DEFAULT_CONTACT_SIZE; pcont->size = 0; }
2.扩容空间
这里就是但我们增加联系人的时候空间不够就使用realloc重新扩容空间,当然我们要检测是否扩容成功(本地内存是否够)。
static bool _Inc(Contact *pcont) { PersonInfo *new_cont = (PersonInfo *)realloc(pcont->cont, sizeof(PersonInfo)*(pcont->capacity * 2)); if (new_cont == NULL) { printf("内存不足,扩容失败......\n"); return false; } pcont->cont = new_cont; pcont->capacity *= 2; return true; }
3.增加联系人
有了上面内存的扩充,那我们也需要对增加联系人这块进行改进。
void AddContact(Contact *pcont) { assert(pcont != NULL); if (IsFullContact(pcont) && !_Inc(pcont)) { printf("通讯录空间已满,不能新增信息.....\n"); return; } printf("姓名:>"); scanf("%s", pcont->cont[pcont->size].name); printf("性别:>"); scanf("%s", pcont->cont[pcont->size].sex); printf("年龄:>"); scanf("%d", &pcont->cont[pcont->size].age); printf("电话:>"); scanf("%s", pcont->cont[pcont->size].tel); printf("住址:>"); scanf("%s", pcont->cont[pcont->size].address); pcont->size++; printf("增加完成.......\n"); }
4.销毁空间
这里我们采用动态开辟,那我们使用完成后就要对开辟的空间进行释放,否则会造成内存泄漏,时间久了,会使我们电脑的空间不足。
void DestroyContact(Contact *pcont) { assert(pcont != NULL); free(pcont->cont); pcont->cont = NULL; pcont->capacity = pcont->size = 0; }
下来我们展示完整代码
完整代码
utili.h
#ifndef _UTILI_H_ #define _UTILI_H_ #include<stdio.h> #include<assert.h> #include<string.h> #include<stdbool.h> #include<malloc.h> #endif /* _UTILI_H_ */
contact.h
#ifndef _CONTACT_H_ #define _CONTACT_H_ #include"utili.h" enum { QUIT, ADD, DEL, FIND, MODIFY, SHOW, CLEAR, SORT }; #define MAX_NAME_SIZE 10 #define MAX_SEX_SIZE 3 #define MAX_TEL_SIZE 12 #define MAX_ADDR_SIZE 128 //#define MAX_CONTACT_SIZE 2 #define DEFAULT_CONTACT_SIZE 2 //定义通讯录人员信息 typedef struct PersonInfo { char name[MAX_NAME_SIZE]; char sex[MAX_SEX_SIZE]; int age; char tel[MAX_TEL_SIZE]; char address[MAX_ADDR_SIZE]; }PersonInfo; //定义通讯录结构 typedef struct Contact { //PersonInfo cont[MAX_CONTACT_SIZE]; //静态开辟 PersonInfo *cont; //动态开辟 size_t capacity; size_t size; }Contact; ///////////////////////////////////////////////////////////// bool IsFullContact(Contact *pcont); void InitContact(Contact *pcont); void AddContact(Contact *pcont); void ShowContact(Contact *pcont); int FindContact(Contact *pcont); void DelContact(Contact *pcont); void ModifyContact(Contact *pcont); void SortContact(Contact *pcont); void ClearContact(Contact *pcont); void DestroyContact(Contact *pcont); #endif /* _UTILI_H_ */
contact.cpp
#include"contact.h" void InitContact(Contact *pcont) { assert(pcont != NULL); pcont->cont = (PersonInfo*)malloc(sizeof(PersonInfo)* DEFAULT_CONTACT_SIZE); memset(pcont->cont, 0, sizeof(PersonInfo)* DEFAULT_CONTACT_SIZE); pcont->capacity = DEFAULT_CONTACT_SIZE; pcont->size = 0; } static bool _Inc(Contact *pcont) { PersonInfo *new_cont = (PersonInfo *)realloc(pcont->cont, sizeof(PersonInfo)*(pcont->capacity * 2)); if (new_cont == NULL) { printf("内存不足,扩容失败......\n"); return false; } pcont->cont = new_cont; pcont->capacity *= 2; return true; } bool IsFullContact(Contact *pcont) { assert(pcont != NULL); return pcont->size >= pcont->capacity; } void AddContact(Contact *pcont) { assert(pcont != NULL); if (IsFullContact(pcont) && !_Inc(pcont)) { printf("通讯录空间已满,不能新增信息.....\n"); return; } printf("姓名:>"); scanf("%s", pcont->cont[pcont->size].name); printf("性别:>"); scanf("%s", pcont->cont[pcont->size].sex); printf("年龄:>"); scanf("%d", &pcont->cont[pcont->size].age); printf("电话:>"); scanf("%s", pcont->cont[pcont->size].tel); printf("住址:>"); scanf("%s", pcont->cont[pcont->size].address); pcont->size++; printf("增加完成.......\n"); } void ShowContact(Contact *pcont) { assert(pcont != NULL); printf("%-10s%-5s%-6s%-13s%s\n", "姓名", "性别", "年龄", "电话", "住址"); for (int i = 0; i<pcont->size; ++i) { printf("%-10s%-5s%-6d%-13s%s\n", pcont->cont[i].name, pcont->cont[i].sex, pcont->cont[i].age, pcont->cont[i].tel, pcont->cont[i].address); } } int FindContact(Contact *pcont) { assert(pcont != NULL); printf("请输入要查找的姓名:>"); char name[MAX_NAME_SIZE] = { 0 }; scanf("%s", name); printf("%-10s%-5s%-6s%-13s%s\n", "姓名", "性别", "年龄", "电话", "住址"); for (int i = 0; i<pcont->size; ++i) { if (strcmp(name, pcont->cont[i].name) == 0) { printf("%-10s%-5s%-6d%-13s%s\n", pcont->cont[i].name, pcont->cont[i].sex, pcont->cont[i].age, pcont->cont[i].tel, pcont->cont[i].address); return i; } } return -1; } void DelContact(Contact *pcont) { assert(pcont != NULL); printf("请输入要删除的名字:>"); char name[MAX_NAME_SIZE] = { 0 }; scanf("%s", name); int i; for (i = 0; i<pcont->size; ++i) { if (strcmp(name, pcont->cont[i].name) == 0) break; } if (i >= pcont->size) { printf("要删除的信息不存在.....\n"); return; } for (int k = i; k<pcont->size - 1; ++k) pcont->cont[k] = pcont->cont[k + 1]; pcont->size--; printf("删除完成.......\n"); } void ModifyContact(Contact *pcont) { assert(pcont != NULL); printf("请输入要修改的名字:>"); char name[MAX_NAME_SIZE] = { 0 }; scanf("%s", name); int i; for (i = 0; i<pcont->size; ++i) { if (strcmp(name, pcont->cont[i].name) == 0) break; } if (i >= pcont->size) { printf("要修改的信息不存在.....\n"); return; } printf("你想修改什么信息(1-姓名 2-性别 3-年龄 4-电话 5-住址)\n"); int select; scanf("%d", &select); if (select == 1) { printf("请输入要修改姓名:>"); scanf("%s", pcont->cont[i].name); } else if (select == 2) { printf("请输入要修改性别:>"); scanf("%s", pcont->cont[i].sex); } else if (select == 3) { printf("请输入要修改住址:>"); scanf("%d", &pcont->cont[i].age); } else if (select == 4) { printf("请输入要修改电话:>"); scanf("%s", pcont->cont[i].tel); } else if (select == 5) { printf("请输入要修改性别:>"); scanf("%s", pcont->cont[i].address); } printf("修改完成.......\n"); } void SortContact(Contact *pcont) { assert(pcont != NULL); for (int i = 0; i<pcont->size - 1; ++i) { for (int j = 0; j<pcont->size - 1 - i; ++j) { if (strcmp(pcont->cont[j].name, pcont->cont[j + 1].name) > 0) { PersonInfo tmp = pcont->cont[j]; pcont->cont[j] = pcont->cont[j + 1]; pcont->cont[j + 1] = tmp; } } } printf("排序完成.......\n"); } void ClearContact(Contact *pcont) { assert(pcont != NULL); pcont->size = 0; printf("清除完成.......\n"); } void DestroyContact(Contact *pcont) { assert(pcont != NULL); free(pcont->cont); pcont->cont = NULL; pcont->capacity = pcont->size = 0; }
contactMain.cpp
#include"contact.h" void Menu() { printf("****************通 讯 录****************\n"); printf("* [1] Add [2] Del *\n"); printf("* [3] Find [4] Modify *\n"); printf("* [5] Show [6] Clear *\n"); printf("* [7] Sort [0] Quit *\n"); printf("****************************************\n"); } void main() { Contact cont; InitContact(&cont); int select = 1; while (select) { Menu(); printf("请选择:>"); scanf("%d", &select); if (select == QUIT) break; switch (select) { case ADD: AddContact(&cont); break; case DEL: DelContact(&cont); break; case FIND: FindContact(&cont); break; case MODIFY: ModifyContact(&cont); break; case SHOW: ShowContact(&cont); break; case CLEAR: ClearContact(&cont); break; case SORT: SortContact(&cont); //qsort break; } } DestroyContact(&cont); }