学生成绩档案管理系统

学生成绩档案管理系统

题目

学生信息录入,包括学号、姓名、专业、四门课成绩、总分、名次;
系统可对学生信息浏览、增加、删除和修改;
按学生成绩确定名次及信息输出,双向冒泡排序、希尔排序、快速排序、堆排序。
要求可对学生信息查询,根据学号或姓名进行查找;
信息修改仅可修改四门课成绩;
文件存取学生信息。

系统设计

使用Visual Studio 2019 开发环境完成相应C++主函数设计。
定义结构体,包含学生学号、姓名、专业、成绩、总分、名次。将友元函数声明为public类型,声明增加、浏览、查找、修改、删除、排序、保存这几个友元函数。

功能模块

增加模块(增加学生信息)
浏览模块(浏览信息)
查找模块(查找学生条件)
修改模块(修改学生成绩)
删除模块(删除学生的信息)
排序模块(双向冒泡排序、希尔排序、快速排序、堆排序)
保存模块(保存学生成绩信息)

排序算法

双向冒泡排序

比较相邻两个元素的大小。如果前一个元素比后一个元素大,则两元素位置交换
对数组中所有元素的组合进行第1步的比较
奇数趟时从左向右进行比较和交换
偶数趟时从右向左进行比较和交换
当从左端开始遍历的指针与从右端开始遍历的指针相遇时,排结束

希尔排序

初始时,有一个大小为 10 的无序序列。
在第一趟排序中,我们不妨设 gap1 = N / 2 = 5,即相隔距离为 5 的元素组成一组,可以分为 5 组。
接下来,按照直接插入排序的方法对每个组进行排序。
在第二趟排序中,我们把上次的 gap 缩小一半,即 gap2 = gap1 / 2 = 2 (取整数)。这样每相隔距离为 2的元素组成一组,可以分为 2 组
按照直接插入排序的方法对每个组进行排序。
在第三趟排序中,再次把 gap 缩小一半,即gap3 = gap2 / 2 = 1。 这样相隔距离为 1 的元素组成一组,即只有一组
按照直接插入排序的方法对每个组进行排序。

快速排序

首先设定一个分界值,通过该分界值将数组分成左右两部分
将大于或等于分界值的数据集中到数组右边,小于分界值的数据集中到数组的左边。此时,左边部分中各元素都小于或等于分界值,而右边部分中各元素都大于或等于分界值
然后,左边和右边的数据可以独立排序。对于左侧的数组数据,又可以取一个分界值,将该部分数据分成左右两部分,同样在左边放置较小值,右边放置较大值。右侧的数组数据也可以做类似处理
重复上述过程,可以看出,这是一个递归定义。通过递归将左侧部分排好序后,再递归排好右侧部分的顺序。当左、右两个部分各数据排序完成后,整个数组的排序也就完成了

堆排序

算法原理:
堆排序是指利用堆这种数据结构所设计的一种排序算法。堆是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于它的父节点。
算法步骤:
首先将待排序的数组构造成一个大根堆,此时,整个数组的最大值就是堆结构的顶端
将顶端的数与末尾的数交换,此时,末尾的数为最大值,剩余待排序数组个数为n-1
将剩余的n-1个数再构造成大根堆,再将顶端数与n-1位置的数交换,如此反复执行,便能得到有序数组

实现代码

scoreManage.h
 
#include <string>
#include<iostream>
using namespace std;
struct student {
	int id;//学号
	string name;//姓名
	string major;//专业
	double math_score;//高数成绩
	double english_score;//英语成绩
	double psy_score;//大物成绩
	double major_score;//专业成绩
	double total_score;//总分
	int sortid = 1;
};
struct studentNode {
	student stu;//包含学生信息
	studentNode* next;
};
class scoreManage {
public:
	studentNode* first;
public:
	scoreManage();
	~scoreManage();
	void load_file();//加载文件信息
	void save_file();//保存
	int total();//计算学生总数
	bool is_same(studentNode* bt);//判断学号是否重复的函数的声明
	void add_student(studentNode* bt, int t = 1);//添加学生
	void del_student(int id);//删除学生
	void modify_score(double score);//修改成绩
	studentNode* tool();//学生信息
	studentNode* find_student(int id);//通过学号查找学生
	studentNode* find_student(string name);//通过姓名查找
	void print_one(studentNode* bt);//输出单个学生信息
	void print();//输出所有学生信息
	void sort_print();//输出排序后的学生信息
	void bubble_sort();//双向冒泡排序
	void Hill_sort();//希尔排序
	void quick_sort(student a[], int low, int high);//快速排序
	void heap_sort();//堆排序
	student* linktoarray();//链表->数组
	void arrytolink(student* stu);
private:
	void heapp(student* a, int k, int n);//调整堆
};
void start();
void menu();
scoreManange.cpp
#include <iostream>
#include<stdio.h>
#include<fstream>
#include<conio.h>//catch() 任意键继续
#include <windows.h>//system("cls") 清屏
#pragma warning(disable:4996)
#include<iostream>
#include<fstream>
#include<iomanip>
#include<string>
#include<algorithm>
#include<sstream>
#include "scoreManage.h"
#include<string>
using namespace std;
scoreManage test;
/*
* 初始化,读取文件
*/
scoreManage::scoreManage() {
	first = NULL;
	load_file();
}
/*
* 对象调用结束
*/
scoreManage::~scoreManage() {
}
/*
* 判断学号是否重复(学号必须唯一)
*/
bool scoreManage::is_same(studentNode* bt) {
	studentNode* p = first;
	while (p)
	{
		if (p->stu.id == bt->stu.id)
		{
			return false;
		}
		p = p->next;
	}
	return true;
}
/*
* 将txt中数据读入链表中
*/
void scoreManage::load_file() {
	FILE* fp;
	studentNode* p = new studentNode;
	fp = fopen("E://c//studentScore.txt", "r");//以可读方式打开文件
	if (!fp)
	{
		printf("文件不存在\n");
		start();
		return;
	}
	//判断文件内容是否为空,通过读取,判断是否有
	ifstream ifs("E://c//studentScore.txt", ios::in);
	char ch;
	ifs >> ch;
	if (ifs.eof())
	{
		cout << "文件为空,请先添加!" << endl;
		return;
	}
	ifstream in;
	in.open("E://c//studentScore.txt");
	string sline;//每一行
	while (getline(in, sline))   //逐行读取txt文件
 
	{
		istringstream sin(sline);
		sin >> p->stu.id >> p->stu.name >> p->stu.major >> p->stu.math_score >> p->stu.english_score >> p->stu.psy_score >> p->stu.major_score >> p->stu.total_score >> p->stu.sortid;
		add_student(p, 0);
		p = new studentNode;
	}
}
/*
* 将一系列操作后的数据重新保存
*/
void scoreManage::save_file() {
	studentNode* p;
	p = first;
	if (p == NULL)
	{
		printf("现在没有学生信息,请先输入学生信息\n\n");
		studentNode* q = tool();
		add_student(q);
		return;
	}
	//先清空txt
	fstream file("E://c//studentScore.txt", ios::out);
	fstream in("E://c//studentScore.txt");     //打开txt
	int c = 0;
	while (p)
	{
		in << p->stu.id << setw(10) << p->stu.name << setw(10) << p->stu.major << setw(10) << p->stu.math_score << setw(10) << p->stu.english_score << setw(10) << p->stu.psy_score << setw(10) << p->stu.major_score << setw(10) << p->stu.math_score + p->stu.english_score + p->stu.psy_score + p->stu.major_score << setw(10) << p->stu.sortid;
		in << '\n';
		p = p->next;
	}
	in.close();
 
	cout << "保存成功" << endl;
}
/*
* 计算学生总数
*/
int scoreManage::total() {
	if (!first) {
		cout << ' 0' << endl;
		return 0;
	}
	int n = 0;
	studentNode* p = first;
	while (p->next != NULL)
	{
		n++;
		p = p->next;
	}
	//cout << "一共有" << n + 1 << "个学生." << endl;
	return n + 1;
}
/*
* 用于添加的学生信息
*/
studentNode* scoreManage::tool() {
	studentNode* p = new studentNode;
	cout << "请输入学号:" << endl;
	int id;
	cin >> id;
	p->stu.id = id;
	cout << "请输入姓名:" << endl;
	string name;
	cin >> name;
	p->stu.name = name;
	cout << "请输入专业:" << endl;
	string major;
	cin >> major;
	p->stu.major = major;
	cout << "高数成绩:" << endl;
	double score1;
	cin >> score1;
	p->stu.math_score = score1;
	cout << "英语成绩:" << endl;
	double score2;
	cin >> score2;
	p->stu.english_score = score2;
	cout << "大物成绩:" << endl;
	double score3;
	cin >> score3;
	p->stu.psy_score = score3;
	cout << "专业成绩:" << endl;
	double score4;
	cin >> score4;
	p->stu.major_score = score4;
	p->stu.total_score = score1 + score2 + score3 + score4;
	return p;
}
/*
* 添加学生信息
*/
void scoreManage::add_student(studentNode* bt, int t) {
	studentNode* p = new studentNode;
	if (first == NULL)//如果链表为空
	{
		first = bt;
		bt->next = NULL;
		return;//插入完成返回
	}
	else {
		if (is_same(bt))//判断学号是否重复
		{
			p = first;//从头结点开始找
			while (p)//p非空则一直循环
			{
				if (p->next == NULL)//找到尾节点
				{
					p->next = bt;
					bt->next = NULL;
					return;//插入完成返回
				}
				p = p->next;//找下一个节点
			}
		}
		else {
			cout << "学号重复!此学生信息添加失败" << endl;
			if (t == 0) {
				return;
			}
			if (t == 1) {
				cout << "是否重新输入:(1-yes 2-no)" << endl;
				int d;
				cin >> d;
				switch (d)
				{
				case 1:
				{studentNode* q = tool();
				add_student(q);//重新添加
				};
				default:
					break;
				}
			}
		}
	}
}
/*
* 删除某个学生信息
*/
void scoreManage::del_student(int id) {
	studentNode* pre = new studentNode;//前驱指针
	studentNode* p = first;
	pre->next .= p;
	while (p)
	{
		if (p->stu.id == id)//找到
		{
			pre->next = p->next;
			p->next = NULL;
			delete p;
			cout << "删除成功" << endl;
		}
		pre->next = p;
		p = p->next;
	}
	cout << "未找到信息!" << endl;
}
/*
* 修改学生成绩,通过选择判断输入具体学科的成绩
*/
void scoreManage::modify_score(double score) {
	studentNode* p;
	cout << "查找学生的方式:(1-学号查找 2-姓名查找)" << endl;
	int chioce;
	cin >> chioce;
	switch (chioce)
	{
	case 1: {
		cout << "请输入学号:" << endl;
		int name;
		cin >> name;
		p = find_student(name);
		if (!p) {
			cout << "未找到相关信息!" << endl;
			modify_score(score);
		}
		else {
			cout << "选择要修改的学科:(1-高数 2-英语 3-大物 4-专业)" << endl;
			int c;
			ci.n >> c;
			switch (c) {
			case 1:
				p->stu.math_score = score;
				cout << "修改成功" << endl;
				break;
			case 2:
				p->stu.english_score = score;
				cout << "修改成功" << endl;
				break;
			case 3:
				p->stu.psy_score = score;
				cout << "修改成功" << endl;
				break;
			case 4:
				p->stu.major_score = score;
				cout << "修改成功" << endl;
				break;
			default:
				cout << "无效字符" << endl;
				modify_score(score);
				break;
			}
			p->stu.total_score = p->stu.math_score + p->stu.english_score + p->stu.psy_score + p->stu.major_score;
		}
	}
		  break;
	case 2: {
		cout << "请输入姓名:" << endl;
		string name;
		cin >> name;
		p = find_student(name);
		if (!p) {
			cout << "未找到相关信息!" << endl;
			modify_score(score);
		}
		else {
			cout << "选择要修改的学科:(1-高数 2-英语 3-大物 4-专业)" << endl;
			int c;
			cin >> c;
			switch (c) {
			case 1:
				p->stu.math_score = score;
				break;
			case 2:
				p->stu.english_score = score;
				break;
			case 3:
				p->stu.psy_score = score;
				break;
			case 4:
				p->stu.major_score = score;
				break;
			default:
				cout << "无效字符" << endl;
				modify_score(score);
				break;
			}
			p->stu.total_score = p->stu.math_score + p->stu.english_score + p->stu.psy_score + p->stu.major_score;
		}
	}
		  break;
	default:
		cout << "无效字符" << endl;
		cout << "是否重新输入:(1-yes 2-no)" << endl;
		int d;
		cin >> d;
		switch (d)
		{
		case 1:
			modify_score(score);//重新继续输入
		default:
			break;
		}
 
		break;
	}
}
studentNode* scoreManage::find_student(int id) {
	studentNode* p = new studentNode;
	p = first;
	while (p)
	{
		if (p->stu.id == id)
		{
			return p;
		}
		p = p->next;
	}
	return NULL;
}
studentNode* scoreManage::find_student(string name) {
	studentNode* p = new studentNode;
	p = first;
	while (p)
	{
		if (strcmp(name.c_str(), p->stu.name.c_str()) == 0)//必须是字符数组
		{
			return p;
		}
		p = p->next;
	}
	return NULL;
}
void scoreManage::print_one(studentNode* bt) {
	if (!bt) {
		cout << "未找到相关信息!" << endl;
	}
	else {
		cout << "查找成功" << endl;
		cout << "学号\t姓名\t专业\t高数成绩\t英语成绩\t大物成绩\t专业成绩\t总分成绩\t\t排名" << endl;
		cout << bt->stu.id << '\t' << bt->stu.name << '\t' << bt->stu.major << '\t' << bt->stu.math_score << "\t        " << bt->stu.english._score << "\t        " << bt->stu.psy_score << "\t        " << bt->stu.major_score << "\t          " << bt->stu.total_score << "\t        " << bt->stu.sortid << endl;
	}
}
/*
* 打印所有学生
*/
void scoreManage::print() {
	if (!first) {
		cout << "没有学生信息" << endl;
		return;
	}
	studentNode* bt;
	bt = first;
	cout << "学号\t姓名\t专业\t高数成绩\t英语成绩\t大物成绩\t专业成绩\t总成绩\t\t排名" << endl;
	while (bt) {
		cout << bt->stu.id << '\t' << bt->stu.name << '\t' << bt->stu.major << '\.t' << bt->stu.math_score << "\t        " << bt->stu.english_score << "\t        " << bt->stu.psy_score << "\t         " << bt->stu.major_score << "\t        " << bt->stu.total_score << "\t        " << bt->stu.sortid << endl;
		bt = bt->next;
	}
}
void scoreManage::sort_print() {
	print();
}
 
/*
*/
student* scoreManage::linktoarray() {
	studentNode* p;
	p = first;
	int n = total();
	student* stu = new student[n];
	if (!first) {
		cout << "没有学生" << endl;
		return NULL;
	}
	for (int i = 0;i < n;i++) {
		stu[i] = p->stu;
		p =. p->next;
	}
	return stu;
}
/*
*/
void scoreManage::arrytolink(student* stu) {
	studentNode* p;
	p = first;
	int n = total();
	for (int j = 0;j < n;j++) {
		while (p) {
			if (stu[j].id == p->stu.id) {//为链表中的sortid赋值 排序序号
				p->stu.sortid = n - j;
			}
			p = p->next;
		}.
		p = first;//p指向头节点
	}
}
/*
* 双向冒泡排序
*/
void scoreManage::bubble_sort() {
	student* arr;//学生数组
	arr = linktoarray();//有学生链表得到学生数组
	int n = total();//链表长度
	int flag = 1;int i = 0;//flag=1有交换,flag=0无交换
	while (flag == 1)
	{
		flag = 0;
		for (int j = n - i - 1;j > i;j--)//从后往前比较
		{
			if (arr[j - 1].total_score > arr[j].total_score)
			{
				flag = 1;
				student tmp = arr[j];
				arr[j] = arr[j - 1];
				arr[j - 1] = tmp;
			}
		}
		for (int j = i + 1;j < n - i - 1;j++)//从前往后比较
		{
			if (arr[j].total_score > arr[j + 1].total_score)
			{
				flag .= 1;
				student tmp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = tmp;
			}
		}
 
		i++;
	}
	arrytolink(arr);
}
void scoreManage::Hill_sort() {
	student* arr;
	arr = linktoarray();//链表数组
	int n = total();//链表长度
	int  j, i;.
	student temp;
	int divide = ceil(n / 2);//取长度一半,取整
	for (divide;divide >= 1; divide = ceil(divide / 2)) {//对每个h分组进行插入排序,直到h==0
		for (i = divide;i < n;i++) {//单次插入排序
			if (arr[i].total_sco.re < arr[i - divide].total_score) {
				temp = arr[i];
				//	将A[i]插入到A[i - h],A[i - 2h]...中
				for (j = i - divide;j >= 0 && arr[j].total_score > temp.total_score;j = j - divide) {
					arr[j + divide] = arr[j];
				}
				arr[j + divide] = temp;
			}
		}
	}
 
	arrytolink(arr);
}
 
void scoreManage::quick_sort(student* a, int low, int high) {
	if (low < high)  //判断是否满足排序条件,递归的终止条件
	{
		int i = low, j = high;   //把待排序数组元素的第一个和最后一个下标分别赋值给i,j,使用i,j进行排序;
		student x = a[low];    //第一个元素作为哨兵,将数组划分为大于哨兵以及小于哨兵的两部分
		while (i < j)
		{
			while (i < j && a[j].total_score >= x.total_score) j--; 
			if (i < j)
			{
				a[i++] = a[j];
			}  
			while (i < j && a[i].total_score <= x.total_score) i++; 
			if (i < j) {
				a[j--] = a[i];
			}//把不满足位次条件的那个元素值赋值给下标为j的元素,并把j的加1
		}
		a[i] = x;   //完成一次排序,把哨兵赋值到下标为i的位置,即前面的都比它小,后面的都比它大
		quick_sort(a, low, i - 1);  //递归进行哨兵前后两部分元素排序 , low,high的值不发生变化,i处于中间
		quick_sort(a, i + 1, high);
	}
}
/*
*构造小根堆
* */
void scoreManage::heapp(student* a, int i, int n) {
	int j = 2 * i + 1;//找到当前结点的左孩子
	student temp = a[i];//为值转化做准备
	while (j < n) {
		if (j + 1 < n && a[j].total_score < a[j + 1].total_score)  ++j;//确保与父节点交换的是最大的孩子
		if (temp.total_score > a[j].total_score) 	break;
		else {
			a[i] = a[j];
			i = j;
			j = 2 * i + 1;
		}
	}
	a[i] = temp;
}
 
/*
* 堆排序
*/
void scoreManage::heap_sort() {
	student* a;
	a = linktoarray();//链表数组
	int n = total();//链表长度
	for (int i = n / 2 - 1; i >= 0; i--)
		heapp(a, i, n);
	for (int i = n - 1; i >= 1; i--) {//逆序
		student t;
		t = a[0];
		a[0] = a[i];
		a[i] = t;
		heapp(a, 0, i);
	}
	arrytolink(a);
}
void menu() {
	printf("   || ☆☆☆☆☆☆☆☆请选择相应功能 
 1 添加学生成绩信息               ||\n");
	          2 查看所有学生成绩信息           
3 按学号查找学生成绩信息        
  4 按姓名查找学生成绩信息        
    5 删除学生成绩信息              
   6 修改学生成绩信息              
     7 选择排序方法              
    8 保存所有学生信息           
      9 查看学生人数              
       10退出系统                       ||\n\n");
void start() {
	int choose;
	menu();
	cout << "请输入选择:" << endl;;/*用户的选择*/
	cin >> choose;
	switch (choose)
	{
	case 1:
	{
		system("cls");//清屏
		studentNode* p = test.tool();
		test.add_student(p);
		cout << "按任意键继续" << endl;
		getch();
		start();
	}
	break;
	case 2:
	{
		system("cls");//清屏
		test.print();
		cout << "按任意键继续" << endl;
		getch();
		start();
	}
	break;
	case 3:
	{
		system("cls");//清屏
		cout << "请输入学号:" << endl;
		int id;
		cin >> id;
		studentNode* p = test.find_student(id);
		test.print_one(p);
		cout << "按任意键继续" << endl;
		getch();
		start();
	}
	break;
	case 4:
	{
		system("cls");//清屏
		cout << "请输入name:" << endl;
		string name;
		cin >> name;
		studentNode* p = test.find_student(name);
		test.print_one(p);
		cout << "按任意键继续" << endl;
		getch();
		start();
	}
	break;
	case 5:
	{
		system("cls");//清屏
		cout << "请输入要删除学生的学号" << endl;
		int id;
		cin >> id;
		test.del_student(id);
		cout << "按任意键继续" << endl;
		getch();
		start();
	}
	break;
	case 6:
	{
		system("cls");//清屏
		cout << "请输入修改的成绩:(先输入成绩,在选择学生)" << endl;
		double score;
		cin >> score;
		test.modify_score(score);
		cout << "按任意键继续" << endl;
		getch();
		start();
	}
	break;
	case 7:
	{
		system("cls");//清屏
		cout << "请选择要采用的排序算法:(1-双向冒泡排序 2-希尔排序 3-快速排序 4-堆排序)" << endl;
		int chioce;
		cin >> chioce;
		switch (chioce)
		{
		case 1:.
			test.bubble_sort();
			cout << "排序完成" << endl;
			//	start();
			break;
		case 2:
			test.Hill_sort();
			cout << "排序完成" << endl;
			//	start();
			break;
		case 3:
		{
			student* arr;
			arr = test.linktoarray();
			int n = test.total();
			test.quick_sort(arr, 0, n - 1);
 
			test.arrytolink(arr);
		}
		cout << "排序完成" << endl;
		//start();
		break;
		case 4:
		{
			test.heap_sort();
 
			cout << "排序完成" << endl;
		}
		break;
		default:
			cout << "无效字符" << endl;
			break;
		}
		cout << "按任意键继续" << endl;
		getch();
		start();
	}
	break;
	case 8:
		system("cls");//清屏
		test.save_file();
		cout << "按任意键继续" << endl;
		getch();
		start();
		break;
	case 9:
		cout << "一共有" << test.total() << "个学生" << endl;;
		cout << "按任意键继续" << endl;
		getch();
		start();
		break;
	case 10:
		cout << "再见" << endl;
		exit(0);
		break;
	default:
		cout << "无效符号" << endl;
		start();
		break;
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值