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

学生考勤系统课程设计

一、课程设计题目:1、课程设计名称:学生考勤系统。

2、课程设计内容:对学生考勤信息的统计与管理,可以分为若干个模块来实现,如:理论课考勤、实验课考勤、班级或院系会议考勤、课外活动考勤等等。

缺勤的情况可以按不同的类型(缺席、迟到、早退、请假)设置不同的权值。

系统要求能对考勤信息进行数据录入、情况的统计、信息的输出显示等等。

学生也可以根据自己的理解,去考虑更多的功能,并给予实现。

能按各种条件进行组合查询和数据统计,并能按指定顺序进行格式化输出。

对数据的新增,修改及删除应注意满足相应的约束条件。

二、问题的分析:在进行问题的分析前,我们应该知道该问题的任务和需求。

任务和需求如下:考勤信息记录了学生的在校所有学习生活的出勤情况,它包括:缺席日期、缺席类型。

如:若是缺课,则应记录缺课日期、第几节课、课程名称、学生学号、学生姓名、缺课类型(迟到、早退、请假及旷课)。

试设计一考勤管理系统,使之能提供以下功能:1、录入学生的缺勤记录;2、修改某个学生的缺勤记录;3、查询某个学生的缺勤情况;4、统计某段时间内,缺勤学生学号及缺勤次数,按缺勤权值统计学生的负分值,并能进行排序;5、统计某段时间内,有学生旷课的课程及旷课人次,按旷课人次由多到少排序;6、系统以菜单方式工作。

具体要求如下:1、采取模块化方式进行程序设计,要求程序的功能设计、数据结构设计及整体结构设计合理。

学生也可根据自己对题目的理解增加新的功能模块(视情况可另外加分)。

2、系统以菜单界面方式(至少采用文本菜单界面,如能采用图形菜单界面更好)工作,运行界面友好,演示程序以用户和计算机的对话方式进行。

3、程序算法说明清晰,理论分析与计算正确,运行情况良好,实验测试数据无误,容错性强(能对错误输入进行判断控制)。

4、编程风格良好(包括缩进、空行、适当注释、变量名和函数名见名知意,程序容易阅读等);所以进行问题的分析时我们应该进行以下工作:(1)备工作:a、仔细阅读课程设计任务书,明确实验设计的目的、实验内容、实验要求、所需知识点等。

b、阅读教材及相关材料,更深入的了解所需知识点,并与其它知识点能够融会贯通,加深对各知识点的了解,使得在进行课程设计的时候能够更好的运用各知识点。

当看到本设计所设计的知识点时,心里真的很害怕,因为其中有很多的知识点我都不知道,所以在课程设计开始的第一周我基本没做出什么。

后来经过翻阅资料,问题被逐一解决。

(2)设计整体框架:由实验设计内容、目的与要求来分析该如何简略设计该实验的总体框架,,然后一步步完善整个程序。

a、分析实验题目,确定需要用到对象,分析如何使用对象,并分配好成员函数和成员数据。

b、分析实验要求的功能,按功能确定需要用到的外部函数。

c、大概想想是不是需要其他的外部函数来辅助外部函数来实现实验要求的功能。

d、想想主函数如何实现。

(3)、完善函数:按实验设计的总体框架一步步来编写函数。

对于暂时想不到的函数先跳过或查书,一步步写完函数。

(4)、程序实现思路:开始是设计程序的界面,了解需要实现的功能模块。

对数据结构的选择写出的界面,现在需要做的事情其实就是要将所有的菜单功能进行实现。

可以考虑将用户输入每个学生的记录用一个结构体里面,即:struct Student_info {std::string date; //缺课日期std::string class_num; //第几节课std::string course_name; //课程名称std::string stu_name; //学生姓名std::string non_attendance_type; // 缺课类型};最后所有的学生记录都保存到一个vector里面,然后根据需要再将里面需要查找的元素进行查找,相应的排序可能就是将他们尽可能压进关联式容器map,有的部分就压入set里面,这些都是根据模块的功能来选定的。

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

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

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

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

采用switch语句很快就解决。

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

3、查询某个学生的缺课情况查询某个学生的缺课情况,这个模块是在以下这个函数中实现的:find_student_absent(vector<Student_info>& students, string& name)其中name为用户本人输入的学生姓名,这样可以很快在vector里面找到该学生的所有的记录。

为了达到查询结果按照日期升序排序,同一天内按照所缺课程的时间升序排序的目的,那就需要选择一个数据结构need来保存查找得到的该学生的所有缺课记录,即:map<string, map<string, vector<string> > > need这个数据结构看起来有点复杂,其实非常好用。

第一个索引值string 类型保存学生的缺课的日期,第二个map的键值则为该学生当天在第几节课缺课,而vector用来保存该学生其余信息,那么得到的need保存的记录已经满足了查询结果按照日期升序排序,同一天内按照所缺课程的时间升序排序的要求,只需要按格式输出这些记录即可。

4、统计旷课学生姓名及旷课节数和有学生旷课的课程及旷课人次这两个模块之所以放在一起讨论,是由于它们其实功能都是大同小异的。

可以考虑用泛型编程来解决。

不过我在源程序中并没有这么做,而是写成两个函数模块。

这个两个模块根据课程名称来找出所有与“旷课”这个字符串有关的记录先暂存到一个vector。

考虑到vector远远不能满足客户的要求,那么可以考虑新建一个数据结构来保存这些记录,同时满足要求,即:map<int, set<string> > need; //将统计出来的结果保存属于这段时间的学生旷课记录其中set保存的是旷课学生姓名(有学生旷课的课程),map的键值为学生旷课节数(旷课人次)。

最后会发现一个小问题,输出的结果并不是用户需要的结果先按旷课节数(旷课人次)降序排序,旷课节数相同的学生按姓名(有学生旷课的课程)升序排序,解决的办法很简单,只需要再输出的时候定义一个迭代器即可解决,即:map<int, set<string> >::const_reverse_iterator mapset_it = need.rbegin();该功能得以解决。

5、退出系统三、算法的设计:根据任务要求,我定义了5个子函数和一个结构体,分别将五个字函数分为五个模块。

第一个模块:输入学生的缺课记录。

在该模块中,调用s.clear()来清空s的记录,用in.clear();//将记录的错误状态恢复正确,以继续读取记录,用bool is_empty(vector<Student_info>& s)//判断输入学生的记录是否为空,为空则返回真,用bool compare(Student_info& x,Student_info& y)//按照时间排序,若日期相等则看课程时间,然后再根据bool time(const Student_info& stud,int y1,int m1,int d1,int y2,int m2,int d2)//筛选符合输入时间段的数据。

第二个模块:修改某个学生的缺课情况。

首先清空MAP容器,根据ix2=s_name.find(name); //符合名字要求的数据,用for(ix2=s_name.begin();ix2!=s_name.end();ix2++)//将改写后的数据放入vector容器中。

第三个模块:查找某学生的缺课情况。

用bool compare2(Search_struct& x,Search_struct& y)//按照次数排序,次数相等的则按照名字排序。

第四个模块:查找某段时间内旷课学生姓名及旷课节数。

第五个模块:查找某段时间内旷课的课程及旷课人次。

四、上机调试过程:本次课程设计总体上感觉比之前做过的实验综合性比较强。

在这里我主要总结一下我设计这个学生考勤管理系统的心得和在编译程序的过程中遇到的问题以及解决的办法。

为了使得程序的编写更加有条理,阅读更加明了,在写每个模块的时候都将自己的思路写在每个函数的第一行,告诉自己我这个函数将要做的是什么事情。

下面实对调试过程中遇到的一些小收获:①编译时发现这样的小错误:1>d:\my documents\visual studio 2005\projects\course1\course1\main.cpp(69) : error C2360: initialization of 'name' is skipped by 'case' label最后得到的解决答案实:原来在case 语句中,是不允许声明变量的。

②初次使用const_reverse_iterator的总结:运行的时候出现“map set iterator not incrementable”这样的运行终止错误问题的结局:经过检验查出是const_reverse_iterator原因是:map<int, set<string> >::const_reverse_iterator mapset_it = need.rbegin();for(; mapset_it != need.rend(); mapset_it--)mapset_it的操作不能是mapset_it--操作,而应该是mapset_it++五、测试结果及其分析:如:1.录入学生的缺课情况:2008-2-3 1-2 林 C++ 旷课2008-2-4 3-4 夏历史早退如果再按4:查找某段时间内旷课学生姓名及旷课节数。

会显示出如下结果:时间段,2008-2-1至2008-2-28,旷课姓名:林,旷课节数:1-2.六、参考文献:[1].郑莉等编著《C++语言程序设计(第三版)》北京:清华大学出版社[2].郑莉等编著《C++语言程序设计(第三版)学生用书》北京:清华大学出版社[3].刘振安等编著《C++程序设计课程设计》机械工业出版社[4].吴乃陵等编著《C++程序设计》北京:高等教育出版社[5].李春葆等编著《C++程序设计学习与上机实验指导》北京:清华大学出版社七、附录 源程序:#include <algorithm>#include <iomanip>#include <iostream>#include <vector>#include <stdexcept>#include <string>#include <iterator>#include <map>using namespace std;struct Student_info{int year,month,day,lesson1,lesson2;std::string course,name,type;std::istream& read(std::istream&);};istream& Student_info::read(istream& in){in>>year>>month>>day>>lesson1>>lesson2>>course>>name>>type;return in;}istream& read_record(istream& in,vector<Student_info>& s)//第一个模块--------------输入学生的缺课记录{Student_info record;s.clear();//调用s.clear()来清空s的记录while(record.read(in)){s.push_back(record);}in.clear();//将记录的错误状态恢复正确,以继续读取记录return in;}bool is_empty(vector<Student_info>& s)//判断输入学生的记录是否为空,为空则返回真{return s.empty();}bool compare(Student_info& x,Student_info& y)//按照时间排序,若日期相等则看课程时间{if(x.year==y.year&&x.month==y.month&&x.day==y.day){return x.lesson1<y.lesson1;}else if(x.year==y.year&&x.month==y.month&&x.day!=y.day){return x.day<y.day;}else if(x.year==y.year&&x.month!=y.month){return x.month<y.month;}else {return x.year<y.year;}}bool time(const Student_info& stud,int y1,int m1,int d1,int y2,int m2,int d2)//筛选符合输入时间段的数据{if ((y1 == stud.year && stud.month == m1 && stud.day < d1) || (y2 == stud.year && stud.month == m2 && stud.day > d2))return 0;else if ((y1 == stud.year && stud.month < m1) || (y2 == stud.year && stud.month > m2))return 0;else if (y1 > stud.year || y2 < stud.year)return 0;elsereturn 1;}void rewrite(vector<Student_info>& s)//第二个模块--------------修改某个学生的缺课情况{if(!is_empty(s)){int n,m,j,k;map<string,vector<Student_info> > s_name;map<string,vector<Student_info> >::iterator ix2;vector<Student_info>::iterator ix,iter,itera;string name;//-------------------定义这些参数和迭代器必须在SWITHC外,不然它可能被忽略跳过while(true){cout<<" *********************************************************"<<endl;cout<<" * 1.请输入你要修改缺课记录的学生姓名 *"<<endl;cout<<" * *"<<endl;cout<<" * 2.返回上一级菜单*"<<endl;cout<<" *********************************************************"<<endl;cout<<"请选择菜单选项: ";cin>>n;if(n==1){s_name.clear();//------------------------------清空MAP容器for(ix=s.begin();ix!=s.end();++ix){s_name[(*ix).name].push_back(*ix);}s.clear();cout<<"请输入该学生的姓名: ";cin>>name;cout<<endl;if(s_name.find(name)!=s_name.end()){ix2=s_name.find(name); //----------找到符合名字要求的数据,并显示出for(iter=(*ix2).second.begin();iter!=(*ix2).second.end();++iter){cout<<(*iter).year<<"-"<<(*iter).month<<"-"<<(*iter).day<<"\t";cout<<(*iter).lesson1<<"-"<<(*iter).lesson2;cout<<"\t"<<(*iter).course<<"\t"<<(*iter).name<<"\t"<<(*iter).type<<endl;}itera=(*ix2).second.begin();cout<<"请输入要更改记录的序号: ";for(k=0;k!=j-1;++k){++itera;}cout<<"**************************************************************************"<<endl;cout<<" * 需要更改的项目*"<<endl;cout<<" * *"<<endl;cout<<" * 1 日期 2 节次 3 课程名称 4 姓名 5 缺课类型 6 返回上一级 *"<<endl;cout<<" * *"<<endl;cout<<"**************************************************************************"<<endl;cout<<"请选择要更改的项目号: ";cin>>m;switch(m){case 1:cout<<"请输入更改的日期(年月日): ";cin>>(*itera).year>>(*itera).month>>(*itera).day;break;case 2:cout<<"请输入更改的节次(L1、L2): ";cin>>(*itera).lesson1>>(*itera).lesson2;break;case 3:cout<<"请输入要更改的课程名称: ";cin>>(*itera).course;break;case 4:cout<<"请输入要更改的学生姓名: ";cin>>(*itera).name;break;case 5:cout<<"请输入缺课类型: ";cin>>(*itera).type;break;case 6:break;default:cout<<"你的选择错了,请看清楚!"<<endl;}for(ix2=s_name.begin();ix2!=s_name.end();ix2++)//将改写后的数据放入vector容器中{for(iter=ix2->second.begin();iter!=ix2->second.end();iter++){s.push_back(*iter);}}}else{cout<<"没有这个学生的缺课记录"<<endl;cout<<endl;}break;}else if(n==2){return ;}elsecout<<"你的选择错了,请看清楚!"<<endl;}}elsecout<<"记录为空,没有学生的缺课记录!"<<endl;}void Search_record(vector<Student_info>& s)//第三个模块-------------查找某学生的缺课情况{if(!is_empty(s)){int i;vector<Student_info>::iterator iter;map<string,vector<Student_info> >::iterator it1;map<string,vector<Student_info> > s_name;map<string, vector<Student_info> >::iterator itera;vector<Student_info>::iterator it;string name;while(true){cout<<" **********************************************************"<<endl;cout<<" * *"<<endl;cout<<" * 1 输入你要查询的学生姓名 2 返回上一级 *"<<endl;cout<<" * *"<<endl;cout<<" **********************************************************"<<endl;cout<<"请选择菜单: ";cin>>i;if(i==1){s_name.clear();for(it=s.begin();it!=s.end();++it){s_name[(*it).name].push_back(*it);}for(itera=s_name.begin();itera!=s_name.end(); ++itera){sort(itera->second.begin(),itera->second.end(),compare);}cout<<"请输入名字: ";cin>>name;cout<<endl;if(s_name.find(name)!=s_name.end()){it1=s_name.find(name);for(iter=(*it1).second.begin();iter!=(*it1).second.end();++iter){cout<<(*iter).year<<"-"<<(*iter).month<<"-"<<(*iter).day<<"\t";cout<<(*iter).lesson1<<"-"<<(*iter).lesson2;cout<<"\t"<<(*iter).course<<"\t"<<(*iter).name<<"\t"<<(*iter).type<<endl;}}else{cout<<"没有这个学生."<<endl;cout<<endl;}}else if(i==2){return ;}elsecout<<"对不起,没有这个选项!"<<endl;}}elsecout<<"没有这个学生的缺课记录"<<endl;}struct Search_struct{string name,course;int times;};//定义另一个结构模块bool compare2(Search_struct& x,Search_struct& y)//按照次数排序,次数相等的则按照名字排序{if(x.times==y.times)return <;elsereturn x.times>y.times;}void Search_s_t(vector<Student_info>& std)//第四个模块----------------查找某段时间内旷课学生姓名及旷课节数{if(!is_empty(std)){vector<Student_info>::iterator it;vector<Search_struct>::iterator itera;map<string,int>::iterator iter;vector<Search_struct> vec;int y1,m1,d1,y2,m2,d2;map<string,int> ret;cout<<"请输入你要查找的一个时间段(y1 m1 d1 y2 m2 d2): "<<endl;cin>>y1>>m1>>d1>>y2>>m2>>d2;for(it=std.begin();it!=std.end();++it){if(time(*it,y1,m1,d1,y2,m2,d2)){ret[it->name]+=(it->lesson2-it->lesson1+1);}}for(iter=ret.begin();iter!=ret.end();iter++){Search_struct tmp;=iter->first;tmp.times=iter->second;vec.push_back(tmp);}sort(vec.begin(),vec.end(),compare2);for(itera=vec.begin();itera!=vec.end();itera++){cout<<itera->name<<"\t"<<itera->times<<endl;}}elsecout<<"对不起,没有你要查找的记录!"<<endl;}void Search_c_t(vector<Student_info>& std)//第五个模块---------------查找某段时间内旷课的课程及旷课人次{if(!is_empty(std)){vector<Student_info>::iterator it;vector<Search_struct>::iterator itera;map<string,int>::iterator iter;vector<Search_struct> vec;int y1,m1,d1,y2,m2,d2;map<string,int> ret;cout<<"请输入你想要查找的时间段(y1 m1 d1 y2 m2 d2): "<<endl;cin>>y1>>m1>>d1>>y2>>m2>>d2;for(it=std.begin();it!=std.end();++it)//建立map容器{if(time(*it,y1,m1,d1,y2,m2,d2)){ret[it->course]+=1;}}for(iter=ret.begin();iter!=ret.end();iter++){Search_struct tmp;tmp.course=iter->first;tmp.times=iter->second;vec.push_back(tmp);}sort(vec.begin(),vec.end(),compare2);for(itera=vec.begin();itera!=vec.end();itera++){cout<<itera->course<<"\t"<<itera->times<<endl;}}elsecout<<"这段时间内没有学生的缺课纪录!"<<endl;}int main(){vector<Student_info> stu;int choice;while(true){cout<<" *************************************************************"<<endl;cout<<" * 学生考勤管理系统*"<<endl;cout<<" ************************************************************ "<<endl;cout<<" * 1. 录入学生的缺课记录*"<<endl;cout<<" * *"<<endl;cout<<" * 2. 修改某个学生的缺课记录*"<<endl;cout<<" * *"<<endl;cout<<" * 3. 查找某学生的缺课情况*"<<endl;cout<<" * *"<<endl;cout<<" * 4. 查找某段时间内旷课学生姓名及旷课节数 *"<<endl;cout<<" * *"<<endl;cout<<" * 5. 查找某段时间内旷课的课程及旷课人次 *"<<endl;cout<<" * *"<<endl;cout<<" * 6. 退出系统*"<<endl;cout<<" *************************************************************"<<endl;cout<<"请选择菜单选项: ";cin>>choice;if(choice==1){cout<<"请输入数据: "<<endl<<"年月日 L1 L2 姓名课程名称缺课类型 "<<endl;read_record(cin,stu);}else if(choice==2){rewrite(stu);cout<<endl;}else if(choice==3){Search_record(stu);cout<<endl;}else if(choice==4){Search_s_t(stu);cout<<endl;}else if(choice==5){Search_c_t(stu);cout<<endl;}else if(choice==6){return 0;}elsecout<<"对不起,没有这个菜单项!"<<endl; }return 0;}。

相关主题