目录
动态通讯录的实现
一、实验的目的和意义
1、巩固和加深对C语言知识的理解
2、学会使用编译器的各种调试
3、提高解决实际问题的能力
二、实验内容描述
通讯录,是用来存放联系人的信息,它在如今电子信息发展的社会中是不可或缺的。联系人的信息主要包括名字、性别、年龄、地址等。
本次课程设计使用C语言来实现通讯录,正常的通讯录应具备以下主要功能:
增:增加联系人
删:删除联系人
查:查找联系人
改:修改联系人的某项信息
显示:显示通讯录所有联系人的信息
排序:对通讯录中的联系人进行排序
三、功能描述
通讯录的主要功能为增加联系人、删除联系人、查找联系人、修改联系人的信息等等
下面具体描述各功能的作用:
1、增加:可以添加联系人,其信息主要包括名字、性别、年龄、电话、地址
2、删除:输入想要删除联系人的名字进行删除,联系人查找存在且删除后则提示删除成功,联系人查找不存在则提示要删除的联系人不存在,或者通讯录为空则输出通讯录已空,无法删除
3、查找:输入想要查找的联系人的名字,联系人存在则打印出联系人的全部信息,否则提示联系人不存在
4、修改:输入想要修改联系人信息的名字,先对联系人查找,联系人存在则对需要修改的信息进行修改,联系人不存在则显示联系人不存在
5、显示:显示通讯录所有联系人的信息
6、排序:对通讯录中的联系人按名字、年龄进行排序,并且显示排序后通讯录中的联系人
四、数据结构
文件名 作用 DynamicContact.h 通讯录的函数声明、头文件声明及各种声明 DynamicContact.c 通讯录函数接口的实现 test.c 通讯录函数功能测试
1、三大模块
通讯录大致分为三大模块,详情如下:
2、结构设计
定义一个结构体 PeoInfo ,结构体包括名字、性别、年龄、电话、地址,另一个结构体 Contact 嵌套着 PeoInfo 这个结构体,用于创建通讯录,类似于顺序表。
3、动态开辟
typedefstructPeoInfo{ charname[NAME_MAX]; charsex[SEX_MAX]; intage; chartele[TELE_MAX]; charaddr[ADDR_MAX]; }PeoInfo; typedefstructContact{ PeoInfo*data;//存放联系人的信息intcount;//通讯录中已经保存的信息个数intcapacity;//记录通讯录当前的最大容量}Contact;
3、动态开辟
1、通讯录的联系人可以用数组储存,但是考虑到空间浪费的问题,就要对需要空间的多少进行动态开辟。
1、通讯录的联系人可以用数组储存,但是考虑到空间浪费的问题,就要对需要空间的多少进行动态开辟。
1、通讯录的联系人可以用数组储存,但是考虑到空间浪费的问题,就要对需要空间的多少进行动态开辟。
比如用数组进行储存,开辟了1000个空间,但实际上只用了10个空间,剩余的空间就会造成很大大的浪费。
但是使用动态开辟空间,需要多大的空间就开辟出多大的空间,对开辟的空间不会造成很大的浪费。
这时候就要动态内存函数,通讯录中使用 malloc 函数和 realloc 函数。
2、两个内存函数的区别,想了解详细的可以去 C++ 官网查阅。
C++ 官网:
4、文件操作
通讯录结束运行后,存储好的联系人的信息也随之销毁了。
我们想要在程序结束运行后,联系人的信息依旧保存,这时候就要运用C语言文件操作相关的知识,在程序结束运行之前把联系人保存在一个文件中,这样联系人的信息就可以存储不被销毁。
通讯录数据以二进制的方式储存。
通讯录代码中使用如下两个:
如图:contact.data 就是通讯录退出程序前保留的数据
5、主要函数
//初始化通讯录 void InitContact(Contact* p); //销毁通讯录 void DestroyContact(Contact* p); //添加联系人 void AddContact(Contact* p); //删除联系人 void DelContact(Contact* p); //查找联系人 void SearchContact(const Contact* p); //修改联系人信息 void ModifyContact(Contact* p); //打印联系人 void PrintContact(const Contact* p); //排序 void SortContact(const Contact* p); //保存通讯录的信息到文件 void SaveContact(const Contact* pc); //加载文件信息到通讯录中 void LoadContact(Contact* p);
五、流程图及模块算法
1.Contacct 程序运行流程图
2、AddContct(增加)函数流程图
3、DelContct(删除)函数流程图
4、SearchContct(查找)函数流程图
5、ModifyContct(修改)函数流程图
6、SortContct(排序)函数流程图
画流程图使用的工具
六、实验测试结果
声明一点,请输入字符,不要输入中文
1、通讯录代码正常运行
2、进行添加联系人,正常运行
3、对联系人进行删除,正常运行
4、对联系人进行修改,正常运行
5、对联系人进行排序,正常运行
七、实验总结
本次课程设计我选择的是设计通讯录管理系统。
总的来说,这次的课程设计使我体会较大的是应用比理论学习难得多,它涉及到各种实际问题,但是也加深了我对知识的理解和运用,也深知只有多写代码、练习等才能写出一个好的程序。
1、在代码方面,所有代码运行都没有问题,就排序函数无法运行,进行排序程序就会崩掉,进行一个下午的调试才找到代码误
进行排序就崩掉,显示 0xC0000005: 读取位置 xxx时发生访问冲突
看到错误提示,我已经想到指针发生越界了,调试一下午才找到错误,如图
2、
这次课程设计也是一次很好的对自我检查,让我知道哪一个方面存在不足,对知识的了解还不够深入,对一些学过的知识没有很好的掌握。
3、
在编写代码时需要小心谨慎,否则就会写出很多的 bug。在调试上,这次课程设计加强了我对代码的调试能力。
八、源代码
源代码 gitee 上也有,需要的可以自行查看
链接
https://gitee.com/Maple_fylqh/code/tree/master/code_c/DynamicContact/DynamicContact
1、DynamicContact.h
//vs 编译器需要,其他编译器不需要,可自行删去//动态版通讯录//类型声明//PeoInit结构体所用//通讯录初始状态的容量大小//枚举选项enumOption//test函数所用的枚举{ EXIT, ADD, DEL, SEARCH, MODIFY, SORT, PRINT}; enumModify//修改联系人所用的枚举{ EXIT0, NAME, SEX, AGE, TELE, ADDR}; //结构体声明typedefstructPeoInfo{ charname[NAME_MAX]; charsex[SEX_MAX]; intage; chartele[TELE_MAX]; charaddr[ADDR_MAX]; }PeoInfo; typedefstructContact{ PeoInfo*data;//存放联系人的信息intcount;//通讯录中已经保存的信息个数intcapacity;//记录通讯录当前的最大容量}Contact; //函数声明//初始化通讯录voidInitContact(Contact*p); //销毁通讯录voidDestroyContact(Contact*p); //添加联系人voidAddContact(Contact*p); //删除联系人voidDelContact(Contact*p); //查找联系人voidSearchContact(constContact*p); //修改联系人信息voidModifyContact(Contact*p); //打印联系人voidPrintContact(constContact*p); //排序voidSortContact(constContact*p); //保存通讯录的信息到文件voidSaveContact(constContact*pc); //加载文件信息到通讯录中voidLoadContact(Contact*p);
2、DynamicContact.c
//排序所用菜单voidmenu2() { printf("********************************\n"); printf("****** 1.name 2.age ******\n"); printf("****** 0.exit ******\n"); printf("********************************\n"); } //修改联系人所用的菜单voidmenu1() { printf("********************************\n"); printf("****** 1.name 2.sex ******\n"); printf("****** 3.age 4.tele ******\n"); printf("****** 5.addr 0.exit ******\n"); printf("********************************\n"); } //检测通讯录容量voidCheckCapacity(Contact*p) { assert(p); if (p->capacity==p->count) { PeoInfo*tmp= (PeoInfo*)realloc(p->data, (p->capacity+2) *sizeof(PeoInfo)); if (p->data!=NULL) { p->data=tmp; } else { perror("CheckCapacity::realloc"); return; } p->capacity+=2; printf("增容成功\n"); } } //初始化通讯录voidInitContact(Contact*p) { assert(p); p->count=0; p->capacity=DEFAULT_SZ; p->data= (PeoInfo*)malloc(p->capacity*sizeof(PeoInfo)); if (p->data==NULL) { perror("InitContact::malloc"); return; } memset(p->data, 0, p->capacity*sizeof(PeoInfo));//把PeoInit全部初始化为0//加载文件信息到通讯录中LoadContact(p); } //销毁通讯录voidDestroyContact(Contact*p) { free(p->data); p->data=NULL; p->capacity=0; p->count=0; printf("销毁成功\n"); } //添加联系人voidAddContact(Contact*p) { //检查容量CheckCapacity(p); //录入信息printf("请输入名字:>"); scanf("%s", p->data[p->count].name); printf("请输入性别:>"); scanf("%s", p->data[p->count].sex); printf("请输入年龄:>"); scanf("%d", &(p->data[p->count].age)); printf("请输入电话:>"); scanf("%s", p->data[p->count].tele); printf("请输入地址:>"); scanf("%s", p->data[p->count].addr); p->count++; printf("添加成功\n\n"); } //查找,找到了返回下标,找不到返回 -1intFindName(constContact*p, charname[]) { assert(p); inti=0; for (i=0; i<p->count; i++) { if (0==strcmp(p->data[i].name, name)) { returni; } } return-1; } //删除联系人voidDelContact(Contact*p) { assert(p); if (0==p->count) { printf("通讯录已空,无法删除\n"); return; } charname[NAME_MAX]; printf("请输入要查找的名字:>"); scanf("%s", name); intposition=FindName(p, name);//查找if (-1==position) { printf("要删除的联系人不存在\n\n"); return; } //删除inti=0; for (i=position; i<p->count-1; i++) { p->data[i] =p->data[i+1]; } p->count--; printf("删除成功\n\n"); } //查找联系人voidSearchContact(constContact*p) { assert(p); charname[NAME_MAX]; printf("请输入要查找的名字:>"); scanf("%s", name); intposition=FindName(p, name);//查找if (-1==position) { printf("要查找的联系人不存在\n\n"); return; } printf("\n-----------------------------------------------\n"); printf("%-10s %-5s %-5s %-12s %-30s\n", "姓名", "性别", "年龄", "电话", "地址"); printf("%-10s %-5s %-5d %-12s %-30s\n", p->data[position].name, p->data[position].sex, p->data[position].age, p->data[position].tele, p->data[position].addr); printf("\n-----------------------------------------------\n\n"); } //修改联系人信息voidModifyContact(Contact*p) { assert(p); intintput=0; charname[NAME_MAX]; printf("请输入要修改联系人的名字:>"); scanf("%s", name); intposition=FindName(p, name);//查找if (-1!=position) { printf("\n-----------------------------------------------\n"); printf("%-10s %-5s %-5s %-12s %-30s\n", "姓名", "性别", "年龄", "电话", "地址"); printf("%-10s %-5s %-5d %-12s %-30s\n", p->data[position].name, p->data[position].sex, p->data[position].age, p->data[position].tele, p->data[position].addr); printf("\n-----------------------------------------------\n\n"); do { menu1(); printf("请输入要修改的选项:>"); scanf("%d", &intput); switch (intput) { caseNAME: printf("请修改名字:>"); scanf("%s", p->data[position].name); printf("修改成功\n\n"); break; caseSEX: printf("请修改性别:>"); scanf("%s", p->data[position].sex); printf("修改成功\n\n"); break; caseAGE: printf("请修改年龄:>"); scanf("%d", &(p->data[position].age)); printf("修改成功\n\n"); break; caseTELE: printf("请修改电话号码:>"); scanf("%s", p->data[position].tele); printf("修改成功\n\n"); break; caseADDR: printf("请修改地址:>"); scanf("%s", p->data[position].addr); printf("修改成功\n\n"); break; caseEXIT0: printf("退出修改\n\n"); break; default: printf("选择错误,请重新选择\n\n"); break; } } while (intput); } else { printf("所要修改的联系人不存在\n\n"); return; } } //打印联系人voidPrintContact(constContact*p) { assert(p); inti=0; printf("\n-----------------------------------------------\n"); printf("%-10s %-5s %-5s %-12s %-30s\n", "姓名", "性别", "年龄", "电话", "地址"); for (i=0; i<p->count; i++) { printf("%-10s %-5s %-5d %-12s %-30s\n", p->data[i].name, p->data[i].sex, p->data[i].age, p->data[i].tele, p->data[i].addr); } printf("-----------------------------------------------\n\n"); } intcmp_name(constvoid*e1, constvoid*e2) { returnstrcmp(((structPeoInfo*)e1)->name, ((structPeoInfo*)e2)->name); } intcmp_age(constvoid*e1, constvoid*e2) { return (((structPeoInfo*)e1)->age- ((structPeoInfo*)e2)->age); } //排序voidSortContact(constContact*p) { assert(p); intintput=0; do { menu2(); printf("请选择需要排序的选项:>"); scanf("%d", &intput); switch (intput) { case1: qsort(p->data, p->count, sizeof(structPeoInfo), cmp_name); printf("按名字排序成功\n\n"); break; case2: qsort(p->data, p->count, sizeof(structPeoInfo), cmp_age); printf("按年龄排序成功\n\n"); break; case0: printf("退出排序\n\n"); break; default: printf("选择错误,请重新选择\n\n"); break; } } while (intput); } //保存通讯录的信息到文件voidSaveContact(constContact*p) { //打开并创建文件FILE*pf=fopen("contact.data.txt", "w");//w:只写,if (pf==NULL) { perror("SaveContact::fopen"); return; } //写文件inti=0; for (i=0; i<p->count; i++) { fwrite(p->data+i, sizeof(PeoInfo), 1, pf); } //关闭文件fclose(pf); pf=NULL; } //加载文件信息到通讯录中voidLoadContact(Contact*p) { //打开文件FILE*pf=fopen("contact.data.txt", "r");//r:只读if (pf==NULL) { perror("LoadContact::fopen"); return; } //读文件PeoInfotmp= { 0 }; while (fread(&tmp, sizeof(PeoInfo), 1, pf)) { CheckCapacity(p); p->data[p->count] =tmp; p->count++; } //关闭文件fclose(pf); pf=NULL; }
3、test.c
voidmenu() { printf("================================\n"); printf("*********** Contact ************\n"); printf("================================\n"); printf("*** 1.add 2.del ***\n"); printf("*** 3.search 4.modify ***\n"); printf("*** 5.sort 6.print ***\n"); printf("*** 0.exit ***\n"); printf("================================\n"); } voidtest() { intintput=0; Contactcon;//创建通讯录InitContact(&con);//初始化通讯录do { menu(); printf("请选择:>"); scanf("%d", &intput); switch (intput) { caseADD: AddContact(&con); break; caseDEL: DelContact(&con); break; caseSEARCH: SearchContact(&con); break; caseMODIFY: ModifyContact(&con); break; caseSORT: SortContact(&con); break; casePRINT: PrintContact(&con); break; caseEXIT: SaveContact(&con);//销毁通讯录之前把数据存入文件中DestroyContact(&con); printf("退出通讯录\n"); break; default: printf("输入错误,请重新输入\n\n"); break; } } while (intput); } intmain() { test(); return0; }
最后
文章到这就结束了,希望对你有帮助,觉得文章不错就点个赞吧。
文章有什么问题可以留言,感谢支持!!