完整word版通讯录管理系统的设计和实现.docx
- 文档编号:25386521
- 上传时间:2023-06-07
- 格式:DOCX
- 页数:32
- 大小:436.49KB
完整word版通讯录管理系统的设计和实现.docx
《完整word版通讯录管理系统的设计和实现.docx》由会员分享,可在线阅读,更多相关《完整word版通讯录管理系统的设计和实现.docx(32页珍藏版)》请在冰豆网上搜索。
完整word版通讯录管理系统的设计和实现
南通大学
二○一一~二○一二学年第一学期
计算机科学与技术学院
课程设计报告书
课程名称:
数据结构课程设计
班级:
计101
学号:
1013022015
姓名:
徐鹏
指导教师:
顾颀
二○一二年一月
设计题目:
通讯录管理系统的设计与实现
1.需求分析
1.1描述要求编程解决的问题,给出程序要达到的具体要求
1.1.1基本要求
①设计通讯录数据的逻辑结构和物理结构
②通讯录至少包括下列数据信息:
姓名、电话、单位等。
③完成图示基本功能。
④软件易用,操作简单。
⑤根据自己使用通讯录的体会,扩充其他功能,如按姓名查找、按号码查找、按序号删除等。
⑥设计足够多的测试用例。
1.1.2较高要求
①数据输入有效性的检验:
如姓名不能为空、号码中不能有非法字符等。
②提供分组管理的相关功能,如:
分组显示、加入组、组创建、组查询等。
③可视化的界面设计。
1.2测试案例设计,包括以下两方面案例:
1.2.1合理的输入,给出的合理的输出
输入:
1张三12345678计1012-102
输出:
输入成功!
1.2.2不合理的输入,给出的输出
输入:
2李四12**5678计1012-102
输出:
电话号码中出现非法输入
请重新输入:
2.概要设计
2.1功能划分与定义,功能结构图
基本功能模块如下图所示:
输入:
记录的输入。
显示:
通讯录显示。
查找:
按指定的方式,输入关键字,查找指定记录。
插入:
实现记录的添加或在指定位置插入新纪录。
删除:
提供指定记录的删除功能。
保存:
将内存中正在被操作的通讯录以文件形式保存到磁盘。
读入:
保存的逆操作,将存在磁盘里的通讯录文件读取到内存中。
排序:
按指定关键字对通讯录进行排序。
修改:
提供修改某条记录的功能。
移动:
移动记录在通讯录中的存储位置,使其被查找或显示时的位序前移或后移。
退出:
结束程序运行。
2.2给出数据的逻辑设计、抽象的数据类型描述
(1)数据域描述通讯录的相关信息,每个人的基本信息含有多个属性,其中包括姓名、电话、单位等,为此可根据人员信息建立结构体,类型定义如下:
structDatatype{
intid;//编号
charname[10];//姓名
charphone[12];//电话
charclass[10];//单位
};
3.详细设计
3.1数据的存储设计
根据通讯录的设计要求,可使用单链表实现该通讯系统的功能,链表节点只含一个数据域和一个指针,线性表的链式存储结构如下:
structNode
{
Datatypedata;//数据域,存放表元素
Node*next;//指针域,指向下一个结点
};
3.2界面设计,包括菜单、数据输入输出格式等
主菜单:
查找联系人子菜单:
显示通讯录子菜单:
1-添加联系人1-按序号查找1-按序号显示
2-查找联系人2-按姓名查找2-按姓名显示
3-修改联系人3-按号码查找3-按号码显示
4-删除联系人
5-移动联系人
6-显示通讯录
7-退出
数据输入格式:
请输入联系人的相关信息
编号:
1
姓名:
张三
电话:
1300000001
单位:
计102
住址:
2-102
数据输出格式:
编号姓名电话单位住址
1张三130000001计1022-102
3.2各功能的算法描述,可采用伪码、流程图、N-S图等方式
读入函数intRead(),将存在磁盘中的文件读到内存中。
是是否打开源文件否
新建元素结点
Nodes
读取文件到新建
节点的数据域返回
新结点链入表尾
s->next=p->next
p->next=s
读入数据
关闭文件
保存函数intWrite(),将内存中正在被操作的通讯录以文件形式保存到磁盘。
排序函数voidSort(),分别按姓名和号码进行排序
char(*a)[12]=newchar[n][12]
char(*b)[12]=newchar[n][12]
inti=0,j,t
Node*p=Head->next;
p!
=NULL
p->data.id=i+1;
sort1[i]=sort2[i]=p->data.id;
strcpy(a[i],p->data.name);
strcpy(b[i],p->data.phone);
p=p->next;
i++;
i=1
i j=0 j 是strcmp(a[j],a[j+1])>0否 t=sort1[j]; sort1[j]=sort1[j+1]; sort1[j+1]=t; 是strcmp(b[j],b[j+1])>0否 t=sort2[j]; sort2[j]=sort2[j+1]; sort2[j+1]=t; delete[]a;delete[]b; 输入函数DatatypeInput(),输入数据,并进行数据的校验 输出: 请输入联系人的相关信息 输入编号cin>>id 输入姓名cin>>name 输入电话cin>>phone 电话号码出现非法字符 输入单位cin>>danwei 输入地址cin>>address 显示函数voidPrintall(),显示通讯录 Node*p;p=Head->next 选择显示方式 1.按编号 2.按姓名 3.按号码 i=0 i=0 i=0 i 按链表顺序输 出个节点数据 i 按姓名索引表 sort1[]输出个 节点数据 i 按号码索引表 sort2[]输出个 节点数据 插入函数,intInsert(inti),在表中第i个位置插入元素 j=0 Node*p;p=Head; j p=p->next j++ Nodes s->data=Input() s->next=p->next p->next=s 删除函数voidDelete(inti),删除表中第i个元素 Node*p,*q p=Head p->next&&p->next->data.id! =i p=p->next q=p->next p->next=q->next deleteq 查找函数intSearch(),通过序号查找 Node*p;p=Head->next; 选择查找方式 1-按序号查找 2-按姓名查找 3-按号码查找 cin>>i charch[12]; cin>>ch charch[12] cin>>ch; p->data.id! =i p=p->next; p&&strcmp(p->data.name,ch) p=p->next; p&&strcmp(p->data.phone,ch) p=p->next; Showlist(); p=NULL 是否 p=NULL 是否 returnp->data.id return0 return p->data.id return0 return p->data.id 移动函数intMove(inti),移动联系人资料 Node*p=Head,*q=Head; k=0 cin>>j k p=p->next k++ q->data.id! =i q=q->next Delete(i) q->next=p->next p->next=q 修改函数voidAmend(inti),修改联系人资料,i为要修改的联系人的位置。 Node*p p=Head->next p->data.id! =i p=p->next p->data=Input 4.调试、测试、分析 4.1给出软件使用说明及测试案例的运行情况的记录 运行程序,显示主菜单 ①选择操作1,输入联系人的相关信息 ②选择操作2,查找联系人 显示查找子菜单,程序提供三种查找方式 选择查找方式1 选择查找方式2 选择查找方式3 ③选择操作3: 修改联系人 系统提示首先选择查找方式,找到该联系人,显示该联系人的原始信息,然后输入该联系人的修改信息,修改成功。 ④选择操作4: 删除联系人 首先也是查找到该联系人,显示该联系人的原始信息,然后删除。 ⑤选择操作5: 移动联系人 输入移动的目标位置 ⑥选择操作6: 显示通讯录 显示显示子菜单,系统提供3种显示方式 选择1-按编号显示 选择2-按姓名显示 选择3-按号码显示 ⑦选择操作7 结束运行,将内存中正在被操作的通讯录以文件形式保存到磁盘。 4.2对主要算法进行复杂度分析 ①排序函数Sort(),采用冒泡排序法,时间复杂度为O(n2) ②移动函数intMove(inti),插入函数intInsert(inti),删除函数voidDelete(inti),修改函数voidAmend(inti),查找函数intSearch()算法的时间主要耗费在查找数据的位置上,时间复杂度为O(n) ③输出函数voidPrintall(),采用两层循环,外层for循环统计输出节点数目,内循环在链表上查找对应的节点,故时间复杂度为O(n2) 5.总结与体会 本实验程序主要使用了有头结点单链表的基本操作算法,包括创建表、元素插入、元素删除、元素查找、元素移动等。 链式存储的优点是结点空间的动态分配使得无需预先确定存储空间,而且结点的前驱与后继靠指针指示,因此在链表中任何位置上进行插入和删除,只需修改指针,无需移动元素。 链表的缺点就是只能顺序访问,查找结点需要从头指针进入逐个查找。 由于存储中需存储数据元素信息以外的存储空间,用于存储数据元素之间的逻辑关系,所以其存储密度低于顺序表。 另外,该程序还涉及到文件的读取和写入相关知识,既要会将存在磁盘中的文件读到内存中,也要能将内存中正在被操作的通讯录以文件形式保存到磁盘。 程序设计时考虑到数据的校验问题,在数据生效之前,对输入数据的合法性进行验证,以免非法数据的输入。 由于功能较多,本程序采用了多级菜单的形式。 第一次做这种综合程序的设计,题目涉及的问题比较多,程序规模比较大,在设计的过程中遇到了不小的困难。 在自己的努力和同学的帮助下,最终还是实现了这个程序,同时自己的编程能力也在程序的一个个错误的修正中得到提高。 6.附: 源程序 main.cpp #include #include #include"LinkList.h" intmain() { inti,choice; LinkListL; L.Read();//将存在磁盘里的通讯录文件读取到内存中 L.Sort();//更新索引表 do {//显示主菜单 cout<<"1-添加联系人\n"; cout<<"2-查找联系人\n"; cout<<"3-修改联系人\n"; cout<<"4-删除联系人\n"; cout<<"5-移动联系人\n"; cout<<"6-显示通讯录\n"; cout<<"7-退出\n"; cout<<"Enterchoice: "; cin>>choice; switch(choice) { case1: cout<<"请输入插入的位置: "; cin>>i; L.Insert(i); L.Sort();//当源数据表数据发生变化(如修改、插入、删除、移动)时,及时更新索引表 break; case2: L.Search(); break; case3: //删除指定位置元素 i=L.Search();//函数返回值为联系人的序号 if(i==0)break; else { L.Amend(i); L.Sort();//更新索引表 break; } case4: i=L.Search();//函数返回值为联系人的序号 if(i==0)break; else { L.Delete(i); cout<<"删除成功! "< L.Sort();//更新索引表 break; } case5: i=L.Search();//函数返回值为联系人的序号 if(i==0)break; else { L.Move(i); L.Sort();//更新索引表 break; } case6: L.Printall(); break; case7: //退出 cout<<"结束运行"< break; default: // cout<<"错误选项\n"; break; } }while(choice! =7);// L.Write();//将内存中正在被操作的通讯录以文件形式保存到磁盘 return0; } linklist.h #include #include usingnamespacestd; #ifndefMY_1 #defineMY_1 structDatatype { intid;//编号 charname[12];//姓名 charphone[12];//电话 chardanwei[12];//单位 charaddress[12];//住址 }; structNode { Datatypedata;//数据域,存放表元素 Node*next;//指针域,指向下一个结点 }; classLinkList { private: Node*Head;//链表头指针 intn;//单链表中节点的个数,即联系人的数目 intsort1[999];//按姓名排序的索引表 intsort2[999];//按电话排序的索引表 public: LinkList();//构造函数,创建空链表 ~LinkList();//析构函数,删除表空间 intRead();//将存在磁盘中的文件读到内存中 intWrite();//将内存中正在被操作的通讯录以文件形式保存到磁盘 DatatypeInput();//输入数据,并进行数据的校验 voidPrintall();//显示通讯录 voidShowdata(Node*c);//显示一个节点数据域,即显示一个联系人的信息 voidShowlist();//显示通讯录包含的成员(编号,姓名,单位,电话等) intInsert(inti);//在表中第i个位置插入元素 intSearch();//通过序号查找 voidAmend(inti);//修改联系人资料 voidDelete(inti);//删除表中第i个元素 intMove(inti);//移动联系人资料 voidSort();//排序 }; LinkList: : LinkList() {//构建函数,建一空链表 Head=newNode; Head->next=NULL; n=0; } LinkList: : ~LinkList() {//析构函数,释放链表所占空间 Node*p; while(Head)//从头结点开始,依次释放结点 { p=Head; Head=Head->next; deletep; } Head=NULL;//头结点指向空 } voidLinkList: : Showlist() { cout<<"编号"<<'\t'<<"姓名"<<'\t'<<"电话"<<"\t\t"<<"单位"<<'\t'<<"住址"< } voidLinkList: : Showdata(Node*c) { cout< } voidLinkList: : Sort() { char(*a)[12]=newchar[n][12];//存放n给联系人姓名的二维数组 char(*b)[12]=newchar[n][12];//存放n给联系人电话的二维数组 inti=0,j,t; Node*p;//设置工作指针 p=Head->next;//从首元结点开始遍历 while(p)//对索引表初始化 { p->data.id=i+1;//对id初始化 sort1[i]=sort2[i]=p->data.id; strcpy(a[i],p->data.name); strcpy(b[i],p->data.phone); p=p->next; i++; } for(i=1;i { for(j=0;j { if(strcmp(a[j],a[j+1])>0) {t=sort1[j];sort1[j]=sort1[j+1];sort1[j+1]=t;} if(strcmp(b[j],b[j+1])>0) {t=sort2[j];sort2[j]=sort2[j+1];sort2[j+1]=t;} } } delete[]a;delete[]b; } intLinkList: : Move(inti) { cout<<"请输入移动的目标位置: "; intj; cin>>j; if(j<1||j>n)//当目标位置为负或者超过总联系人数时 {cout<<"位置异常"< intk=0; Node*p,*q; p=Head;//工作指针初始化 q=Head; while(k { p=p->next; k++; } while(q->data.id! =i) q=q->next; Datatypea; a=q->data; Delete(i);n++; q->next=p->next; p->next=q; q->data=a; cout<<"移动成功! "< return0; } intLinkList: : Insert(inti) {//在指定位置插入元素 if(i<0||i>n+1)//当目标位置为负或者超过总联系人数时 {cout<<"位置异常"< intj=0; Node*p; p=Head;//工作指针初始化 while(j { p=p->next; j++; } Node*s; s=newNode; s->data=Input(); s->next=p->next;//结点S链接到p结点之后 p->next=s; n++; cout<<"插入成功! "< return0; } voidLinkList: : Delete(inti) {//删除指定位置元素 Node*p,*q;//设置工作指针 p=Head;//查找从头结点开始 while(p->next&&p->next->data.id! =i)//p定位到删除点的前驱 p=p->next; q=p->next;//暂存删除结点位置 p->next=q->next;//从链表中摘除删除结点 deleteq;//释放删除点 n--; } voidLinkList: : Amend(inti)//修改联系人资料 { Node*p;//设置工作指针 p=Head->next;//从首元结点开始遍历 while(p->data.id! =i) p=p->next; p->data=Input(); cout<<"修改成功! "< } intLinkList: : Read() { ifstreamin("source.txt");//说明输入文件流对象in if(! in){cout<<"不能打开源文件source.txt"< Node*p,*s;//设置工作指针。 p指向尾结点 p=Head; Datatypea; while(in>>a.id>>a.name>>a.phone>>a.danwei>>a.address) {//用文件流对象in读取文件并判断文件流对象in是否出错 s=newNode;//新建元素结点 s->data=a;//输入新建数据元素值 s->next=p->next;//新结点链入表尾 p->next=s; p=s; n++; } in.close();//关闭文件 return0; } voidLinkList: : Printall()//遍历显示链表 { cout<<"1-按编号显示"< cout<<"2-按姓名显示"< cout<<"3-按号码显示"< intkey,i; cout<<"请选择显示方式: "; cin>>key; Showlist
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 完整 word 通讯录 管理 系统 设计 实现