第一篇:数据结构课程设计-职工管理系统
目录
一、前言--------2
二、需求分析--3
三、概要设计--4
四、详细设计--5
五、调试分析--6
六、用户使用说明---------------------------7
七、测试结果--8
八、总结-------11
九、主要参考文献和附录-----------------12
前言
员工管理系统是一个工作单位不可缺少的管理工具,它管理的数据对于公司的决策者和管理者来说都至关重要,所以员工管理系统应该能够为用户提供充足的信息和快捷的查询手段。但一直以来各个公司基本上都是靠传统的人工方式来管理员工信息,这种管理方式存在着许多缺点,如:效率低、保密性差,另外时间一长,将产生大量的文件和数据,这对于信息的查找、更新和维护都带来了不少的困难。
当今社会,信息迅速膨胀,随着各个公司的规模增大,有关信息管理工作所涉及的数据量越来越大,员工信息量也大大增加,利用传统的手工查询、登记、修改等方法的处理速度远远跟不上公司的需求,有的公司不得不靠增加人力、物力来进行信息管理。
随着计算机技术的不断提高,计算机作为知识经济时代的产物,其强大的功能已为人们深刻认识,它已进入人类社会的各个行业和领域并发挥着越来越重要的作用,成为人们工作和生活中不可缺少的一部分。
而作为计算机应用的一部分,使用计算机对员工进行管理,具有手工管理所无法比拟的优点。例如:检索迅速、查找方便、可靠性高、存储量大、保密性好、寿命长、成本低等。这些优点能够极大地提高员工管理的效率,也是公司的科学化、正规化管理和与世界接轨的重要条件。
员工管理系统作为一种管理软件正在各公司中得到越来越广泛的应用,且已达到了良好效果。
需求分析
员工信息管理系统是企业管理中的一个重要内容,随着时代的进步,企业也逐渐变得庞大起来。如何管理好企业内部员工的信息,成为企业管理中的一个大问题。在这种情况下,开发一个人力资源管理系统就显得非常必要
现在,市场上可以选购的应用开发产品很多,流行的也有数十种。在目前市场上这些众多的程序开发工具中,有些强调程序语言的弹性与执行效率;有些则偏重于可视化程序开发工具所带来的便利性与效率的得高,各有各的优点和特色,也满足了不同用户的需求。然而,语言的弹性和工具的便利性是密不可分的,只强调程序语言的弹性,却没有便利的工具作配合,会使一些即使非常简单的界面处理动作,也会严重地浪费程序设计师的宝贵时间;相反,如果只有便利的工具,却没有弹性的语言作支持,许多特殊化的处理动作必需要耗费数倍的工夫来处理,使得原来所标榜的效率提高的优点失去了作用。
本系统结合公司实际的人事、制度,经过实际的需求分析,采用功能强大的Visual C++ 6.0作为开发工具而开发出来的管理系统。整个系统从符合操作简便、界面友好、灵活、实用、安全的要求出发,本管理系统具有如下功能:
1、问题描述
对单位的员工进行管理,包括插入、删除、查找、排序等功能。
2、要求
员工对象包括姓名、性别、年龄、职位、工龄等信息。
(1)新增一名员工:将新增员工对象按姓名以字典方式员工管理文件中,基本信息中的编号是按照添加顺序自动增加的。
(2)删除一名员工:从员工管理文件中删除一名员工对象,分为根据编号删除、根据姓名删除。
(3)查询:从员工管理文件中查询符合某些条件(编号、姓名)的员工。(4)修改:根据编号检索出对象,既可以对整个对象修改,也可对某个属性修改。
(5)排序:按照年龄、工龄对所有的员工排序(降序),也可以回复排序以前的员工现实状态。
3、实现提示
员工对象数不必很多,便于一次读入内存,所有操作不经过内外存交换。(1)当启动程序是,自动从文件(message.txt)中读出员工信息(2)由键盘输入员工对象存入链表当中。
(3)对员工对象中的“编号、年龄、工龄”按字典顺序进行排序。(4)对排序后的员工对象进行增、删、查询、修改、排序等操作。(5)当退出程序时,将此刻单链表中存储的数据写入到文件(message.txt)中去,保存起来。
概要设计
(一)数据类型定义:
typedef struct{ int num;//编号
char name[MAX_NUM];//姓名
int age;//年龄
char job[MAX_NUM];//职位;
int workTime;// 工龄
}People;ypedef struct node{ People people;struct node * next;int len;//表示链表长度
}linklist;
(二)流程图:
(图1)
(三)各程序模块之间的层次图:
(图2)
详细设计
1、主菜单模块:显示员工管理系统的主菜单,供用户选择所需的功能,通过自己定义的void main()函数来实现。
2、添加员工模块:输入员工的编号、姓名、年龄、职位、工龄以,通过自己定义的void addMessage()函数来实现。
3、查询员工信息模块:浏览所有员工的相关信息,通过自己定义的void searchPeople()函数来实现。
(1)按员工姓名查询:可以按员工工号来查询员工的相关信息,通过自己定义的void searchPeopleByName()函数来实现。
(2)按员工编号查询:可以按员工职务来查询员工的相关信息,通过自己定义的void searchPeopleByNum()函数来实现。
(3)退出。
4、删除员工模块:删除需要删除的员工的所有信息,通过自己定义的void deletePeople()函数来实现。
(1)按员工姓名删除模块:可以按员工工号来删除员工的相关信息,通过自己定义的void deletePeopleByName()函数来实现。
(2)按员工编号删除模块:可以按员工编号删除员工的相关信息,通过自己定义void deletePeopleByNum()函数来实现。
(3)退出
5、修改模块:可以修改需要修改的员工的相关信息,通过自己定义的 void editMessage()函数来实现。
(1)修改整条记录,可以修改该员工的全部信息,通过自己定义的void editAll()函数来实现。
(2)修改部分记录,可以修改该员工的部分信息,通过自己定义的void editSome()
函数来实现。
(3)退出。
6、员工信息排序模块:可以按照规定要求对员工信息排序,通过自己定义的void sort()函数来实现。
(1)按年龄排序:可以按员工工号对员工信息排序,通过自己定义的void sortByAge()函数来。
(2)按工龄排序:可以按员工工龄对员工信息排序,通过自己定义的void sortByWorkTime()函数来实现。
(3)回复原排序:可以回复排序前的顺序,通过自己定义的void sortByNum()函数来实现。
(4)退出。
7、退出系统模块:退出员工信息管理系统,通exit(0)函数来实现。
函数调用图:
(图3)
调试分析
测试是使用人工或者自动手段来运行或测试某个系统的过程,其目的在于检验是否满足规定的需求或弄清预期结果与实际结果之间的差别。
在调试查询修改功能过程中,查询的结果显示,没有找到员工信息,最后发现查找的结点不正确,查询应该与输入的值和头结点next比较。此外查询结点不知道如何循环,反复修改程序才知道如何继续查找而不出错误。
本次课程设计是围绕数据结构进行。根据问题描述可知,需要解决问题并不复杂,整个问题只需要实现一个员工管理系统功能,那就是在这个系统中实现对员工信息的插入、删除、查询、排序、修改。但是,为了实现该功能,却需要优秀的算法和数据结构以保证实现的时间和空间效率。把员工信息存储在一个单链表中,利用指针实现对员工信息的各项基本操作。
虽然设计的程序完成了题目描述所需要实现的功能,但是仍然存在不如人意的地方。可以排序上面多设计几个算法,实现多角度排序。在这个系统中没有员工序号的信息,所以允 6
许员工姓名相同,在一定程度上可能存在员工信息重复。
经过这次数据结构课程设计,我们不仅及时巩固的了数据结构、算法、以及软件工程的知识,并明白数据结构和算法对于程序时间和空间性能的影响,及软件工程提供的开发流程和工具对于实现特定功能程序的重要意义。
当我们面对一个实际问题,应该迅速根据问题性质和特点抽象成特定的数据结构,当然每个问题都有可能能够抽象成多种数据结构,每种数据结构适应于不同的算法。因此应该综合考虑这样的数据结构、算法以及它们的空间和时间效率,然后从中选择一个作为实现程序的基础。
用户使用说明
进入员工管理系统,首先看到的就是主菜单界面,然后提示:“请选择主菜单(0---6):” 如果选择1,进入添加员工模块,按照提示语依次录入员工对象信息。选择2,进入展示员工所有的信息模块,DOS界面显示刚才录入的员工信息。选择3,进入员工查询模块,在此模块下: 系统提示:按姓名查询、按编号查询,系统根据用户选择进行相应的处理,退 出查询模块时,系统进入主菜单模块。
选择4,进入删除员工模块,在此模块下: 系统提示:按编号删除、按姓名删除,系统根据用户选择,进行相应的处理,退出删除模块时,系统进入主菜单模块。
选择5,进入修改员工信息模块,在该模块下: 系统提示:修改整条信息,修改部分信息,系统根据用户选择,进行相应的功 能处理。当用户选择退出修改模块时,系统进入主菜单模块。
选择6,进入排序模块,在该模块下: 系统提示:按年龄排序、按工龄排序、回复原排序,系统根据用户的选择,进 行相应的处理。
选择0,退出系统。
测试结果
(一)当操作人员运行程序时,弹出的DOS界面如下:
(二)根据提示语,输入1,添加员工信息,操作如下界面:
(三)在主菜单输入2,进入输出员工功能,操作如下:
添加员工、展示所有员工信息功能实现。
(四)在主菜单输入3,查询员工信息
按编号查询,测试如下:
按姓名查询,测试如下:
以上查询功能测试功能。
(五)在主菜单,输入4,删除员工功能:
按编号删除,测试如下:
按姓名删除如下:
以上测试完成。
(六)在主菜单输入5,进入修改信息功能:
上面是对每一条记录进行的修改。当你选择2的菜单时,则是对某条信息的某个字段对其进行内容修改,在这里就不做演示了。
(七)在主菜单输入6,进入排序功能:
按年龄排序,测试如下:
按工龄排序相同操作,测试成功。回复排序,回复到未排序状态,测试成功。
(八)退出,将所有的员工信息写入message.txt 文件中,实现永久保存。退出系统,测试完成。
总结
在本系统的开发过程中由于时间也比较仓促、准备不充分,系统必然会存在一些缺陷和不足。对员工信息管理的整个流程不够熟悉,在需求分析时未能做到完全满足用户的需求。
课程设计中我们遇到很多问题。我们在开发时,我们查阅了许多资料,了解到即是对员工的编号号,姓名,年龄,工龄等复杂多样的信息,能够较清晰,快捷而操作方便的现代化管理系统。弄清了这个基本概念以后,我们又详细理解了老师所讲的设计要求和注意事项,大致确定了总体的设计思路,初步提出问题的解决方案,以及系统大致设计方案和框架,接下来我们就着手编程。在编程过程中,先是根据系统所要求,找出所需要知识点。编完程序,我们在机房进行了一次又一次的调试,找出了其中的错误,一一纠正,并且修改了其中不太完善的部分,力求做到实用并且精确
尽管本管理系统存在着很多不足,但其功能全面、易于日后程序更新、数据库管理容易、界面友好、操作方便、效率高、安全性好等优点是本管理系统所必需的。通过开发这个系统,我组掌握了的项目基本开发过程,用到的知识巩固了我对C语言的学习,但在这次设计中的最大收获并不是掌握这几门开发工具的应用,而是学会了设计系统的思维方法。
通过本次课程设计,我们对数据结构知识掌握了很多,并能将它用以程序编写中,并且提高了自己的解决实际问题的能力。
主要参考文献
[1]李云清,杨庆红,揭安全.数据结构(C语言版)[M].北京:人民邮电大学出版社,2004.6 [2]潘彦.算法设计与分析基础[M].北京:清华大学出版社,2007.1 [3]软件工程原理与应用/曾强聪,赵歆编著 北京:清华大学出版社,2011 [4] 吕凤翥.C++语言程序设计(第2版)[M].北京:电子工业出版社,2007.2 [5] 严蔚敏,吴伟民.数据结构(C语言版)[M].北京:清华大学出版社,2002.9----------------------------11
附录:源代码
#include
#define MAX_NUM 40
typedef struct{ int num;//编号
char name[MAX_NUM];//姓名
int age;//年龄
char job[MAX_NUM];//职位;
int workTime;// 工龄
}People;
typedef struct node{ People people;struct node * next;int len;//表示链表长度
}linklist;
void doAddMessage(linklist * s){ int i=0,value1=0,j;char ch;printf(“t请输入员工的姓名(以#号键结束):”);scanf(“%c”,&ch);while(ch!='#'){
s->people.name[i]=ch;
i++;
scanf(“%c”,&ch);} for(j=i;j<40;j++){
s->people.name[j]=' ';} getchar();printf(“t请输入员工的年龄:”);scanf(“%d”,&value1);s->people.age=value1;
getchar();printf(“t请输入员工的职位(以#号键结束):”);12
i=0;scanf(“%c”,&ch);while(ch!='#'){
s->people.job[i]=ch;
i++;
scanf(“%c”,&ch);} for(j=i;j<40;j++){
s->people.job[j]=' ';}
getchar();printf(“t请输入员工的工龄: ”);scanf(“%d”,&value1);s->people.workTime=value1;
}
//执行修改某个字段的信息 void doEditSome(linklist * p){ int i=0,max=0,value1=0,j;int flag=0;char str1[4],str2[40],ch;char a[]=“姓名”;char b[]=“年龄”;char c[]=“职位”;char d[]=“工龄”;getchar();printf(“t请输入你要修改的字段名称(以#号键结束):”);scanf(“%c”,&ch);while(ch!='#'){
str1[i]=ch;
i++;
scanf(“%c”,&ch);}
for(i=0;i if(a[i]==str1[i]) flag=1; else{ flag=0; break; } } 13 if(flag==0){ for(i=0;i if(b[i]==str1[i]) flag=2; else{ flag=0; break; } } } if(flag==0){ for(i=0;i if(c[i]==str1[i]) flag=3; else{ flag=0; break; } } } if(flag==0){ for(i=0;i if(d[i]==str1[i]) flag=4; else{ flag=0; break; } } } getchar(); if(flag==0){ printf(“t没有找到您要修改的字段!n”);}else if(flag==1){ printf(“t请输入该字段的值(以#号键结束):”);i=0;scanf(“%c”,&ch);while(ch!='#'){ str2[i]=ch; i++; scanf(“%c”,&ch);} for(j=i;j<40;j++){ str2[j]=' ';14 } } } for(i=0;i<40;i++){ } printf(“t请输入该字段的值:”);scanf(“%d”,&value1);p->people.age=value1;printf(“t请输入该字段的值(以#号键结束):”);i=0;scanf(“%c”,&ch);while(ch!='#'){ } for(j=i;j<40;j++){ } for(i=0;i<40;i++){ } printf(“t请输入该字段的值:”);scanf(“%d”,&value1);p->people.workTime=value1;p->people.job[i]=str2[i];str2[j]=' ';str2[i]=ch;i++;scanf(“%c”,&ch);p->people.name[i]=str2[i];}else if(flag==2){ }else if(flag==3){ }else{ //按编号查询员工信息 void searchPeopleByNum(linklist * head){ int number,flag=0;linklist * p;printf(“t请输入你要查询的编号:”);scanf(“%d”,&number);p=head->next;while(p!=NULL){ printf(“t%-10d%-20s%-10d%-20s%-10d”,p->people.num,p->people.name,p->people.age,p->if(p->people.num==number){ printf(“t编号 姓名 年龄 职位 工龄n”);15 people.job,p->people.workTime); } //按照姓名查找员工信息 void searchPeopleByName(linklist * head){ int j=0, i=0,flag=0;char a,ch[40];linklist * p;p=head->next;getchar();printf(“t请输入你要查询的姓名(以#号键结束):”);scanf(“%c”,&a);while(a!='#'){ } while(p!=NULL){ for(j=0;j } if(i==j){ printf(“t编号 姓名 年龄 职位 工龄if(p->people.name[j]!=ch[j])break;ch[i]=a;i++;scanf(”%c“,&a); } if(flag==0){ } printf(”t没有查到与你输入编号相匹配的员工信息!n“); } printf(”n“);flag=1;break;p=p->next;}else{ n”);printf(“t%-10d%-20s%-10d%-20s%-10d”,p->people.num,p->people.name,p->people.age,p-> } } else p=p->next;printf(“n”);flag=1;break;people.job,p->people.workTime);16 if(flag==0){ printf(“t没有查到与你输入姓名相匹配的员工信息!n”);} } //根据编号删除员工信息 void deletePeopleByNum(linklist * head){ int number,flag=0;linklist * p,* q;printf(“t请输入你要删除的编号:”);scanf(“%d”,&number);p=head->next;q=head;while(p!=NULL){ if(p->people.num==number){ q->next=p->next; free(p); flag=1; break; }else{ q=q->next; p=p->next; } } if(flag==0){ printf(“t没有查到与你输入编号相匹配的员工信息!n”);}else{ printf(“t删除成功!n”);} } //根据姓名删除 员工信息 void deletePeopleByName(linklist * head){ int j=0, i=0,flag=0;char a,ch[40];linklist * p,*q;p=head->next;q=head;getchar();printf(“t请输入你要查询的姓名(以#号键结束):”);scanf(“%c”,&a);while(a!='#'){ 17 ch[i]=a; i++; scanf(“%c”,&a);} while(p!=NULL){ for(j=0;j if(p->people.name[j]!=ch[j]) break; } if(i==j){ q->next=p->next; free(p); flag=1; break; } else{ q=q->next; p=p->next; } } if(flag==0){ printf(“t没有查到与你输入姓名相匹配的员工信息!n”);}else{ printf(“t删除成功!n”);} } //修改 void edit(linklist * head,char ch){ int number,flag=0;linklist * p,* q;printf(“t请输入你要修改信息的编号:”);scanf(“%d”,&number);p=head->next;q=head;while(p!=NULL){ if(p->people.num==number){ if(ch=='1'){ doAddMessage(p); } if(ch=='2'){ doEditSome(p); } flag=1; break; }else{ q=q->next; p=p->next; } } if(flag==0){ printf(“t没有查到与你输入编号相匹配的员工信息!n”);}else{ printf(“t修改成功!n”);} } //实现 三种条件的排序 void sortAll(linklist * head,char a){ linklist * p,* q,*s;int flag=0;int i=0;for(i=0;i flag=0; p=head; q=p->next; s=q->next; while(s!=NULL){ if((q->people.age < s->people.age)&&a=='1'){ q->next=s->next; s->next=q; p->next=s; flag=1; } if((q->people.workTime < s->people.workTime)&&a=='2'){ q->next=s->next; s->next=q; p->next=s; flag=1; } if((q->people.num > s->people.num)&&a=='3'){ q->next=s->next; s->next=q; p->next=s; flag=1; } p=p->next;19 } } } q=p->next;s=q->next;if(flag==0)break; printf(“t排序完成,请继续操作!n”);//添加员工信息 void addMessage(linklist * head){ } //展示所有员工的信息 void showAllMessage(linklist * head){ printf(“t%-10d%-20s%-10d%-20s%-10d”,p->people.num,p->people.name,p->people.age,p->linklist * p;p=head->next;printf(“t编号 姓名 年龄 职位 工龄n”);while(p!=NULL){ char ch;int i=0,value1;linklist * s,* p;s=(linklist *)malloc(sizeof(linklist));s->people.num=head->len+1;printf(“nt员工的编号为:%dn”,s->people.num);doAddMessage(s);p=head;while(p->next!=NULL){ } s->next=p->next;p->next=s;head->len=head->len +1;getchar(); printf(“t是否继续添加(是、否/y、n):”);scanf(“%c”,&ch);getchar();if(ch=='y'||ch=='Y'){ } addMessage(head);getchar();p=p->next;20 people.job,p->people.workTime); p=p->next; printf(“n”);} printf(“n”);} //查询员工信息 void searchPeople(linklist * head){ char ch='y';if(head->next==NULL){ printf(“t目前暂无存储任何人员信息,无法进行任何查询操作!n”);}else{ printf(“t1.按编号查询。n”); printf(“t2.按姓名查询。n”); printf(“t3.退出查询界面。n”); printf(“t******************************************************n”); printf(“t请选择操作菜单(1-3): ”); scanf(“%c”,&ch); switch(ch){ case '1': searchPeopleByNum(head); break; case '2': searchPeopleByName(head); break; case '3':break; } } getchar();} //删除员工信息 void deletePeople(linklist * head){ char ch='y';if(head->next==NULL){ printf(“t目前暂无存储任何人员信息,无法进行任何删除操作!n”);}else{ printf(“t1.按编号删除。n”); printf(“t2.按姓名删除。n”); printf(“t3.退出删除界面。n”);printf(“t******************************************************n”);21 printf(“t请选择操作菜单(1-3): ”); scanf(“%c”,&ch); switch(ch){ case '1': deletePeopleByNum(head); break; case '2': deletePeopleByName(head); break; case '3':break; } } getchar();} //修改员工信息 void editMessage(linklist * head){ char ch='y';if(head->next==NULL){ printf(“t目前暂无存储任何人员信息,无法进行任何删除操作!n”);}else{ printf(“t1.修改整条记录。n”); printf(“t2.修改部分。n”); printf(“t3.退出修改界面。n”); printf(“t******************************************************n”); printf(“t请选择操作菜单(1-3): ”); scanf(“%c”,&ch); switch(ch){ case '1': edit(head,ch); break; case '2': edit(head,ch); break; case '3':break; } } getchar();} //单链表排序 void sort(linklist * head){ char ch='y';22 if(head->next==NULL){ printf(“t目前暂无存储任何人员信息,无法进行任何排序操作!n”);}else if(head->next->next==NULL){ printf(“t只有一条数据无需进行排序!n”);}else{ printf(“t1.按年龄排序。n”); printf(“t2.按工龄排序。n”); printf(“t3.恢复原顺序。n”); printf(“t4.退出排序界面。n”); printf(“t******************************************************n”); printf(“t请选择操作菜单(1-4): ”); scanf(“%c”,&ch); switch(ch){ case '1': sortAll(head,ch); break; case '2': sortAll(head,ch); break; case '3': sortAll(head,ch); break; case '4':break; } } getchar();} //退出时保存将文件保存到文件中 void saveMessage(linklist * head){ FILE * fp;linklist *p,*p0;fp=fopen(“message.txt”,“wb”); p=head;if(fp==NULL){ printf(“nt文件保存失败!n请重新启动本系统...n”);exit(0);} while(p!=NULL){ //将链表中的信息写入文件中 if(fwrite(p,sizeof(linklist),1,fp)!=1){ printf(“nt写入文件失败!n请重新启动本系统!n”);} 23 p0=p;p=p->next;free(p0);} head=NULL;fclose(fp);} //登录时加载信息 void loadAddMessage(linklist * head){ FILE *fp;linklist *p1,*p2,*p3;int flag=0;fp=fopen(“message.txt”,“rb”);p1=(linklist *)malloc(sizeof(linklist));fread(p1,sizeof(linklist),1,fp);p3 = p2=head;//读出信息,重新链入链表 while(!feof(fp)){ p1=(linklist *)malloc(sizeof(linklist));fread(p1,sizeof(linklist),1,fp);p2->next=p1;p3=p2;p2=p1;flag=1;} p3->next=NULL;if(p3->people.num < 1){ head->len=0;head->next=NULL;}else if(flag==1){ head->len=p3->people.num;}else{ head->len=0;} free(p1);fclose(fp);} //主函数 int main(){ char ch='y';linklist * head;head =(linklist *)malloc(sizeof(linklist));head->len =0;head->next=NULL;24 loadAddMessage(head);printf(“tttt员工管理系统n”);printf(“t******************************************************n”);do{ printf(“tttt操作菜单n”); printf(“t1.添加员工t2.展示所有的员工信息t3.查询员工信息n”); printf(“t4.删除员工t5.修改员工信息 t6.排序n”); printf(“t0.退出系统n”); printf(“t******************************************************n”); printf(“t请选择操作菜单(0-6): ”); scanf(“%c”,&ch); getchar(); switch(ch){ case '1': addMessage(head); break; case '2': showAllMessage(head); break; case '3': searchPeople(head); break; case '4': deletePeople(head); break; case '5': editMessage(head); break; case '6': sort(head); break; case '0': saveMessage(head); printf(“t保存成功!”); exit(0);} }while(ch!='0');getchar();return 0;} 《数据结构》 课程设计报告书 一.课程设计题目 图书借阅管理系统 二.课程设计内容 实现图书管理信息系统的设计 (一)管理员功能: ①登录:输入管理员密码,若密码错误则不得执行管理员操作。 ②添加新书:增加新的图书资料,同时需检查新书的图书编号是否已存在于原图书资料中,若已存在则应取消添加或提示重新输入。 ③修改图书:通过编号查询该图书资料,若该编号存在,则显示已有信息,允许修改,否则提示 无该图书信息。 ④删除图书:通过编号查询该图书资料,若该编号存在,则显示已有信息,允许删除,否则提示无该图书信息。删除对象包括该图书资料以及“图书状态”和“借阅人”中与此书相关的所有记录。 ⑤查找图书: A.按书号查找:通过编号查询该图书资料,若该编号存在,则显示图书信息,否则提示无该图书信息。 B.按书名查找:通过书名查询该图书资料,若该编号存在,则显示图书信息,否则提示无该图书信息。 C.按作者查找:通过作者查询该图书资料,若该编号存在,则显示图书信息,否则提示无该图书信息。 ⑥查看全部图书:显示所有图书资料,包括书号、书名、作者、状态和借阅人等信息。 ⑦修改读者:通过姓名查询该读者信息,若该姓名存在,则显示已有信息,允许修改,否则提示无该读者信息。 ⑧删除读者:通过姓名查询该读者信息,若该姓名存在,则显示已有信息,允许删除,否则提示无该读者信息。删除对象包括该读者姓名、班级、电话以及“图书状态”和“借阅人”中与此人相关的所有记录。 ⑨查看所有读者:显示所有读者资料,包括姓名、班级、电话等信息。 (二)读者功能: ①登录:输入读者姓名,若未经注册则不得进入读者服务界面。②注册:新用户经注册方可登录系统并使用读者服务功能。③借书: A.输入所需图书编号,判断该编号是否存在,若不存在则提示重新输入。 B.若所输入图书编号存在,则判断该书籍是否已被借出,若已借则不允许执行借书操作。 C.若所输入图书未借,则提示输入读者姓名,判断所输入读者姓名是否存在,若不存在则提示重新输入。D.若读者姓名存在,则允许执行借书操作。 E.借书处理包括在“图书状态”中加上“已借”标记。④还书: A.输入所借书编号,判断该编号是否存在,若不存在则提示重新输入。B.判断该书是否已借出,若未借则不允许执行还书操作。C.借书处理包括在“图书状态”中加上“未借”标记。⑤查询图书: A.按书号查找:通过编号查询该图书资料,若该编号存在,则显示图书信息,否则提示无该图书信息。 B.按书名查找:通过书名查询该图书资料,若该编号存在,则显示图书信息,否则提示无该图书信息。 C.按作者查找:通过作者查询该图书资料,若该编号存在,则显示图书信息,否则提示无该图书信息。 ⑥查看借阅情况:输入读者姓名,若该姓名不存在则提示重新输入,若该姓名存在则显示该读者借阅信息。 三.算法设计 1.流程图(部分示例) ①管理员登录 ②读者登录 ③读者借阅图书 ④管理员或读者按书名查找图书 2.代码实现 #include #include //将字符串BookFile替换原文件中的宏名称book #define ReaderFile “reader.txt” using namespace std;//**********读者结构体,用于存放读者基本信息********** class Reader { private: char rname[10]; char rclass[10]; char rtel[10];public: Reader()//构造函数,实现数据初始化 {strcpy(rname,“");strcpy(rclass,”“);strcpy(rtel,”“);} //初始化 void set_rname(char *rn)//设置读者姓名 {strcpy(rname,rn);} //将rn的字符复制给rname char * get_rname()//获得读者姓名 {return rname;} //返回rname的值 void set_rclass(char *rc)//设置班级 {strcpy(rclass,rc);} char *get_rclass() //获得班级 {return rclass;} void set_rtel(char *rt) //设置电话 {strcpy(rtel,rt);} char *get_rtel() //获得电话 {return rtel;} void copy(Reader m)//读者Reader结构体copy函数 {strcpy(rname,m.get_rname());strcpy(rclass,m.get_rclass());strcpy(rtel,m.get_rtel());} };//*********读者管理结构体,实现对读者用户的管理********* class ReaderManage { Reader readers[50];//定义读者结构体数组对象,最多50位 int length; void readFile() //读取读者文件函数 { ifstream fread;//定义输入文件流对象fread length=0; //计数 if(!fread) {cout<<”读取磁盘文件失败!“< fread.open(ReaderFile,ios::binary);//使文件流与文件关联,以二进制方式打开 int i=0; while((fread.read((char *)&readers[i],sizeof(Reader))))//计算并返回所占字节数 i++; length=i; fread.close();//关闭磁盘文件 } void saveFile()//保存读者文件 { ofstream fwrite; //定义输出文件流对象fwrite if(!fwrite) {cout<<”文件保存失败!n“;exit(1);} fwrite.open(ReaderFile,ios::binary);//使文件流与文件关联,以二进制方式打开 fwrite.write((char *)readers,length*sizeof(Reader));//计算并返回所占字节数 fwrite.close();//关闭磁盘文件 } public: ReaderManage()//构造函数,读取读者文件 {readFile();} ~ReaderManage()//析构函数,保存读者文件 {saveFile();} void add_reader(Reader r)//添加读者用户函数 { if(length>=50) {cout<<”对不起,注册人数已满!n“;return;} readers[length].copy(r);//调用读者结构体copy函数 length++;} int search(char *rn)//按姓名查找读者函数 { for(int i=0;i if(strcmp(readers[i].get_rname(),rn)==0)//判断是否相等 return i; return-1; } bool revise(Reader reader,int i)//修改读者资料函数 { readers[i].copy(reader);//调用读者结构体cpoy函数 return true;} void delete_reader(int index)//删除读者函数 { for(int i=index;i readers[i].copy(readers[i+1]);//用后面的地址覆盖前面的地址 length--;} bool log_reader(Reader r)//登录时判断读者用户是否存在函数,相当于遍历 { for(int i=0;i if(strcmp(readers[i].get_rname(),r.get_rname())==0) return true; return false; } void reg_reader()//注册用户函数 { char n[10]; //姓名name char c[10]; //班级class char t[10]; //电话tel Reader reader; cout<<”nt请输入您的姓名:“; cin>>n; cout<<”nt请输入您的所在班级:“; cin>>c; cout<<”nt请输入您的联系电话:“; cin>>t; reader.set_rname(n);//调用读者结构体设置读者姓名函数 reader.set_rclass(c);//调用读者结构体设置读者班级函数 reader.set_rtel(t);//调用读者结构体设置联系电话函数 add_reader(reader);//调用读者结构体添加读者函数 cout<<”nt注册成功!“;} void show_reader()//不带参的显示读者信息函数 { cout<<”n ☆☆☆☆☆☆☆☆☆☆☆☆读★★者★★信★★息★★列★★表☆☆☆☆☆☆☆☆☆☆☆nn“; cout<<”姓名ttt班级ttt电话n“; for(int i=0;i { cout< cout<<”ttt“< cout<<”ttt“< } } void show_reader(int i)//带参的显示读者信息函数 { cout<<”n ☆☆☆☆☆☆☆☆☆☆☆☆读★★者★★信★★息★★列★★表☆☆☆☆☆☆☆☆☆☆nn“; cout<<”姓名ttt班级ttt电话n“; cout< cout<<”ttt“< cout<<”ttt“< } }; //********书籍结构体,用于存放书籍基本信息******** class Book { private: char bnum[10]; //书号 char bname[20]; //书名 char bauthor[10]; //作者 char rname[10]; //借阅人 public: int tag; //状态标记判断指标(已借/在架)Book() //构造函数初始化信息 {strcpy(bnum,”“);strcpy(bname,”“);strcpy(bauthor,”“);strcpy(rname,”“);tag=0;} void set_bnum(char *no) //设置书号 {strcpy(bnum,no);} //把字符串no中的字符复制到字符串bnum中 char *get_bnum() //获得书号 { return bnum;} //返回值为bnum void set_bname(char *n) //设置书名 {strcpy(bname,n);} char *get_bname() //获得书名 {return bname;} void set_bauthor(char *a) //设置作者 {strcpy(bauthor,a);} char * get_bauthor() //获得作者姓名 {return bauthor;} void set_tag(int t) //状态设置 {tag=t;} void set_rname(char *rn) //设置借阅人 {strcpy(rname,rn);} char *get_rname() //获得借阅人姓名 {return rname;} void show_tag() //显示图书状态 { if(tag==1) {cout<<”已借“;} else {cout<<”在架“;} } void copy(Book m) //Book结构体copy函数 { strcpy(bnum,m.get_bnum()); //将获得书号函数里的返回值里的字符复制到bnum strcpy(bname,m.get_bname()); strcpy(bauthor,m.get_bauthor()); tag=0; } };//**********书籍管理结构体,实现管理书籍功能********** class BookManage { private: Book books[100]; //定义Book书籍结构体数组对象,最大容量100本 int length; void saveFile() //保存书籍文件 { ofstream fwrite;//定义输出文件流ofstream结构体对象fwrite if(!fwrite) {cout<<”文件保存失败!n“;exit(1); } fwrite.open(BookFile,ios::binary);//使文件流与文件建立关联,以二进制方式打开 fwrite.write((char *)books,length*sizeof(Book));//计算并返回所占字节数 fwrite.close(); //关闭磁盘文件 } void readFile() //读取书籍文件 { ifstream fread;//定义输入文件流对象fread length=0; if(!fread) {cout<<”文件读取失败!“< Book temp; //定义书籍结构体临时对象temp int i=0; fread.open(BookFile ,ios::binary);//使文件流与文件建立关联,以二进制方式打开 while((fread.read((char *)&books[i],sizeof(Book)))) i++; //每读完一次,指针后移一位,直到不能读出正确结果为止 length=i; fread.close();} public: BookManage() //构造函数,读取磁盘文件 { length=0; //从头读起,计数,最大100 readFile(); //调用读取文件函数 } ~BookManage() //析构函数,保存磁盘文件 { saveFile(); //调用保存文件函数 } bool add(Book book) //添加图书资料 { if(length>=100) { cout<<”对不起,储存已满,您无法继续添加!n“; return-1; } else { books[length].copy(book);//调用书籍结构体copy函数 length++; return(length-1); } } int bnu_search(char *bnu) //按书号查找书籍 { for(int i=0;i if(strcmp(books[i].get_bnum(),bnu)==0)//字符串比较,判断是否相等 return i; return-1; } int bna_search(char *bna) //按书名查找书籍 { for(int i=0;i if(strcmp(books[i].get_bname(),bna)==0)//判断 return i; return-1; } int bau_search(char *bau)//按作者查找书籍 { for(int i=0;i if(strcmp(books[i].get_bauthor(),bau)==0)//判断 return i; return-1; } int rn_search(char *rn)//按借阅人查找书籍 { for(int i=0;i if(strcmp(books[i].get_rname(),rn)==0)//判断 return i; return-1; } void revise(Book book,int i)//带参的修改书籍函数 {books[i].copy(book);} //调用Book结构体copy函数 void deleteBook(int index)//带参的删除书籍资料函数 { for(int i=index;i books[i].copy(books[i+1]);//用后面的地址将当前的地址覆盖 length--; } void show_book()//不带参的显示书籍函数 { cout<<” ☆☆☆☆☆☆☆☆☆☆☆书★★籍★★信★★息★★列★★表☆☆☆☆☆☆☆☆☆☆☆nn“; cout<<”书号“; cout.width(10); cout<<”书名“; cout.width(10); cout<<”作者“; cout.width(17); cout<<”状态“; cout.width(25); cout<<”借阅人n“; for(int i=0;i { cout< cout.width(10); cout< cout.width(10); cout< cout.width(20); books[i].show_tag(); cout.width(20); cout< } } void show_book(int i)//带参的显示书籍函数 { cout<<” ☆☆☆☆☆☆☆☆☆☆☆书★★籍★★信★★息★★列★★表☆☆☆☆☆☆☆☆☆☆☆nn“; cout<<”书号“; cout.width(10); cout<<”书名“; cout.width(10); cout<<”作者“; cout.width(17); cout<<”状态“; cout.width(25); cout<<”借阅人n“; cout< cout.width(10); cout< cout.width(10); cout< cout.width(20); books[i].show_tag(); cout.width(20); cout< } void br_book()//读者借、还书功能函数 { ReaderManage reader; int choi;//选择 int a; //图书状态指标(1已借2在架) char sh[10];//需要还书的书号 char dz[10];//读者姓名 cin>>sh; int index=bnu_search(sh);//定义一个变量等于查找到的书号 if(index>=0) { if(books[index].tag==1)//已借 a=1; if(books[index].tag==0)//在架 a=2; switch(a) { case 1: cout<<”nt该书目前状态为<已借出>n“; cout<<”nt请选择您需要的服务:1:还书 0:返回n“; cin>>choi; cin.ignore();//清除以回车结束的输入缓冲区的内容,消除上一次输入对下一次输入的影响 if(choi!=1&&choi!=0) { cout<<”nt操作有误,请重新选择(0/1)!n“; return; } else if(choi==1) { cout<<”nt请输入您的姓名:“; cin>>dz; cin.ignore(); int index1=reader.search(dz); if(index1==-1) { cout<<”nt对不起,系统无该读者记录,新用户请先注册!“; return; } else { strcpy(dz,”“);//将读者姓名已空白代替 books[index].set_rname(dz);//借阅人一项变为空白 books[index].set_tag(0);//图书状态变为在架 cout<<”nt还书成功!“< } }break; case 2: cout<<”nt该书目前状态为<在馆>n“; cout<<”nt请您需要的服务:1:借书 0:返回n“; cin>>choi; cin.ignore(); if(choi!=1&&choi!=0) { cout<<”nt操作有误,请重新选择(0/1)!n“; return; } else if(choi==1) { cout<<”nt请输入您的姓名:“; cin>>dz; int index1=reader.search(dz); if(index1==-1) { cout<<”nt对不起,系统无改读者记录,新用户请先注册!“; return; } else { books[index].set_rname(dz); books[index].set_tag(1); cout<<”nt借书成功!“< } }break; } } else { cout<<”nt对不起,系统无该书记录!“;} } bool in(int i)//判断图书是否在架函数 { if(books[i].tag==1) return false; return true; } };//**********菜单结构体,实现界面引导********** class Menu { BookManage bm; //定义书籍管理结构体对象bm ReaderManage rm; //定义读者管理结构体对象rm Reader r; //定义读者结构体对象r private: int choice; //菜单序号选择 int key; //管理员密码 public: void header() //页眉 { system(”color fd“); cout<<”t ☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆n“; cout<<”t ☆ ☆n“; cout<<”t ☆ ☆n“; cout<<”t ☆ 图 书 借 阅 管 理 系 统 ☆n“; cout<<”t ☆ ☆n“; cout<<”t ☆ ☆n“; cout<<”t ☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆n“;} void log_menu() //主界面登录菜单 { system(”color fd“); header(); cout<<”nttt< 请 选 择 登 录 身 份 >n“; cout<<”ntttt1: 管理员nntttt2: 读 者nntttt0: 退 出nt您的选择是: “;choice: cin>>choice; cin.ignore(); //清除以回车结束的输入缓冲区的内容,消除上一次输入对下一次输入的影响 switch(choice) { case 1: log_admin(); //管理员登录,需密码验证 break; case 2: reader_lr(); //读者登录或注册 break; case 0: exit(1); //退出系统 break; default: cout<<”nt您的操作有误,请重新选择(0→2): “; goto choice; } } void admin_menu() //管理员管理菜单 { system(”cls“); system(”color f9“); cout<<”t ☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆n“; cout<<”t ☆ ☆n“; cout<<”t ☆ 系★统★管★理★界★面 ☆n“; cout<<”t ☆ ☆n“; cout<<”t ☆ 1: 添加新的图书资料 2: 修改已有图书资料 ☆n“; cout<<”t ☆ ☆n“; cout<<”t ☆ 3: 删除已有图书资料 4: 查找已有图书资料 ☆n“; cout<<”t ☆ ☆n“; cout<<”t ☆ 5: 查看所有图书资料 6: 修改读者用户信息 ☆n“; cout<<”t ☆ ☆n“; cout<<”t ☆ 7: 删除读者用户信息 8: 查看所有读者信息 ☆n“; cout<<”t ☆ ☆n“; cout<<”t ☆ 9: 返回系统登录界面 0: 退出图书管理系统 ☆n“; cout<<”t ☆ ☆n“; cout<<”t ☆ ☆n“; cout<<”t ☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆n“; cout<<”nt请选择您需要的服务序号: “;choice: cin>>choice; cin.ignore(); switch(choice) { case 1: //添加图书 addBook(); bm.~BookManage(); break; case 2: //修改图书 reviseBook(); bm.~BookManage(); break; case 3: //删除图书 delBook(); bm.~BookManage(); break; case 4: //查找图书 absearch_menu(); break; case 5: //查看全部图书 bm.show_book(); cout<<”nt显示完毕!“; system(”pause“); admin_menu(); break; case 6: //修改读者 reviseReader(); rm.~ReaderManage(); break; case 7: //删除读者 delReader(); rm.~ReaderManage(); break; case 8: //查看所有读者 rm.show_reader(); cout<<”nt显示完毕!“; system(”pause“); admin_menu(); break; case 9: //返回系统登录界面 system(”cls“); log_menu(); case 0: //退出系统 exit(1); break; default: cout<<”nt您的操作有误,请重新选择(0→7): “; goto choice; } } void reader_menu() //读者服务菜单 { system(”cls“); system(”color f9“); cout<<”t ☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆n“; cout<<”t ☆ ☆n“; cout<<”t ☆ 读★者★服★务★界★面 ☆n“; cout<<”t ☆ ☆n“; cout<<”t ☆ 1: 借 阅 图 书 2: 归 还 图 书 ☆n“; cout<<”t ☆ ☆n“; cout<<”t ☆ 3: 查 找 图 书 4: 借 阅 情 况 ☆n“; cout<<”t ☆ ☆n“; cout<<”t ☆ 5: 返 上 一 级 0: 退 出 系 统 ☆n“; cout<<”t ☆ ☆n“; cout<<”t ☆ ☆n“; cout<<”t ☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆n“; cout<<”nt请选择您需要的服务序号: “;choice: cin>>choice; cin.ignore(); switch(choice) { case 1: cout<<”nt请输入您欲借阅的图书书号: “; bm.br_book(); bm.~BookManage(); break; case 2: cout<<”nt请输入您欲归还的图书书号: “; bm.br_book(); bm.~BookManage(); break; case 3: bsearch_menu(); break; case 4: rn_search(); break; case 5: system(”cls“); reader_lr(); break; case 0: exit(1); break; default: cout<<”nt您的操作有误,请重新选择(0→5): goto choice; } } void bsearch_menu() //读者查找书籍菜单 { system(“color f2”); cout<<“ttt☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆n”;cout<<“ttt☆ ☆n”; cout<<“ttt☆ 书★籍★查★找★界★面 ☆n”; cout<<“ttt☆ ☆n”; cout<<“ttt☆ 1: 按 书号查找 ☆n”; cout<<“ttt☆ ☆n”; cout<<“ttt☆ 2: 按 书名查找 ☆n”; cout<<“ttt☆ ☆n”; cout<<“ttt☆ 3: 按 作者查找 ☆n”; cout<<“ttt☆ ☆n”; cout<<“ttt☆ 4: 返 回 上 级 ☆n”; cout<<“ttt☆ ☆n”; cout<<“ttt☆ 0: 退 出 系 统 ☆n”;cout<<“ttt☆ ☆n”; cout<<“ttt☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆n”; int bsc;//book search choice cout<<“nt请输入您需要的服务序号: ”; cin>>bsc; cin.ignore(); switch(bsc){ case 1: bnu_search(); break; case 2: bna_search(); “; break; case 3: bau_search(); break; case 4: reader_menu(); break; case 5: exit(1); default: cout<<”nt操作有误,请重新选择<0→4>“; break; } } void absearch_menu() //管理员查找书籍菜单 { system(”color f2“); cout<<”ttt☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆n“; cout<<”ttt☆ ☆n“; cout<<”ttt☆ 书★籍★查★找★界★面 ☆n“; cout<<”ttt☆ ☆n“; cout<<”ttt☆ 1: 按 书号查找 ☆n“; cout<<”ttt☆ ☆n“; cout<<”ttt☆ 2: 按 书名查找 ☆n“; cout<<”ttt☆ ☆n“; cout<<”ttt☆ 3: 按 作者查找 ☆n“; cout<<”ttt☆ ☆n“; cout<<”ttt☆ 4: 返 回 上 级 ☆n“; cout<<”ttt☆ ☆n“; cout<<”ttt☆ 0: 退 出 系 统 ☆n“; cout<<”ttt☆ ☆n“; cout<<”ttt☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆n“; int bsc;//book search choice cout<<”nt请输入您需要的服务序号: “; cin>>bsc; cin.ignore(); switch(bsc) { case 1: bnu_search(); break; case 2: bna_search(); break; case 3: bau_search(); break; case 4: admin_menu(); break; case 5: exit(1); default: cout<<”nt操作有误,请重新选择<0→4>“; break; } } void reader_lr()//读者登录或注册菜单 { system(”cls“); header(); system(”color f1“); cout<<”nttt< 读 者 登 录 界 面 >n“; cout<<”nttt 1: 登 录t2: 注 册nnttt 3: 返 回t0: 退 出nt您的选择是: “; int rlc;//reader login choice choice: cin>>rlc; cin.ignore(); switch(rlc) { case 1: //已注册读者登录 cout<<”nt请输入您的姓名: “; char rn[10];//reader name cin>>rn; r.set_rname(rn); if(rm.log_reader(r)) { cout<<”nt登录成功!“; system(”pause“); reader_menu(); } else cout<<”nt登录失败!新用户请先注册!“; system(”pause“); reader_lr(); break; case 2: //新用户注册 rm.reg_reader(); rm.~ReaderManage(); system(”pause“); reader_lr(); break; case 3: system(”cls“); log_menu(); case 0: exit(1); break; default: cout<<”nt您的操作有误,请重新选择(0→2): goto choice; } } void log_admin() //管理员登录 { cout<<“nt请输入管理员密码:”; int key; cin>>key; if(key==14125) { cout<<“nt登录成功!nnt”; system(“pause”); admin_menu(); //管理员操作菜单 } else {cout<<“nt登录失败!原因是密码错误!n”; cout<<“nt请选择 <1:返回上一级菜单 0:退出系统> cin>>choice; cin.ignore(); switch(choice) ”;“; { case 1: system(”cls“); log_menu(); break; case 0: exit(1); break; default: cout<<”nt操作有误,请重新选择(0/1)“; } } } void rn_search() //按书号查找函数 { char rn[10];//reader name cout<<”nt请输入您的姓名:“; cin>>rn; int index=bm.rn_search(rn); if(index>=0) bm.show_book(index); else cout<<”nt对不起,系统无您的借阅记录!“; cout<<”nt“; system(”pause“); reader_menu(); } void bnu_search() //按书号查找函数 { char bnu[10]; cout<<”nt请输入您要查找的书号:“; cin>>bnu; int index=bm.bnu_search(bnu); if(index>=0) bm.show_book(index); else cout<<”nt对不起,系统无该书籍记录!“; cout<<”nt“; system(”pause“); bsearch_menu(); } void bna_search() //按书名查找函数 { cout<<”nt请输入您要查找的书名:“< char bna[20]; cin>>bna; int index=bm.bna_search(bna); if(index>=0) bm.show_book(index); else cout<<”nt对不起,系统无该书籍记录!“; cout<<”nt“; system(”pause“); bsearch_menu(); } void bau_search() //按作者查找函数 { cout<<”nt请输入您要查找的作者:“< char bau[10]; cin>>bau; int index=bm.bau_search(bau); if(index>=0) bm.show_book(index); else cout<<”nt对不起,系统无该书籍记录!“; cout<<”nt“; system(”pause“); bsearch_menu(); } void addBook() //新增书籍函数 { char numb[10]; //书号 char nameb[20]; //书名 char authorb[10];//作者 Book book; //书籍结构体对象book int tag1;input1:cout<<”nt请输入新书书号:“; cin>>numb; int index=bm.bnu_search(numb); if(index==-1) { cout<<”nt系统目前尚无该书记录,您可以继续操作!n“; cout<<”nt请输入新书书名:“; cin>>nameb; cout<<”nt请输入新书作者:“; cin>>authorb; tag1=0; book.set_bnum(numb); book.set_bname(nameb); book.set_bauthor(authorb); book.set_tag(tag1); bm.add(book); cout<<”nt恭喜您!新书资料录入成功!“; } else { cout<<”nt对不起,该书号纪录已存在!请重新输入!“; goto input1; } system(”pause“); admin_menu();} void reviseBook() //修改书籍函数 { char numb[10]; char nameb[20]; char authorb[10]; Book book; int index=-1;input2: cout<<”nt请输入您要修改书籍的书号:“; cin>>numb; index=bm.bnu_search(numb); if(index==-1) { cout<<”nt对不起,您输入的书号不存在,请重新输入!“< goto input2; return; } bool sta=bm.in(index);//判断是否在馆 if(sta) { cout<<”nt该书目前处于<在架>状态,您可以继续操作!“; cout<<”nt请输入更改后的书名:“; cin>>nameb; cout<<”nt请输入更改后的作者:“; cin>>authorb; book.set_bnum(numb); book.set_bname(nameb); book.set_bauthor(authorb); bm.revise(book,index); cout<<”nt恭喜您!书籍资料修改成功!“;} else cout<<”nt该书已被借出,请于读者归还后再进行相关操作!“< system(”pause“); admin_menu(); } void delBook() //删除书籍函数 { char numb[10]; cout<<”nt请输入您要删除书籍的书号:“; cin>>numb; int index=bm.bnu_search(numb); if(index>=0) { cout<<”nt您确定要删除该书记录吗(y/n) “; char y; cin>>y; if(y=='y'||y=='Y') { bm.deleteBook(index); cout<<”nt删除成功!“; } else cout<<”nt删除取消!“; } else cout<<”nt对不起,系统没有该图书记录!“; system(”pause“); admin_menu(); } void reviseReader()//修改读者用户函数 { char namer[10]; Reader reader;get1: cout<<”nt请输入你要修改读者用户的姓名: “; cin>>namer; int index=rm.search(namer); if(index==-1) { cout<<”nt对不起,系统无改读者记录,重新输入请按1,返回请按0: int a; cin>>a;get2: cin.ignore(); switch(a) { case 1: goto get1; break; case 0: system(“pause”); admin_menu(); break; default: cout<<“nt您的操作有误,请重新选择(0/1): ”; goto get2; } return; } “; else { char namer[10]; char classr[10]; char telr[10]; Reader reader; cout<<”nt请输入更改后的读者姓名:“; cin>>namer; cout<<”nt请输入更改后的班级名称:“; cin>>classr; cout<<”nt请输入更改后的联系电话:“; cin>>telr; reader.set_rname(namer); reader.set_rclass(classr); reader.set_rtel(telr); cout<<”nt是否真的修改该记录(y/n?):“; char y; cin>>y; if(y=='y'||y=='Y') { rm.revise(reader,index); cout<<”nt修改成功!n“; } else cout<<”nt操作取消!n“; } system(”pause“); admin_menu(); } void delReader() //删除读者用户函数 { cout<<”nt请输入您要删除的读者用户的姓名:“< char namer[10]; cin>>namer; int index=rm.search(namer); if(index>=0) { cout<<”nt是否真的删除该记录(y/n?): “; char y; cin>>y; if(y=='y'||y=='Y') { rm.delete_reader(index); cout<<”nt删除成功!n“; } else cout<<”nt操作取消!n“; } else cout<<”nt对不起,系统尚无该读者记录!“; system(”pause“); admin_menu(); } };//********主函数******** int main(){ system(”color fd“);Menu menu;//定义菜单结构体对象menu cout<<”ttt 文计091-1 庞丽萍 200990514125 “;cout<<”ttt 当前日期:2011-6-22 星期三“;cout<<”ttt 当前时间:08:00 “;cout<<”nttt ★ 欢 “;cout<<”★ 迎 “; } cout<<”★ 进 “;cout<<”★ 入 ★nn";menu.log_menu();return 0;四.程序正确性验证 1主页面 2.管理员登陆页面 3.图书添加 五.课程设计过程中出现的问题、原因及解决方法 1.用户登录密码时,不能使用暗码来保护密码。(未解决成功)2.每个界面都能退出到主页面,而不是直接跳出系统。(以解决)3.书名字长太多影响书籍、作者、数量等之间的一一对应关系。(为解决成功) 六.课程设计的主要收获 通过这几天学习设计图书信息管理系统,认识到一切看似简单的事情只有自己动手做,明白了其中的原理才会更好的把它变成自己的东西。图书管理系统主要用到了文件的输入输出,以及利用简单的顺序查找知识,加深了对数据结构的理解与应用。对于这次的课程设计,首先,许多知识不仅仅只是课本上的,需要我们自己去图书馆或网上收集资料。其次,编程过程终遇到各种错误,需要我们耐心分析,讨论,最后得出正确结果。第三,程序无错,进行调试,然后进行加工修改优化。 七.对今后课程设计的建议 希望老师可以分小组做课程设计,题目可以相应的增大难度。分组可以锻炼团对合作能力,队员可以相互讨论解决问题,彼此能够激发更多的思想,做出更完善的作品,同时也防止了互相拷贝的情况,让每个同学都积极的参与到设计中,而不是坐享其成。 数据结构课程设计报告 课程名称:数据结构课程设计 课设题目: 西文图书管理系统 教师姓名: 郭 艳 本科生姓名: 王瑞林 本科生学号: 20121002932 班 号: 191124 日 期:2014年6月20日 题号:十 题目:西文图书管理 1.需求分析 图书管理系统对象有两个,包括读者和管理员。 读者的需求:借书,还书,续借,查询当前所借书籍还书截至日期,查询借阅历史,修改登陆密码。其中借书可以根据书号和书名两种方式查询借阅。 管理员的需求:采编入库,清除库存,注册读者,删除读者,根据书号查询书籍,修改管理员用户名和密码。 2.设计 2.1设计思想 (1)数据与操作特性: 有搜索,插入,删除操作。而数据有:读者信息,书籍信息,读者借阅书籍历史信息,书籍读者借阅历史信息,读者当前所借书籍信息。(2)数据结构设计: 数据的逻辑结构有线性结构和树形结构。 根据书号和书名建立两个B-树,便于读者查询借阅,其中关键字设置为书籍指针,便于找到书籍 后直接进行修改书籍信息。 读者和书籍的信息从文件中读取,由于会不断注册和删除读者以及新增删除书籍,因此书籍和读者的信息采用单链表存储。 读者的借阅历史和书籍的读者历史,都采用数组的形式存储,为了节省存储空间,每个借阅历史数组最大空间为15。超过15个借阅历史,则删除最早的借阅历史。2.2设计表示(1)数据类型定义 typedef struct //日期结构体类型 { int year;//记录年 int month;//记录月 int day;//记录日 }Date;//记录借阅者所借书籍的信息结构体 typedef struct { char bookID[15];//书号 char name[15];//书名 char writer[15];//作者 Date bordate;//借阅时间 Date backdate;//还书时间 int flag;//是否续借,续借为1.否则为0 }BookHistory;//记录借阅者当前所借书籍的信息结构体 typedef struct { char bookID[15];//书号 char name[15];//书名 char writer[15];//作者 Date bordate;//借阅时间 Date lastdate;//最后还书期限 int flag;//是否续借,续借为1.否则为0 }BookRec;//记录书籍被借阅的读者记录 typedef struct { char readerID[15];//记录读者的借阅证号 char readername[15];//读者的名字 Date bor;//记录读者的借书日期 Date back;//记录读者的还书日期 int flag;//借阅者是否有续借迹象(flag取值0或者1)}ReaderHistory;//记录读者信息的结构体类型(允许读者同时借阅五本书,每本书支持续借一次)typedef struct { char readerID[12];//记录读者的借书证号,一般是学号 //记录书的信息的结构体类型 typedef struct { char bookID[15];//书号 char title[15];//记录书名 char writer[15];//记录著者 int currentnum;//书现存量 int totalnum;//书总存量 int bortimes;//被借的历史总次数 //B_LQueue *B_LQH; ReaderHistory RH[15];//借书者记录,规定链式队列的最大节点个数为15,来节省空间 char name[15];//读者的名字 char password[16];//读者登陆密码 BookRec rec[5];//读者现在所借书籍 int hn;//总借阅数量 //R_LQueue *R_LQH; BookHistory bh[15];//记录读者的借阅记录,规定链式队列的最大节点个数为15,来节省空间 int bn;//读者现在所借书籍数量,最大数量为5本 }Reader;}Book;//根据 书名为关键字的B-树的结构体类型 typedef struct Namenode //根据书名为关键字建立的B树 { typedef struct///根据书名建立的B树的搜索结果 { //根据书号为关键字的B-树的结构体类型 typedef struct IDnode //根据书号为关键字建立的B树 { typedef struct///根据书号建立的B树的搜索结果 { //从文件中读取书籍数据后存储在单链表里 typedef struct BookNode { //从文件中读取学生数据后存储在单链表里 typedef struct ReaderNode { Book SLbook;struct BookNode *next;BTIDnode *pt;////指向找到的节点指针 int i;//所找关键字在节点里的位置 int tag;//查找成功值为1,查找失败值为0 int n;//记录结点中的关键字(即书号)个数 Book *key[MAXM];//key[0...n-1],Maxsize个关键字(即书号)域 struct IDnode *chd[MAXM];//ptr[0...n],MAXM个指向子结点的指针域 BTNamenode *pt;////指向找到的节点指针 int i;//所找关键字在节点里的位置 int tag;//查找成功值为1,查找失败值为0 int n;//记录结点中的关键字(即书号)个数 Book *key[MAXM];//key[0...n-1],Maxsize个关键字(即书名)域 struct Namenode *chd[MAXM];//ptr[0...n],MAXM个指向子结点的指针域 struct Namenode *par;//指向父结点的指针域 }BTNamenode;}NameResult;struct IDnode *par;//指向父结点的指针域 }BTIDnode;}IDResult;}BookSLNode;Reader SLreader;struct ReaderNode *next;}ReaderSLNode;2.3详细设计 (1)登陆界面login():有管理员和读者登陆,都必须输入密码和用户名。 (2)管理员登陆adminer_login():管理员需输入登录名和密码,为了安全登录,将输入密码错误次数限制在5次。其中管理员密码和用户名以及初始用户名和密码从管理员文件里读出赋值给全局变量。当输入正确时,管理员功能界面函数admin_menu();当密码输入错误达6次以上,将调用锁定系统函数lock_admin_menu(),将系统锁定,下次进入系统时将不再显示登陆界面,而是初始管理员登陆。 (3)管理员采编入库insert_stock():输入新书的信息,调用SearchBTree_ID()按照书号在B-树搜索书籍,如果没有找到,返回书籍插入的位置,然后调用插入函数InsertBTree_Name(),InsertBTree_ID(),分别将书籍按书名和书号插入到相应的树中,同时将书籍信息插入到书籍链表里调用ListInsert_Book();同时将全局变量书籍总数booknum加1。 (4)管理员清除库存deletestock():根据书号书名搜索到书籍,在B-树中删除书籍,同时在书籍信息链表里删除。并将书籍总数booknum减1。 (5)管理员读者模块adminer_reader():有删除读者和注册读者两个功能,删除读者,按读者的ID查找到,在读者信息链表里删除读者,读者总数readernum减1;注册读者,初始密码为读者ID后6位,同时读者总数readernum加1。 (6)管理员修改用户名和密码adminer_change_password():连续两次输入新密码,两次结果一样,修改成功。 (7)学生登陆student_login():输入密码成功,调用 stu_menu()功能界面。(8)学生借书borrow():有两种搜索所借书籍的方式,按书名搜索,按书号搜索,使用相应的B-树搜索功能。借书成功后,将书籍信息写到读者当前所借书籍里面。并将书籍当前存量减1.(9)学生还书back():进入还书界面,将显示出读者当前所借书籍,让读者选择归还书籍。归还后将书籍从读者当前所借书籍里删除,此书当前存量加1,并将书籍信息写到读者借阅历史里面。 (10)学生续借renew():显示当前所借书籍信息,读者选择续借书目,当书籍信息的续借标志为0时可以续借,否则 不能续借,续借成功,将对应的读者当前所借书籍的续借标志置为1.(11)学生查询最后还书期限deadline():进入之后显示当前所借书籍信息,里面包含最后还书期限。 (12)学生查询借阅历史history():显示读者信息里面的借阅历史。 (13)学生修改密码change_reader_password():两次新密码输入一致,修改成功。(14)锁定系统admin_lock(),锁定系统后登陆lock_admin_menu():全局变量m_lock,当其值为1时解锁,值为0时锁定。 (15)建立读者书籍链表readreader(),readbook():首先从文件中读取读者总数,采用for循环,将每个读者信息写到链表里,在循环中,读取读者的ID、姓名、密码,然后读取读者当前所借书籍,采用for循环,将所借书籍信息写到数组里面,依次读取所借书籍信息。之后读取读者历史所借书籍数量,当数量大于15时,使用for循环,循环15次,依次读取书籍信息;如果 数量小于等于 15,采用for循环,循环当前借阅历史书籍数量次,将书籍信息写道数组中。然后将每个读者插入到链表里。书籍链表类似读者链表的建立。 (16)B-树的搜索插入删除功能(以按书名建立的B-树为例);搜索,SearchBTree_ID(),搜索成功返回搜索到的位置,搜索失败,返回插入的位置。Search_Name()函数将在当前节点搜索到关键字的位置。 插入,InsertBTree_Name(),如果为空,调用NewRoot_name()函数,建立根节点。如果不为空,将调用Insert_Name()将插入到节点里,判断是否大于最大关键字个数,如果大于,调用Split_Name()进行分裂。删除,并非自己完成,参考网上代码。 (16)建立B-树newBT():按书名建立,使用B树搜索功能,没有找到,将根据返回的位置进行插入。按书号的类似。 (17)打印文件printftxt():分别将书籍和读者 信息写到文件里,同时将管理员信息也写道文件中。在每个退出系统的接口中都进行调用此函数,保证文件不丢失,同时更新文件信息。 3.调试分析 在进行调试时,有很多内存读写错误,问题的根本原因是在进行结构体赋值前,没有将结构体里面包含的结构体或者数组链表进行初始化,导致问题十分严重普遍。 4.用户手册 首先登陆时有两种登陆:读者和管理员。然后管理员登陆功能有采编入库,清除库存,读者模块,书籍查询,修改密码和用户名。读者登陆有借书,还书,续借,修改密码,查询借阅历史,查询截至日期。 管理员登陆用户名:123456,密码:123456 管理员初始用户名:20121002932,初始密码:167350 读者的ID和密码请到reader.txt文件中查询,文件格式见下面说明。文件的格式: 1.reader.txt: 其中第一行的数字“4”为当前读者总数,第二行为: ID 名字 密码 第三行的数字”0“为当前所借书籍数量,之后为所借书籍信息: 书号 名称 作者 借阅时间年 月 日 最后还书日期年 月 日 是否续借 第三行数字 “0”为历史所借书籍数量,之后为所借书籍信息: 书号 名称 作者 借阅时间年 月 日 还书日期年 月 日 是否续借 2.book.txt: 第一行数字”4“为当前书籍总数 第二行为书籍信息: 书号 书名 作者 现存量 总存量 第三行数字”0“为读者借阅历史,以《飞鸟集》为例: ID 姓名 借阅时间年 月 日 还书时间年 月 日 是否续借 20121002932 王瑞林 114 17 5 17 1 3.adminer.txt: 第一行:管理员名称; 第二行:管理员登陆密码; 第三行:管理员初始用户名; 第四行:管理员初始密码; 第五行:锁定系统标志,此时为未锁定状态。 5.测试数据及测试结果 初始登陆界面: 管理员登陆界面: 采编入库: 清除库存: 读者模块: 删除读者: 此时删除读者后,读者文件中应该不存在该读者。书籍查询: 修改用户名和密码: 修改用户名: 修改密码: 修改用户名和密码后,退出系统后,查看adminer.txt文件,第一行和第二行为用户名和密码,将改变为4567890。读者登陆: 读者借书: 当读者借书成功之后退出系统,在reader.txt文件中对应读者的ID信息的缩进的第二级为读者当前所借书籍数量和所借书籍信息,在此之后可以看到读者现在所借书籍信息 读者还书: 读者还书后,在reader.txt文件中,缩进的第三级为读者历史借阅书籍数量和书籍信息,此时应该看到刚才还书的信息。 读者续借: 当读者还书成功后,对应的当前所借书籍的flag值为1.查询借阅历史: 查询截至日期: 修改登录密码: 当修改成功之后,reader.txt文件中对应读者的信息密码修改为当前密码。 6.致谢 感谢郭老师的指导,让我们在实践中提高了合理设计数据结构的能力,巩固了课堂所学。同时感谢王鑫学姐,帮助我们调试程序,并传输经验。 7.参考文献 《数据结构—使用C语言》第四版 朱站立编著 《C程序设计》第四版 谭浩强编著 import java.io.*;import java.util.*;public class LittleProgram { static boolean isDelete = true; static boolean isFind = true; public static void main(String [] args)//主方法,程序从这里开始运行 throws IOException,NumberNotFoundException { int choice=-1; do{ LittleProgram lp = new LittleProgram(); System.out.println(); System.out.println(“t #”); System.out.println(); System.out.println(“tt通訊錄管理系统”); System.out.println(“t 请用号码插入,查找,修改,删除数据”); System.out.println(); System.out.println(“t #n”); System.out.print(“1.增加号码:n”+ “2.查找号码:n”+ “3.删除号码:n”+ “4.清除所有号码:n”+ “5.把号码全部打印到屏幕n”+ “6.把通讯录按号码排序n”+ “7.修改号码n”+ “8.统计通码讯录的总人数n”+ “9.关于作者n”+ “0.退出程序.n” + “输入:”); BufferedReader in = //从终 new BufferedReader(//端接 new InputStreamReader(System.in));//收数 String inputLine = in.readLine(); //字选 choice= Integer.valueOf(inputLine).intValue();//项; switch(choice) { case 1: {//1.增加号码 String str = lp.inputData(); lp.addData(str); System.out.println(“增加号码成功.”); timeOut(1); }break; case 2: {//2.查找号码 long find = 0; System.out.print(“请输入你要查找的号码:”); BufferedReader inn = new BufferedReader(new InputStreamReader(System.in)); String inputLi = inn.readLine(); find = Integer.valueOf(inputLi).longValue(); lp.findData(find); timeOut(2); }break; case 3: {//3.删除号码 long deleteNumber = 0; System.out.print(“请输入你想删除号码:”); BufferedReader bf = new BufferedReader(new InputStreamReader(System.in)); String inputL = bf.readLine(); deleteNumber = Integer.valueOf(inputL).longValue(); lp.deleteData(deleteNumber); if(isDelete) System.out.println(“删除号码成功!”); timeOut(1); }break; case 4: { lp.clearData();//4.清除所有号码 timeOut(1); }break; case 5: { print();//5.把号码全部打印到屏幕 timeOut(2); }break; case 6: { lp.numSort();//6.把号码按号码排序 System.out.println(“按照号码从小到大排序成功!n”+ “排序后:n”); print(); timeOut(2); }break; case 7: { lp.rewrite();//7.修改号码 timeOut(2); }break; case 8: { int count = lp.count(); System.out.println(“共有”+count+“个号码记录.”); timeOut(2); }break; case 9: { System.out.print(“tt李雪萍n”+ “tt安徽理工大學理學院n”+ “ttQQ:1154646392n”); timeOut(4); }break; }}while(choice!= 0); System.out.println(“Bye!^-^”); System.exit(0); } public String inputData()//从终端接收数据的方法,返回字符串 throws IOException,NumberFormatException { System.out.print(“请依次输入 :号码 姓名 地址 生日n” + “每项数据请用空格隔开:”); String all = “"; try{ BufferedReader in = //从终 new BufferedReader(//端接 new InputStreamReader(System.in)); //收数 String inputLine = in.readLine(); //据 StringTokenizer str = new StringTokenizer(inputLine,” “);//接收的数据用空格隔开,这个类用来提取每个字符串 long num = Integer.valueOf(str.nextToken()).longValue();//号码 String name =(String)str.nextToken(); //姓名 String add =(String)str.nextToken(); // 地址 String birth =(String)str.nextToken();//出生年月 all = String.valueOf(num)+” , “+ name +” , “+ add +” , “+ String.valueOf(birth);//把所有的数据用” , “隔开然后在连起来放进字符串all }catch(IOException e){} catch(NumberFormatException e){} return all;//返回字符串all } public void addData(String str)//增加号码的方法 throws IOException { String s1 =”“,s2=”“ ,s3= ”“; File file = new File(”c:data.txt“); if(file.exists())//如果文件data.txt存在 { try{ BufferedReader in = new BufferedReader(new FileReader(file)); while((s1=in.readLine())!=null) s2+=s1+”n“;//把文件中的每行数据全部放进一个字符串s2 s2+=str+”n“; //再把s2于形参str相连放进s2 BufferedReader in2 = //把字符 new BufferedReader(//串s2也 new StringReader(s2)); //就是原 PrintWriter out = //文件+ new PrintWriter(//形参str(新输入的一行数据) new BufferedWriter(//重新写进data.txt new FileWriter(file))); //覆盖原来的数据 while((s3=in2.readLine())!= null) { out.println(s3); } out.close(); //System.out.println(”write data true.“); }catch(IOException e){} }else{ System.err.println(”File “data” Missing!“); } } public void clearData()//清除data.txt的所有数据的方法 throws IOException { File file = new File(”c:data.txt“); if(file.exists())//如果文件在{ try{ PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(file))); out.print(”“);//在文件data.txt里写进一个空字符,所以清除了原来的内容 out.close();//关闭文件 System.out.println(”clear data true!“); }catch(IOException e){} }else{ System.err.println(”File “data” Missing!“); } } public void deleteData(long deleteNumber)//删除某条号码数据 throws IOException,FileNotFoundException { isDelete = true; try{ DataMap mp = new DataMap();//生成一个自己编写的容器 long j=0; String s1=”“,s2=”“,s3=”“; BufferedReader in = new BufferedReader(new FileReader(”c:data.txt“)); while((s1=in.readLine())!=null) { j=numberTokenizer(s1); mp.put(j,s1); } try{ if(mp.containsKey(String.valueOf(deleteNumber).toString())) { mp.remove(deleteNumber); }else throw new NumberNotFoundException(); Collection c = mp.values(); Iterator iter = c.iterator(); while(iter.hasNext()) { s1 =(String)iter.next(); s3 +=s1+”n“; } BufferedReader in2 = new BufferedReader(new StringReader(s3)); PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(”c:data.txt“))); //System.out.println(”delete No“+deleteNumber); while((s1 = in2.readLine())!=null) { out.println(s1); } out.close();}catch(NumberNotFoundException e){ isDelete = false; System.out.println(deleteNumber+” no found :(“); } }catch(IOException e){} } public long numberTokenizer(String s) throws IOException { StringTokenizer st = new StringTokenizer(s,” “); return Integer.valueOf((st.nextToken())).longValue(); } public void findData(long find)//查找数据 throws IOException,NumberNotFoundException { isFind = true; String s = ”“,findString =”“;long i;DataMap dm = new DataMap();BufferedReader in = new BufferedReader(new FileReader(”c:data.txt“)); while((s=in.readLine())!=null) { i=numberTokenizer(s); dm.put(i,s); } //in.close(); try{ if(dm.containsKey(String.valueOf(find).toString())) { findString = dm.get(find); System.out.println(”学号“+find+”学生的资料是:“); System.out.println(findString); }else throw new NumberNotFoundException(); }catch(NumberNotFoundException e){ System.out.println(find+” no found :(“); isFind = false; } } public static void print()//读取文本文件把数据打印到终端的方法 throws IOException { try{ BufferedReader in = new BufferedReader(new FileReader(”c:data.txt“)); String read = ”“; while((read = in.readLine())!=null) System.out.println(read); }catch(IOException e){} } public static void timeOut(double sec)//停顿短暂时间的一个方法完全可以不要这个功能 { double seconds = sec; long t = System.currentTimeMillis()+(int)(seconds*1000); while((System.currentTimeMillis()) ; } public void numSort()//按学号排序 throws IOException { long i = 0; String s = ”“; try{ DataArrayList dal = new DataArrayList(); BufferedReader in = new BufferedReader(new FileReader(”c:data.txt“)); while((s=in.readLine())!=null) { i=numberTokenizer(s); dal.add(i); } Collections.sort(dal); DataMap dm = new DataMap(); BufferedReader in2 = new BufferedReader(new FileReader(”c:data.txt“)); while((s=in2.readLine())!=null) { i=numberTokenizer(s); dm.put(i,s); } PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(”c:data.txt“))); Iterator it = dal.iterator(); long temp = 0; String tempStr = ”“; while(it.hasNext()) { temp = Integer.valueOf((String)it.next()).longValue(); tempStr = dm.get(temp); out.println(tempStr); } out.close(); }catch(IOException e){} } public void rewrite() throws IOException,NumberNotFoundException { try{ System.out.print(”请输入你要修改的学生号码:“); BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); String inputLine = in.readLine(); long num = Integer.valueOf(inputLine).longValue(); findData(num); if(isFind) { deleteData(num);System.out.print(”请重新输入该号码:“);String str = inputData(); addData(str); System.out.println(”rewrite true!“); } }catch(IOException e){} catch(NumberNotFoundException e){} } public int count() throws IOException { DataArrayList dal = new DataArrayList(); try{ String s = ”“; long i =0; BufferedReader in = new BufferedReader(new FileReader(”c:data.txt“)); while((s=in.readLine())!=null) { i=numberTokenizer(s); dal.add(i); } }catch(IOException e){} return dal.size(); } } /* * * @author RangWei * TODO 这是个写的一个容器,继承公共类HashMap * 大概的功能就相当一个数组 * */ class DataMap extends HashMap//一个存储数据的Map { public void put(long i,String str)//把学号和数据放进这个Map { //以后一个学号(key)对应的是一个人的数据(value) put(String.valueOf(i).toString(),str); } public void remove(long i)//接收学号,然后删除学号(key)和它对应的数据(value) { remove(String.valueOf(i).toString().toString()); } public String get(long i)//接收一个学号,然后返回这个key对应的value { String s = String.valueOf(i).toString(); if(!containsKey(s)) { System.err.println(”Not found Key: "+s); } return(String)get(s); } } /* * * @author RangWei * * TODO 这个类继承ArrayList * 用来按数字排序,在用号码排序时要用到它 * */ class DataArrayList extends ArrayList { public void add(long num) { String numToString = String.valueOf(num).toString(); add(numToString); } } /* * * @author RangWei * * TODO 增加的一个Exception,主要是在文件里没有要找 * 的号码就抛出 * */ class NumberNotFoundException extends Exception { public NumberNotFoundException() {} } 信息科学与技术学院 程序设计基础课程设计报告 题目名称: 通信管理系统 学生姓名: 学 号: 专业班级: 指导教师: 2016年 12月 31日 目录 1.课程设计题目与要求........................1 1.1设计题目..........................................1 1.2设计要求..........................................1 2.总体设计..................................2 2.1 总体功能框架......................................2 2.2 数据结构概要设计..................................2 3.详细设计..................................3 3.1 数据结构详细设计..................................3 3.2 系统功能详细设计.................................10 4.运行结果.................................16 5.课程设计总结.............................20 5.1 编程中的问题及解决方法...........................20 5.2 小结.............................................20 5.3 心得体会.........................................20 5.4 程序设计方法.....................................20 参考文献...................................21 1.课程设计题目与要求 1.1设计题目 通信管理系统 1.2设计要求 用C/C++设计出模拟手机通信录管理系统,实现对手机中的通信录进行管理。 (一)功能要求 (1)查看功能:选择此功能时,列出下列三类选择。 A 办公类 B 个人类 C 商务类,当选中某类时,显示出此类所有数据中的姓名和电话号码) (2)增加功能:能录入新数据(一个结点包括:姓名、电话号码、分类(可选项有:A 办公类 B 个人类 C 商务类)、电子邮件)。例如 杨春 *** 商务类 Chuny@126.C++om 当录入了重复的姓名和电话号码时,则提示数据录入重复并取消录入;当通信录中超过15条信息时,存储空间已满,不能再录入新数据;录入的新数据能按递增的顺序自动进行条目编号。 (3)拔号功能:能显示通信录中所有人姓名,当选中某个姓名时,屏幕上模拟打字机的效果依次显示此人电话号码中的各个数字,并伴随相应的拔号声音。 (4)修改功能:选中某个人的姓名时,可对此人的相应数据进行修改(5)删除功能:选中某个人的姓名时,可对此人的相应数据进行删除,并自动调整后续条目的编号。 (二)其它要求: (1)只能使用C/C++语言,源程序要有适当的注释,使程序容易阅读(2)至少采用文本菜单界面(如果能采用图形菜单界面更好)(3)建议使用结构和链表等数据结构 (4)学生可自动增加新功能模块(视情况可另外加分)2.总体设计 2.1 总体功能框架 新增联系人查看通信录拨号 功能模块 修改信息删除联系人导入通信录导出通信录 退出系统 图 2-1 总体功能框架图 2.2 数据结构概要设计 本通信管理系统采用的数据结构为线性表中的链表。链表的结构体成员分为数据域和指针域。数据域为联系人(contacts)结构体,成员有联系人姓名(name)、联系人电话号码(teleNum)、联系人类别(classes)、电子邮件(email)四个。 图 2-2 数据结构组成 3.详细设计 3.1 数据结构详细设计 结构体名称:contact,LNode,*LinkList typedef struct { string name;//姓名 string teleNum;//电话号码 int classes;//分类 string email;//电子邮件 }contacts; typedef struct LNode { contacts data;//数据域 struct LNode* next;//指针域 }LNode,*LinkList; 具体操作: InitList(&L)操作结果:初始化链表 具体代码: int InitList(LinkList &L){ L = new LNode;L->next = NULL;return 0;} CreateList_H(&L,n)操作结果:前插法创建一个链表 具体代码: void CreateList_H(LinkList &L,int n){ LinkList p;for(int i = 0;i < n;i++)//根据联系人个数创建链表 { p = new LNode;cout <<“请输入联系人的姓名:”; cin >> p->data.name;cout <<“请输入联系人的电话号码:”;cin >> p->data.teleNum;cout <<“请输入联系人的分类(分类如下,输入相应序号即可)”<< endl;cout <<“1 办公类 2 个人类 3 商务类”<< endl;cin >> p->data.classes;cout <<“请输入联系人的电子邮件:”;cin >> p->data.email;p->next = L->next;L->next=p;} } CheckAll(L,c) 操作结果:显示类别为c的联系人姓名和电话号码 具体代码: void CheckAll(LinkList L,int c)//c是联系人类别 { LinkList p; p = L->next; cout <<“姓名tt”<<“电话号码”<< endl;//表头 while(p)//当链表没到尾部时 { if(p->data.classes==c)//若符合类别则输出联系人姓名和电话号码 { cout << p->data.name <<“tt”<< p->data.teleNum << endl; } p=p->next; } } CheckAll(L) 操作结果:显示已有联系人的姓名 具体代码: void CheckAll(LinkList L){ LinkList p;p=L->next;while(p) { cout << p->data.name << endl;p=p->next;} } Search(L, name) 操作结果:找到名为name的联系人位置 具体代码: LinkList Search(LinkList L,string name){ LinkList p;p=L->next;while(p&&p->data.name!=name)//当链表没到尾部且没找到联系人时 { p=p->next;} return p;} IfExist(L, c)操作结果:判断是否存在联系人contacts 具体代码: char IfExist(LinkList L,contacts c){ LinkList p;p=L->next;while(p&&p->data.name!=c.name)//根据姓名查找是否存在该联系人 { p=p->next;} if(!p)//若到达链表尾部,则不存在 return 'n';if(p->data.teleNum==c.teleNum)//若找到联系人姓名 if(p->data.classes==c.classes)//依次判断电话号码、类别、电子邮件是否相同 if(p->data.email==c.email)return 'y';return 'n';} Length(L) 操作结果:获取链表的长度 具体代码: int Length(LinkList L){ int i=0;LinkList p=L->next;while(p){ ++i;p=p->next;} return i;} Add(&L, c)操作结果:把contacts添加到链表中 具体代码: int Add(LinkList &L,contacts c){ LinkList p,s;if(Length(L)>=MAXSIZE)//判断链表长度是否达到最大值 { cout <<“存储空间已满,无法新增联系人!”<< endl;return 0;} if(IfExist(L,c)=='y')//判断输入的联系人是否已经存在 { cout <<“对不起,您输入的联系人已存在!”<< endl;return 0;} //若通讯录中不存在该联系人,则增加到通信录 p=L;s=new LNode;s->data=c;s->next=p->next;p->next=s;return 0;} Dail(L,name) 操作结果:拨打姓名为name的联系人的电话 具体代码: void Dail(LinkList L,string name){ LinkList p,s;p=L->next;s=Search(L,name);//根据姓名查找联系人所在 //模拟打字机效果,输出联系人电话号码 string tele=s->data.teleNum;for(int i=0;i cout << endl;//播放声音 PlaySound(“E:670.wav”,NULL,SND_FILENAME|SND_ASYNC);} ChangeInfo(&L,name)操作结果:修改姓名为name的联系人的信息 具体代码: void ChangeInfo(LinkList &L,string name){ LinkList p;p=Search(L,name);//找到联系人的位置所在 cout <<“ 请输入要修改的信息(输入对应序号即可):”<< endl;cout <<“1 姓名”<< endl;cout <<“2 电话号码”<< endl;cout <<“3 分类”<< endl;cout <<“4 电子邮件”<< endl; //根据选择修改联系人信息 int elec;cin >> elec;switch(elec){ case 1: { cout <<“姓名改为:”<< endl;string newName;cin >> newName;p->data.name=newName;break;} case 2: { cout <<“电话号码改为:”< cout <<“分类改为(分类如下,输入相应序号即可)”;cout <<“1 办公类 2 个人类 3 商务类”<< endl;int newCalsses;cin >> newCalsses;p->data.classes=newCalsses;break;} case 4: { cout <<“电子邮件改为:”<< endl;string newEmail;cin >> newEmail;p->data.email=newEmail;break;} } } Delete(&L,name)操作结果:删除姓名为name的联系人 具体代码: void Delete(LinkList &L,string name){ LinkList p=L,s;//找到需删除联系人的前一个位置 while(p->next&&p->next->data.name!=name){ p=p->next;} s=p->next;p->next=s->next;delete s;//删除联系人 } Read(L)操作结果:从文件中读入信息到链表 具体代码: void Read(LinkList L){ LinkList p; //打开文件导入通信录 ifstream fin;fin.open(“通信录.txt”,ios::in);string s1,s2,s3,s4;fin >> s1 >> s2 >> s3 >> s4; while(!fin.eof())//当没有到文件尾时 { string s5; contacts c; fin >> c.name >> c.teleNum >> s5 >> c.email; if(s5.compare(“办公类”)==0) c.classes=1; if(s5.compare(“个人类”)==0) c.classes=2; if(s5.compare(“商务类”)==0) c.classes=3; Add(L,c);//将联系人c增加到链表中 } fin.close();} 操作结果:将所有联系人导出到文件里保存 具体代码: void Write(LinkList L)Write(L){ endl; } LinkList p=L->next;int l=Length(L);//打开文件写入通信录 ofstream fout(“通信录.txt”,ios::out|ios::trunc);fout <<“姓名t”<<“电话号码t”<<“分类t”<<“电子邮件 ”<< for(int i=0;i case 1: { fout <<“办公类”; break; } case 2: { fout <<“个人类”; break; } case 3: { fout <<“商务类”; break; } } fout <<“t”<< p->data.email;if(i<(l-1)) fout << endl;p=p->next;} fout.close();3.2 系统功能详细设计 3.2.1 文件数据读出(1)函数原型: void CreateList_H(LinkList &L,int n)(2)函数功能: 创建链表,给链表增加n个联系人 (3)函数形参: CreateList_H(&L,n),其中L是链表指针,n是增加的联系人的数目 (4)函数算法流程:如图3-1所示 3-1算法流程图1 3.2.2 文件数据读出 (1)函数原型: int Add(LinkList &L,contacts c)(2)函数功能: 单个增加联系人 (3)函数形参: Add(&L, c),其中L是链表指针,c是具体的联系人(4)函数算法流程:如图3-2所示 3-2算法流程图2 3.2.3 文件数据读出 (1)函数原型:void Dail(LinkList L,string name)(2)函数功能: 拨打姓名为name的联系人的电话,在拨打时依次显示此人电话号码中的各个数字,并伴随相应的拔号声音 (3)函数形参: Dail(L, name),其中L为链表指针,name为拨号的联系人的姓名 (4)函数算法流程:如图3-3所示 3-3 算法流程图3 3.2.4 文件数据读出 (1)函数原型: void ChangeInfo(LinkList &L,string name)(2)函数功能: 修改姓名为name的联系人的信息 (3)函数形参: ChangeInfo(&L,name),其中L为链表指针,name为将要修改信息的联系人的姓名 (4)函数算法流程:如图3-4所示 3-4 算法流程图4 3.2.5 文件数据读出 (1)函数原型: void Delete(LinkList &L,string name)(2)函数功能: 从链表中删除姓名为name的联系人 (3)函数形参: Delete(&L,name),其中L为链表指针,name为将要删除的联系人的姓名 (4)函数算3-5所示 法流程:如图 3-5 算法流程图5 3.2.6 文件数据读出 (1)函数原型: void Read(LinkList L)(2)函数功能: 将文件中的联系人信息导入通信管理系统中(3)函数形参:Read(L),其中L为链表指针(4)函数算法流程:如图3-6所示 3-6 算法流程图6 3.2.7 文件数据读出 (1)函数原型: void Write(LinkList L)(2)函数功能: 将通信管理系统中所有联系人的各项信息有序的导出,保存在文件里 (3)函数形参: Write(L),其中L为链表指针(4)函数算法流程:如图3-7所示 3-7 算法流程图7 4.运行结果 (1)打开系统,显示主菜单界面,如图4-1所示: 图4-1 主菜单界面 (2)输入数字1,进行新增联系人的操作。接着输入1选择批量增加,输入数字2选择单个增加。批量增加如图4-2所示,单个增加如图4-3所示: 图4-2 批量增加联系人 图4-3 单个增加联系人 (3)输入数字2,进行查看通信录的操作,然后选择联系人的类别,查看此类中的所有联系人姓名及电话号码,如图4-4所示: 图4-4 按类别查看联系人 (4)输入数字3,进行拨号操作,如图4-5所示: 图4-5 拨号 (5)输入数字4,进行修改信息操作,然后输入将要修改信息的联系人姓名,再选择学要修改的信息项,如图4-6所示: 图4-6 修改联系人信息 (6)输入数字5,然后输入将要删除的联系人姓名,进行删除联系人的操作,如图4-7所示: 图4-7 删除联系人 (7)输入数字6,进行导入通信录操作,将文件“通讯录.txt”中的联系人信息导入通讯管理系统,如图4-8所示: 图4-8 导入通信录 (8)输入数字7,进行导出通信录操作,如图4-9所示;导出的通信录如图4-10所示: 图4-9 导出通信录 图4-10 已导出通信录列表 (9)输入数字0,退出通信管理系统,如图4-11所示: 图4-11 退出通信管理系统 5.课程设计总结 5.1 编程中的问题及解决方法 在本次程序设计过程中,遇到的主要问题是模拟打字机效果输出联系人电话号码以及从导入通信录。 前者是由于对字符串的理解不到位,后来查阅了相关资料后意识到可以将字符串看作字符数组,从而获取单个的字符,然后在每个字符的输出后利用系统的休眠函数Sleep设置停顿,从而达到想要的效果。 后者是因为在导出通信录的时候多输出了一个回车换行符,导致在进行文件读入时多读入一个回车换行符,以至于总是多一个联系人。然后便在导出文件时,不再在末尾输出回车换行符,从而解决了该问题。5.2 小结 总的来说这次课程设计完成总体较好。首先在已经学习了的数据结构基础上,我很快的想出了具体的设计思路,接着利用课余时间写出了大体的框架。再写出大题框架后随即进行了细节的完善,最后大概用了两天时间进行各项功能的调试。在代码的编写过程中并未产生太大瓶颈,遇到问题在查阅相关资料以及仔细调试后也得到了很好地解决,这是一次能好的体验,也是对自己能力的一次考验。5.3 心得体会 经过这次课程设计,我对数据结构这门课程有了更深刻的了解,不再仅仅是书本上抽象的代码,还对如和将数据结构应用到具体的实例中有了更好的认识。编程不仅需要对理论知识的理解,更重要的是它实际的应用,只有具体地进行过程序的设计,才能有更深刻的记忆和领会。同时通过查阅资料和读别人的代码,我也学会到一些新的内容和一些巧妙的思想。5.4 程序设计方法 本程序设计主要采用的方法是利用结构体进行编程,而采用的数据结构是线性表中的链表结构。参考文献 [1] 严蔚敏,吴伟民.数据结构(c语言版)[M].2.北京:清华大学出版社,2016 [2] 陈维新,林小茶.c++面向对象课程设计教程[M].清华大学出版社第二篇:图书管理系统 数据结构 课程设计
第三篇:数据结构课程设计—西文图书管理系统
第四篇:数据结构课程设计—java通讯录管理系统
第五篇:通讯录管理系统-数据结构课程设计报告