文章目录
动态通讯录的实现
——接上篇1.0版本静态通讯录的优化2.0版本
一.通讯录的各项功能及主体框架
本次优化版本与上一次的1.0版本相比,改变了原有的固定内存存储通讯录联系人的方式。
原来的存储联系人方式是我们规定一个数组存储1000个结构体进行存储联系人的各种信息,但是有时候我们用不了这么多的空间,没有那么多的联系人,那样我们开辟的内存空间就浪费了,所以这次我们的通讯录做了以下优化:
1. 通讯录我们开辟的动态内存空间默认最大的联系人数量是2个
2. 如果再添加联系人,我们将调整动态内存空间的大小,再次增加两个联系人的数量,这样极大的节约了空间的占有率。
3. 我们开辟的动态内存需要free ,防止内存泄漏的问题,所以在EXIT的功能后添加了DestroyContact函数来对开辟的空间进行释放。
1.通讯录的要求实现功能
0.退出菜单
1.添加联系人信息
2.删除指定名字的联系人信息
3.修改联系人的信息
4.查找好友的信息
5.展示通讯录联系人信息
我们根据通讯录的各项功能进行编写页面菜单
2.页面菜单
void menu(){//打印通讯录菜单//0.退出菜单//1.添加联系人信息//2.删除指定名字的联系人信息//3.修改联系人的信息//4.查找好友的信息//5.展示通讯录联系人信息//6.对通讯录指定信息进行排序printf("*************************************************\n");printf("********** ——欢迎来到通讯录菜单—— *********\n");printf("********** 0.退出菜单 *********\n");printf("********** 1.添加联系人信息 *********\n");printf("********* 2.删除联系人信息 *********\n");printf("********* 3.修改联系人信息 *********\n");printf("********* 4.查找联系人信息 *********\n");printf("********* 5.展示联系人信息 *********\n");printf("*************************************************\n");}
3.通讯录的主体框架实现
//将菜单的功能一一列举出来,以枚举的类型呈现enum{ EXIT, ADD, DEL, MODIFY, SEARCH, SHOW,};int main(){int input = 0;//创建通讯录struct Contact con; //Con就是通讯录,里面包含1000个人的信息,及sizeInitContact(&con);do{menu();printf("请选择功能:>");scanf("%d", &input);switch (input){case ADD:AddContact(&con);break;case DEL:DelContact(&con);break;case MODIFY :MotifyContact(&con);break;case SEARCH :SearchContact(&con);break;case SHOW:ShowContact(con);break;case EXIT:DestroyContact(&con);break;default:printf("选择错误,请重新输入!!\n");break;}} while(input);return 0;}
我们用枚举类型将功能一一列举出来,同时每一个枚举成员也代表着对应的数字,我们在switch ...case 语句中也不用 case 1,case 2来记录每一功能对应的数字了,直接以case ADD,case DEL表示,更加直接了当。
4.通讯录初始化及个人信息的表示
#define _CRT_SECURE_NO_WARNINGS 1#define MAX 1000#define MAX_name 20#define MAX_tel 20#define MAX_sex 5#define MAX_addr 30#define DEFAULT_SZ 2struct PeoInfor{char name[MAX_name];int age;char sex[MAX_sex];char tel[MAX_tel];char addr[MAX_addr];};//struct Contact//{// struct PeoInfor date[MAX]; // 存放个人信息// int size; //记录当前已有的元素个数//};//通讯录信息的动态内存的建立struct Contact{struct PeoInfor* date; // 存放个人信息int size; //表示当前通讯录的联系人的数量int capacity; //表示当天通讯录的联系人的最大空间能容纳的联系人数量};//动态内存的初始化void InitContact(struct Contact * ps){ ps->date = (struct PeoInfor *)malloc(DEFAULT_SZ * sizeof(struct PeoInfor));if (ps->date == NULL){printf("通讯录初始化失败");exit(1);} ps->size = 0; ps->capacity = 2;}
二、功能函数的具体实现
1.增加联系人的信息
void AddContact(struct Contact* ps){if (ps->size == ps->capacity){//增容struct PeoInfor * ptr = realloc(ps->date, (ps->capacity + 2)*sizeof(struct PeoInfor));if (ptr == NULL){printf("增容失败\n");return;}else{printf("增容成功\n"); ps->capacity += 2;}}printf("请输入姓名:>");scanf("%s", ps->date[ps->size].name);printf("请输入年龄:>");scanf("%d", &(ps->date[ps->size].age));printf("请输入性别:>");scanf("%s", ps->date[ps->size].sex);printf("请输入电话:>");scanf("%s", ps->date[ps->size].tel);printf("请输入地址:>");scanf("%s", ps->date[ps->size].addr); ps->size++;printf("添加成功\n");}
2.删除联系人的信息
void DelContact(struct Contact *ps){ // 查找要删除的人在什么位置,根据名字char name[MAX_name];printf("请输入要删除的联系人名字:>");scanf("%s", name);int i = 0;int j = 0;//查找名字for (i = 0; i < ps->size; i++){if (0 == strcmp(name, ps->date[j].name)){break;}} if (i==ps->size) // i从循环里出来,strcmp还是不等于0{printf("未找到该联系人的信息\n");} else { for (j = i; j < ps->size; j++) { ps->date[j] = ps->date[j + 1]; } } ps->size--; printf("删除成功\n");}
3.修改联系人的信息
void MotifyContact(struct Contact *ps){char name[MAX_name];printf("请输入要删除的联系人名字:>");scanf("%s", name);int i = 0;//查找名字for (i = 0; i < ps->size; i++){if (0 == strcmp(name, ps->date[i].name)){break;}}if (i == ps->size) // i从循环里出来,strcmp还是不等于0{printf("未找到该联系人的信息\n");}//表示找到该联系人//对下标为i的联系人信息进行修改else{printf("请输入姓名:>");scanf("%s", ps->date[i].name);printf("请输入年龄:>");scanf("%d", &(ps->date[i].age));printf("请输入性别:>");scanf("%s", ps->date[i].sex);printf("请输入电话:>");scanf("%s", ps->date[i].tel);printf("请输入地址:>");scanf("%s", ps->date[i].addr);}printf("修改成功\n");}
4.查找联系人的信息
void SearchContact(struct Contact *ps){char name[MAX_name];printf("请输入要查找的联系人名字:>");scanf("%s", name);int i = 0;//查找名字for (i = 0; i < ps->size; i++){if (0 == strcmp(name, ps->date[i].name)){break;}}if (i == ps->size) // i从循环里出来,strcmp还是不等于0{printf("未找到该联系人的信息\n");}//表示找到该联系人//对下标为i的联系人信息进行显示else{printf("%10s\t%4s\t%5s\t%12s\t%20s\n", "名字", "年龄", "性别", "电话", "地址");printf("%10s\t%4d\t%5s\t%12s\t%20s\n", ps->date[i].name, ps->date[i].age, ps->date[i].sex, ps->date[i].tel, ps->date[i].addr);}}
5.展示通讯录联系人信息
void ShowContact(struct Contact ps){if (ps.size == 0){printf("通讯录为空,无法展示\n");}else{printf("%10s\t%4s\t%5s\t%12s\t%20s\n","名字","年龄","性别","电话","地址");int i = 0;for (i = 0; i < ps.size; i++){printf("%10s\t%4d\t%5s\t%12s\t%20s\n", ps.date[i].name, ps.date[i].age, ps.date[i].sex, ps.date[i].tel, ps.date[i].addr);}}}
整体代码展示
1.test.c 通讯录主体框架测试文件
#define _CRT_SECURE_NO_WARNINGS 1#include <stdio.h>#include "contact.h"#include <string.h>void menu(){//打印通讯录菜单//0.退出菜单//1.添加联系人信息//2.删除指定名字的联系人信息//3.修改联系人的信息//4.查找好友的信息//5.展示通讯录联系人信息//6.对通讯录指定信息进行排序printf("*************************************************\n");printf("********** ——欢迎来到通讯录菜单—— *********\n");printf("********** 0.退出菜单 *********\n");printf("********** 1.添加联系人信息 *********\n");printf("********* 2.删除联系人信息 *********\n");printf("********* 3.修改联系人信息 *********\n");printf("********* 4.查找联系人信息 *********\n");printf("********* 5.展示联系人信息 *********\n");printf("*************************************************\n");}//将菜单的功能一一列举出来,以枚举的类型呈现enum{ EXIT, ADD, DEL, MODIFY, SEARCH, SHOW,};int main(){int input = 0;//创建通讯录struct Contact con; //Con就是通讯录,里面包含1000个人的信息,及sizeInitContact(&con);do{menu();printf("请选择功能:>");scanf("%d", &input);switch (input){case ADD:AddContact(&con);break;case DEL:DelContact(&con);break;case MODIFY :MotifyContact(&con);break;case SEARCH :SearchContact(&con);break;case SHOW:ShowContact(con);break;case EXIT:DestroyContact(&con);break;default:printf("选择错误,请重新输入!!\n");break;}} while(input);return 0;}
2.contact.c 通讯录函数文件
#define _CRT_SECURE_NO_WARNINGS 1#include <stdio.h>#include <string.h>#include "contact.h"#include <stdlib.h>//静态通讯录的信息初始化//void InitContact(struct Contact* ps)//{// memset(ps->date, 0, sizeof(ps->date));// ps->size = 0; //设置通讯录的元素有0个//}//动态通讯录的信息初始化void InitContact(struct Contact * ps){ ps->date = (struct PeoInfor *)malloc(DEFAULT_SZ * sizeof(struct PeoInfor));if (ps->date == NULL){printf("通讯录初始化失败");exit(1);} ps->size = 0; ps->capacity = 2;}//静态内存增添联系人的信息//void AddContact(struct Contact* ps)//{// if (ps->size == MAX)// {// printf("该通讯录空间已满,无法储存\n");// }// else// {// printf("请输入姓名:>");// scanf("%s", ps->date[ps->size].name);// printf("请输入年龄:>");// scanf("%d", &(ps->date[ps->size].age));// printf("请输入性别:>");// scanf("%s", ps->date[ps->size].sex);// printf("请输入电话:>");// scanf("%s", ps->date[ps->size].tel );// printf("请输入地址:>");// scanf("%s", ps->date[ps->size].addr);// ps->size++;// printf("添加成功\n");// }////}//动态内存实现增添联系人的信息void AddContact(struct Contact* ps){if (ps->size == ps->capacity){//增容struct PeoInfor * ptr = realloc(ps->date, (ps->capacity + 2)*sizeof(struct PeoInfor));if (ptr == NULL){printf("增容失败\n");return;}else{printf("增容成功\n"); //如果增容成功,那么ptr的值要赋给 ps->date; // ptr是realloc 开辟的内存,可能返回原来ps->date的地址,也可能是一个新的内存空间的地址 ps->date = ptr; ps->capacity += 2;}}printf("请输入姓名:>");scanf("%s", ps->date[ps->size].name);printf("请输入年龄:>");scanf("%d", &(ps->date[ps->size].age));printf("请输入性别:>");scanf("%s", ps->date[ps->size].sex);printf("请输入电话:>");scanf("%s", ps->date[ps->size].tel);printf("请输入地址:>");scanf("%s", ps->date[ps->size].addr); ps->size++;printf("添加成功\n");}void ShowContact(struct Contact ps){if (ps.size == 0){printf("通讯录为空,无法展示\n");}else{printf("%10s\t%4s\t%5s\t%12s\t%20s\n","名字","年龄","性别","电话","地址");int i = 0;for (i = 0; i < ps.size; i++){printf("%10s\t%4d\t%5s\t%12s\t%20s\n", ps.date[i].name, ps.date[i].age, ps.date[i].sex, ps.date[i].tel, ps.date[i].addr);}}}void DelContact(struct Contact *ps){ // 查找要删除的人在什么位置,根据名字char name[MAX_name];printf("请输入要删除的联系人名字:>");scanf("%s", name);int i = 0;int j = 0;//查找名字for (i = 0; i < ps->size; i++){if (0 == strcmp(name, ps->date[j].name)){break;}} if (i==ps->size) // i从循环里出来,strcmp还是不等于0{printf("未找到该联系人的信息\n");} else { for (j = i; j < ps->size; j++) { ps->date[j] = ps->date[j + 1]; } } ps->size--; printf("删除成功\n");}void MotifyContact(struct Contact *ps){char name[MAX_name];printf("请输入要删除的联系人名字:>");scanf("%s", name);int i = 0;//查找名字for (i = 0; i < ps->size; i++){if (0 == strcmp(name, ps->date[i].name)){break;}}if (i == ps->size) // i从循环里出来,strcmp还是不等于0{printf("未找到该联系人的信息\n");}//表示找到该联系人//对下标为i的联系人信息进行修改else{printf("请输入姓名:>");scanf("%s", ps->date[i].name);printf("请输入年龄:>");scanf("%d", &(ps->date[i].age));printf("请输入性别:>");scanf("%s", ps->date[i].sex);printf("请输入电话:>");scanf("%s", ps->date[i].tel);printf("请输入地址:>");scanf("%s", ps->date[i].addr);}printf("修改成功\n");}void SearchContact(struct Contact *ps){char name[MAX_name];printf("请输入要查找的联系人名字:>");scanf("%s", name);int i = 0;//查找名字for (i = 0; i < ps->size; i++){if (0 == strcmp(name, ps->date[i].name)){break;}}if (i == ps->size) // i从循环里出来,strcmp还是不等于0{printf("未找到该联系人的信息\n");}//表示找到该联系人//对下标为i的联系人信息进行显示else{printf("%10s\t%4s\t%5s\t%12s\t%20s\n", "名字", "年龄", "性别", "电话", "地址");printf("%10s\t%4d\t%5s\t%12s\t%20s\n", ps->date[i].name, ps->date[i].age, ps->date[i].sex, ps->date[i].tel, ps->date[i].addr);}}//对开辟的动态内存空间进行释放,防止内存泄漏void DestroyContact(struct Contact *ps){free(ps->date); ps->date = NULL; ps->size = 0; ps->capacity = 0;}
3.contact.h 宏定义及函数声明文件
#define _CRT_SECURE_NO_WARNINGS 1#define MAX 1000#define MAX_name 20#define MAX_tel 20#define MAX_sex 5#define MAX_addr 30#define DEFAULT_SZ 2 //通讯录系统默认的内存存储的联系人数量struct PeoInfor{char name[MAX_name];int age;char sex[MAX_sex];char tel[MAX_tel];char addr[MAX_addr];};//静态通讯录的结构体创建//struct Contact//{// struct PeoInfor date[MAX]; // 存放个人信息// int size; //记录当前已有的元素个数//};//动态通讯录的结构体创建struct Contact{struct PeoInfor* date; // 存放个人信息int size; //表示当前通讯录的联系人的数量int capacity;};// 声明函数void InitContact(struct Contact* ps); //通讯录信息初始化void AddContact(struct Contact* ps); //增加联系人相关信息void ShowContact(struct Contact ps); //展示联系人相关信息void DelContact(struct Contact *ps); //删除联系人相关信息void MotifyContact(struct Contact *ps); //修改联系人相关信息void SearchContact(struct Contact *ps); //搜索联系人相关信息void DestroyContact(struct Contact *ps); //程序结束后释放开辟的动态内存,防止内存泄漏
小结
我们写的通讯录实现了动态内存空间管理的功能,我们可以在这个程序内进行以上增删改查功能,但是我们退出了这个程序以后,我们存储的联系人信息将全部丢失,无法保存在一个固定的文件里,所以仍然存在限制和缺点。
这就是通讯录的2.0版本,后续将持续更新,我们将在3.0版本升级为拥有文件操作保存联系人信息的通讯录。
欢迎大家的关注与欣赏!!