各位CSDN的uu们你们好呀,今天,小雅兰的内容是动态版通讯录啦,其实之前,我就已经写过静态版的通讯录了,只是存在着一些问题,具体细节可以详细看看我的静态版通讯录,好了,话不多说,现在,就让我们进入动态版通讯录的世界吧
静态版通讯录——“C”_认真学习的小雅兰.的博客-CSDN博客
动态内存管理(上)——“C”_认真学习的小雅兰.的博客-CSDN博客
动态的版本
- 默认能够存放3个人的信息
- 不够的话,每次增加两个人的信息
之前写通讯录是这样写的:
typedef struct Contact{PeoInfo data[MAX];//存放数据int sz;//记录通讯录中有效信息的个数}Contact;
现在我们仔细想想,在此结构体中,存放数据采用数组的方式就会有问题啊,所以,要把它改写成指针的形式,另外,我们还需要新定义一个变量,来表示通讯录当前的容量
typedef struct Contact{PeoInfo *data;//data指向了存放数据的空间int sz;//记录通讯录中有效信息的个数int capacity;//通讯录当前的容量}Contact;
这样子改写之后,就可以啦
之前初始化通讯录,是这样写的:
//初始化通讯录void InitContact(Contact* pc){pc->sz = 0;memset(pc->data, 0, sizeof(pc->data));}
当然,改为动态版通讯录了,就要修改一下啦,默认容量是3
//初始化通讯录void InitContact(Contact* pc){pc->sz = 0;pc->data = (PeoInfo*)malloc(DEFAULT_SZ * sizeof(PeoInfo));if (pc->data == NULL){printf("通讯录初始化失败:%s\n", strerror(errno));return;}pc->capacity = DEFAULT_SZ;}
扩容:
//扩容void CheckCapacity(Contact* pc){if (pc->sz == pc->capacity)//容量和信息数相等时{PeoInfo* ptr = (PeoInfo*)realloc(pc->data, (pc->capacity + INC_SZ) * sizeof(PeoInfo));if (ptr == NULL){printf("CheckCapacity:%s\n", strerror(errno));return;}else{pc->data = ptr;pc->capacity += INC_SZ;printf("增容成功,当前容量:%d\n", pc->capacity);}}}
但是这个代码仍然不是很好,我们仔细想想:在增加联系人信息的时候,调用扩容函数,但是,扩容也有可能失败呀,那我们什么也不做的话,那怎么才能知道到底是扩容成功了还是失败了呢?下面,我们对上述代码进行改进,使得扩容函数返回值为int类型
//扩容//扩容失败,返回0//扩容成功,或者后面的空间足够,不需要扩容,返回1int CheckCapacity(Contact* pc){if (pc->sz == pc->capacity)//容量和信息数相等时{PeoInfo* ptr = (PeoInfo*)realloc(pc->data, (pc->capacity + INC_SZ) * sizeof(PeoInfo));if (ptr == NULL){printf("CheckCapacity:%s\n", strerror(errno));return 0;}else{pc->data = ptr;pc->capacity += INC_SZ;printf("增容成功,当前容量:%d\n", pc->capacity);return 1;}}return 1;}
下面这个代码就好多啦
增加联系人信息:
//增加指定联系人void AddContact(Contact* pc){if (CheckCapacity(pc) == 0){printf("空间不够,扩容失败\n");return;}else{printf("请输入姓名:>");scanf("%s", pc->data[pc->sz].name);printf("请输入年龄:>");scanf("%d", &(pc->data[pc->sz].age));printf("请输入性别:>");scanf("%s", pc->data[pc->sz].sex);printf("请输入电话:>");scanf("%s", pc->data[pc->sz].tele);printf("请输入地址:>");scanf("%s", pc->data[pc->sz].addr);pc->sz++;printf("添加成功\n");}}
销毁通讯录:
//销毁通讯录void DestroyContact(Contact* pc){free(pc->data);pc->data = NULL;pc->capacity = 0;pc->sz = 0;printf("释放内存......\n");}
上述这些改动就是对静态版通讯录的所有改动啦,此动态版通讯录很好地解决了容量问题,但是其实,这个动态版通讯录还是存在着一定的问题,因为:这个动态版通讯录还是不能够保存信息,程序一退出,信息就都没了,那么这个问题又该怎么解决呢?等小雅兰学习到文件的知识点,再来给大家分享分享吧
接下来,附上源代码:
txl.h的内容:
#pragma once#define MAX 100#define MAX_NAME 20#define MAX_SEX 5#define MAX_TELE 12#define MAX_ADDR 30#include#include#include#include#define DEFAULT_SZ 3#define INC_SZ 2//表示一个人的信息typedef struct PeoInfo{char name[MAX_NAME];int age;char sex[MAX_SEX];char tele[MAX_TELE];char addr[MAX_ADDR];}PeoInfo;typedef struct Contact{PeoInfo *data;//data指向了存放数据的空间int sz;//记录通讯录中有效信息的个数int capacity;//通讯录当前的容量}Contact;//初始化通讯录void InitContact(Contact* pc);//销毁通讯录void DestroyContact(Contact* pc);//增加指定联系人void AddContact(Contact* pc);//显示联系人信息void ShowContact(const Contact* pc);//删除指定联系人void DelContact(Contact* pc);//void DelContact(pContact pc);//查找指定联系人void SearchContact(const Contact* pc);//void SearchContact(pContact pc);//修改指定联系人void ModifyContact(Contact* pc);//按照名字来排序void SortContact(Contact* pc);
txl.c的内容:
#define _CRT_SECURE_NO_WARNINGS 1#include"txl.h"//初始化通讯录void InitContact(Contact* pc){pc->sz = 0;pc->data = (PeoInfo*)malloc(DEFAULT_SZ * sizeof(PeoInfo));if (pc->data == NULL){printf("通讯录初始化失败:%s\n", strerror(errno));return;}pc->capacity = DEFAULT_SZ;}//扩容//扩容失败,返回0//扩容成功,或者后面的空间足够,不需要扩容,返回1int CheckCapacity(Contact* pc){if (pc->sz == pc->capacity)//容量和信息数相等时{PeoInfo* ptr = (PeoInfo*)realloc(pc->data, (pc->capacity + INC_SZ) * sizeof(PeoInfo));if (ptr == NULL){printf("CheckCapacity:%s\n", strerror(errno));return 0;}else{pc->data = ptr;pc->capacity += INC_SZ;printf("增容成功,当前容量:%d\n", pc->capacity);return 1;}}return 1;}//增加指定联系人void AddContact(Contact* pc){if (CheckCapacity(pc) == 0){printf("空间不够,扩容失败\n");return;}else{printf("请输入姓名:>");scanf("%s", pc->data[pc->sz].name);printf("请输入年龄:>");scanf("%d", &(pc->data[pc->sz].age));printf("请输入性别:>");scanf("%s", pc->data[pc->sz].sex);printf("请输入电话:>");scanf("%s", pc->data[pc->sz].tele);printf("请输入地址:>");scanf("%s", pc->data[pc->sz].addr);pc->sz++;printf("添加成功\n");}}//销毁通讯录void DestroyContact(Contact* pc){free(pc->data);pc->data = NULL;pc->capacity = 0;pc->sz = 0;printf("释放内存......\n");}//显示联系人信息void ShowContact(const Contact* pc){int i = 0;//姓名 年龄性别 电话地址//zhangsan13 男123456 北京//打印标题printf("%-15s %-4s %-5s %-12s %-30s\n", "姓名", "年龄", "性别", "电话", "地址");for (i = 0; i sz; i++){printf("%-15s %-4d %-5s %-12s %-30s\n", pc->data[i].name,pc->data[i].age, pc->data[i].sex, pc->data[i].tele, pc->data[i].addr);}}static int FindByName(const Contact* pc, char name[]){int i = 0;for (i = 0; i sz; i++){if (0 == strcmp(pc->data[i].name, name)){return i;}}return -1;} //删除指定联系人void DelContact(Contact* pc){char name[MAX_NAME] = { 0 };if (pc->sz == 0){printf("通讯录为空,无法删除\n");return;}//删除//1.找到要删除的人 - 位置(下标)printf("输入要删除人的名字:>");scanf("%s", name);int pos = FindByName(pc, name);if (pos == -1){printf("要删除的人不存在\n");return;}//2.删除-删除pos位置上的元素int i = 0;for (i = pos; i sz - 1; i++){pc->data[i] = pc->data[i + 1];}pc->sz--;printf("删除成功\n");}//查找指定联系人void SearchContact(const Contact* pc){char name[MAX_NAME] = { 0 };printf("请输入要查找的人的名字:>");scanf("%s", name);//查找int pos = FindByName(pc, name);if (pos == -1){printf("要查找的人不存在\n");return;}//打印printf("%-15s %-4s %-5s %-12s %-30s\n", "姓名", "年龄", "性别", "电话", "地址");printf("%-15s %-4d %-5s %-12s %-30s\n", pc->data[pos].name,pc->data[pos].age, pc->data[pos].sex, pc->data[pos].tele, pc->data[pos].addr);}//修改指定联系人void ModifyContact(Contact* pc){char name[MAX_NAME] = { 0 };printf("请输入要修改人的名字:>");scanf("%s", name);int pos = FindByName(pc, name);if (pos == -1){printf("要修改的人不存在\n");return;}//修改printf("请输入姓名:>");scanf("%s", pc->data[pos].name);printf("请输入年龄:>");scanf("%d", &(pc->data[pos].age));printf("请输入性别:>");scanf("%s", pc->data[pos].sex);printf("请输入电话:>");scanf("%s", pc->data[pos].tele);printf("请输入地址:>");scanf("%s", pc->data[pos].addr);printf("修改成功\n");}//排序通讯录元素//按照名字来排序int cmp_by_name(const void* e1, const void* e2){return strcmp(((PeoInfo*)e1)->name, ((PeoInfo*)e2)->name);}void SortContact(Contact* pc){qsort(pc->data, pc->sz, sizeof(PeoInfo), cmp_by_name);ShowContact(pc);printf("排序成功\n");}
test.c的内容:
#define _CRT_SECURE_NO_WARNINGS 1#include"txl.h"void menu(){printf("#############################################\n");printf("#############1.add ############\n");printf("#############2.del ############\n");printf("#############3.search############\n");printf("#############4.modify############\n");printf("#############5.show############\n");printf("#############6.sort############\n");printf("#############0.exit############\n");printf("#############################################\n");}enum Option{EXIT,ADD,DEL,SEARCH,MODIFY,SHOW,SORT};int main(){int input = 0;Contact con;//通讯录//初始化通讯录InitContact(&con);do{menu();printf("请选择:>");scanf("%d", &input);switch (input){case ADD:AddContact(&con);break;case DEL:DelContact(&con);break;case SEARCH:SearchContact(&con);break;case MODIFY:ModifyContact(&con);break;case SHOW:DestroyContact(&con);ShowContact(&con);break;case SORT:SortContact(&con);break;case EXIT:printf("退出通讯录\n");break;default:printf("选择错误\n");break;}} while (input);return 0;}
好啦,小雅兰今天的动态版通讯录的内容就到这里啦,继续加油噢!!!