打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
UC头条:[基于动态内存 文件操作]通讯录管理系统
userphoto

2023.06.06 山西

关注

对于一个通讯录管理系统来说,较为重要的是清楚具体需要什么功能以及每一块功能的实现。

下面,实现一个通讯录,该通讯录能够进行联系人的添加,删除,查找,修改,展示,排序,保存,销毁,等功能。

我们知道,一个联系人有以下基本信息:联系人姓名,年龄,性别,电话,住址等。

所以下面来实现功能时,按照每一个功能逐一实现即可。

每一个项目文件的说明

该通讯录包含三个项目文件:

Contact.c文件

Contact.h文件

test.c文件

Contact.c文件是用来实现每个区域的功能。

Contact.h文件是用来声明函数,包含头文件的。

test.c文件是用来测试代码的(建议封装完一个函数,写完一个函数后就测试代码)

打印基本菜单,以供用户选择。

实现菜单较为简单,列出功能,共用户选择即可。

voidmenu(void){printf('*******************************\n');printf('******1.Add2.Del******\n');printf('******3.Search4.Modify******\n');printf('******5.Show6.Sort******\n');printf('******7.Clean8.Save******\n');printf('******0.Exit******\n');printf('*******************************\n');}

点击加载图片

1.创建一个适合存放联系人信息的结构体

上面讲到,联系人的信息有姓名,年龄,性别,电话,地址等

#defineMAX100#defineNAME_MAX20#defineSEX_MAX5#defineTELE_MAX12#defineADDR_MAX30#defineCAPACITY_SIZE3//个人信息typedefstructPeoInfo{charname[NAME_MAX];intage;charsex[SEX_MAX];chartele[TELE_MAX];charaddr[ADDR_MAX];}PeoInfo;

基本联系人信息如上。

然而,这只是一个人的信息,一个通讯录有成百上千人,我们需要一块空间来存放联系人的信息,这就需要到一个结构体数组来存放每一个结构体联系人的信息,如下图:

点击加载图片

又有一个问题了,当存放了第一个人的信息后,怎么找到第二个人的空间来存放?第三个人呢?

由此可以联想到,需要用到一个存储下标的结构体变量,每存储一个人的信息,该下标变量就++。

点击加载图片

我们在一开始申请空间的时候,不适宜申请太多空间,申请多少空间,就用一个变量来记录,叫做capacity(容量),也就是结构体的申请的空间大小。

所以可以创建一个大空间存放每个人的信息,该空间也是一个结构体,包含一个数组和存储下标的变量和一个结构体的容量(能容纳多少个联系人)。

//整个通讯录信息typedefstructContact{PeoInfo*data;intsz;intcapacity;}Contact;

2.初始化通讯录(加载上次的联系人,检查容量是否充足)

在初始化通讯录时,我们可以分装一个函数,专门实现该功能。

我们在写入联系人信息时,该信息会保存到本地的磁盘中,当我们再次进入通讯录时,应该加载上一次存放好的联系人的信息,防止用户重复存放等。

所以应该也需要封装一个加载信息的函数:

voidLoadContact(Contact*ps){assert(ps);FILE*pfread=fopen('Contact.txt','rb');//二进制形式读取PeoInfotmp={0};//把读取的联系人先放着,先判断容量够不够,再放进data里if(pfread==NULL){printf('LoadContact:%s\n',strerror(errno));}else{while(fread(&tmp,sizeof(PeoInfo),1,pfread)){CheckCapacity(ps);//判断容量够不够ps->data[ps->sz]=tmp;ps->sz++;}}fclose(pfread);pfread=NULL;}

初始化完通讯录后,就加载上一次的联系人信息出来。由于我们在进入通讯录时,申请的空间不多,有可能在本地磁盘中存储的联系人信息有多个,我们申请的空间只要少量,所以需要检查容量是否充足,如果容量不足,则需要再次申请空间。

//检查容量voidCheckCapacity(Contact*ps){assert(ps);if(ps->sz==ps->capacity){//扩容PeoInfo*ptr=realloc(ps->data,sizeof(PeoInfo)*(2+ps->capacity));//一次扩容两个if(ptr==NULL){printf('%s\n',strerror(errno));printf('增容失败\n');}else{ps->data=ptr;ps->capacity+=2;printf('增容成功\n');}}}

用上面的函数来检查容量。

voidInitContact(Contact*ps){assert(ps);ps->data=(PeoInfo*)malloc(sizeof(PeoInfo)*CAPACITY_SIZE);if(ps->data==NULL){printf('%s\n',strerror(errno));}ps->capacity=CAPACITY_SIZE;ps->sz=0;}

初始化完通讯录之后,就可以开始逐一实现每个函数的功能了。

枚举常量内部内容:

对于枚举来说,其成员的排序是从0开始的,即第一个成员的序号是0,第二个成员的序号是1…

enum{Exit,//0Add,//1Del,//2Search,//3Modify,//4Show,//5Sort,//6Clean,//7Save//8};

(1)增加联系人信息

再增加联系人之前,需要检查当前的容量是否足够,如果不够,也是一样需要增容。

增加联系人的信息,就需要输入姓名,年龄,性别,电话,住址等。

并且每次增加完之后,指向联系人的下标的变量就需要++,向前走。

voidAddContact(Contact*ps){assert(ps);CheckCapacity(ps);检查容量是否充足printf('请输入姓名:>\n');scanf('%s',ps->data[ps->sz].name);printf('请输入年龄:>\n');scanf('%d',&ps->data[ps->sz].age);printf('请输入性别:>\n');scanf('%s',ps->data[ps->sz].sex);printf('请输入电话:>\n');scanf('%s',ps->data[ps->sz].tele);printf('请输入住址:>\n');scanf('%s',ps->data[ps->sz].addr);ps->sz++;printf('添加成功\n');}

(2)删除联系人信息

实现代码之前,先想想,删除一个联系人,是不是要先找到该联系人?不然怎么删除呢?

而找该联系人,就是第三个功能:查找联系人。

而第四个功能:删除联系人,同理,必须先找到想修改的联系人的信息,才能修改。

所以,这三个功能都有相同点:先找到目标联系人

封装一个函数来实现:

staticintFindByName(constContact*ps){assert(ps);charname[NAME_MAX]={0};scanf('%s',name);for(inti=0;isz;i++){if(strcmp(ps->data[i].name,name)==0){returni;}}return-1;}

以名字来查找。

有了这个函数,就可以删除目标联系人了。

所谓的删除,不过就是往前覆盖,进行下标再--

点击加载图片

voidDelContact(Contact*ps){assert(ps);printf('请输入要删除的人的名字:>\n');intpos=FindByName(ps);if(pos==-1){printf('要删除的人不存在\n');return;}//删除也就是向前覆盖即可for(inti=pos;isz-1;i++){ps->data[i]=ps->data[i+1];}ps->sz--;printf('删除成功\n');}

(3)查找联系人信息

查找联系人信息,然后打印出来。

voidSearchContact(constContact*ps){assert(ps);printf('请输入要查找的人的名字:>\n');intpos=FindByName(ps);if(pos==-1){printf('要查找的人不存在\n');return;}printf('%-20s\t%-4s\t%-5s\t%-12s\t%-30s\n','姓名','年龄','性别','电话','住址');printf('%-20s\t%-4d\t%-5s\t%-12s\t%-30s\n',ps->data[pos].name,ps->data[pos].age,ps->data[pos].sex,ps->data[pos].tele,ps->data[pos].addr);}

(4)修改联系人信息

voidModifyContact(Contact*ps){assert(ps);printf('请输入要修改的人的名字:>\n');intpos=FindByName(ps);if(pos==-1){printf('要修改的人不存在\n');return;}printf('请输入姓名:>\n');scanf('%s',ps->data[pos].name);printf('请输入年龄:>\n');scanf('%d',&ps->data[pos].age);printf('请输入性别:>\n');scanf('%s',ps->data[pos].sex);printf('请输入电话:>\n');scanf('%s',ps->data[pos].tele);printf('请输入住址:>\n');scanf('%s',ps->data[pos].addr);printf('修改成功\n');}

(5)展示联系人信息

voidShowContact(constContact*ps){assert(ps);if(ps->sz==0){printf('通讯录为空\n');return;}printf('%-20s\t%-4s\t%-5s\t%-12s\t%-30s\n','姓名','年龄','性别','电话','住址');for(inti=0;isz;i++){printf('%-20s\t%-4d\t%-5s\t%-12s\t%-30s\n',ps->data[i].name,ps->data[i].age,ps->data[i].sex,ps->data[i].tele,ps->data[i].addr);}}

(6)对联系人信息进行排序

提供的排序种类有:姓名,年龄,性别,电话,住址

intcmp_name(constvoid*e1,constvoid*e2){returnstrcmp(((PeoInfo*)e1)->name,((PeoInfo*)e2)->name);}intcmp_age(constvoid*e1,constvoid*e2){return((PeoInfo*)e1)->age-((PeoInfo*)e2)->age;}intcmp_sex(constvoid*e1,constvoid*e2){returnstrcmp(((PeoInfo*)e1)->sex,((PeoInfo*)e2)->sex);}intcmp_tele(constvoid*e1,constvoid*e2){returnstrcmp(((PeoInfo*)e1)->tele,((PeoInfo*)e2)->tele);}intcmp_addr(constvoid*e1,constvoid*e2){returnstrcmp(((PeoInfo*)e1)->addr,((PeoInfo*)e2)->addr);}voidSortContact(Contact*ps){assert(ps);chartmp[5]={0};printf('请输入要排序的种类:>\n');printf('(姓名,年龄,性别,电话,住址)\n');scanf('%s',tmp);char*arr[5]={'姓名','年龄','性别','电话','住址'};if(strcmp(arr[0],tmp)==0){//起始地址,排序个数,每个元素大小,比较方法qsort(ps->data,ps->sz,sizeof(ps->data[0]),cmp_name);}if(strcmp(arr[1],tmp)==0){//起始地址,排序个数,每个元素大小,比较方法qsort(ps->data,ps->sz,sizeof(ps->data[0]),cmp_age);}if(strcmp(arr[2],tmp)==0){//起始地址,排序个数,每个元素大小,比较方法qsort(ps->data,ps->sz,sizeof(ps->data[0]),cmp_sex);}if(strcmp(arr[3],tmp)==0){//起始地址,排序个数,每个元素大小,比较方法qsort(ps->data,ps->sz,sizeof(ps->data[0]),cmp_tele);}if(strcmp(arr[4],tmp)==0){//起始地址,排序个数,每个元素大小,比较方法qsort(ps->data,ps->sz,sizeof(ps->data[0]),cmp_addr);}printf('排序成功\n');}

voidCleanContact(Contact*ps){if(ps->sz==0){printf('通讯录已为空,无需清除\n');return;}memset(ps->data,0,ps->sz);ps->sz=0;printf('清除成功\n');}

7)清空联系人列表

voidCleanContact(Contact*ps){if(ps->sz==0){printf('通讯录已为空,无需清除\n');return;}memset(ps->data,0,ps->sz);ps->sz=0;printf('清除成功\n');}

(8)保存当前的联系人信息到本地磁盘中

保存信息也就是写入文件。

voidSaveContact(Contact*ps){assert(ps);size_tcount=0;if(ps->sz==0){printf('无要保存的联系人\n');return;}FILE*pfwrite=fopen('Contact.txt','wb');//以二进制形式写入if(pfwrite==NULL){printf('SaveContact:%s\n',strerror(errno));}for(inti=0;isz;i++){count=fwrite(&(ps->data[i]),sizeof(ps->data[0]),1,pfwrite);//size_tfwrite(constvoid*buffer,size_tsize,size_tcount,FILE*stream);}if(ps->sz==(int)count){printf('所有联系人全部保存成功\n');}else{printf('保存了%zd个联系人',count);}fclose(pfwrite);pfwrite=NULL;}

所有函数的声明

//初始化通讯录voidInitContact(Contact*ps);//增加联系人信息voidAddContact(Contact*ps);//展示联系人信息voidShowContact(constContact*ps);//删除联系人信息voidDelContact(Contact*ps);//搜索联系人信息voidSearchContact(constContact*ps);//修改联系人信息voidModifyContact(Contact*ps);//对联系人进行排序voidSortContact(Contact*ps);//清空联系人voidCleanContact(Contact*ps);//退出时销毁通讯录voidDestroyContact(Contact*ps);//保存通讯录信息voidSaveContact(Contact*ps);

头文件如下:

#include#include#include#include#include

完整代码如下:

Contact.h项目文件

#define_CRT_SECURE_NO_WAR#define_CRT_SECURE_NO_WARNINGS1#include#include#include#include#include#defineMAX100#defineNAME_MAX20#defineSEX_MAX5#defineTELE_MAX12#defineADDR_MAX30#defineCAPACITY_SIZE3//个人信息typedefstructPeoInfo{charname[NAME_MAX];intage;charsex[SEX_MAX];chartele[TELE_MAX];charaddr[ADDR_MAX];}PeoInfo;//整个通讯录信息typedefstructContact{PeoInfo*data;intsz;intcapacity;}Contact;//初始化通讯录voidInitContact(Contact*ps);//增加联系人信息voidAddContact(Contact*ps);//展示联系人信息voidShowContact(constContact*ps);//删除联系人信息voidDelContact(Contact*ps);//搜索联系人信息voidSearchContact(constContact*ps);//修改联系人信息voidModifyContact(Contact*ps);//对联系人进行排序voidSortContact(Contact*ps);//清空联系人voidCleanContact(Contact*ps);//退出时销毁通讯录voidDestroyContact(Contact*ps);//保存通讯录信息voidSaveContact(Contact*ps);enum{Exit,//0Add,//1Del,//2Search,//3Modify,//4Show,//5Sort,//6Clean,//7Save//8};

Contact.c项目文件如下:

#include'Contact.h'//检查容量voidCheckCapacity(Contact*ps){assert(ps);if(ps->sz==ps->capacity){//扩容PeoInfo*ptr=realloc(ps->data,sizeof(PeoInfo)*(2+ps->capacity));//一次扩容两个if(ptr==NULL){printf('%s\n',strerror(errno));printf('增容失败\n');}else{ps->data=ptr;ps->capacity+=2;printf('增容成功\n');}}}//加载联系人信息voidLoadContact(Contact*ps){assert(ps);FILE*pfread=fopen('Contact.txt','rb');//二进制形式读取PeoInfotmp={0};//把读取的联系人先放着,先判断容量够不够,再放进data里if(pfread==NULL){printf('LoadContact:%s\n',strerror(errno));}else{//size_tfread(void*buffer,size_tsize,size_tcount,FILE*stream);while(fread(&tmp,sizeof(PeoInfo),1,pfread)){CheckCapacity(ps);//判断容量够不够ps->data[ps->sz]=tmp;ps->sz++;}}fclose(pfread);pfread=NULL;}//初始化通讯录voidInitContact(Contact*ps){assert(ps);ps->data=(PeoInfo*)malloc(sizeof(PeoInfo)*CAPACITY_SIZE);if(ps->data==NULL){printf('%s\n',strerror(errno));}ps->capacity=CAPACITY_SIZE;ps->sz=0;LoadContact(ps);//从上次保存的文件中加载联系人信息出来//memset(ps->data,0,sizeof(ps->data));//ps->sz=0;}voidAddContact(Contact*ps){assert(ps);CheckCapacity(ps);printf('请输入姓名:>\n');scanf('%s',ps->data[ps->sz].name);printf('请输入年龄:>\n');scanf('%d',&ps->data[ps->sz].age);printf('请输入性别:>\n');scanf('%s',ps->data[ps->sz].sex);printf('请输入电话:>\n');scanf('%s',ps->data[ps->sz].tele);printf('请输入住址:>\n');scanf('%s',ps->data[ps->sz].addr);ps->sz++;printf('添加成功\n');}staticintFindByName(constContact*ps){assert(ps);charname[NAME_MAX]={0};scanf('%s',name);for(inti=0;isz;i++){if(strcmp(ps->data[i].name,name)==0){returni;}}return-1;}voidDelContact(Contact*ps){assert(ps);printf('请输入要删除的人的名字:>\n');intpos=FindByName(ps);if(pos==-1){printf('要删除的人不存在\n');return;}//删除也就是向前覆盖即可for(inti=pos;isz-1;i++){ps->data[i]=ps->data[i+1];}ps->sz--;printf('删除成功\n');}voidSearchContact(constContact*ps){assert(ps);printf('请输入要查找的人的名字:>\n');intpos=FindByName(ps);if(pos==-1){printf('要查找的人不存在\n');return;}printf('%-20s\t%-4s\t%-5s\t%-12s\t%-30s\n','姓名','年龄','性别','电话','住址');printf('%-20s\t%-4d\t%-5s\t%-12s\t%-30s\n',ps->data[pos].name,ps->data[pos].age,ps->data[pos].sex,ps->data[pos].tele,ps->data[pos].addr);}voidModifyContact(Contact*ps){assert(ps);printf('请输入要修改的人的名字:>\n');intpos=FindByName(ps);if(pos==-1){printf('要修改的人不存在\n');return;}printf('请输入姓名:>\n');scanf('%s',ps->data[pos].name);printf('请输入年龄:>\n');scanf('%d',&ps->data[pos].age);printf('请输入性别:>\n');scanf('%s',ps->data[pos].sex);printf('请输入电话:>\n');scanf('%s',ps->data[pos].tele);printf('请输入住址:>\n');scanf('%s',ps->data[pos].addr);printf('修改成功\n');}voidShowContact(constContact*ps){assert(ps);if(ps->sz==0){printf('通讯录为空\n');return;}printf('%-20s\t%-4s\t%-5s\t%-12s\t%-30s\n','姓名','年龄','性别','电话','住址');for(inti=0;isz;i++){printf('%-20s\t%-4d\t%-5s\t%-12s\t%-30s\n',ps->data[i].name,ps->data[i].age,ps->data[i].sex,ps->data[i].tele,ps->data[i].addr);}}intcmp_name(constvoid*e1,constvoid*e2){returnstrcmp(((PeoInfo*)e1)->name,((PeoInfo*)e2)->name);}intcmp_age(constvoid*e1,constvoid*e2){return((PeoInfo*)e1)->age-((PeoInfo*)e2)->age;}intcmp_sex(constvoid*e1,constvoid*e2){returnstrcmp(((PeoInfo*)e1)->sex,((PeoInfo*)e2)->sex);}intcmp_tele(constvoid*e1,constvoid*e2){returnstrcmp(((PeoInfo*)e1)->tele,((PeoInfo*)e2)->tele);}intcmp_addr(constvoid*e1,constvoid*e2){returnstrcmp(((PeoInfo*)e1)->addr,((PeoInfo*)e2)->addr);}voidSortContact(Contact*ps){assert(ps);chartmp[5]={0};printf('请输入要排序的种类:>\n');printf('(姓名,年龄,性别,电话,住址)\n');scanf('%s',tmp);char*arr[5]={'姓名','年龄','性别','电话','住址'};if(strcmp(arr[0],tmp)==0){//起始地址,排序个数,每个元素大小,比较方法qsort(ps->data,ps->sz,sizeof(ps->data[0]),cmp_name);}if(strcmp(arr[1],tmp)==0){//起始地址,排序个数,每个元素大小,比较方法qsort(ps->data,ps->sz,sizeof(ps->data[0]),cmp_age);}if(strcmp(arr[2],tmp)==0){//起始地址,排序个数,每个元素大小,比较方法qsort(ps->data,ps->sz,sizeof(ps->data[0]),cmp_sex);}if(strcmp(arr[3],tmp)==0){//起始地址,排序个数,每个元素大小,比较方法qsort(ps->data,ps->sz,sizeof(ps->data[0]),cmp_tele);}if(strcmp(arr[4],tmp)==0){//起始地址,排序个数,每个元素大小,比较方法qsort(ps->data,ps->sz,sizeof(ps->data[0]),cmp_addr);}printf('排序成功\n');}voidCleanContact(Contact*ps){if(ps->sz==0){printf('通讯录已为空,无需清除\n');return;}memset(ps->data,0,ps->sz);ps->sz=0;printf('清除成功\n');}voidDestroyContact(Contact*ps){free(ps->data);ps->data=NULL;printf('销毁成功\n');}voidSaveContact(Contact*ps){assert(ps);size_tcount=0;if(ps->sz==0){printf('无要保存的联系人\n');return;}FILE*pfwrite=fopen('Contact.txt','wb');//以二进制形式写入if(pfwrite==NULL){printf('SaveContact:%s\n',strerror(errno));}for(inti=0;isz;i++){count=fwrite(&(ps->data[i]),sizeof(ps->data[0]),1,pfwrite);//size_tfwrite(constvoid*buffer,size_tsize,size_tcount,FILE*stream);}if(ps->sz==(int)count){printf('所有联系人全部保存成功\n');}else{printf('保存了%zd个联系人',count);}fclose(pfwrite);pfwrite=NULL;}

test.c项目文件如下:

#include'Contact.h'voidmenu(void){printf('*******************************\n');printf('******1.Add2.Del******\n');printf('******3.Search4.Modify******\n');printf('******5.Show6.Sort******\n');printf('******7.Clean8.Save******\n');printf('******0.Exit******\n');printf('*******************************\n');}intmain{intinput=0;//创建通讯录Contactcon;//初始化通讯录InitContact(&con);do{menu;printf('请选择:>\n');scanf('%d',&input);switch(input){caseExit:SaveContact(&con);//退出时自动保存printf('在您退出通讯录时,已自动为您保存\n');DestroyContact(&con);//退出时销毁通讯录printf('退出通讯录\n');break;caseAdd:AddContact(&con);break;caseDel:DelContact(&con);break;caseSearch:SearchContact(&con);break;caseModify:ModifyContact(&con);break;caseShow:ShowContact(&con);break;caseSort:SortContact(&con);break;caseClean:CleanContact(&con);break;caseSave:SaveContact(&con);break;default:printf('选择错误,请重新选择:>\n');break;}}while(input);return0;}

小编想说的话

在实现通讯录的功能时,还有诸多不够完善的地方,以上通讯录系统是小编花好些时间一点点封装出来的,如有bug,欢迎在评论区指正!谢谢呀。

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
一个定长版本的通讯录c语言实现
[问题求助]fflush(stdin)的用法? — 编程爱好者论坛 bbs.program...
多记记吧、、、
C语言解二元一次方程
通讯录系统部分代码
C语言实现通讯录的录入与显示,基础编程由此开始(第三十一节)
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服