当前位置:文档之家› 学生考勤管理系统课程设计报告

学生考勤管理系统课程设计报告

一.需求分析功能需求:1、录入学生的缺勤记录;2、修改某个学生的缺勤记录;3、查询某个学生的缺勤情况;4、统计某段时间内,缺勤学生学号及缺勤次数,按缺勤权值统计学生的负分值,并能进行排序;5、统计某段时间内,有学生旷课的课程及旷课人次,按旷课人次由多到少排序;6、系统以菜单方式工作数据需求本系统主要涉及的数据有学生缺课信息类和有关信息排序类。

学生缺课信息包括缺课时间,学生姓名,课程名称,第几节,学生迟到次数,早退次数,请假次数,旷课次数。

有关信息排序类包括对课程排序和对姓名排序。

性能需求要求系统具有可靠性,速度要快二、系统的主要功能(1)、录入学生的缺课记录,函数代码void input(records *r){}模块中。

首先提示用户按照正确的格式进行学生缺课记录的录入,这个步骤比较简单,只需要不断地将记录的每个数据项存入结构体对应的成员中。

(2)、修改某个学生的缺课记录,函数代码void edt(records *r){}模块中。

首先必须查找到你所需要修改的那位的学生全部缺课记录。

这个模块不需要定义新的结构体。

在修改前当然要检查记录是否为空了,不为空的话,可以设置下面这五个菜单供用户选择:1、缺课日期2、第几节课3、课程名称4、学生姓名5、缺课类型6、退出修改程序并返回系统主菜单。

修改很简单,仅需要对该学生的某个部分进行替换即可。

采用switch语句很快就解决。

最后实现对所选记录的修改,完成后更新原有的学生记录。

(3)、查询某个学生的缺课情况,函数代码void search(records *r){}模块中。

达到查询结果按照日期升序排序,同一天内按照所缺课程的时间升序排序的目的,(4)、统计,函数代码为void order_c(){}和void order_s(){}的类模块中。

其中实现对课程排序和对学生姓名的排序。

三、流程图学生考勤系统结构图:四、数据结构设计此程序运用多种条件语句,主体采用的是动态数组、指针。

系统的设计采用了数组语句、选择语句和循环语句,在需要处理大量同类数据时,这样就使程序书写更加简洁。

程序使用了布尔函数。

选择语句多采用if多分支选择结构与switch语句。

首先计算switch表达式,然后在caes子句中寻找值相等的常量表达式,并以此为入口符号,由此开始顺序执行。

循环语句采用了for语句等、do-while语句,for语句用于已知循环次数的循环结构,括号中的三个量分别用来表示循环变量初值、循环终值和循环增量。

do-while语句先循环后判断, Break 语句在switch语句中,保证多分支情况的正确执行,在循环语句中,强制终止本层循环。

保存和读取函数是典型的函数功能,一个程序是由若干个函数组成的,保存和读取函数是和其他函数互相调用的再有使用有关类的设计,学生缺课信息类和有关信息排序类,如下:class record //学生缺课信息类{public:void set(string d,int cno,string c,string s,int type){date.assign(d);//日期cname.assign(c);//课程名字sname.assign(s);//学生姓名this->cno=cno;//对缺课类型的选择为int型this->type=type;//缺课类型}void set(record re){date.assign(re.date);cname.assign(ame);sname.assign(re.sname);this->cno=o;this->type=re.type;}string date,cname,sname;int cno,type;};class records //实现学生旷课情况排序的类{public:records() //构造函数{r=new record[100];n=0;}void order_s() //姓名的排序{int i;int j;string *s=new string[n];int *c=new int [n];s[0].assign(r[0].sname);c[0]=1;int k=1,flag;for( i=1;i<n;i++){flag=0;for( j=0;j<k;j++)if(r[i].sname==s[j]){c[j]++;flag=1;break;}if(!flag){s[k]=r[i].sname;c[k++]=1;}}for(i=1;i<k;i++)for( j=i;j>0;j--){if(c[j]>c[j-1]){int tmp=c[j];c[j]=c[j-1];c[j-1]=tmp;string stmp=s[j];s[j]=s[j-1];s[j-1]=stmp;}}cout<<"旷课学生姓名\t旷课次数"<<endl;for(i=0;i<k;i++)cout<<s[i]<<"\t\t"<<c[i]<<endl;}void order_c() //课程排序{int i,j;string *s=new string[n];int *c=new int [n];s[0].assign(r[0].cname);c[0]=1;int k=1,flag;for( i=1;i<n;i++){flag=0;for(j=0;j<k;j++)if(r[i].cname==s[j]){c[j]++;flag=1;break;}if(!flag){s[k]=r[i].cname;c[k++]=1;}}for(i=1;i<k;i++)for( j=i;j>0;j--){if(c[j]>c[j-1]){int tmp=c[j];c[j]=c[j-1];c[j-1]=tmp;string stmp=s[j];s[j]=s[j-1];s[j-1]=stmp;}}cout<<"课程名\t旷课人次"<<endl;for(i=0;i<k;i++)cout<<s[i]<<"\t"<<c[i]<<endl;}record *r;int n;};把所有的学生记录都保存到一个文件里面,然后根据需要再将里面需要查找的元素进行查找,相应的排序可能就是将他们尽可能压进关联式容器map,有的部分就压入set里面,这些都是根据模块的功能来选定的。

可以这么说,选择好合理的数据结构查找与排序就可以一劳永逸了。

这点在后面部分会有详细的说明。

还有就是对各功能子函数的编写应用。

五、类设计系统中主要涉及了两个类:一个是class record //关于学生考勤基本信息类另一个是class records//实现学生旷课情况排序的类六、主要算法设计关键算法:旷课情况的排序:class records//实现学生旷课情况排序的类{public:records() //构造函数{r=new record[100];n=0;旷课记录的修改:cout<<"请输入要修改缺课记录的学生姓名: "<<flush;string t1,t3,t4;char tmp[30];int t2,t5,flag=0;cin>>tmp;t1.assign(tmp);for(i=0;i<r->n;i++)if(r->r[i].sname==t1){flag=7;break;}if(!flag){cout<<"查无此学生!"<<endl;return;}t1=r->r[i].date;t2=r->r[i].cno;t3=r->r[i].cname;t4=r->r[i].sname;t5=r->r[i].type;旷课项目的修改!cout<<"请输入要修改的项目:\n(1.缺课日期 2.缺课节次 3.缺课名称 4.学生姓名 5.缺课类型 6.全部) "<<flush;e0:cin>>flag;switch(flag){case 1:goto e1;case 2:goto e2;case 3:goto e3;case 4:goto e4;case 5:goto e5;case 6:goto e1;default:goto e0;}用到的知识点有:函数的作用域、函数的调用、数组赋值、函数循环、以及类的定义,另外还用到了for函数、getch函数、switch函数、case函数、default函数等等。

七、主要代码第一部分:学生考勤管理系统#include "stdlib.h"#include "hanshushixian.h"#include "record.h"#include <string>#include <iostream>#include <iomanip>#include <fstream>using namespace std;#include "record.h"int main(){c1: //主菜单实现system("cls");{cout<<"*************************************************************"<<endl;cout<<" *** ★欢迎访问学生考勤管理系统★***"<<endl;cout<<"*************************************************************"<<endl;cout<<" *** 系统主菜单: 1.显示所有学生的缺课记录***"<<endl;cout<<" *** 2.录入学生的缺课信息记录***"<<endl;cout<<" *** 3.查询某个学生的缺课情况***"<<endl;cout<<" *** 4.修改某个学生的缺课记录***"<<endl;cout<<" *** 5.删除某个学生的缺课记录***"<<endl;cout<<" *** 6.统计某段时间内旷课情况***"<<endl;cout<<" *** 7. 退出系统***"<<endl;cout<<"*************************************************************"<<endl;}cout<<"O(∩_∩)O 请选择你所需要的操作 O(∩_∩)O: "<<flush;int chose;c2:cin>>chose;if(chose==7)exit(0);records *r=new records();rd(r);switch(chose){case 1:pri(r);break;case 2:input(r);break;case 3:search(r);break;case 4:edt(r);break;case 5:del(r);break;case 6:search_s(r);break;default:goto c2;}cout<<"是否返回主菜单? (y/n)——你的选择: "<<flush;char yn;c3:cin>>yn;if(yn=='y')goto c1;else if(yn=='n')exit(0);else goto c3;return 0;}第二部分:record.h (类的设计部分)#include <iostream>#include <string>using namespace std;#ifndef record_class#define record_classclass record //关于学生考勤基本信息类{public:void set(string d,int cno,string c,string s,int type){date.assign(d);cname.assign(c);sname.assign(s);this->cno=cno;this->type=type;}void set(record & re){date.assign(re.date);//assign可以避免不必要的内存分配,可以提高效率cname.assign(ame);sname.assign(re.sname);this->cno=o;this->type=re.type;}string tostr(){string s;char tmp[3];s.assign(date);itoa(cno,tmp,10);s.append("#");s.append(tmp);//直接添加另一个完整的字符串s.append("#");s.append(cname);s.append("#");s.append(sname);itoa(type,tmp,10);s.append("#");s.append(tmp);return s;}string date;string cname;string sname;int cno;int type;};#endif record_class#ifndef records_class#define records_classclass records//实现学生旷课情况排序的类{public:records() //构造函数{r=new record[100];n=0;}void order_s() //姓名的排序{int i;int j;string *s=new string[n];int *c=new int [n];s[0].assign(r[0].sname);c[0]=1;int k=1,flag;for( i=1;i<n;i++){flag=0;for( j=0;j<k;j++)if(r[i].sname==s[j]){c[j]++;flag=1;break;}if(!flag){s[k]=r[i].sname;c[k++]=1;}}for(i=1;i<k;i++)for( j=i;j>0;j--){if(c[j]>c[j-1]){int tmp=c[j];c[j]=c[j-1];c[j-1]=tmp;string stmp=s[j];s[j]=s[j-1];s[j-1]=stmp;}}cout<<"旷课学生姓名\t旷课次数"<<endl;for(i=0;i<k;i++)cout<<s[i]<<"\t\t"<<c[i]<<endl;}void order_c() //课程排序{int i,j;string *s=new string[n];int *c=new int [n];s[0].assign(r[0].cname);c[0]=1;int k=1,flag;for( i=1;i<n;i++){flag=0;for(j=0;j<k;j++)if(r[i].cname==s[j]){c[j]++;flag=1;break;}if(!flag){s[k]=r[i].cname;c[k++]=1;}}for(i=1;i<k;i++)for( j=i;j>0;j--){if(c[j]>c[j-1]){int tmp=c[j];c[j]=c[j-1];c[j-1]=tmp;string stmp=s[j];s[j]=s[j-1];s[j-1]=stmp;}}cout<<"课程名\t旷课人次"<<endl;for(i=0;i<k;i++)cout<<s[i]<<"\t"<<c[i]<<endl;}record *r;int n;};#endif records_class第三部分:hanshushixian.h (功能子函数的实现部分)#include "record.h"#include <string>#include <iostream>#include <fstream>#include "stdlib.h"#include <iomanip>using namespace std;void wt(records *r)//实现对文件的输出{ofstream outf("data.txt");for(int i=0;i<r->n;i++)outf<<r->r[i].tostr()<<endl;outf<<"!"<<endl;}void rd(records *r)//实现对文件的输入{ifstream inf("data.txt");if(inf.eof()){cout<<"记录为空!"<<endl;return;}string t1,t3,t4;char tmp[30];int t2,t5;r->n=0;while(true){inf.getline(tmp,10,'#');if(tmp[0]=='!')break;t1.assign(tmp);inf.getline(tmp,3,'#');t2=atoi(tmp);inf.getline(tmp,30,'#');t3.assign(tmp);inf.getline(tmp,30,'#');t4.assign(tmp);inf.getline(tmp,3);t5=atoi(tmp);r->r[r->n++].set(t1,t2,t3,t4,t5);}}bool timechk(string t1){int year=atoi(t1.substr(0,2).c_str());int month=atoi(t1.substr(2,2).c_str());int day=atoi(t1.substr(4,2).c_str());if(!(t1.length()==6&&year>0&&year<99&&month>0&&month<13&&day>0&&day<32)) {cout<<"日期录入有误! 请重新录入: "<<endl;return false;}else return true;}void input(records *r)//录入学生的缺课记录{string t1,t3,t4;int t2,t5,flag=0;char yn;cout<<"录入一条学生缺课记录:"<<endl;//endl表示终止一行并刷新缓冲区m1:cout<<"请输入缺课日期: (例如110627) "<<flush;//flush表示刷新缓冲区cin>>t1;if(!(timechk(t1)))goto m1;m2:cout<<"请输入缺第几节课: "<<flush;cin>>t2;if(t2<1||t2>10){cout<<"节次录入有误! 请重新录入: "<<endl;goto m2;}cout<<"请输入缺课名称: "<<flush;cin>>t3;cout<<"请输入缺课学生姓名: "<<flush;cin>>t4;m3:cout<<"请输入缺课类型: (1.迟到 2.早退 3.请假 4.旷课) "<<flush;cin>>t5;if(t5<1||t5>4){cout<<"类型输入有误! 请重新录入: "<<endl;goto m3;}for(int i=0;i<r->n;i++)if(r->r[i].date==t1&&r->r[i].cno==t2&&r->r[i].cname==t3&&r->r[i].sname==t4&& r->r[i].type==t5){cout<<"该条记录已存在,是否添加为新记录? (y/n) "<<flush; n1:cin>>yn;if(yn=='y')break;else if(yn=='n')goto n2;else goto n1;}r->r[r->n++].set(t1,t2,t3,t4,t5);n2:cout<<"是否继续输入? (y/n) "<<flush;n3:cin>>yn;if(yn=='y')goto m1;else if(yn=='n'){cout<<"保存修改? (y/n) "<<flush;cin>>yn;if(yn=='y')wt(r);else return;}else goto n3;}void prione(record r){cout<<r.date<<"\t\t"<<o<<"\t"<<ame<<"\t\t"<<r.sname<<"\t\t"<<flush;switch(r.type){case 1:cout<<"迟到"<<endl;break;case 2:cout<<"早退"<<endl;break;case 3:cout<<"请假"<<endl;break;case 4:cout<<"旷课"<<endl;break;default:;}}void pri(records *r)//修改学生信息{if(r->n==0){cout<<"记录为空!"<<endl;return;}cout<<"\n序号\t缺课日期节次\t课程名称\t学生姓名\t缺课类型"<<endl;for(int i=0;i<r->n;i++){cout<<i<<"\t"<<flush;prione(r->r[i]);}}void edt(records *r)//修改学生信息{int i;if(r->n==0){cout<<"记录为空!"<<endl;return;}cout<<"请输入要修改缺课记录的学生姓名: "<<flush;string t1,t3,t4;char tmp[30];int t2,t5,flag=0;cin>>tmp;t1.assign(tmp);for(i=0;i<r->n;i++)if(r->r[i].sname==t1){flag=7;break;}if(!flag){cout<<"查无此学生!"<<endl;return;}t1=r->r[i].date;t2=r->r[i].cno;t3=r->r[i].cname;t4=r->r[i].sname;t5=r->r[i].type;cout<<"请输入要修改的项目:\n(1.缺课日期 2.缺课节次 3.缺课名称 4.学生姓名 5.缺课类型 6.全部) "<<flush;e0:cin>>flag;switch(flag){case 1:goto e1;case 2:goto e2;case 3:goto e3;case 4:goto e4;case 5:goto e5;case 6:goto e1;default:goto e0;}e1:cout<<"请输入缺课日期: (例如080612) "<<flush;cin>>t1;if(flag!=6)goto e6;e2:cout<<"请输入缺第几节课: "<<flush;cin>>t2;if(flag!=6)goto e6;e3:cout<<"请输入缺课名称: "<<flush;cin>>t3;if(flag!=6)goto e6;e4:cout<<"请输入缺课学生姓名: "<<flush;cin>>t4;if(flag!=6)goto e6;e5:cout<<"请输入缺课类型: (1.迟到 2.早退 3.请假 4.旷课) "<<flush;cin>>t5;e6:r->r[i].set(t1,t2,t3,t4,t5);char yn;cout<<"保存修改? (y/n) "<<flush;cin>>yn;if(yn=='y')wt(r);else return;}void del(records *r)//删除学生信息{if(r->n==0){cout<<"记录为空!"<<endl;return;}cout<<"请输入要删除的记录的序号: (输入-1删除全部) "<<flush;int flag;cin>>flag;if(flag>r->n-1&&flag<-1){cout<<"不存在所要删除的记录!"<<endl;return;}else if(flag==-1)r->n=0;else{for(int i=flag;i<r->n-1;i++)r->r[i].set(r->r[i+1]);r->n--;}char yn;cout<<"保存修改? (y/n) "<<flush;cin>>yn;if(yn=='y')wt(r);else return;}void search(records *r)//查找学生信息{if(r->n==0){cout<<"记录为空!"<<endl;return;}cout<<"请输入要查询的学生姓名: "<<flush;string str;int j=0,flag=0;cin>>str;for(int i=0;i<r->n;i++)if(r->r[i].sname==str){if(!flag)cout<<"\n序号\t缺课日期节次\t课程名称\t学生姓名\t缺课类型"<<endl;cout<<j++<<"\t"<<flush;prione(r->r[i]);flag=1;}if(!flag)cout<<"没有查到该学生的缺课记录!"<<endl;}void search_s(records *r)//一定范围查找学生信息{int i;if(r->n==0){cout<<"记录为空!"<<endl;return;}records *r1=new records();g1:cout<<"请输入要检索的时间范围: (例如110610-110612) "<<flush;string tmp,ld,hd;cin>>tmp;ld.assign(tmp.substr(0,6));hd.assign(tmp.substr(7,6));if(!timechk(ld)||!timechk(hd))goto g1;for(i=0;i<r->n;i++)if(r->r[i]pare(ld)>=0&&r->r[i]pare(hd)<=0&&r->r[i].type==4 )r1->r[r1->n++].set(r->r[i]);cout<<"请选择统计方式: (1.学生旷课情况降序显示 2.课程旷课情况降序显示)"<<flush;g2:cin>>i;switch(i){case 1:cout<<"\n在"<<ld<<"到"<<hd<<"期间学生旷课情况如下:"<<endl;r1->order_s();break;case 2:cout<<"\n在"<<ld<<"到"<<hd<<"期间课程旷课情况如下:"<<endl;r1->order_c();break;default:goto g2;}}八、系统运行结果样例当用户执行程序时首先会出现如下界面也是主菜单界面:当输入序号1时会出现所有学生记录:再选择y就会又回到主菜单界面,选n时就会退出。

相关主题