计算机高级语言课程设计报告
——学生成绩管理系统
班 级:191131
学 号:20131000310
姓 名:蔡路
日 期:20##年1月18日
一.课程设计题目与要求
实习题目:学生成绩管理系统
【实习内容】
C++语言,面向对象的分析与设计。
【基本要求】
学生成绩管理是高等学校教务管理的重要组成部分,主要包括学生成绩的录入、删除、
查找及修改、成绩的统计分析等等。请设计一个系统实现对学生成绩的管理。
系统要求实现以下功能:
(1)增加记录:要求可以连续增加多条记录。
(2)删除一个学生的记录:要求可以先查找,再删除。删除前,要求用户确认。
(3)成绩修改:若输入错误可进行修改;要求可以先查找,再修改。
(4)查找:可以根据姓名(或学号)查找某个学生的课程成绩,查找某门课程成绩处
于指定分数段内的学生名单等等。
(5)统计分析:对某个班级学生的单科成绩进行统计,求出平均成绩;求平均成绩要
求实现函数的重载,既能求单科的平均成绩,又能求三科总分的平均成绩。求出
一门课程标准差和合格率;
(6)排序功能:要求按总分进行排序(从高到低),若总分相同,则按数学排序;若总
分和数学相同,则按物理排序;若总分和各科成绩都相同,则按学号排序;
(7)文件操作:可以打开文件,显示班级的所有学生信息;可以将增加或修改后的成
绩重新写入文件;可以将排序好的信息写入新的文件。
【较高要求】
查找可以实现模糊查询,即输入名字的一部分,可以列出满足条件的所有记录。再从这
个记录中进行二次选择。
【测试数据】
一个文本文件(学生成绩数据.TXT)
【实现提示】
设计一个学生的类。类的设计请参考测试数据的记录和将要实现的功能。学生一条记录
包括:学号、姓名、数学成绩、物理成绩和英语成绩。主函数显示功能菜单,供用户选择操
作。每步操作之前,都要显示菜单。在主函数中调用类的方法。
二.需求分析
1.问题描述:
用c ++编写一个简单的学生成绩管理系统。至少需要2个类。
1——学生类:是由若干个学生成绩记录组成,每个记录由学号、姓名、三科成绩五部分组成,学号、姓名为char类型,成绩为int型数据。
2— —学生信息存储类:此类使该系统具有以下功能:
(1)程序开始执行时显示主菜单:
cout<<"***********************************************************"<<endl;
cout<<" 学生成绩管理系统"<<endl;
cout<<"********************************************************** "<<endl;
cout<<"请输入你要执行的功能(同时输入多条指令,只读取第一条指令): "<<endl;
cout<<"*************************************************************"<<endl;
cout<<" a.增加记录 b.增加文本 c.删除记录 "<<endl
<<" d.修改成绩 e.查找成绩 f.区间成绩 "<<endl
<<" g.统计分析 h.排序功能 i.保存信息 j.查看信息 "<<endl;
(2)通过键盘输入数字后,程序能够执行相应的功能,执行完后回到上述主菜单继续等待用户输入。
(3)选择“添加”后,按程序提示依次输入学号,姓名,性别,成绩,添加记录成功。
(4)选择“查找”,按提示输入要查找的学生的学号或姓名,输入学号或姓名,若该学号或姓名存在,则输出相应的学生记录,如该学号或姓名不存在,则返回主菜单。
(5)选择“修改”,按提示输入要修改的学生的学号或姓名,输入学号或姓名,若该学号或姓名存在,则修改相应的学生记录,如该学号或姓名不存在,则返回主菜单。
(6)选择“删除”,按提示输入要删除的学生的学号或姓名,输入学号或姓名,若改学号或姓名存在,则删除相应的学生记录,如果该学号或姓名不存在,则按任意键返回主菜单。
(7)选择“加载”,可将文件中的相关信息导出
(8)选择“保存”,系统会将已有的学生记录保存在默认的文件名为“学生成绩数据.txt”的文件中。
(9)选择“排序”,则对学生信息进行排序。
(10)选择“统计”,则调用相应函数进行运算。
……
2. 系统环境、运行要求:Visual c ++ 6.0
三.概要设计(包括系统流程设计,系统模块设计等)
1.主函数模块及模板函数student类流程设计:函数模板
grade类流程设计分支:
添加函数:
寻找函数:用于查找学生各项信息
修改函数:用于修改学生各项信息
删除函数:用于删除学生信息
排序函数:对学生各项信息进行排序操作
保存和加载函数:将学生信息保存到文件中,并在需要的时候调用该文件将其中的学生信息显示出来
……
2.grade类模块流程设计:
四.详细设计
1.包括类的函数成员和数据成员设计:
//**********grade类
class grade{ //定义一个成绩管理类
private:
string name; //学生姓名
string number; //学生学号
int math,physics,english; //学生的数学,物理,英语成绩
public:
grade(){}; //默认的构造函数
~grade(){}; //析构函数
grade(const grade &a); //拷贝构造函数
grade & operator=(const grade &a);//赋值运算符重载
grade(string,string,int,int,int); //构造函数
void input(); //输入学生信息
void graderegister(string,string,int,int,int); //获得学生信息
void change1(); //修改成绩
void show(); //显示成绩
void show2();
void find1();//学号查询
void find2();//区间查询
string getname(){ return name;};
string getnumber(){ return number;}
int getmath(){ return math;}
int getphysics(){ return physics;}
int getenglish(){ return english;}
};
//定义一个存储学生的模版类
template <typename T> class student{
private:
T list[100]; //存放学生数据的数组
int last; //已存表项的最后位置
public:
student(){last=-1;} //初始化为空表
int find(string);//检查学号是否在表中,并找到是第几个
int find2(string);//检查姓名是否在表中,并找到是第几个
void insert(); //手动存入数据
void insert1(); //从文本读入数据
void remove(); //删除学生信息
void change2(); //修改学生信息
void show();
void show2();
void findgrade(); //按学号查询成绩
void findname(); //按名字
void m(string); //模糊查询
void findlist(); //按区间查询成绩
void tongji(); //统计学生数据
void print(); //显示各项数据
void order(); //按成绩排序
void file(); //写入文本
};
2.界面设计(见问题提示):主函数显示功能菜单,供用户选择操作。每步操作之前,都要显示菜单,在主函数中调用类的方法。
在主函数中定义类对象 student Grade;//****定义类对象
调用student类成员函数 Grade.Menu();//**********显示菜单
在while中调用Menu()实现每步操作之前,都要显示菜单
3.其它模块的设计与实现:
五.测试
包括对各功能模块的测试:
1.进入页面,编译后进入的初始页面2.进入菜单循环选择页面,选择序号来执行操作,且每次操作后都会提醒是否继续操作或返回此页面
3.加载原始学生成绩记录,记录为已有文本,直接打开显示班级所有信息。
4.添加一条记录,依次输入学号,姓名,成绩等,添加成功后判断是否继续添加?5.继续添加几条记录直到不继续添加并保存!
6.按区间查找
7.统计,算出单科平均成绩,所有总分平均成绩,一门课程的标准差和合格率并显示
8.排序,只能按总分排序(功能不完善,需改进)
9.查找,可以按姓名查找,按学号查找,显示出信息
10.修改,1,可以指出输入错误2,可以修改个人信息所有项,需保存
11.删除,可以逐一删除学生信息
六.结论
对系统开发的总结,设计的亮点,存在的不足,需要改进的地方:
这是一个非常实际,具有非常强综合力的系统开发,刚开始的时候很有信心可以把它完整的做出来,但一接触便发现有相当的困难,不但一些知识点没有掌握牢固,就是一些掌握了的一旦到实际应用阶段还是有些生疏。可见只有通过平时多加练习,才能有助于自己巩固知识点。
这是一个面向对象的程序设计,与面向过程有很大的区别。我个人认为我的程序的优点就是比较充分的体现了类的概念,整个程序使用了两个类,有数据成员和函数成员,操作大部分都是通过类来完成。另外,程序用了多文件结构,便于编译和改错。还有就是本程序可以基本实现题目的要求,虽然有的功能不太完整。在缺点方面,本程序有很多的不足和缺陷,1.安全性不够高,输错容易导致程序崩溃。2.代码繁琐.3.虽然体现了类,但封装性不好,没有做到数据成员私有化。4.部分功能没有实现或有误差,比如数据的存入,读取和模糊查询等问题。这些问题我会在寒假一一进行改进,纠正过来。最后想说的是,调试程序真的很关键。调试程序需要较大的耐心,我在调试方面花费了很多的时间,调试程序的时间比自己编写整个程序的时间还要长,下的工夫还要深,但这是一个身为程序员必须了解,也必须接受的事实。
通过这个实验的练习,我学到了很多东西,特别是加深了对类和对象理解和应用得方面,非常感谢老师给我的帮助!也希望在以后的学习中能够学好c ++,做出更完美的系统!
参考文献:C++程序设计(第二版)高等教育出版社,c ++ Primer 中文版等。
七.附录
程序源代码:(多文件结构)
#include"grade.h"
using namespace std;
int main(){
student<grade> stu;
while(1){
cout<<"*************************************************************"<<endl;
cout<<" 学生成绩管理系统 "<<endl;
cout<<"*************************************************************"<<endl;
cout<<"请输入你要执行的功能(同时输入多条指令,只读取第一条指令): "<<endl;
cout<<"*************************************************************"<<endl;
cout<<" a.增加记录 b.增加文本 c.删除记录 "<<endl
<<" d.修改成绩 e.查找成绩 f.区间成绩 "<<endl
<<" g.统计分析 h.排序功能 i.保存信息 j.查看信息 "<<endl
<<"********************************************************************"<<endl;
char x1;
cin>>x1; while(x1!='a'&&x1!='b'&&x1!='c'&&x1!='d'&&x1!='e'&&x1!='f'&&x1!='g'&&x1!='h'&&x1!='i'&&x1!='j'&&x1!='A'&&x1!='B'&&x1!='C'&&x1!='D'&&x1!='E'&&x1!='F'&&x1!='G'&&x1!='H'&&x1!='I'&&x1!='J'){
cout<<"不存在该操作,请重新输入:"<<endl;
cin>>x1;
}
switch(x1){
case 'a':case 'A':{
char a;
do{
stu.insert();
cout<<"是否继续增加记录? 继续请输入Y,取消请输入N(不区分大小写):"<<endl;
cin>>a;
while(a!='Y'&&a!='y'&&a!='N'&&a!='n'){
cout<<"输入错误,请重新输入:"<<endl;
cin>>a;
}
}while(a=='Y'||a=='y');
}break;
case 'b':case 'B':stu.insert1();break;
case 'c':case 'C':stu.remove();break;
case 'd':case 'D':stu.change2();break;
case 'e':case 'E':
{cout<<"请输入要查找的方式 (输入完请按回车):"<<endl;
cout<<"A 按学号查询 B 按姓名查询 C 模糊查询 "<<endl;
char a;
cin>>a;
switch(a){
case 'A':case 'a':stu.findgrade();break;//按学号查找
case 'B':case 'b':stu.findname();break;//按姓名查找
case 'C':case 'c':{
cout<<"请输入模糊姓名并回车:"<<endl;
string s;
cin>>s;
stu.m(s);break;
}//模糊查找
default:{cout<<"输入错误!"<<endl;}
}
break;}
case 'f':case 'F':stu.findlist();break;
case 'g':case 'G':stu.tongji();break;
case 'h':case 'H':stu.order();stu.show2();break;
case 'i':case 'I':stu.file();break;
case 'j':case 'J':stu.print();break;
}
cout<<endl<<endl;
}
return 0;
}
#include"grade.h"
grade::grade(string na,string nu,int ma,int ph,int en){
name=na;
number=nu;
math=ma;
physics=ph;
english=en;
}
grade::grade(const grade &a){
name=a.name;
number=a.number;
math=a.math;
physics=a.physics;
english=a.english;
}
grade & grade::operator=(const grade &a)
{name=a.name;
number=a.number;
math=a.math;
physics=a.physics;
english=a.english;
return *this;
}
void grade::input(){
cout<<"请依次输入学号、姓名、数学成绩、物理成绩、英语成绩:"<<endl;
cin>>number>>name>>math>>physics>>english;
}
void grade::graderegister(string na,string nu,int ma,int ph,int en){
name=na;
number=nu;
math=ma;
physics=ph;
english=en;
}
void grade::change1(){
cout<<"请依次输入修改后的数学成绩、物理成绩、英语成绩:"<<endl;
int m,p,e;
cin>>m>>p>>e;
math=m;
physics=p;
english=e;
}
void grade::show(){
cout<<setw(10)<<number<<setw(10)<<name<<setw(10)<<math<<setw(10)<<physics<<setw(10)<<english<<endl;
}
void grade::show2(){
cout<<setw(10)<<number<<setw(10)<<name<<setw(10)<<math<<setw(10)<<physics<<setw(10)<<english<<setw(10)<<math+physics+english<<endl;
}
#include<iostream>
#include<iomanip>
#include<cmath>
#include<string>
#include<fstream>
using namespace std;
class grade{ //定义一个成绩管理类
private:
string name; //学生姓名
string number; //学生学号
int math,physics,english; //学生的数学,物理,英语成绩
public:
grade(){}; //默认的构造函数
~grade(){}; //析构函数
grade(const grade &a); //拷贝构造函数
grade & operator=(const grade &a);//赋值运算符重载
grade(string,string,int,int,int); //构造函数
void input(); //输入学生信息
void graderegister(string,string,int,int,int); //获得学生信息
void change1(); //修改成绩
void show(); //显示成绩
void show2();
void find1();//学号查询
void find2();//区间查询
string getname(){ return name;};
string getnumber(){ return number;}
int getmath(){ return math;}
int getphysics(){ return physics;}
int getenglish(){ return english;}
};
template <typename T> class student{//定义一个存储学生的模版类
private:
T list[100]; //存放学生数据的数组
int last; //已存表项的最后位置
public:
student(){last=-1;} //初始化为空表
int find(string);//检查学号是否在表中,并找到是第几个
int find2(string);//检查姓名是否在表中,并找到是第几个
void insert(); //手动存入数据
void insert1(); //从文本读入数据
void remove(); //删除学生信息
void change2(); //修改学生信息
void show();
void show2();
void findgrade(); //按学号查询成绩
void findname(); //按名字
void m(string); //模糊查询
void findlist(); //按区间查询成绩
void tongji(); //统计学生数据
void print(); //显示各项数据
void order(); //按成绩排序
void file(); //写入文本
};
template <typename T>void student<T>::show(){
int i;
cout<<setw(10)<<"学号 "<<setw(10)<<"姓名"<<setw(12)<<" 数学"<<setw(10)<<"英语"<<setw(10)<<"物理"<<endl;
for(i=0;i<=last;i++) list[i].show();
}
template <typename T>void student<T>::show2(){
int i;
cout<<setw(10)<<"学号 "<<setw(10)<<"姓名"<<setw(12)<<" 数学"<<setw(10)<<"英语"<<setw(10)<<"物理"<<setw(10)<<"总分"<<endl;
for(i=0;i<=last;i++) list[i].show2();
}
template <typename T>int student<T>::find(string xuehao){
int i;
for(i=0;i<=last;i++) if(xuehao==list[i].getnumber()) break;
if(i<=last) return i;
else{
cout<<"不在表中!"<<endl;
return -1;
}
}
template <typename T>int student<T>::find2(string name){
int i;
for(i=0;i<=last;i++){
if(name==list[i].getname())break;
}
if(i<=last) return i;
else{
cout<<"所操作姓名不在表中!"<<endl;
return -1;
}
}
template <typename T>void student<T>::insert(){
last++;
grade g1;
g1.input();
list[last]=g1;
}
template <typename T>void student<T>::insert1(){
ifstream ifile;
ifile.open("d:\\成绩单1.txt");
string number1;
string name1;
int m,p,e;
while(1){
ifile>>number1>>name1>>m>>p>>e;
if(ifile.eof()!=0)break;
grade g1;
g1.graderegister(name1,number1,m,p,e);
last++;
list[last]=g1;
}
ifile.close();
}
template <typename T>void student<T>::remove(){
string xuehao;
cout<<"输入要删除的学号(输入完请按回车):"<<endl;
cin>>xuehao;
int i=find(xuehao);
if(i>=0){
cout<<"确认删除?"<<endl<<"确认请输入Y,取消请输入N(不区分大小写,输入完请按回车):"<<endl;
char m;
cin>>m;
if(m=='Y'||m=='y'){
for(int j=i;j<=last-1;j++)list[j]=list[j+1];
last--;
}
else if(m=='N'||m=='n');
else cout<<"输入错误!";
}
}
template <typename T>void student<T>::change2(){
string xuehao;
cout<<"输入要修改的学号(输入完请按回车):"<<endl;
cin>>xuehao;
int i=find(xuehao);
if(i>=0)list[i].change1();
}
template <typename T>void student<T>::findgrade(){
string xuehao;
cout<<"输入要查找学生的学号(输入完请按回车):"<<endl;
cin>>xuehao;
int i=find(xuehao);
if(i>=0){
cout<<setw(10)<<"学号 "<<setw(10)<<"姓名"<<setw(12)<<" 数学"<<setw(10)<<" 物理"<<setw(10)<<" 英语"<<endl;
list[i].show();
}
}
template <typename T>void student<T>::findname(){
string name;
cout<<"输入要查找的名字(输入完请按回车):"<<endl;
cin>>name;
int i=find2(name);
if(i>=0){
cout<<setw(10)<<"学号 "<<setw(10)<<"姓名"<<setw(12)<<" 数学"<<setw(10)<<"英语"<<setw(10)<<"物理"<<endl;
list[i].show();
}
else ;
}
template <typename T>void student<T>::m(string s){
int i;
cout<<setw(10)<<"学号 "<<setw(10)<<"姓名"<<setw(12)<<" 数学"<<setw(10)<<"英语"<<setw(10)<<"物理"<<endl;
for(i=0;i<=last;i++){
int a;
a=list[i].getname().find(s);
if(a!=-1)list[i].show();
}
}
template <typename T>void student<T>::findlist(){
cout<<"请选择科目:数学请输入m,英语请输入e,物理请输入p(不区分大小写,输入完请按回车):"<<endl;
char n;
cin>>n;
cout<<"请依次输入分数区间最小值、最大值:"<<endl;
int a,b;
cin>>a>>b;
int i;
if(n=='m'||n=='M'){
cout<<"学生名单如下:"<<endl;
for(i=0;i<=last;i++)if(list[i].getmath()>=a&&list[i].getmath()<=b)cout<<list[i].getname()<<endl;
}
else if(n=='e'||n=='E'){
cout<<"学生名单如下:"<<endl;
for(i=0;i<=last;i++)if(list[i].getenglish()>=a&&list[i].getenglish()<=b)cout<<list[i].getname()<<endl;
}
else if(n=='p'||n=='P'){
cout<<"学生名单如下:"<<endl;
for(i=0;i<=last;i++)if(list[i].getphysics()>=a&&list[i].getphysics()<=b)cout<<list[i].getname()<<endl;
}
else cout<<"科目输入错误!"<<endl;
}
template <typename T>void student<T>::tongji(){
int i,smath=0,seng=0,sphy=0;
float amath,aeng,aphy,asum,rmath,reng,rphy;
for(i=0;i<=last;i++)smath=smath+list[i].getmath();
amath=smath/(last+1);
for(i=0;i<=last;i++)seng=seng+list[i].getenglish();
aeng=seng/(last+1);
for(i=0;i<=last;i++)sphy=sphy+list[i].getphysics();
aphy=sphy/(last+1);
asum=(smath+seng+sphy)/(last+1);
cout<<"数学平均分:"<<amath<<'\t'<<"英语平均分:"<<aeng<<'\t'<<"物理平均分:"<<aphy<<'\t'<<"总平均分:"<<asum<<endl;
int j;
float nmath=0,neng=0,nphy=0;
for(j=0;j<=last;j++)if(list[j].getmath()>=60)nmath++;
rmath=nmath/(last+1);
for(j=0;j<=last;j++)if(list[j].getenglish()>=60)neng++;
reng=neng/(last+1);
for(j=0;j<=last;j++)if(list[j].getphysics()>=60)nphy++;
rphy=nphy/(last+1);
cout<<"数学合格率:"<<rmath*100<<'%'<<'\t'<<"英语合格率:"<<reng*100<<'%'<<'\t'<<"物理合格率:"<<rphy*100<<'%'<<endl;
float cmath=0,ceng=0,cphy=0,bmath,beng,bphy;
int k;
for(k=0;k<=last;k++) cmath=cmath+(list[k].getmath()-amath)*(list[k].getmath()-amath);
bmath=sqrt(cmath/(last+1));
for(k=0;k<=last;k++) ceng=ceng+(list[k].getenglish()-aeng)*(list[k].getenglish()-aeng);
beng=sqrt(ceng/(last+1));
for(k=0;k<=last;k++) cphy=cphy+(list[k].getphysics()-aphy)*(list[k].getphysics()-aphy);
bphy=sqrt(cphy/(last+1));
cout<<"数学标准差:"<<bmath<<'\t'<<"英语标准差:"<<beng<<'\t'<<"物理标准差:"<<bphy<<endl;
}
template <typename T>void student<T>::print(){
int i;
cout<<setw(10)<<"学号 "<<setw(10)<<"姓名"<<setw(12)<<" 数学"<<setw(10)<<"物理"<<setw(10)<<"英语"<<endl;
for(i=0;i<=last;i++) list[i].show();
}
template <typename T>void student<T>::order(){//*************冒泡排序法
bool noswap;
int s[100], i,j,m;
T temp;
for(i=0;i<=last;i++)s[i]=list[i].getmath()+list[i].getenglish()+list[i].getphysics();
for(i=0;i<last;i++)
{
noswap=true;//未交换标志为真
for(j=last;j>i;j--)
{
if(s[j]<s[j-1]||s[j]==s[j-1]&&list[j].getmath()<list[i-1].getmath()||s[j]==s[j-1]&&list[j].getmath()==list[j-1].getmath()&&list[j].getphysics()<list[j-1].getphysics()||s[j]==s[j-1]&&list[j].getmath()==list[j-1].getmath()&&list[j].getphysics()==list[j-1].getphysics()&&list[j].getenglish()<list[j-1].getenglish()||s[j]==s[j-1]&&list[j].getmath()==list[j-1].getmath()&&list[j].getphysics()==list[j-1].getphysics()&&list[j].getenglish()==list[j-1].getenglish()&&list[j].getnumber()<list[j-1].getnumber())
{
temp=list[j];
list[j]=list[j-1];
list[j-1]=temp;
m=s[j];
s[j]=s[j-1];
s[j-1]=m;
noswap=false;//未交换标志为假
}
}
if(noswap)break;//检查是否交换
}
}
template <typename T>void student<T>::file(){
ofstream ofile;
ofile.open("d:\\成绩单.txt");
ofile<<setw(10)<<"学号 "<<setw(10)<<"姓名"<<setw(12)<<"数学"<<setw(10)<<"物理"<<setw(10)<<"英语"<<endl;
int i;
for(i=0;i<=last;i++)ofile<<setw(10)<<list[i].getnumber()<<setw(10)<<list[i].getname()<<setw(12)<<list[i].getmath()<<setw(10)<<list[i].getphysics()<<setw(10)<<list[i].getenglish()<<endl;
ofile.close();
}