通讯录管理系统实验报告
学 院:物理与电子工程学院
专 业:电子信息科学与技术
学 号:1319200011
姓 名:朱大神
日 期:20##年6月12日
一. 题目要求
? 用C设计出模拟手机通信录管理系统,实现对手机中的通信录进行管理。
? 功能要求
? (1)查看功能:选择此功能时,列出下列三类选择。A办公类,B个人类,C商务类,当选中某类时,显示出此类中的所有数据。
? (2)增加功能:能录入新数据,一个结点包括:姓名、电话号码、分类(可选项有:A 办公类,B 个人类,C 商务类)、电子邮件。例如:杨春 13589664454 商务类 chuny@126.com。
? 当录入了重复的姓名和电话号码时,则提示数据录入重复并取消录入;录入的新数据能按递增的顺序自动进行条目编号。
? (3)修改功能:选中某个人的姓名时,可对此人的相应数据进行修改。
? (4)删除功能:选中某个人的姓名时,可对此人的相应数据进行删除,并自动调整后续条目的编号。
二. 程序功能
主要包含以下功能:
1.建立功能——建立通讯录
2.保存功能——保存通讯录
3.读取功能——读取文件
4.查找功能——查找联系人
5.删除功能——删除联系人
6.添加功能——添加联系人
7.修改功能——修改联系人
8.退出功能——退出系统
三.系统功能模块
建立功能:
在主菜单中输入1,进入建立功能。用户输入联系人姓名,电话,类别,邮箱,建立一个新的通讯录。在输入姓名处输入“*”结束添加。
保存功能:
在主菜单中输入2,进入保存功能。将已创建的通讯录保存到文件中。
读取功能:
在主菜单中输入3,进入读取功能。读取已经存在的通讯录文件。
查找功能:
在主菜单中输入4,进入查找功能。创建通讯录或读取文件之后才能进行查找。查找方式有三种:1. 按姓名查找2. 按类型查找3. 查看所有人。
删除功能:
在主菜单中输入5,进入删除功能。创建通讯录或读取文件之后才能进行删除。用户输入待删除联系人的姓名,系统显示待删除联系人的信息,并提示是否删除该联系人。
添加功能:
在主菜单中输入6,进入添加功能。创建通讯录或读取文件之后才能按提示添加联系人。
修改功能:
在主菜单中输入7,进入修改功能。创建通讯录或读取文件之后才能进行修该。通过姓名查找到联系人进行修改。
退出功能:在主菜单中输入8,退出通讯录管理系统。
四.函数流程图
1.建立通讯录(单链表)
2.保存通讯录
3.读取文件
4.查找联系人
5.删除联系人
6.添加联系人
7.修改联系人
五.实验结果
开始界面:
建立通讯录:
保存通讯录:
读取文件:
查找联系人:
1.按姓名查找
2.按类别查找
3.显示所有
删除联系人:
添加联系人:
修改联系人:
退出系统:
六.体会
终于写到体会这部分了,这个程序设计花了我不少时间和精力。从一开始拿到题目,完全没有头绪,到后来慢慢分析题目,选数据结构,查资料,请教前辈,到最后终于用将近一个星期写出了这个通讯录管理系统,满满的都是泪啊。
这次程序设计让我对单链表有了新的认识。之前学习C语言的时候觉得单链表没什么用,经过这次程序设计,我发现单链表的功能是十分强大的,主要看你会不会用而已。
尽管单链表相对简单,但是第一学期学习链表的时候我并没有学好,这导致我在编程的过程中指针的使用出了很多问题,后来通过重温书本,请教同学,终于搞定了这部分。这也让我更加掌握链表这块知识。
还有文件读取与保存这块,第一学期C语言课并没有讲,我当时觉得它很难也懒得去自学了,后来到了这个程序设计,我不得不去学习这部分的知识。但让我意想不到的是,文件这部分内容比我想象的要简单得多,文件应该是这个通讯录管理系统中最简单的两个函数了。所以,有些事情你不去探索,不知道难易,有些事情你不去摸索,不知道它多有趣。
最后,尽管编程过程痛苦,但是让我巩固了以前的知识,提高了动手能力,而且程序写出来让我非常有成就感,所以还是很感谢有这门课程的。
七.参考文献
1.C语言程序设计(第四版)
2.数据结构(C语言版)
3.百度知道
八.源程序
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
#define TEL struct telephone_list
struct telephone_list
{
char name[100]; //姓名
char tel[100]; //电话
char type[100]; //类型
char mail[100]; //邮箱
TEL *next;
};
int total=0; //统计联系人
void Save(TEL *head); //函数声明
TEL* Create()
{
total=0;
int k=0; //判断是否成功添加第一个联系人
int i=0; //判断联系人是否重复
TEL *head,*p1,*p2,*p3;
char saveflag;
head=p1=p2=NULL;
while(1) //添加联系人
{
p1= (TEL*)malloc(sizeof(TEL)); //分配动态存储空间
printf("请输入姓名,添加完成时在姓名后输入*,结束添加\n");
scanf("%s",p1->name);
if(strcmp(p1->name,"*")==0) //结束添加联系人
{
if(total==0)
{
printf("添加了0个联系人\n");
free(p1); //释放p1空间
return (head);
}
else
{
break; //跳出while(1)
}
}
printf("请输入电话号码:\n");
scanf("%s",p1->tel);
printf("请输入类别:(办公类/个人类/商务类)\n");
scanf("%s",p1->type);
printf("请输入邮箱:\n");
scanf("%s",p1->mail);
if(k>0) //添加第一个联系人之后
{
p3=head; //遍历链表
while(p3!=NULL) //判断联系人是否重复
{
if((strcmp(p1->name,p3->name)==0)&&(strcmp(p1->tel,p3->tel)==0)) //重复
{
free(p1);
printf("该联系人已存在\n");
i=1;
printf("按任意键返回主菜单\n");
getch(); //任意键
break;
}
if((strcmp(p1->name,p3->name))&&(strcmp(p1->tel,p3->tel))&&(p3==p2)) //无重复
{
i=0;
break; //跳出if(k>0)
}
p3=p3->next; //下一个结点
}
if(i==1) //联系人重复
{
break; //跳出while(p3!=NULL)
}
}
if(head==NULL) //添加第一个联系人head为空
{
head=p1;
p2=p1;
}
else
{
p2->next=p1;
p2=p1;
}
total++; //人数+1
k++;
}
p2->next=NULL; //最后一个结点的指针域为空
if(i==0)
{
free(p1);
printf("\n新建通讯录成功,共有%d个联系人,是否保存?(Y/N)\n ",total);
getchar();
scanf("%c",&saveflag);
if(saveflag=='y'||saveflag=='Y')
Save (head); //保存
else
printf("\联系人未保存\n");
}
return head; //返回头指针
}
void Save(TEL *head)
{
FILE *fp; //文件指针
TEL *f;
if ((fp=fopen("telephone.txt","w"))==NULL) //打开输出文件
{
printf("文件打开失败\n");
getch();
exit(0); //退出
}
f=head;
while(f!=NULL)
{
fwrite(f,sizeof(TEL),1,fp); //从f所指向的文件中读入一个大小为sizeof(TEL)的数据存到fp中
f=f->next; //下一个结点
}
fclose(fp); //关闭文件
printf("文件保存成功,按任意键返回主菜单\n");
getch();
}
TEL *Read()
{
FILE *fp; //文件指针
TEL *f1,*f2,*head=NULL;
char ch; //存放文件的第一个字符
if((fp=fopen("telephone.txt","r"))==NULL) //打开输入文件
{
printf("该文件不存在,按任意键返回主菜单\n");
getch();
exit(0);
}
ch=fgetc(fp); //从fp所指文件读入一个字符,读取成功带回所读字符,失败则返回文件结束标志EOF(即-1)
if(ch==EOF) //文件为空
{
printf("文件为空,请建立通讯录,按任意键返回主菜单\n");
getch();
return head; //返回头指针
}
else
{
rewind(fp); //把文件位置指针移至文件开头
}
f1=(TEL *) malloc(sizeof(TEL));
head=f1;
while(!feof(fp)) //文件结束,feof返回非零值,否则返回0
{
if(fread(f1,sizeof(TEL),1,fp)!=1) //fread函数执行成功返回1
break; //跳出while(!feof(fp))
total++; //人数+1
f1->next=(TEL *)malloc(sizeof(TEL)); //为下一个结点申请存储空间
f2=f1;
f1=f1->next;
}
f2->next=NULL; //最后一个结点的指针域为空
free(f1);
fclose(fp); //关闭文件
printf("文件读取成功,按任意键返回主菜单\n");
getch();
return head; //返回头指针
}
void Search(TEL* head)
{
int choice;
int count=1; //联系人序号
TEL *p;
int flag;
int searchflag=1;
char go;
char name[100];
char type[100];
printf("查询方式:(请输入序号)\n");
printf("1.姓名\n");
printf("2.类别\n");
printf("3.显示所有\n");
scanf("%d",&choice);
getchar();
switch(choice) //选择查询方式
{
case 1:
while(searchflag)
{
flag=0;
printf("\n请输入待查找联系人的姓名: \n");
scanf("%s",&name);
getchar();
p=head;
while(p!=NULL)
{
if(strcmp(p->name,name)==0)
{
printf("%d.",count);
count++; //编号
printf("姓名:%s\t电话号码: %s\t类型:%s\t邮箱:%s\n",p->name,p->tel,p->type,p->mail);
flag=1; //找到该联系人
}
p=p->next;
}
if(flag==0) //没有找到该联系人
{
printf("\n该联系人不存在\n");
}
printf("\n查找完毕,是否继续查询?(Y/N)\n");
scanf("%c",&go);
getchar();
if(go=='y'||go=='Y')
{
searchflag=1; //继续查找
}
else
{
searchflag=0; //停止查找
}
}
break;
case 2: //与case1相似
while(searchflag)
{
flag=0;
printf("\n请输入类别:\n");
scanf("%s",type);
getchar();
p=head;
while(p!=NULL)
{
if(strcmp(p->type,type)==0)
{
printf("%d.",count);
count++; //编号
printf("姓名:%s\t电话号码:%s\t类型:%s\t邮箱:%s\n",p->name,p->tel,p->type,p->mail);
flag=1; //找到该联系人
}
p=p->next;
}
if(flag==0) //没有找到该联系人
{
printf("\n该联系人不存在\n");
}
printf("\n查找完毕,是否继续查询?(Y/N)\n"); //flag==1
scanf("%c",&go);
getchar();
if(go=='y'||go=='Y')
{
searchflag=1; //继续查找
}
else
{
searchflag=0; //停止查找
}
}
break;
case 3: //相当于遍历整个链表并输出
p=head;
while(p!=NULL)
{
printf("%d.",count);
count++; //编号
printf("姓名:%s\t电话号码:%s\t类型:%s\t邮箱:%s\n",p->name,p->tel,p->type,p->mail);
p=p->next;
}
printf("查找完成,按任意键返回主菜单\n");
getch();
break;
default:
printf("输入错误,按任意键返回主菜单\n");
getch();
}
}
TEL* Delete(TEL *head)
{
TEL *p1,*p2,*p3;
char deleteflag;
char saveflag;
int i; //判断联系人是否存在
p1=p2=p3=head;
char name[100];
printf("请输入要删除的联系人姓名:\n");
scanf("%s",name);
getchar();
while(p3!=NULL) //确定要删除的联系人是否存在
{
if(strcmp(p3->name,name)==0)
{
i=1; //联系人存在
break;
}
if(strcmp(p3->name,name)&&(p3->next)==NULL)
{
i=0; //联系人不存在
break;
}
p3=p3->next;
}
if(i==1) //确定要删除的结点的位置
{
while(strcmp(p1->name,name)&&p1!=NULL)
{
p2=p1; //p2是p1的前一个结点
p1=p1->next;
}
}
if(i==0)
{
printf("该联系人不存在,按任意键返回主菜单\n");
getch();
}
if((i==1)&&(p1!=NULL)) //删除联系人
{
printf("要删除的联系人为:\n");
printf("姓名:%s\t电话号码:%s\t类型:%s\t邮箱:%s\n",p1->name,p1->tel,p1->type,p1->mail);
printf("是否要删除该联系人?(Y/N)?\n");
scanf("%c",&deleteflag);
getchar();
if(deleteflag=='y'||deleteflag=='Y')
{
if(p1==head) //数据为第一个结点
head=p1->next; //删除
else //结点不是头结点
p2->next=p1->next;
free(p1);
printf("删除成功,是否保存?(Y/N)\n");
scanf("%c",&saveflag);
getchar();
if(saveflag=='y'||saveflag=='Y')
{
Save(head); //保存
total--; //人数-1
}
else
{
printf("联系人未保存,按任意键返回主菜单\n");
getch();
}
}
else //不删除联系人
{
printf("该联系人没有被删除,按任意键返回主菜单\n");
getch();
}
}
return head; //返回被修改的头指针
}
TEL* Incert(TEL* head) //尾插法
{
char saveflag;
int i=0; //判断联系人是否重复
TEL *p1,*p2,*p3,*add;
p1=p2=head;
add=(TEL*)malloc(sizeof(TEL)); //申请动态存储空间
while(p1!=NULL) //使p2成为最后一个结点
{
p2=p1;
p1=p1->next;
}
printf("请输入联系人的姓名:\n");
scanf("%s",add->name);
printf("请输入联系人的电话号码:\n");
scanf("%s",add->tel);
printf("请输入联系人的类型:\n");
scanf("%s",add->type);
printf("请输入联系人的邮箱:\n");
scanf("%s",add->mail);
p3=head;
while(p3!=NULL)
{
if((strcmp(add->name,p3->name)==0)&&(strcmp(add->tel,p3->tel)==0)) //联系人重复
{
free(add);
printf("该联系人已存在,按任意键返回主菜单\n");
i=1;
getch();
break;
}
if((strcmp(add->name,p3->name))&&(strcmp(add->tel,p3->tel))&&(p3==p2)) //到最后一个结点联系人还没有重复
{
i=0;
break; //跳出while(p3!=NULL)
}
p3=p3->next;
}
if(i==0) //联系人不重复
{
add->next=NULL; //add作为最后一个节点,指针与为空
if(p1==head) //头结点为空
{
head=add;
}
else
{
p2->next=add; //add在链表尾部插入
}
total++;
free(p1);
printf("添加成功,是否保存?(Y/N)\n");
getchar();
scanf("%c",&saveflag);
if(saveflag=='y'||saveflag=='Y')
{
Save(head); //保存
total++;
}
else
{
printf("联系人未保存,按任意键返回主菜单\n");
getch();
}
}
return head; //返回已修改头指针
}
TEL* Change(TEL* head) //与delete相似
{
TEL *p1,*p2,*p3;
char saveflag;
p1=p2=p3=head;
char name[100];
int i; //判断要修改的联系人是否存在
printf("请输入要修改的联系人姓名:\n");
scanf("%s",name);
while(p3!=NULL)
{
if(strcmp(p3->name,name)==0)
{
i=1; //要修改的联系人存在
break;
}
else
{
i=0; //要修改的联系人不存在
break;
}
p3=p3->next;
}
if(i==1) //联系人存在,查找该结点的位置
{
while(strcmp(p1->name,name)&&p1!=NULL) //找到联系人循环结束
{
p2=p1; //p2是p1的前一个结点
p1=p1->next;
}
}
if(i==0) //联系人不存在
{
printf("该联系人不存在,按任意键返回主菜单\n");
getch();
}
if((i==1)&&(p1!=NULL)) //查找
{
printf("要修改的联系人为:\n");
printf("姓名 %s\t电话号码 %s\t类型:%s\t邮箱:%s\n",p1->name,p1->tel,p1->type,p1->mail);
printf("请输入修改后的电话号码:\n");
scanf("%s",p1->tel);
printf("请输入修改后的类型:\n");
scanf("%s",p1->type);
printf("请输入修改后的邮箱:\n");
scanf("%s",p1->mail);
printf("修改成功,是否进行保存? (Y/N)\n");
getchar();
scanf("%c",&saveflag);
if(saveflag=='y'||saveflag=='Y')
Save(head); //保存
else
printf("联系人未保存,按任意键返回主菜单\n");
getch();
}
return head; //返回已修改头指针
}
void main()
{
TEL *head=NULL;
int choice;
int go=0;
while(1)
{
printf("\n\n\n");
printf(" ⊙▽⊙▽⊙▽⊙▽⊙▽⊙▽⊙▽⊙▽⊙▽⊙▽⊙▽⊙▽⊙\n");
printf("\n *通讯录管理系统*\n\n");
printf(" ⊙▽⊙▽⊙▽⊙▽⊙▽⊙▽⊙▽⊙▽⊙▽⊙▽⊙▽⊙▽⊙\n");
printf(" 1. 建立通讯录\n");
printf(" 2. 保存通讯录\n");
printf(" 3. 读取文件\n");
printf(" 4. 查找联系人\n");
printf(" 5. 删除联系人\n");
printf(" 6. 添加联系人\n");
printf(" 7. 修改联系人\n");
printf(" 8. 退出系统\n");
printf(" *Made by Nanmeng Zhu*\n");
printf(" ⊙▽⊙▽⊙▽⊙▽⊙▽⊙▽⊙▽⊙▽⊙▽⊙▽⊙▽⊙▽⊙\n");
printf("\n");
scanf("%d",&choice);
getchar();
switch(choice)
{
case 1:
head=Create(); //创建
go=1;
break;
case 2:
Save(head); //保存
break;
case 3:
head=Read(); //读取文件
go=2;
break;
case 4:
if((go==1)||(go==2)) //创建通讯录或读取文件之后才能查找
{
Search(head); //查找
}
else
{
printf("请先创建通讯录或读取文件");
printf("按任意键返回主菜单\n");
getch();
}
break;
case 5:
if((go==1)||(go==2)) //创建通讯录或读取文件之后才能删除
{
head=Delete(head); //删除
}
else
{
printf("请先创建通讯录或读取文件");
printf("按任意键返回主菜单\n");
getch();
}
break;
case 6:
if((go==1)||(go==2)) //创建通讯录或读取文件之后才能添加
{
head=Incert(head); //添加
}
else
{
printf("请先创建通讯录或读取文件\n\n");
printf("按任意键返回主菜单\n");
getch();
}
break;
case 7:
if((go==1)||(go==2)) //创建通讯录或读取文件之后才能删除
{
head=Change(head); //修改
}
else
{
printf("请先创建通讯录或读取文件\n\n");
printf("按任意键返回主菜单\n");
getch();
}
break;
case 8:
exit(0); //退出
break;
default:
printf("输入错误,重新输入\n");
}
}
}