C++课程设计学生通讯管理系统.docx
- 文档编号:9600750
- 上传时间:2023-05-20
- 格式:DOCX
- 页数:72
- 大小:388.57KB
C++课程设计学生通讯管理系统.docx
《C++课程设计学生通讯管理系统.docx》由会员分享,可在线阅读,更多相关《C++课程设计学生通讯管理系统.docx(72页珍藏版)》请在冰点文库上搜索。
C++课程设计学生通讯管理系统
课程设计报告
一课程设计目的及要求
学生通讯系统
学生通信录信息包括:
姓名、学号、年龄、性别、家庭住址、联系电话、寝室号等信息。
现要求编写程序来完成如下功能:
●学生通信录信息的输入
●学生的通信录信息删除和修改
●学生的通信录信息查询和统计功能
●学生的通信录信息输出显示。
二课程设计具体实现
1.总体设计
学生通讯管理系统
只修改学号
管理员登陆系统
普通用户登陆系统
删除信息
退出系统
密码校验
增加信息
查找信息
修改信息
修改密码
全部修改
只修改姓名
2.详细设计
在进行系统的各项功能介绍之前,有必要先说一下我所选的课程项设计的主要思路。
这个系统的核心部分就是结构体链表,它贯穿整个程序。
一切数据的增、删、查、改都要以它为支撑。
整个程序其实就是在操作一张很大的链表。
我在15周时就已经开始考虑课程设计题目,当时是想先做一个关于面向过程的课题,立马就考虑的先用结构体链表做为数据的容器。
而且已经做成型了。
后来老师您把题目给改了,要求都用面向对象做,我是考虑过用vector或者是list来做数据的容器的,但想想程序几经初成型,就不改变容器了,就直接把类的对象做为结构体的数据部分,程序当然也有较大改动,但基本框架是没有变的。
先来说链表的构造,在主菜单下选择功能之前,链表就已经认构造完毕,程序按行读取文本文件,每读一行,便对其进行分割。
分割出来的字符串为学生类对象对应的每一项信息。
在分割字符串时,我按字符‘@’进行分割(当然,在数据存储时也是按行存储,且每项信息以‘@’分开),其关键代码如下:
voidread_info(){//读取文件
head=NULL;
Students;//构造学生类对象
ifstreamin("student_info.txt");
stringread;
intno;
while(getline(in,read)){//按行读取
no=0;
inti;
while(read.find_first_of("@")!
=-1){
stringtemp;
i=read.find_first_of("@");
temp=read.substr(0,i);
if(no==0){
s.name=temp;//赋予姓名
}
if(no==1){
s.tel=temp;//赋予电话
}
if(no==2){
s.xuehao=temp;//赋予学号
}
if(no==3){
s.sex=temp;//赋予性别
}
if(no==4){
s.banji=temp;//赋予班级
}
no++;
read=read.substr(i+1);
}
s.dizhi=read;//赋予地址
if(s.name.size()>0&&s.xuehao.size()>0){//判断学号与姓名是否为空
insert_into_list(s);//插入链表
}
}
in.close();
}
voidinsert_into_list(Studentst){
structlist*curr,*ne;
curr=(structlist*)new(structlist);//申请空间
curr->student=st;
ne=head;
if(head==NULL){//如果头指针为空插入第一条数据
head=curr;
curr->next=NULL;
}
else
{while(ne->next!
=NULL)ne=ne->next;//遍历结构体,直到尾
ne->next=curr;
curr->next=NULL;
}
}
Txt文件才的储存形式如下:
所以,能正确的读取所有数据在于字符串的分割,当然用此种方法读到的数据全是字符串,只是本系统为学生通讯系统,并不需要其他类型的数据,如有必要,字符串也可以转化。
就这样,当文件按行读取完毕时,链表中的每个结构体都包含有一个不同的学生类对象,至此,链表已初始化完毕。
在程序接下来的运行过程中,对数据的操作就是直接操作链表的节点。
下面对系统功能进行介绍:
i.
登陆系统:
通过欢迎界面后,将进入登陆方式选择界面,如图:
ii.若选择以普通用户身份登录系统,会出现以下界面:
普通用户的功能包括:
1.增加数据;2.查询数据;3.浏览数据;4.数据统计
1)增加数据功能的界面如下:
用户根据系统提示,对单个学生信息进行逐项输入,按回车键结束输入。
除姓名与学号外,其他信息只要直接按回车键就可以跳过输入,系统将保存为空。
对信息的输入还要有一定的规范性,如学号与电话为纯数字;姓名长度最多只有四个字;性别若有,只能为男或女,系统会自动对输入的信息进行校验,包括规范性校验与数据是否重复校验。
若无法通过校验,数据不会保存。
其关键代码如下:
●规范性校验:
boolStudent:
:
check_tel_xuehao(){//学号与电话检查函数
if(xuehao.size()==0){//如果学号为空,返回false
returnfalse;
}
if(!
check_string(xuehao)||!
check_string(tel)){//如果学号中处在数字以外的字符,返回false
cout<<"学号或电话输入有误!
"< returnfalse; } returntrue; } boolcheck_string(stringa){//检测字符串中是否只包含数字 charb; for(inti=0;i { b=a.at(i); if(b>'9'||b<'0')returnfalse; } returntrue; } boolStudent: : check_name_other(){//姓名检测函数 if(name.size()==0||name.size()>10){//如果姓名为空或者姓名长度过长 cout<<"姓名输入有误! "< returnfalse; } else returntrue; } boolStudent: : check_sex(){//此为性别检测函数,性别可以为空,可以为男,也可以为女,但不可以为其他字符,或者返回false if(sex.size()>2||(sex.size()>0&&(pare("男")&&pare("女")))){ cout<<"性别输入错误! "< returnfalse; } else returntrue; } ●数据是否重复校验代码如下: structlist*User: : check_repeat(stringkey,inttype){//此函数也可用于数据查询,key代表要查询的关键字。 type=1表示按姓名查找,type=2表示按学号查找 structlist*ne; ne=head;//注意这个head不能空,要初始化 intcom; while(ne! =NULL){//遍历列表 com=0; if((type==1||type==0)&&! pare(ne->student.name))com++;//对比姓名 if((type==2||type==0)&&! pare(ne->student.xuehao))com++;//对比学号 if(com>0){//若m>0,证明原有数据中含有被检数据,或者的话,将会返回NULL。 returnne; } if(ne->next==NULL)break; ne=ne->next; } cout< returnNULL; } 2)数据查询功能界面如下: 进行数据查询时,可输入任何字符,只要学生信息中任何一项包含输入的关键字,该信息都会被显示出来,如上图,分别输入了“女”,“B105”,进行查询,结果信息都完整的显示了出来,以下是进行信息查询的关键代码: voidUser: : find_info(){ stringkey;//关键字 structlist*ne;//结构体指针 intfind;//找到的数据量 intcom; chars;//选择 FIND: system("cls"); cout<<"请输入要查询的关键字: "; cin>>key; ne=head;//注意这个head不能空,要初始化 find=0; show_table_head(); while(ne! =NULL){//遍历链表,指针每移一位都要调出指针所指的学生类,然后进行每项数据的对比 com=0; if(check_string(ne->student.name,key))com++;//如果相关信息内包含关键字,com++,下同 if(check_string(ne->student.banji,key))com++; if(check_string(ne->student.dizhi,key))com++; if(check_string(ne->student.sex,key))com++; if(check_string(ne->student.tel,key))com++; if(check_string(ne->student.xuehao,key))com++; if(com>0){//即至少有一项匹配,则横排显示 find++; ne->student.show_info(find); } if(ne->next==NULL)break;//指针指向尾部,退出 ne=ne->next; } cout<<'\n'<<"找到"< \n"< cout<<"是否继续查找(y/n)? "; cin>>s; if(s=='y')gotoFIND; } 3)数据浏览功能: 此功能可以显示所有存入的数据,界面如下: 在数据显示时,主要用的技术就是对结构体链表进行遍历,指针指向结构体的学生类对象,然后调用该类的自身数据显示函数,这样就可显示所有数据。 关键代码如下: voidUser: : show_all(){//显示所有信息 system("cls");//清屏 structlist*ne;//链表指针 ne=head;//指向头指针 inti=1; show_table_head();//显示表头 while(ne! =NULL)//遍历链表 { ne->student.show_info(i);//横排显示学生信息 i++; if(ne->next==NULL)break;//如果到达尾指针,退出 ne=ne->next;//指针指向下一位 } system("pause"); } voidStudent: : show_info(inti){//横行显示信息 cout< cout< cout< cout< cout< cout< cout< } 4)数据统计功能: 数据可以按照三种方式进行统计,即按性别、按班级,按住址。 计时,对应条目相等的数据会显示在同体列表下,并会显示数据总数。 一下截图是按住址统计的部分结果: 以下是关键代码: voidUser: : tongji_info(){ TONGJI: system("cls"); chars; cout<<"选择您可以统计方式: \n\t1.按性别统计\n\t2.按住址统计\n\t3.按班级统计\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n请选择: "; cin>>s; if(s=='1'){ find_info (1); } elseif(s=='2'){ find_info (2); } elseif(s=='3'){ find_info(3); } else{ err_show(); } cout<<"\n继续还是回主菜单[1_or_2]: "; cin>>s; if(s=='1')gotoTONGJI; } voidUser: : find_info(inttype){ tyhead=NULL; structlist*ne;//结构体list指针 ne=head;//注意这个head不能空,要初始化 while(ne! =NULL){//遍历链表,指针每移一位都要调出指针所指的学生类,然后进行每项数据的对比 stringkey; if(type==1){ key=ne->student.sex; } elseif(type==2){ key=ne->student.dizhi; } else{ key=ne->student.banji; } if(! contain(key)){ add(key); } if(ne->next==NULL)break;//指针指向尾部,退出 ne=ne->next; } structtypelist*ne2; ne2=tyhead; system("cls"); while(ne2! =NULL){//遍历链表typelist show_table_head();//表头显示函数 stringkey; key=ne2->atype; if(key.size()==0){ key="其他"; cout< "< } else { cout< "< } if(ne2->next==NULL)break;//指针指向尾部,退出 ne2=ne2->next; cout< } } intsee_list(inttype,stringkey,boolnullinfo){//type条目类型,key表示此条目下的数据,此函数用于返回某项包含相同数据的数目 structlist*ne;//结构体list指针 ne=head;//注意这个head不能空,要初始化 intfind=0; while(ne! =NULL){//遍历链表,指针每移一位都要调出指针所指的学生类,然后进行每项数据的对比 inti=0; if(type==1){ if(! ne->pare(key)||((ne->student.sex.size())==0&&nullinfo))//检查性别是否匹配 { find++; ne->student.show_info(find); } } elseif(type==2){ if(! ne->pare(key)||((ne->student.dizhi.size()==0)&&nullinfo))//检查地址是否匹配 { find++; ne->student.show_info(find); } } else{ if(! ne->pare(key)||((ne->student.banji.size()==0)&&nullinfo))//检查班级是否匹配 { find++; ne->student.show_info(find); } } if(ne->next==NULL)break;//指针指向尾部,退出 ne=ne->next; } returnfind; } voidadd(stringkey){ structtypelist*curr,*ne;//结构体typelist指针 curr=(structtypelist*)new(structtypelist);//申请空间 curr->atype=key; ne=tyhead;//ne指向头指针,如果初始化数据时,文件中有数据,此时头指针一定不为空 if(tyhead==NULL){//若链表为空 tyhead=curr;//头指针指向current curr->next=NULL;//current为第一数据,表头的next指针为空 } else//如果头指针不为空 { while(ne->next! =NULL)//遍历链表,直到ne指针指向尾部 { ne=ne->next; } ne->next=curr;//尾指针的next指针指向current,此时current已插入链表 curr->next=NULL;//current位于链表尾部,其next指针当为NULL } } boolcontain(stringkey){ structtypelist*ne;//结构体指针typelist ne=tyhead; while(ne! =NULL){//遍历链表 if(! ne->pare(key))returntrue; if(ne->next==NULL)break;//指针指向尾部,退出 ne=ne->next; } returnfalse; } iii.若选择以管理员身份登录系统 则会出现管理员界面: 当正确输入用户名与密码后,方可进行功能操作。 其中,增加数据、查询数据、浏览数据与数据统计功能与普通用户的代码实现相同,因为管理员类继承与普通用户类,所以此函数直接继承。 在此不多作描述。 下面介绍删除数据与修改数据功能。 1)数据修改 进行数据修改时,需要先输入正确的学号或姓名,在找到数据后,可按提示进行修改,次系统有一个方便的地放就是若不想修改某项数据,可直接按回车键,如下图。 关键代码实现如下: voidManager: : edit_info(){ stringkey;//关键字 chars; structlist*xiu; EDIT: system("cls"); Studenttemp;//用于做缓存的学生类对象 cout<<"\n请输入要修改的条目关键字: "; cin.ignore(1024,'\n'); getline(cin,key); if(((xiu=check_repeat(key,1))! =NULL)||((xiu=check_repeat(key,2))! =NULL)){ boolf; xiu->student.show_info();//以下为数据录入 cout<<"\n请输入新数据,若不必修改,请直接按回车键: \n"; cout<<"请输入姓名: "; getline(cin,temp.name); cout<<"请输入电话: "; getline(cin,temp.tel); cout<<"请输入学号: "; getline(cin,temp.xuehao); cout<<"请输入性别: "; getline(cin,temp.sex); cout<<"请输入班级: "; getline(cin,temp.banji); cout<<"请输入住址: "; getline(cin,temp.dizhi); //以下为数据检查 if(temp.name.size()>0){//若重输了姓名 if(check_repeat(temp.name,1)! =NULL)gotoWRONG;//检查未通过 }elsetemp.name=xiu->student.name; if(temp.xuehao.size()>0){ if(check_repeat(temp.xuehao,1)! =NULL)gotoWRONG; }elsetemp.xuehao=xiu->student.xuehao; if(temp.sex.size()==0){ temp.sex=xiu->student.sex; } if(temp.tel.size()==0){ temp.tel=xiu->student.tel; } if(temp.banji.size()==0){ temp.banji=xiu->student.banji; } if(temp.dizhi.size()==0){ temp.dizhi=xiu->student.dizhi; } if(temp.check_name_other()&&(temp.check_sex()&&temp.check_tel_xuehao())){//数据规范性检查 xiu->student=temp;//对指针下数据进行修改 cout<<"\n修改成功! "< edit_flag=true; cout<<"\n修改后的数据为: "< xiu->student.show_info(); gotoASK; } elsegotoWRONG; } else{ err_show(); cout<<"无效的数据,是否继续(y/n)? " cin>>s; if(s=='y'){ gotoEDIT; } gotoASK; } WRONG: err_show(); cout<<"\n错误! 未修改数据! "< ASK: cout<<"\n继续还是回主菜单[1_or_2]: "; cin>>s; if(s=='1')gotoEDIT; } 2)数据删除 删除数据需要先输入学号或姓名,数据的删除本质上就是链表节点的删除。 截图如下: 关键代码如下: intManager: : del_info(){//删除信息 stringm;//删除的关键字 structlist*la,*ne; chars; DEL: system("cls"); ne=head; if(head==NULL){//如果数据为空 err_show(); cout<<"\n空链表! 不可进行下一步操作! "< gotoASK; } cout<<"输入要删除的学号或姓名: "; cin.ignore(50,'\n'); getline(cin,m); if(! pare(head->student.name)||! pare(head->student.xuehao)){//如果姓名或学号的所对对应的学生对象位于链表头部,则需要改变头指针,头指针指向内容将要删除 head=ne->next;//改变头指针 ne->student.show_info();//显示信息 cout<<"\n确认删除(y/n)? "; c
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- C+ 课程设计 学生 通讯 管理 系统