C语言链表实现通讯录系统课程设计
作者:洞·爺·湖
本文实例为大家分享了C语言链表实现通讯录系统的具体代码,供大家参考,具体内容如下
流程图
概要设计
1、数据结构
选择单链表来完成所有操作,便于插入和删除,不利于排序。
2、程序模块
共11个模块,分别是主函数模块实现操作指令和10个子函数模块,分别是主菜单界面、新建联系人、浏览所有联系人、修改联系人信息、删除联系人、查找联系人信息、插入联系人、保存联系人信息(写入文件)、读取文件信息、对所有联系人按照姓名进行字典序排序。
详细设计
1、数据类型定义
定义了一个结构体类型PHONE变量,内部有五个字符数组和一个整型变量分别存放——name(姓名)、home(籍贯)、phone1(电话号码1)、phone2(电话号码2)、email(电子邮箱)、sign(防止重名的标记,只作用于相互重名的人),还有一个PHONE类型的指针作为next域形成链表。此外还有一个全局变量PHONE类型的指针head作为链表的头指针。
2、各个模块的详细实现
2.1 新建联系人
执行这个模块的前提是没有检测到“通讯录”这个文件,那么需要进行新建通讯录,实际实现就是尾插法创建链表,唯一需要注意的是如何停止输入返回操作指令界面,这里才用在输入姓名栏那里输入“over”来结束新建通讯录操作,同时会提示操作者进行保存录入文件。
2.2 浏览所有联系人
这个模块的作用主要是随时能够查看所有联系人的信息,在每一次操作指令完成后,调用这个模块就可以很清晰的看到变化,具体实现只需要利用之前设定的头指针传进来一个副本,然后遍历一遍循环输出即可,利用\t和\n调一下格式就行。
2.3 修改联系人信息
顾名思义这个模块是用于修改指定联系人的某个信息,操作者输入要修改的人的姓名和序号后,通过遍历链表和strcmp函数,找到指定联系人之后让操作者输入操作指令来表示自己要修改哪一项信息,然后输入修改后的信息即可。
2.4 查找联系人信息
这个模块用于查找指定的联系人信息,这里分为按姓名查找和按姓氏查找,查找本身的运作原理都一样,遍历链表,利用strcmp函数比较,输出所有满足该姓名或该姓氏的人的信息即可,唯一要注意的是在按照姓氏查找时可能会输入单姓也可能会输入复姓,所以这里要加个判断,判断完后的操作分支都大同小异,如果查找不到那么就输出查无此人,。
2.5 删除联系人
这个模块用于删除某个指定联系人的所有信息,在操作者输入完姓名后,遍历整个链表,利用strcmp函数输出所有满足该条件的人,然后再让操作者输入序号,即删除哪个该姓名的人,之后只需执行单链表的基本删除操作模板即可,如果没有找到操作者输入的人,那么输出查无此人。
2.6 添加联系人
这个模块用于添加联系人信息,在让操作者输入完要添加的联系人的所有信息后,会有一个很重要的防重名操作,更新要插入的人的序号sign,在插入指定位置前,先定义一个整型变量max赋初值为0,然后把链表遍历一遍,将目前与他重名的最大值赋值给max,最后将max+1赋值给要插入进来的人序号上,保证了重名的存在。之后会有三个选项——首位置插入、尾位置插入和指定姓名前插入,分别对应链表插入的两个特例和一个一般,与之不同的时,指定姓名插入也包含了首位置和尾位置,所以在这个操作内部还需要再分支实现,如果没有找到操作者输入的姓名那么便输出查无此人。
2.7 保存联系人
这个模块的作用是将信息写入文件保存,利用FILE创建一个文件指针,然后通过fopen的只写方式打开,如果打不开可能是内存不够等原因无法创建文件(一般没这种情况),打开后遍历链表利用fprintf写入所有信息即可,\t和\n用于调整格式,最后用fclose关闭文件。
2.8 读取联系人
这个模块在主菜单上并没有显示出来,他在刚开始便执行了,先通过fopen的只读方式打开,如果打不开就代表不存在“通讯录这个文件”,此时便提示操作者要新建联系人。若能打开便先利用feof遍历文件,然后利用fscanf读取信息,尾插法建立单链表和新建过程大同小异。
2.9 对所有联系人按名字进行字典序排序
这里的名字可以是中文也可以是英文,中文切换到GB 2312简体中文编码方式便一样可以通过strcmp函数进行比较,才用的排序算法是冒泡排序,因为是单链表,无法采用更高级的排序算法,唯一一个需要注意点的是,在交换过程中只交换数据域,由于在数据定义过程中没有单独定义数据域的结构体,所以需要一个个交换,不能整体交换结构体的值,否则next域就乱了,如果存在同名现象,采取序号更小的放到前面。
2.10 主菜单界面
利用多个printf打造了一个主菜单函数,将它单独作为一个模块是因为,如果操作者执行的操作比较多可以输入相应的操作指令再显示菜单,而不是每次都划上去看。
2.11 主函数
主函数首先执行了一个color函数来调整背景色和字体颜色,通过查找资料知道,0是底黑色,E是字体淡黄色。然后调用主菜单模块与读取联系人模块,然后定义一个整型变量a,通过while循环不断输入a然后利用swtich检测a,来执行不同的操作。
c代码:
#include<stdio.h> #include<string.h> #include<malloc.h> #include<stdlib.h> #include<windows.h> #define len sizeof(phone) typedef struct PHONE { char name[20]; char home[40]; char phone1[20]; char phone2[20]; char email[25]; int sign; struct PHONE *next; }phone; phone *head; void mainmenuface() { printf("欢迎来到我们的通讯录系统!!!\n"); printf("★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆\n"); printf("☆********************************************************************★\n"); printf("★ 通讯录管理系统 ☆\n"); printf("☆ ★\n"); printf("★ 1.新建联系人信息 2.浏览所有联系人 ☆\n"); printf("☆ ★\n"); printf("★ 3.修改联系人信息 4.查找联系人信息 ☆\n"); printf("☆ ★\n"); printf("★ 5.保存联系人信息 6.添加联系人信息 ☆\n"); printf("☆ ★\n"); printf("★ 7.删除联系人信息 8.返回主菜单 ☆\n"); printf("☆ ★\n"); printf("☆ 9.对通讯录名单按字典序排序 ★\n"); printf("☆********************************************************************★\n"); printf("★ 输入0退出系统 ☆\n"); printf("★ 进行完任意一组操作后记得按5保存 ☆\n"); printf("☆ ------------------------------------------- ★\n"); }//主菜单 void show_one(phone *p) { printf("姓名:%s\t\t",p->name); printf("序号:%d\n",p->sign); printf("籍贯:%s\t",p->home); printf("电话号码1:%s\t",p->phone1); printf("电话号码2:%s\t",p->phone2); printf("电子邮箱:%s\n",p->email); } phone *Lookdata(phone *p1) { phone *p2; p2=head; printf("\n\t\t\t☆☆☆显示数据☆☆☆\n"); printf("----------------------------------------------------------------------\n"); while(p2!=NULL){ printf("姓名:%s\t\t",p2->name); printf("序号:%d\n",p2->sign); printf("籍贯:%s\t",p2->home); printf("电话号码1:%s\t",p2->phone1); printf("电话号码2:%s\t",p2->phone2); printf("电子邮箱:%s\t",p2->email); printf("\n\n"); printf("----------------------------------------------------------------------\n"); p2=p2->next; } return p2; } phone *Inputdata(){ phone*p1,*p2; int flag=1; int k=1,i=1; p1=p2=(phone*)malloc(len); head=NULL; printf("\n\t\t\t☆☆☆新建联系人信息☆☆☆\n"); if(p1!=NULL){ head=p1; while(flag){ printf("----------------------------------------------------------------------\n"); printf("请输入要录入联系人的姓名(姓名一栏中输入over结束建立联系人操作并返回操作指令)\n"); scanf("%s",p1->name); if(strcmp(p1->name,"over")!=0) { printf("请输入要录入联系人的序号(防重名,做标记)\n"); scanf("%d",&p1->sign); getchar(); printf("请输入要录入联系人的籍贯\n"); scanf("%s",p1->home); printf("请输入要录入联系人的电话1(没有可输入“无”)\n"); scanf("%s",p1->phone1); printf("请输入要录入联系人的电话2(没有可输入“无”)\n"); scanf("%s",p1->phone2); printf("请输入要录入联系人的电子邮箱(没有可输入“无”)\n"); scanf("%s",p1->email); p2->next=p1; p2=p1; p1=(phone*)malloc(len); p1->next=NULL; printf("----------------------------------------------------------------------\n"); } else { flag=0; p1->next=NULL; free(p1); printf("-----------------输入成功!退出时勿忘输入5保存信息!------------------\n"); printf("----------------------------------------------------------------------\n"); } } } return (head); } void readfile(){ FILE *fp; phone *p1,*p2,*p3; p1=p2=(phone*)malloc(len); int flag=1; head=NULL; if((fp=fopen("通讯录","r"))==NULL) { printf("未建立通讯录,请输入1新建联系人!\n"); } else { if(p1!=NULL)head=p1; while(1) { if(!feof(fp)) { fscanf(fp,"%s%d%s%s%s%s",p1->name,&p1->sign,p1->home,p1->phone1,p1->phone2,p1->email); p2->next=p1; p3=p2; p2=p1; p1=(phone*)malloc(len); } else { p3->next=NULL; break; } } } fclose(fp); } void Seek(phone *p2) { char name[20]; char ch1[10], ch2[10]; memset(ch1,'\0',sizeof(ch1)); memset(ch2,'\0',sizeof(ch2)); int b; int n; printf("\n\t\t\t☆☆☆查找数据☆☆☆\n"); printf("----------------------------------------------------------------------\n"); printf("---------------------------按姓名请输入1:-----------------------------\n"); printf("---------------------------按姓氏请输入2:-----------------------------\n"); printf("请输入您的选择:"); scanf("%d",&n); getchar(); printf("请输入需要查找的姓名:"); switch(n) { case 1: b=0; scanf("%s",name); while(p2!=NULL) { if(strcmp(name,p2->name)==0) { printf("你要找到的数据\n"); printf("姓名:%s\t\t",p2->name); printf("序号:%d\n",p2->sign); printf("籍贯:%s\t",p2->home); printf("电话号码1:%s\t",p2->phone1); printf("电话号码2:%s\t",p2->phone2); printf("电子邮箱:%s\n",p2->email); printf("----------------------------------------------------------------------\n"); b=1; } p2=p2->next; } if(b==0) { printf("\n--------------------您要查找的人不存在!--------------------------------\n"); } break; case 2: b=0; printf("请输入姓:"); scanf("%s",ch1); while(p2!=NULL) { if(strlen(ch1)==2) { strncpy(ch2,p2->name,2); if(strcmp(ch1,ch2)==0) { printf("你要找到的数据\n"); printf("姓名:%s\t\t",p2->name); printf("序号:%d\n",p2->sign); printf("籍贯:%s\t",p2->home); printf("电话号码1:%s\t",p2->phone1); printf("电话号码2:%s\t",p2->phone2); printf("电子邮箱:%s\n",p2->email); printf("----------------------------------------------------------------------\n"); b=1; } p2=p2->next; } if(strlen(ch1)==4) { strncpy(ch2,p2->name,4); if(strcmp(ch1,ch2)==0) { printf("你要找到的数据\n"); printf("姓名:%s\t\t",p2->name); printf("序号:%d\n",p2->sign); printf("籍贯:%s\t",p2->home); printf("电话号码1:%s\t",p2->phone1); printf("电话号码2:%s\t",p2->phone2); printf("电子邮箱:%s\n",p2->email); printf("----------------------------------------------------------------------\n"); b=1; } p2=p2->next; } } if(b==0) { printf("\n--------------------您要查找的姓不存在!--------------------------------\n"); } } } void Keepdata(phone*p2) { FILE *fp; printf("\n\t\t\t☆☆☆保存数据☆☆☆\n"); printf("----------------------------------------------------------------------\n"); if((fp=fopen("通讯录","w"))==NULL) { printf("cannot open this file\n"); exit(0); } while(p2!=NULL) { fprintf(fp,"%s\t",p2->name); fprintf(fp,"%d\t",p2->sign); fprintf(fp,"%s\t",p2->home); fprintf(fp,"%s\t",p2->phone1); fprintf(fp,"%s\t",p2->phone2); fprintf(fp,"%s\t",p2->email); p2=p2->next; fputc('\n',fp); } printf("\n------------------------------保存成功!-----------------------------\n"); printf("---------------------------------------------------------------------\n"); fclose(fp); } void Changedata(phone *p) { char name[20]; int k, flag=1,a; printf("\n\t\t\t☆☆☆修改数据☆☆☆\n"); printf("----------------------------------------------------------------------\n"); printf("---------------------请输入需要修改的联系人姓名:---------------------\n"); scanf("%s",name); printf("---------------------请输入需要修改的联系人序号:---------------------\n"); scanf("%d",&a); while(p!=NULL) { if(strcmp(p->name,name)==0&&a==(p->sign)) { show_one(p); flag=0; printf("\n------------------请选择要修改的信息:---------------------------\n"); printf("+------------------------------------------------+\n"); printf("| |\n"); printf("| 1.姓名 4.手机2 |\n"); printf("| |\n"); printf("| 2.户籍 5.电子邮箱 |\n"); printf("| |\n"); printf("| 3.手机1 |\n"); printf("| |\n"); printf("+------------------------------------------------+\n"); scanf("%d",&k); switch(k) { case 1: printf("-------------------输入修改后的姓名:------------------\n"); scanf("%s",p->name); break; case 2: printf("-------------------输入修改后的户籍:------------------\n"); scanf("%s",p->home); break; case 3: printf("-------------------输入修改后的手机1:-----------------\n"); scanf("%s",p->phone1); break; case 4: printf("-------------------输入修改后的手机2:-----------------\n"); scanf("%s",p->phone2); break; case 5: printf("--------------------输入修改后的邮箱:------------------\n"); scanf("%s",p->email); break; } printf("-----------------------修改成功!-------------------------------------\n"); printf("----------------------------------------------------------------------\n"); break; } else p=p->next; } if(flag)printf("------------------------查无此人!------------------------------------\n"); printf("----------------------------------------------------------------------\n"); } void deletedata() { phone *p1,*p2; phone *p3; char name[20]; int n,k=1; printf("\n\t\t\t☆☆☆删除数据☆☆☆\n"); printf("----------------------------------------------------------------------\n"); printf("输入您想删除的联系人姓名:\n"); scanf("%s",name); p1=head; if(head==NULL) { printf("未建立联系人信息,通讯录为空\n"); return; } printf("请选择你要删除的人:\n"); printf("----------------------------------------------------------------------\n"); p3=head; while(p3!=NULL) { if(strcmp(name,p3->name)==0) { printf("姓名:%s\t\t",p3->name); printf("序号:%d\n",p3->sign); printf("籍贯:%s\t",p3->home); printf("电话号码1:%s\t",p3->phone1); printf("电话号码2:%s\t",p3->phone2); printf("电子邮箱:%s\n",p3->email); printf("\n\n"); k=0; printf("----------------------------------------------------------------------\n"); } p3=p3->next; } if(k){ printf("查无此人!\n"); return; } printf("请输入您要删除的人序号:\n"); scanf("%d",&n); while(p1!= NULL&&(p1->sign!=n||strcmp(p1->name,name)!=0)) { p2=p1; p1=p1->next; } if(p1==NULL) { printf("查无此人!\n"); return; } if(p1!=NULL) { p1=p1->next; p2->next=p1; printf("------------------------------删除成功!------------------------------\n"); return; } printf("----------------------------------------------------------------------\n"); } void input(phone *p1) { printf("姓名:"); scanf("%s",&p1->name); printf("籍贯:"); scanf("%s",&p1->home); printf("手机号1(没有可输入“无”):"); scanf("%s",&p1->phone1); printf("手机号2(没有可输入“无”):"); scanf("%s",&p1->phone2); printf("邮箱(没有可输入“无”):"); scanf("%s",&p1->email); p1->sign=1; } void Insertdata() { char name2[20]; int flag,max; phone *p1,*p2,*p3,*p4; p1=head; p3=(phone*)malloc(len); printf("\n\t\t\t☆☆☆添加联系人☆☆☆\n"); printf("----------------------------------------------------------------------\n"); printf("-------------------------请输入相关的数据:---------------------------\n"); input(p3); p4=head; max=0; while(p4!=NULL) { if(strcmp(p3->name,p4->name)==0) { if(p4->sign>max) max=p4->sign; } p4=p4->next; } p3->sign=++max; printf("-------------------------请输入插入的位置:---------------------------\n"); printf("+---------------------------------------------------------+\n"); printf("| |\n"); printf("| 1.首位置插入 |\n"); printf("| |\n"); printf("| 2.尾位置插入 |\n"); printf("| |\n"); printf("| 3.指定姓名前插入 |\n"); printf("+---------------------------------------------------------+\n"); scanf("%d",&flag); switch(flag){ case 1: p3->next=p1; head=p3; break; case 2: p2=head; while(p2->next!=NULL) { p2=p2->next; } p2->next=p3; p3->next=NULL; break; case 3: printf("请输入您想插入的姓名前面:\n"); scanf("%s",name2); while(p1->next!=NULL&&strcmp(p1->name,name2)!=0) { p2=p1; p1=p1->next; } if(p1==head) { p3->next=p1; head=p3; return; } if(p1==NULL) { printf("------------------------------查无此人!---------------------------\n"); } else { p3->next=p1; p2->next=p3; } break; } printf("------------------------------插入成功!------------------------------\n"); printf("----------------------------------------------------------------------\n"); return; } void Sort(phone *p) { phone *p1=p; phone *p2=p; char tname[20]; char thome[40]; char tphone1[20]; char tphone2[20]; char temail[25]; int tsign; if(p==NULL||p->next==NULL) { return; } else { while(p1!=NULL) { p2=p1; while(p2!=NULL) { if(strcmp(p1->name,p2->name)>0) { strcpy(tname,p1->name); strcpy(p1->name,p2->name); strcpy(p2->name,tname); strcpy(thome,p1->home); strcpy(p1->home,p2->home); strcpy(p2->home,thome); strcpy(tphone1,p1->phone1); strcpy(p1->phone1,p2->phone1); strcpy(p2->phone1,tphone1); strcpy(tphone2,p1->phone2); strcpy(p1->phone2,p2->phone2); strcpy(p2->phone2,tphone2); strcpy(temail,p1->email); strcpy(p1->email,p2->email); strcpy(p2->email,temail); tsign=p1->sign; p1->sign=p2->sign; p2->sign=tsign; } else if(strcmp(p1->name,p2->name)==0) { if(p1->sign>p2->sign) { strcpy(tname,p1->name); strcpy(p1->name,p2->name); strcpy(p2->name,tname); strcpy(thome,p1->home); strcpy(p1->home,p2->home); strcpy(p2->home,thome); strcpy(tphone1,p1->phone1); strcpy(p1->phone1,p2->phone1); strcpy(p2->phone1,tphone1); strcpy(tphone2,p1->phone2); strcpy(p1->phone2,p2->phone2); strcpy(p2->phone2,tphone2); strcpy(temail,p1->email); strcpy(p1->email,p2->email); strcpy(p2->email,temail); tsign=p1->sign; p1->sign=p2->sign; p2->sign=tsign; } } p2=p2->next; } p1=p1->next; } } printf("------------------------------排序完成!------------------------------\n"); } int main() { int a; system("color 0E"); mainmenuface(); readfile(); while(1) { printf("-------------------请选择您的操作:----------------------\n"); scanf("%d",&a); if(a>=0&&a<=10) { switch(a) { case 0: exit(1); break; case 1: Inputdata(); break; case 2: Lookdata(head); break; case 3: Changedata(head); break; case 4: Seek(head); break; case 5: Keepdata(head); break; case 6: Insertdata(); break; case 7: deletedata(); break; case 8: mainmenuface(); break; case 9: Sort(head); break; } } else { printf("---------------选择的操作不正确!请重新输入:------------------\n"); } } return 0; }
备注:只有一个联系人的时候不要执行浏览所有联系人,会死循环,就这一个bug
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。