数据结构课程设计:学生成绩管理系统

9 篇文章 2 订阅
这是一个使用C++编写的学生成绩管理系统,具备文件读写、登录、增删改查、排序等功能。系统分为学生和管理员两种登录模式,支持按照学号或姓名查询、删除和修改学生信息,并提供了冒泡排序对学生信息进行排序。代码中包含了链表数据结构和文件操作的实现。
摘要由CSDN通过智能技术生成

学生成绩管理系统

需求
学生成绩管理系统应能实现对学生信息实现基本的增删改查,以及根据学生相关信息进行排序,并且对学生信息实现文件的读出和写入。
设计思想
程序结构
主题架构:主函数当中先从文件当中读取学生信息,接着进入登录界面,,用户可以选择已学生身份登录或者管理员身份登录,在两种不同的角色登录成功后,都可以实现在菜单页面选择对于学生成绩信息进行不同的操作(学生身份对于成绩的操作是受限制的)。
数据的持久性:在处理数据之前,要先从文件当中导入学生成绩,再进行修改,在修改完成过后,会保存信息至文件。
算法的实现思路:
创建链表:初始化一个空链表
登录:显示登录界面,提示用户选择
学生登录,学生菜单:显示学生登录界面,显示学生菜单
管理员登录,管理员菜单:显示管理员登录界面,显示管理员菜单
导入学生信息:接收用户输入的文件名,利用fopen打开文件,并创建一个与之相连流。若文件不存在,则以追加的方法创建一个文件。 若文件存在,则将文件内容读入并存放于链表中(后插法)。
显示学生信息:遍历链表,依次输出学生节点的各个信息
删除学生信息:可根据学生的姓名/学号进行删除,遍历链表找到需要删除的节点,然后用一个临时节点存放需要删除的节点,然后更改被删除的节点的前面一个指针的指向。
添加学生信息:前插法插入节点,可批量添加。
查询学生信息:遍历链表,根据对比学生姓名/学号来查询对应的节点,并输出该学生节点的信息,若未查到会提示用户。
查看学生总人数:输出总人数。
修改学生信息:遍历链表,根据ID来找到需要修改信息的学生(会对学号的存在性进行检测,也会对修改过后学号是否重复进行检查)再对节点的信息进行修改。
排序:用户可以选择按照学号排序/单科成绩排序。均为冒泡排序。
保存文件:将链表中的数据写入到文件中。
具体代码如下:
头文件部分

/************************链表实现学生成绩管理系统 (以文件读入形式)************************/ 
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<windows.h>
using namespace std; 

初始化定义数据

/***********************初始化定义数据******************************/ 
typedef struct{
	int id;			//学生学号 
	char name[10];	//学生姓名
	float g[3];		//用数组存储三科成绩(分别是数据结构、java、linux)
}Student;
//链表	
typedef struct Node
{
	Student data;
	struct Node *next;
}Node,*LinkList;
//链表初始化为空
LinkList L=NULL;
//创建文件指针 
FILE* fp;			//文件指针
char filename[10];	//文件名

函数声明

//函数声明
void CreateList();	//创建链表 
void Deng();		//登录 
void GDeng();		//管理员登陆 
void XDeng(); 		//学生登陆 
void Gmenu();		//管理员菜单 
void Xmenu();		//学生菜单 
void OpenFile();	//1.导入学生信息 
void PrintAll();	//2.显示学生信息 
void Delete();		//3.删除学生信息 
void Insert();		//4.添加学生信息 
void SearchMenu();	//5.查询学生信息 
void SearchName();	//5.1按名字查询 
void SearchID(); 	//5.2按学号查询 
void SearchCnt();	//5.3查看总人数 
void ModifyData() ;	//6.修改学生信息 
void Sort();		//7.排序 
void XHSort();		//7.1学号排序 
void CJSort(); 		//7.2单科成绩排序 
void sSort();		//7.2.1按数据结构成绩排序 
void jSort();		//7.2.2按java成绩排序 
void lSort(); 		//7.2.3按Linux成绩排序 
void SaveData();	//8.保存到文件中 

创建空链表

void CreateList() {
	L = new Node;
	L->next = NULL;
}

主菜单函数以及登录要求

void Deng(){
	cout << endl << endl;
	cout << "\t\t\t ------------------------------\n";
	cout << "\t\t\t|           登录界面           |\n";
	cout << "\t\t\t|------------------------------|\n";
	cout << "\t\t\t|      请选择登陆方式!        |\n";
	cout << "\t\t\t|                              |\n";
	cout << "\t\t\t|       1.学生登陆             |\n";
	cout << "\t\t\t|                			  |\n";
	cout << "\t\t\t|       2.管理员登陆           |\n";
	cout << "\t\t\t|                  			  |\n";
	cout << "\t\t\t|       0.退出管理系统         |\n";
	cout << "\t\t\t ------------------------------\n";	
	int n;
	cout<<"\t\t\t";
	cin>>n;
	switch(n){
		case 1:
			XDeng();
			while(1){
			Xmenu();
			}
			break;
		case 2:
			GDeng();
			while(1){
			Gmenu();
			}
			break;
		case 0:
			exit(0);
			break;
	}
}
void XDeng(){
	char name[10];
	int id;
	int n=0;
	LinkList q = L->next;
	cout<<"\t\t\t请输入姓名和学号:"<<endl; 
	cout<<"\t\t\t姓名:";
	cin>>name;
	cout<<"\t\t\t学号:"; 
	cin>>id;
	while (q != NULL) {
		if (strcmp(name, q->data.name) == 0) {	    //名字相同
			if(n==0)
				cout << "\t\t\t登陆成功!" << endl;
			n++;
		}
		q = q->next;
	}
	if (n == 0){
		cout << "\t\t\t姓名或学号错误\n";
		XDeng();
}
	system("cls"); 
}
void GDeng(){
	string x;
	int y; 
	cout<<"\t\t\t请输入用户名和密码:"<<endl; 
	cout<<"\t\t\t用户名:";
	cin>>x;
	cout<<"\t\t\t密码:"; 
	cin>>y;
	if(x=="author"&&y==12345){
		cout<<"\t\t\t登陆成功!";
	}
	else{
		cout<<"\t\t\t用户名或密码有错"<<endl;
		GDeng();
	}
	system("cls");
}

管理员菜单

void Gmenu() {
	cout << endl << endl;
	cout << "\t\t\t ------------------------------\n";
	cout << "\t\t\t|       学生成绩管理(G)        |\n";
	cout << "\t\t\t|------------------------------|\n";
	cout << "\t\t\t|       1.显示学生信息         |\n";
	cout << "\t\t\t|       2.删除学生信息         |\n";
	cout << "\t\t\t|       3.增加学生信息         |\n";
	cout << "\t\t\t|       4.查询学生信息         |\n";
	cout << "\t\t\t|       5.修改学生信息         |\n";
	cout << "\t\t\t|       6.排序学生信息         |\n";
	cout << "\t\t\t|       7.保存学生信息         |\n";
	cout << "\t\t\t|       0.退出登录             |\n";
	cout << "\t\t\t ------------------------------\n";
	cout<<"\t\t\t请输入你的选择:";
	int choise;
	cin>>choise; 
	system("cls");
	switch(choise)
	{
		case 1:
			PrintAll();
			break;
		case 2:
			Delete();
			break;
		case 3:
			Insert();
			break;
		case 4:
			SearchMenu();
			break;
		case 5:
			ModifyData();
			break;
		case 6:
			Sort();
			break;
		case 7:
			SaveData();
			break;
		case 0:
			Deng();
			break;	
	}
}

学生菜单

void Xmenu() {
	cout << endl << endl;
	cout << "\t\t\t ------------------------------\n";
	cout << "\t\t\t|       学生成绩管理(X)        |\n";
	cout << "\t\t\t|------------------------------|\n";
	cout << "\t\t\t|       1.显示学生信息         |\n";
	cout << "\t\t\t|       2.查询学生信息         |\n";
	cout << "\t\t\t|       0.退出登录             |\n";
	cout << "\t\t\t ------------------------------\n";
	int a;
	cout<<"\t\t\t请输入你的选择:";
	cin>>a; 
	system("cls");
	switch(a)
	{
		case 1:
			PrintAll();
			break;
		case 2:
			SearchMenu();
			break;
		case 0:
			Deng();
			break;	
	}
}

文件导入学生信息

void OpenFile() {
	CreateList();			//先初始化链表
	Node * p, *q;			//p是创建的新的结点
	q = L;					//q是指向头结点的指针,用于创建链表
	while (true) {
		cout << "\n\n\t\t\t请输入文件名:";
		cin >> filename;
		if ((fp = fopen(filename, "r")) == NULL) {				//没有该文件
			cout << "\t\t\t没有该文件信息,是否创建(y/n):";
			char ch; cin >> ch;
			if (ch == 'Y' || ch == 'y') {											
				if ((fp = fopen(filename, "a+")) == NULL) {		//创建文件失败
					cout << "\t\t\t创建失败!" << endl;
				}
				else break;
			}
			else continue;
		}
		else break;
	}
	while (true) {
		p = new Node;				//为新创建的结点p分配空间
		if (fscanf(fp, "%d\t%s\t%f\t%f\t%f\n" , &p->data.id, p->data.name ,&(p->data.g[0]),&(p->data.g[1]),&(p->data.g[2])) == EOF){	//从文件读入信息
			free(p);									//没有读出来,需要释放掉该结点空间
			cout << "\t\t\t读入成功!";
			system("pause");
			break;
		}
		//尾插法创建链表:新创建的结点p指针域置为空,将头结点指向p ,q向右移一位
		p->next = NULL;
		q->next = p;
		q = q->next;
	}
	fclose(fp);											//关闭文件
	system("cls");
}

显示学生信息

void PrintAll() {
	system("cls");
	cout << "\n\n\t\t\t-----已显示学生信息----\n";
	LinkList p;
	p = L->next;								//p指向第一个有数据的结点
	cout << "\t\t\t学号\t姓名\t数构\tjava\tlinux\n";
	if (p == NULL) {
		cout << "\t\t\t没有数据!";
		return;
	}
	while (p!=NULL) {
		printf("\t\t\t%d\t%s\t%.2f\t%.2f\t%.2f\n", p->data.id, p->data.name,p->data.g[0], p->data.g[1], p->data.g[2]);
		p = p->next;
	}
	cout << "\t\t\t-----------------------\n";
	cout << "\t\t\t";
	system("pause");
	system("cls"); 
}

删除学生信息

void Delete() {
	cout << "\n\n\t\t\t删除学生信息"; 
	cout << "\n\n\t\t\t1.按照姓名删除" << endl;
	string Name;
	cout << "\n\n\t\t\t2.按照学号删除" << endl;
	double ID;
	int flag;
	cout<<"\n\n\t\t\t请输入你的选择:"; 
	cin >> flag;
	if (flag == 1) {
		cout << "\n\t\t\t请输入你需要删除的学生的姓名:" ;
		cin >> Name;
		LinkList p = L;
		while(p->next->data.name != Name) {
			p = p->next;
		} 
		LinkList q = p->next;
		p->next = q->next;
		delete q;
		cout<<"\n\t\t\t删除成功!";
	}
		
	else if (flag == 2) {
		cout << "\n\t\t\t请输入你需要删除的学生的学号:" ;
		cin >> ID;
		LinkList p = L;
		while (p->next->data.id != ID) {
			p = p->next;
		}
		LinkList q = p->next;
		p->next = q->next;
		delete q;
		cout<<"\n\t\t\t删除成功!";
	}
	else {
		cout << "\n\t\t\terror!" << endl;
	}
	system("pause");
	system("cls");
}

添加学生信息

void Insert() {
	cout << "\n\n\t\t\t请输入你需要添加的学生个数:";
	int n;
	cin >> n;
	if(n>0){
	for (int i = 0; i < n; i++) {
		LinkList p = new Node;
		cout << "\n\t\t\t请输入第" << i + 1 << "个学生的姓名;学号;数据结构成绩;java成绩;linux成绩:" << endl;
		cout << "\t\t\t";
		cin >> p->data.name >> p->data.id >> p->data.g[0] >> p->data.g[1] >> p->data.g[2];
		p->next = L->next; L->next = p;
		cout<<"\n\t\t\t添加成功!"; 
	}
}else {
		cout << "error" << endl;
	}
	system("pause");
	system("cls");
}

查询学生信息

void SearchMenu() {
	int choise=-1;
	while (choise!=4) {
		system("cls");
		cout << endl << endl;
		cout << "\t\t\t ------------------------- \n";
		cout << "\t\t\t|       查询学生信息      |\n";
		cout << "\t\t\t|-------------------------|\n";
		cout << "\t\t\t|       1.按姓名查找      |\n";
		cout << "\t\t\t|       2.按学号查找      |\n";
		cout << "\t\t\t|       3.查看总人数      |\n";
		cout << "\t\t\t|       4.返回主菜单      |\n";
		cout << "\t\t\t -------------------------\n";
		cout << "\t\t\t请选择:";
		cin >> choise;
		switch (choise)
		{
			case 1:
				SearchName();			
				break;
			case 2:
				SearchID();
				break;
			case 3:
				SearchCnt();
			default:
				break;
		}
	}
	
}
void SearchName() {
	system("cls");
	cout << endl << endl;
	cout << "\t\t\t-------正在查询学生信息----- \n";
	cout << "\t\t\t请输入要查找的姓名:";
	char name[10]; cin >> name;
	LinkList q = L->next;				            // q是指向第一个元素的指针
	int n = 0;
	while (q != NULL) {
		if (strcmp(name, q->data.name) == 0) {	    //名字相同
			if(n==0)
				cout << "\t\t\t学号\t姓名\t数构\tjava\tlinux" << endl;
			printf("\t\t\t%d\t%s\t%.2f\t%.2f\t%.2f\n", q->data.id, q->data.name, q->data.g[0],q->data.g[1],q->data.g[2]);
			n++;
		}
		q = q->next;
	}
	cout << "\t\t\t----------------------------\n";
	if (n == 0)
		cout << "\t\t\t查无此人,\n";
	cout << "\t\t\t";
	system("pause");
}
void SearchID() {
	system("cls");
	cout << endl << endl;
	cout << "\t\t\t-------正在查询学生信息----- \n";
	cout << "\t\t\t请输入学号:";
	int id; cin >> id;
	LinkList q = L->next;
	while (q != NULL) {
		if (q->data.id == id) {
			cout << "\t\t\t学号\t姓名\t数构\tjava\tlinux" << endl;
			printf("\t\t\t%d\t%s\t%.2f\t%.2f\t%.2f\n", q->data.id, q->data.name,  q->data.g[0],q->data.g[1],q->data.g[2]);
			cout << "\t\t\t----------------------------\n";
			cout << "\t\t\t";
			system("pause");
			return;
		}
		q = q->next;
	}
	cout << "\t\t\t----------------------------\n";
	cout << "\t\t\t查无此人,";
	system("pause");
}
void SearchCnt() {
	system("cls");
	cout << endl << endl;
	cout << "\t\t\t-------正在查询学生信息----- \n";
	cout << "\n\t\t\t总人数为:";
	int cnt = 0;
	LinkList q = L->next;
	while (q != NULL) {
		if(q!=NULL) cnt++;
		q = q->next;
	}
	cout << cnt << endl;
	cout << "\t\t\t----------------------------\n";
	cout << "\t\t\t";
	system("pause");
	system("cls");
}

修改学生信息

void ModifyData() {
	system("cls");
	cout << endl << endl;
	cout << "\t\t\t-------正在修改学生信息----- \n";
	cout << "\t\t\t请输入需要修改学生的学号:";
	int id,n=0 ; cin >> id;
	LinkList q = L ;
	while (q != NULL) {							//判断学号是否存在
		q = q->next;
		if (q->data.id == id) {
			break;
		}	
		if (q->next == NULL) {
			cout << "\t\t\t学号不存在,请重新输入:";
			cin >> id;
			q = L->next;
			continue;
		}
	}
	LinkList pnew = new Node;
	pnew->next = NULL;
	cout << "\t\t\t请输入修改后的学号:";	
	cin >> pnew->data.id;
	LinkList p = L->next;
	while (p != NULL) {							//判断学号是否重复
		if (pnew->data.id == p->data.id) {
			cout << "\t\t\t学号重复,请重新输入:";
			cin >> pnew->data.id;
			p = L->next;
			continue;
		}
		else p = p->next;
	}

	cout << "\t\t\t请输入修改后的姓名:";
	cin >> pnew->data.name;
	cout << "\t\t\t请输入修改后的三科成绩:";
	cin >> pnew->data.g[0];
	cin >> pnew->data.g[1];
	cin >> pnew->data.g[2]; 
	q->data.id=pnew->data.id;
	strcpy(q->data.name,pnew->data.name);
	q->data.g[0] = pnew->data.g[0];
	q->data.g[1] = pnew->data.g[1];
	q->data.g[2] = pnew->data.g[2];
	free(pnew);
	cout << "\t\t\t----------------------------\n";
	cout << "\t\t\t修改成功,";
	system("pause");
	system("cls");
}

排序

/**********************7.排序**********************/ 
void Sort() {
	int n; 
	system("cls");
	cout<<"\n\t\t\t请选择排序方式"<<endl;
	cout<<"\t\t\t1.按学号排序\n"<<endl;
	cout<<"\t\t\t2.按成绩排序\n"<<endl;
	cout<<"\t\t\t";
	cin>>n;
	switch(n){
		case 1:
			XHSort();
			break;
		case 2:
			CJSort();
			break;
	}
}
/**********************7.1学号排序**********************/ 
void XHSort(){
	system("cls");
	cout << endl << endl;
	cout << "\t\t\t-------正在按学号进行排序----- \n";
	LinkList q = L->next;
	int len = 0;
	while (q != NULL) {						//获取链表长度
		len++;
		q = q->next;
	}

	Node* p1, *p2;
	for (int i = 0; i < len; i++) {			//冒泡排序
		q = L->next;
		for (int j = 0; j < len - i - 1; j++) {
			p1 = q;
			p2 = q->next;
			if (p1->data.id> p2->data.id) {
				Student temp = p1->data;
				p1->data = p2->data;
				p2->data = temp;
			}
			q = q->next;
		}
	}
	cout << "\t\t\t排序完成 " ;
	system("pause");
	system("cls"); 
}
/**********************7.2单科成绩排序**********************/ 
void CJSort(){
	int n;
	system("cls");
	cout<<"\n\t\t\t请选择成绩排序方式"<<endl;
	cout<<"\t\t\t1.按数据结构成绩排序\n"<<endl;
	cout<<"\t\t\t2.按Java成绩排序\n"<<endl;
	cout<<"\t\t\t3.按Linux成绩排序\n"<<endl;
	cout<<"\t\t\t输入你的选择:";
	cin>>n;
	switch(n){
		case 1:
			sSort();
			break;
		case 2:
			jSort();
			break;
		case 3:
			lSort();
			break;
		default:
			break;
			}
}
void sSort(){
	cout << endl << endl;
			cout << "\t\t\t-------正在按数据结构成绩进行排序----- \n";
			LinkList q = L->next;
			int len = 0;
			while (q != NULL) {						//获取链表长度
				len++;
				q = q->next;
			}
			Node* p1, *p2;
			for (int i = 0; i < len; i++) {	
				q = L->next;
				for (int j = 0; j < len - i - 1 ; j++) {
					p1 = q;
					p2 = q->next;
					if (p1->data.g[0] < p2->data.g[0]) {
						Student temp = p1->data;
						p1->data = p2->data;
						p2->data = temp;
					}
					q = q->next;
				}
			}
			cout << "\n\t\t\t排序完成 " ;
			system("pause");
			system("cls");
}
void jSort(){
	cout << endl << endl;
			cout << "\t\t\t-------正在按Java成绩进行排序----- \n";
			LinkList q = L->next;
			int len = 0;
			while (q != NULL) {						//获取链表长度
				len++;
				q = q->next;
			}
			Node* p1, *p2;
			for (int i = 0; i < len; i++) {	
				q = L->next;
				for (int j = 0; j < len - i - 1 ; j++) {
					p1 = q;
					p2 = q->next;
					if (p1->data.g[1] < p2->data.g[1]) {
						Student temp = p1->data;
						p1->data = p2->data;
						p2->data = temp;
					}
					q = q->next;
				}
			}
			cout << "\n\t\t\t排序完成 " ;
			system("pause");
			system("cls");
}
void lSort(){
	cout << endl << endl;
			cout << "\t\t\t-------正在按Linux成绩进行排序----- \n";
			LinkList q = L->next;
			int len = 0;
			while (q != NULL) {						//获取链表长度
				len++;
				q = q->next;
			}
			Node* p1, *p2;
			for (int i = 0; i < len; i++) {	
				q = L->next;
				for (int j = 0; j < len - i - 1 ; j++) {
					p1 = q;
					p2 = q->next;
					if (p1->data.g[2] < p2->data.g[2]) {
						Student temp = p1->data;
						p1->data = p2->data;
						p2->data = temp;
					}
					q = q->next;
				}
			}
			cout << "\n\t\t\t排序完成 " ;
			system("pause");
			system("cls");
}

保存到文件中

void SaveData() {
	LinkList q = L->next;
	if ( (fp = fopen(filename, "w")) == NULL) {
		cout << "\t\t\t打开文件失败,";
		system("pause");
		return;
	}
	else {
		while (q != NULL) {
			fprintf(fp, "%d\t%s\t%.2f\t%.2f\t%.2f\n", q->data.id, q->data.name, q->data.g[0], q->data.g[1], q->data.g[2]);
			q = q->next;
		}
	}
	fclose(fp);
	cout << "\n\n\t\t\t保存成功!";
	system("pause");
	system("cls");
}

主函数

int main() {
	system("color 7D");
	OpenFile();
	Deng();
	return 0; 
}

2023/6/14更新
我看很多人在评论区和私聊问一些问题,在这里写个总结

第一:导入文件名:XX.txt,只要是txt就能导入成功
文件里面形式是学号 姓名 成绩1 成绩2 成绩3,中间空格相隔开就行
第二:运行工具是dev c++ ,这是c++代码,其他c++工具需要修改bug
第三:代码写于2022/1/4,应该不存在过时之类的代码报错问题
第四:很多人出现了bug,澄清一下,今天抽空将上面代码进行了运行操作,管理员管理和学生管理都进行了测试,没有任何问题
第五:提醒:文件编码形式需要改动,不然就是繁体字
第六,目前本人就读于Java方向,所以本次更新并没有更新代码,代码在刚刚接触c++时所写的课程设计,很多地方不足,望谅解
第六:关注我,不迷路,最近一年挺忙的,空下来后每日分享基本知识,带你过Java

数据结构学生成绩管理可以通过堆排序和冒泡排序两种算法来实现。堆排序是一种树形选择排序,它利用完全二叉树的结构和比较关系来选择最小或最大的元素,从而实现排序。在堆排序中,首先构造一个小根堆,然后循环将堆顶元素与堆的最后一个元素交换,并继续调整堆,直到所有元素都被排序完成。 另一种算法是冒泡排序,它通过相邻元素的比较和交换来实现排序。冒泡排序从数组的第一个元素开始,依次比较相邻的两个元素,如果顺序不对就交换它们的位置,直到所有元素都被比较一遍,然后再重复这个过程,直到整个数组排序完成。 以上提到的堆排序和冒泡排序都是常见的排序算法,它们可以用来对数据结构学生成绩进行排序和管理。堆排序的时间复杂度为O(nlogn),而冒泡排序的时间复杂度为O(n^2)。因此,在实际应用中,如果数据量比较大,可以选择使用堆排序来提高排序效率。 总结起来,数据结构学生成绩可以通过堆排序和冒泡排序来进行管理和排序。堆排序利用完全二叉树的结构来选择最小或最大的元素,冒泡排序通过相邻元素的比较和交换来实现排序。堆排序的时间复杂度为O(nlogn),冒泡排序的时间复杂度为O(n^2)。在实际应用中,根据数据量的大小选择适合的排序算法来提高排序效率。<span class="em">1</span><span class="em">2</span><span class="em">3</span><span class="em">4</span>
评论 47
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值