C++ ——学生成绩管理系统

一、实验目的

(1) 加深对C++语法、基础知识和编程技巧的运用,编写具有一定综合应用价值程序。
(2) 熟悉掌握C++的语法和面向对象程序设计方法。进一步理解和运用结构化和面向对象程设计想结合的思想和方法。
(3) 掌握函数的定义方法,掌握利用单继承和多继承的方式定义派生类的方法。
(4) 学会利用流程图或N-S图表示算法。
(5) 理解在各种继承方式下构造函数和析构函数的执行顺序。

二、环境

1、 安装windows XP或者以上版本的操作系统
2、 安装visual c++ 6.0或者visual studio 2017

三、正文

(一)分析
       设计一个简易的学生成绩管理系统,能够完成学生成绩的增加、删除、查找、修改、统计等操作,数据信息使用文件保存。要求系统具有菜单和提示。
(二)设计
1、设计程序功能
       学生成绩系统中学生的成绩信息按照学号的顺序进行排序。根据任务要求,下面将系统进行详细划分,功能结构如下图所示。
在这里插入图片描述

成绩的增加:通过键盘输入学生成绩信息并将其添加到学生成绩信息记录中,按照要求学号顺序插入。
成绩的删除:根据学生的学号从学生成绩信息记录中删除该学生的成绩信息。
成绩的查询:可以根据学生的学号和姓名查询学生的成绩信息,也可以根据某一门成绩的分数段查询学生成绩信息。
成绩的修改:根据学生的学号修改相应学生的成绩信息。
成绩的输出:将所有学生成绩信息输出。
成绩的统计:统计每门课程的及格人数显示不及格学生的信息,统计三门课程成绩全为优秀的学生人数,显示三门课程成绩全不及格的学生信息。
保存数据:利用文件操作将链表中学生成绩信息保存到文件中。
加载数据:利用文件操作从文件中读取学生成绩信息,形成学生记录的链表。

2、设计数据格式
       要完成学生成绩信息的增删改查及统计,首先设计一下内存中存放数据信息的格式。在本设计中采用动态内存空间分配的链表方法,该方法为一个结构分配内存空间。每一次分配一块内存空间可用来存放一个学生成绩的数据,可称之为一个结点。有多少个学生就应该分配多少块内存空间,也就是说建立多少个结点。当然用结构数组也可以完成上述操作,但如果不能预先把握学生人数,也就无法确定数组大小。而且当学生留级、退学之后也不能把该元素占用的内存空间释放出来。
       用动态存储的方法可以很好地解决这些问题。有一个学生就分配一个结点,无需预先确定学生的准确人数,某学生退学,可删去该结点,并释放该结点所占用的内存空间,从而节约了内存资源。另一方面,用数组的方法必须占用一块连续的内存区域。而使用动态分配时,每个结点之间可以是不连续的(结点内是连续的)。结点之间的联系可以在结点结构中定义一个指针项用来存放下一个结点的首地址。
       可在第一个结点的指针域内存入第二个结点的首地址,在第二个结点的指针域内又存入第三个结点的首地址,如此串连下去直到最后一个结点的指针域为空。
3、设计结点的组成
       结点是一个结构体类型,由两部分组成,第一部分是数据部分,在该系统中用来存放学生的学号、姓名、数学成绩、英语成绩、计算机基础成绩、和三门成绩的总分;第二部分定义了一个结构体指针变量,该指针爆开用来存放下一个结点的地址,如下图所示。
在这里插入图片描述
定义存放学生成绩结点信息的语句如下:

struct score
{
	int num;      //学号 
	string name;   //姓名 
	float math;   //数学成绩 
	float computer;   //计算机基础成绩 
	float scoresum;   //三门成绩总和 
	struct score * next;  //next为指向下一结点的指针 
} ;

一个个结点就通过next指针连接起来形成了单向链表的结构,如下图所示。head为指向链表的首结点。
在这里插入图片描述

4、程序设计与实现
在本程序中,使用链表存放学生成绩数据,设计一个功能类record来完成系统的各项功能,具体设计如下:

class record
{
public:
	struct score * InsertRecord(struct score *h);//插入学生成绩信息 
	struct score * DeleteRecord(struct score *h);//删除学生成绩信息 
	struct score * UpdateRecord(struct score *h);//修改学生成绩信息 
	void FindRecord(struct score *h,int  x,float s1,float s2);//根据某门课程的分数段查询学生成绩信息 
	void FindRecord(struct score *h,string  x); //根据学生姓名查询学生成绩信息 
	void FindRecord(struct score *h,int x);     //根据学生学号查询学生成绩信息 
	void StatisticRecord(struct score *h,int x);  //统计某门课程的及格学生人数、及格率,并显示不及格学生信息 
	void StacRecordFind(struct score *h);    //统计三门课程成绩全部优秀的学生人数,并显示全部优秀的学生信息
	void StacRecordDisq(struct score *h);    //统计三门课程成绩全部不及格的学生人数,并显示全部不及格的学生信息 
	void PrintRecord(struct score *h);       //输出所有 学生成绩 
	void SaveRecordFile(struct score *h);     //保存学生成绩信息到文件 
	struct score *LoadRecordFile(struct score *h);   //从文件中加载学生成绩信息 
};

(1)链表的插入操作
       链表的插入操作进针对有序链表来说的,本程序是按照学生学号从大到小顺序存放于链表中结点的。亲结点要插入链一前,应首先找到结点要插入的位置,本程序中就是要查找第一个比要插入的新结点的学号大的结点,将新结点插入到找到的第一个学号比其大的结点之前。在本功能模块中约定指针h为链表的头指针,指针p1为查找的符合要求的结点,指针p2为p1的前一个结点,指针p3 为新增加的结点。根据链表是否为空及找到结点的位置情况,链表的插入操作要考虑下面4种情况。
1、 链表为空
首先考虑链表中没有结点的情况,也就是链表为空,这时新增加的结点就是唯
的结点,新增结点就作为链表的头结点。具体语句如下:

if(h==NULL)
{
	h=p3;  //将新结点p3作为链表的头结点
	return h;	
}

2、插入到原链表头结点之前
       接着考虑表中有结点时,即链表不为空时,我们需要查找插入点的位置,这需要通过循环从头到尾扫描链表中的每个结点,当找到 一个结点的学号大于新结点的学号或查找结点为空时为止。
       若经过循环查找到的第一个大于新结点的学号的结点正好是链表头结点时,新结点p3插入到头结点h 之前,再将p3作为新的链表头结点。
具体语句:

if (p1 == h)
{
	p3->next = h;  //新结点的指针域指向链表的头结点
	h = p3;   //将新结点作为链表的头结点
	return h;
}

3、插入到链表中间的位置
       若经过循环查找到第一个大于新结点学号的结点是除头结点以外的其他结点时,将新结点p3插入到找到的结点p1之前,即将指针p2的next指针指向新结点p3,将p3结点的next指针指向p1指针所指向的结点。
具体语句如下:

if (p3->num <= p1->num)
{
	p2->next = p3;
	p3->next = p1;
}

4、插入到链表尾部
       若经过循环查找没有找到大于新结点学号的结点,即p1为空指针,则将新结点插入链表的最后一个结点的后面作为末尾结点。具体操作为将p2结点的指针域设置为p3,将新的末尾结点p3的指针域设置为空即可赋值为p1,此操作和新结点插入到链表中间的位置代码类似,所以将新结点插入到链表尾部和插入到中间位置的操作合并在一起,在此不再说明。

(2)链表的删除操作
       删除链表,首先根据学号在链表中循环查找要与删除学生学号相同的结点,若找到则在链表删除找到符合条件的结点,并将该结点的空间释放,若没有找到则给出相应的提示。在本功能模块中,约定指针h为链表的头指针,指针p1为查找的符合要求的结点的指针,指针p2为p1的前一个结点指针。根据链表是否为空及找到符合要求结点的位置,链表的删除要考虑下面三种情况。
① 链表为空
首先考虑链表中没有结点的情况,也就是链表为空,就没有结点可以删除了,可以给出适当地提示。具体语句如下:

if (h == NULL)
{
	cout << "\n抱歉,没有任何记录!";
	return h;
}

② 删除的结点为链表的头结点
       当查找到的需要删除的结点为链表的头结点时,即查找到符合条件的结点指针p1指向的就是链表的头结点h,则将将结点指针h指向下一个结点,将下一个结点作为链表的头结点,并且释放原来头结点的存储单元。具体语句如下:

if (p1==h)
{
	h = h->next;
	delete h;
}

③ 删除的结点为链表中非头结点的其他结点
       当查找到的需要删除的结点p1不是链表头结点h时,则将p2指向的结点的指针域指向p1指向结点的后一个结点,并且释放p1结点的存储单元。具体语句如下:

p2->next = p1->next;
delete p1;

(3)链表的更新操作
       要修改链表中结点的记录,则首先在链表中通过循环查找需要修改的记录结点,若找到则根据要求修改结点的相关数据,没有找到符合要求的结点则给出相应的提示。
       在本功能模块中,约定指针h为链表的头指针,指针p1为查找的符合要求的结点指针。查找要修改的结点,首先将头结点的指针h赋给指针p1,若p1不为空,且p1的学号不等于要修改的学生的学号,则将p1指针移向下一个结点,若下移后p1不为空且p1的学号不等于要修改的学生的学号,则再将p1指针移向下一个结点,重复执行操作,直到p1为空或p1的学号等于要修改的学生的学号为止。具体代码如下:

p1 = h;
cout << "\n请输入需要修改记录的学生学号";
cin >> num;
while (p1 != NULL && p1->num1 != num)
{
	p1 = p1->next;
}

执行完上面的操作后若p1为空,则表示没有找到需要修改的记录,给出相应提示,具体代码如下:

if (p1 == NULL)
{
	cout << "\n抱歉,表中没有该记录哦!";
	return h;
}

相反则找到需要修改的记录结点,即p1指向的结点,根据需要进行修改,具体代码如下:

cout << "\n请重新输入学生的数学成绩:";
cin >> p1->math;
cout << "\n请重新输入学生的英语成绩:";
cin >> p1->english;
cout << "\n请重新输入学生的计算机基础成绩:";
cin >> p1->computer;
p1->scoresum = p1->math + p1->english + p1->computer;

(4)链表的输出操作
       链表的输出操作,就是通过循环扫描链表中每一个结点,将结点的数据域的信息输出。在本功能中约定指针p为指向当前结点的指针。首先将指针p指向链表的头结点,若p不为空则输出指向p指向的各项数据,而后将指针p向下移一个结点,若p再不为空则再输出指针p指向的各项数据,接着再将指针p移向下一个结点,依次循环进到指针p 为空为止。因链表的输出操作相对简单,具体代码可看源程序,不再书写。

(三)代码实现

#include<iostream>
#include<string>
#include<fstream>
using namespace std;

struct score     //定义存放学生成绩信息的结点
{
	int num;      //学号 
	string name;   //姓名 
	float math;   //数学成绩 
	float english;  //英语成绩
	float computer;   //计算机基础成绩 
	float scoresum;   //三门成绩总和 
	struct score * next;  //next为指向下一结点的指针 
};
struct score * head;  //指向链表头结点的指针
int studentSum = 0;  //学生总人数

class record
{
public:
	struct score * InsertRecord(struct score *h);//插入学生成绩信息 
	struct score * DeleteRecord(struct score *h);//删除学生成绩信息 
	struct score * UpdateRecord(struct score *h);//修改学生成绩信息 
	void FindRecord(struct score *h, int  x, float s1, float s2);//根据某门课程的分数段查询学生成绩信息 
	void FindRecord(struct score *h, string  x); //根据学生姓名查询学生成绩信息 
	void FindRecord(struct score *h, int x);     //根据学生学号查询学生成绩信息 
	void StatisticRecord(struct score *h, int x);  //统计某门课程的及格学生人数、及格率,并显示不及格学生信息 
	void StacRecordFind(struct score *h);    //统计三门课程成绩全部优秀的学生人数,并显示全部优秀的学生信息
	void StacRecordDisq(struct score *h);    //统计三门课程成绩全部不及格的学生人数,并显示全部不及格的学生信息 
	void PrintRecord(struct score *h);       //输出所有 学生成绩 
	void SaveRecordFile(struct score *h);     //保存学生成绩信息到文件 
	struct score *LoadRecordFile(struct score *h);   //从文件中加载学生成绩信息 
};

struct score *record:: InsertRecord(struct score *h)
{
	struct score *p1, *p2, *p3;
	p3 = new score;     //创建新的学生成绩结点
	cout << "\n请输入学生学号:";
	cin >> p3->num;
	cout << "\n请输入学生姓名:";
	cin >> p3->name;
	cout << "\n请输入学生的数学成绩:";
	cin >> p3->math;
	cout << "\n请输入学生的英语成绩:";
	cin >> p3->english;
	cout << "\n请输入学生的计算机基础成绩:";
	cin >> p3->computer;
	p3->scoresum = p3->math + p3->english + p3->computer;  //计算结点的总成绩
	p3->next = NULL;   //将要插入结点的指针域置为空

	if (h == NULL)
	{
		h = p3;
		return h;
	}
	p1 = p2 = h;
	while (p1 != NULL && p3->num > p1->num)   //查找结点的学号大于要插入结点的学号的第一个结点    
	{                   //指针p1表示符合条件的结点的指针,指针p2是指针p1的前一个结点的指针
		p2 = p1;
		p1 = p1->next;
	}
	if (p1 == h)  //插入位置为链表头结点前
	{
		p3->next = h;
		h = p3;
		return h;
	}
	else   //插入位置为链表的中间的链表的尾部
	{
		p2->next = p3;
		p3->next = p1;
	}
	studentSum += 1;  //学生人数加1
	return h;    //返回链表的头结点
}

void record::PrintRecord(score *h)
{
	if (h == NULL)
	{
		cout << "\n抱歉,没有任何记录!";
		return;
	}
	cout << "\n学号\t姓名\t数学\t英语\t计算机\t总分" << endl;
	while (h)   //输出链表中每个结点的学生成绩信息
	{
		cout << h->num << "\t" << h->name << "\t" << h->math << "\t" << h->english << "\t" << h->computer << "\t" << h->scoresum << endl;
		h = h->next;
	}
}

struct score *record::DeleteRecord(struct score *h)
{
	struct score *p1, *p2;
	int num;
	if (h == NULL)  //链表为空
	{
		cout << "\n抱歉,没有任何记录!";
		return h;
	}
	p1 = p2 = h;//将链表的头指针赋给指针p1和p2
	cout << "\n请输入要删除记录的学生学号";
	cin >> num;
	while (p1 != NULL && p1->num != num)//查找结点的学号等于要删除学生学号的第一个结点
	{                     //指针p1表示符合条件的结点的指针,指针p2是指针p1的前一个结点指针
		p2 = p1;
		p1 = p1->next;
	}
	if (p1 == NULL)
	{
		cout << "\n抱歉啊,表中没有该记录哦!";
		return h;
	}
	if (p1->num == num)
	{
		studentSum -= 1;//学生人数减1
		if (p1 == h)  //删除的是头结点
			h = h->next;
		else      //删除的是非头结点
			p2->next = p1->next;
		delete p1;  //释放p1所指向的存储单元
	}
	return h;
}

struct score *record::UpdateRecord(struct score *h)
{
	struct score *p1;
	int num;
	if (h == NULL)
	{
		cout << "\n抱歉,没有任何记录!";
		return h;
	}
	p1 = h;
	cout << "\n请输入要修改记录的学生学号:";
	cin >> num;
	while (p1 != NULL && p1->num != num) //查找结点的学号等于要修改学生学号的结点指针
	{
		p1 = p1->next;  //将p1指针移到下一个结点
	}
	if (p1 == NULL)  //没有找到符合要求的结点
	{
		cout << "\n抱歉,表中没有该记录!";
		return h;
	}
	if (p1->num == num)  //找到符合要求的结点,并修改学生的相关成绩
	{
		cout << "\n请重新输入学生的数学成绩:";
		cin >> p1->math;
		cout << "\n请重新输入学生的英语成绩:";
		cin >> p1->english;
		cout << "\n请重新输入学生的计算机基础成绩:";
		cin >> p1->computer;
		p1->scoresum = p1->math + p1->english + p1->computer;
	}
	return h;
}

void record::FindRecord(struct score *h, int x, float s1, float s2)
{
	if (h == NULL) //链表为空
	{
		cout << "\n,抱歉,没有任何记录!";
		return;
	}
	cout << "\n学号\t姓名\t数学\t英语\t计算机\t总分" << endl;
	while (h)
	{
		if (x == 1)  //查找数学成绩在某分数段的学生成绩信息
		{
			if (h->math >= s1 && h->math <= s2)
				cout << h->num << "\t" << h->name << "\t" << h->math << "\t" << h->math << "\t" << h->english << "\t" << h->computer << "\t" << h->scoresum << endl;
		}
		if (x == 2)
		{
			if (h->english >= s1 && h->english <= s2)
				cout << h->num << "\t" << h->name << "\t" << h->math << "\t" << h->math << "\t" << h->english << "\t" << h->computer << "\t" << h->scoresum << endl;

		}
		if (x == 3)
		{
			if (h->computer >= s1 && h->computer <= s2)
				cout << h->num << "\t" << h->name << "\t" << h->math << "\t" << h->math << "\t" << h->english << "\t" << h->computer << "\t" << h->scoresum << endl;
		}
		h = h->next;
	}

}

void record::FindRecord(struct score *h, int num)  //根据学生学号查找学生成绩信息
{
	struct score *p1;
	if (h == NULL)
	{
		cout << "\n抱歉,没有任何记录";
		return;
	}
	p1 = h;   //将链表的头结点指针h赋给指针p1
	while (p1 != NULL && p1->num != num) //查找结点的学号等于要查找学生学号的结点指针
	{
		p1 = p1->next;
	}
	if (p1 == NULL)   //没有找到
	{
		cout << "抱歉啊,表中没有该记录的哦!";
		return;
	}
	if (p1->num == num)  //找到并显示信息
	{
		cout << "\n学号\t姓名\t数学\t英语\t计算机\t总分" << endl;
		cout << p1->num << "\t" << p1->name << "\t" << p1->math << "\t" << p1->math << "\t" << p1->english << "\t" << p1->computer << "\t" << p1->scoresum << endl;
	}

}

void record::FindRecord(struct score *h, string name)  //根据学生姓名查找学生成绩信息
{
	struct score *p1;
	if (h == NULL)
	{
		cout << "\n抱歉,没有任何记录!";
		return;
	}
	p1 = h;
	while (p1 != NULL && p1->name != name) //查找结点的姓名等于要查找学生姓名的结点指针
	{
		p1 = p1->next;
	}
	if (p1 == NULL)
	{
		cout << "\n抱歉,表中没有该记录!";
		return;
	}
	if (p1->name == name)
	{
		cout << "\n学号\t姓名\t数学\t英语\t计算机\t总分" << endl;
		cout << p1->num << "\t" << p1->name << "\t" << p1->math << "\t" << p1->math << "\t" << p1->english << "\t" << p1->computer << "\t" << p1->scoresum << endl;
	}
}

void record::StatisticRecord(struct score* h, int x)
{
	struct score *p = h;  //将链表的头结点指针赋给指针p
	int count = 0;//定义统计人数count变量并赋初值为0
	if (p == NULL)
	{
		cout << "\n抱歉,没有任何记录!";
		return;
	}
	while (p)
	{
		if (x == 1)
			if (p->math >= 60)
				count += 1;
		if (x == 2)
			if (p->english >= 60)
				count += 1;
		if (x == 3)
			if (p->computer >= 60)
				count += 1;
		p = p->next;
	}
	if (x == 1)
	{
		cout << "数学成绩及格人数为:";
		cout << count;
		cout << ",及格率为:";
		cout << count / (float)studentSum << endl;
		if (count < studentSum)
			cout << "\n学号\t姓名\t数学" << endl;
		else
			cout << "没有数学成绩不及格学生" << endl;
	}
	else
	{
		if (x == 2)
		{
			cout << "英语成绩及格人数为:";
			cout << count;
			cout << ",及格率为:";
			cout << count / (float)studentSum << endl;
			if (count < studentSum)
				cout << "\n学号\t姓名\t英语" << endl;
			else
				cout << "没有英语成绩不及格学生" << endl;
		}
		else
		{
			if (x == 3)
			{
				cout << "计算机成绩及格人数为:";
				cout << count;
				cout << ",及格率为:";
				cout << count / (float)studentSum << endl;
				if (count < studentSum)
					cout << "\n学号\t姓名\t计算机" << endl;
				else
					cout << "没有计算机成绩不及格学生" << endl;
			}
		}

	}

	p = h;
	while (p)
	{
		if (x == 1)
			if (p->math < 60)
				cout << p->num << "\t" << p->name << "\t" << p->math << endl;
		if (x == 2)
			if (p->english < 60)
				cout << p->num << "\t" << p->name << "\t" << p->english << endl;
		if (x == 13)
			if (p->computer < 60)
				cout << p->num << "\t" << p->name << "\t" << p->computer << endl;
		p = p->next;
	}

}

void record::StacRecordFind(struct score *h)
{
	struct score *p = h;
	int count = 0;
	if (p == NULL)
	{
		cout << "\n抱歉,没有任何记录!";
		return;
	}
	while (p)
	{
		if (p->math >= 90 && p->english >= 90 && p->computer >= 90)
		{
			count += 1;
			
		}
		p = p->next;

	}
	cout << "三门成绩全为优秀的学生人数为:";
	cout << count << endl;
	cout << "全为优秀的学生信息为:" << endl;
	cout << "\n学号\t姓名\t数学\t英语\t计算机\t总分" << endl;
	p = h;
	while (p)
	{
		if (p->math >= 90 && p->english >= 90 && p->computer >= 90)
			cout << p->num << "\t" << p->name << "\t" <<p->math<<"\t"<<p->english<<"\t"<< p->computer <<"\t"<<p->scoresum<< endl;
		p = p->next;
	}
}

void record::StacRecordDisq(struct score *h)
{
	struct  score *p = h;
	int count = 0;
	if (p == NULL)
	{
		cout << "\n抱歉,没有任何记录!";
		return;
	}
	while (p)
	{
		if (p->math < 60 && p->english < 60 && p->computer < 60)
			count += 1;
		p = p->next;
	}
	cout << "三门成绩全不及格的学生人数为:";
	cout << count << endl;
	cout << "全为不及格的学生信息为:" << endl;
	cout << "\n学号\t姓名\t数学\t英语\t计算机\t总分" << endl;
	p = h;
	while (p)
	{
		if (p->math <60 && p->english <60 && p->computer <60)
			cout << p->num << "\t" << p->name << "\t" << p->math << "\t" << p->english << "\t" << p->computer << "\t" << p->scoresum << endl;
		p = p->next;
	}
}

void record::SaveRecordFile(struct score *h) //将链表中的数据写入文件
{
	struct score *p;
	ofstream ofile;  //定义输出文件对象
	ofile.open("score.dat", ios::out);  //以定的方式打开文件score.dat,若该文件不存在,则创建score.dat文件
	if (!ofile)
	{
		cout << "\n数据文件打开错误没有将数据写入文件!\n";
		return;
	}
	ofile << "\n学号\t姓名\t数学\t英语\t计算机\t总分";
	while (h)
	{
		ofile<<endl<< h->num << "\t" << h->name << "\t" << "\t" << h->math << "\t" << h->english << "\t" << h->computer << "\t" << h->scoresum;
		p = h;  //将当前结点的数据信息写入到文件中
		h = h->next;
		delete p;
	}
	ofile.close();
}

struct score* record::LoadRecordFile(struct score *h)
{
	ifstream ifile;  //定义输入文件对象
	ifile.open("score.dat", ios::in);//以读写方式打开文件score.dat
	struct score *p, *q;
	if (!ifile)
	{
		cout << "\n数据文件不存在,加载不成功!\n";
		return NULL;
	}
	char s[50];
	ifile.getline(s, 50); //读取文件指针当前行数据
	while (!ifile.eof()) 
	{
		studentSum = studentSum + 1;
		p = new score;
		ifile >> p->num >> p->name >> p->math >> p->english >> p->computer >> p->scoresum; //
		p->next = NULL;
		if (h == NULL)
		{
			q = h = p;
		}
		else
		{
			q->next = p;
			q = p;
		}
	}
	ifile.close();
	return h;
}

void SystemMenu(record r)
{
	int choice;
	while (1)
	{
		cout << "\n\t\t欢迎进入学生成绩管理系统!";
		cout << "\n@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@";
		cout << "\n\t1、添加学生成绩信息";
		cout << "\n\t2、删除学生成绩信息";
		cout << "\n\t3、修改学生成绩信息";
		cout << "\n\t4、查询学生成绩信息";
		cout << "\n\t5、显示所有学生成绩信息";
		cout << "\n\t6、统计学生成绩信息";
		cout << "\n\t0、退出系统";
		cout << "\n@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@";

		cout << "\n请根据提示选择操作:";
		cin >> choice;
		switch (choice)
		{
		case 1:           //增加学生成绩信息
			head = r.InsertRecord(head);
			break;
		case 2:          //删除学生成绩信息
			head = r.DeleteRecord(head);
			break;
		case 3:    //修改学生成绩信息
			head = r.UpdateRecord(head);
			break;
		case 4:    //查询活到成绩信息        
			while (1)
			{
				int c;
				cout << "\n*************************************";
				cout << "\n\t1、根据学号查询学生成绩信息";
				cout << "\n\t2、根据姓名查询学生成绩信息";
				cout << "\n\t3、根据数学分数查询学生成绩信息";
				cout << "\n\t4、根据英语分数查询学生成绩信息";
				cout << "\n\t5、根据计算机基础成绩查询学生成绩信息";
				cout << "\n\t6、返回上级目录";
				cout << "\n*************************************";

				cout << "\n请根据提示选择操作:";   //显示查询子菜单
				cin >> c;
				if (c == 1)   //根据学生学号查询学生成绩信息
				{
					int x;
					cout << "\n请输入需要查询的学生学号:";
					cin >> x;
					r.FindRecord(head, x);
				}
				if (c == 2)   //根据学生姓名查询学生成绩信息
				{
					string name;
					cout << "\n请输入需要查询的学生姓名:";
					cin >> name;
					r.FindRecord(head, name);
				}
				if (c == 3)  //根据数学分数段查询学生成绩信息
				{  
					float s1, s2;
					cout << "\n请输入查询的数学最低分的最高分:";
					cin >> s1 >> s2;
					r.FindRecord(head, 1, s1, s2);
				}
				if (c == 4)   //根据英语分数段查询学生成绩信息
				{
					float s1, s2;
					cout << "\n请输入查询的英语最低分的最高分:";
					cin >> s1 >> s2;
					r.FindRecord(head, 2, s1, s2);
				}
				if (c == 5)   //根据计算机分数段查询学生成绩信息
				{
					float s1, s2;
					cout << "\n请输入查询的计算机基础最低分的最高分:";
					cin >> s1 >> s2;
					r.FindRecord(head, 3, s1, s2);
				}
				if (c == 6)  //退出查询子菜单
					break;
			}
			break;
		case 5:           //输出所有学生成绩信息
			r.PrintRecord(head); 
			break;
		case 6:             //统计学生成绩信息
			while (1)
			{
				int c;
				cout << "\n***********************************************************";
				cout << "\n\t1、统计数学成绩及格学生人数,并显示不及格学生信息";
				cout << "\n\t2、统计英语成绩及格学生人数,并显示不及格学生信息";
				cout << "\n\t3、统计计算机成绩及格学生人数,并显示不及格学生信息";
				cout << "\n\t4、统计三门功课都不及格的学生人数,并显示学生信息(〉=90)";
				cout << "\n\t5、统计三门功课都优秀的学生人数,并显示学生信息";
				cout << "\n\t6、返回上级目录";
				cout << "\n***********************************************************";

				cout << "\n请根据提示选择操作:";   //显示统计子菜单
				cin >> c;
				if (c == 1)
				{
					r.StatisticRecord(head, 1);//统计数学成绩及格人数,并显示不及格学生信息
				}
				if (c == 2)
				{
					r.StatisticRecord(head, 2);//统计英语成绩及格人数,并显示不及格学生信息
				}
				if (c == 3)
				{
					r.StatisticRecord(head, 3);//统计计算机成绩及格人数,并显示不及格学生信息
				}
				if (c == 4)
				{
					r.StacRecordFind(head);//统计三门功课都不及格学生人数,并显示学生信息
				}
				if (c == 5)
				{
					r.StacRecordDisq(head);//统计三门功课都优秀学生人数,并显示学生信息
				}
				if (c == 6)  //退出统计子菜单
					break;
			}
			break;
		}
		if (choice == 0)//退出系统
		break;
	}
	
}

int main()
{
	head = NULL;
	record r;                   //定义record类的对象r
	head = r.LoadRecordFile(head);  //将文件中的数据读取到链表中
	SystemMenu(r);           //显示系统菜单,并处理用户选择
	r.SaveRecordFile(head);  //将链表中的数据写到文件中
	return 0;

}

(四)结果
1、显示欢迎界面并添加学生成绩
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
2、显示所有学生成绩
在这里插入图片描述

3、查询学生成绩
在这里插入图片描述

4、统计学生成绩
在这里插入图片描述

5、修改学生成绩信息

在这里插入图片描述

6、删除学生成绩信息

在这里插入图片描述

四、总结

通过课程设计能够在下列两个方面得到锻炼:
(1)要根据实际问题的具体情况,结合面向对象的基本理论和基本技巧,正确分析问题,并设计出解决问题的有效算法与程序。
(2)通达上机实验,验证自己设计的算法与程序的正确性,学会利用基本调试方法,找出程序代码中的错误并且修改,进一步提高程序设计水平。

  • 70
    点赞
  • 544
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值