【数据结构/单链表】C/C++ 学生信息管理系统 (文件导入、查询、添加、修改、删除、保存)

1. 头文件及链表结构
#include<iostream>		  //标准输入输出流
#include<cstdio>		  //文件读取写入
#include<cstdlib>		  //动态分配内存
#include<cstring>	  	  //操作字符数组
using namespace std;

//结点储存的数据
typedef struct  {
	int num;			    //学号
	char  name[10];		    //姓名
	float score;		    //成绩
}Student;

//单链表储存结构
typedef struct LNode {
	Student data;			//数据域
	struct LNode* next;		//指针域
}LNode,* LinkList;			//LinkList L 等效于 LNode* L 

LinkList  L = NULL;			//链表L
FILE* fp;					//文件指针
char filename[10];			//文件名
2. 主函数
int main() {
	int choise = -1; 			//初始选择 
	while (choise != 0){
		menu(); 				//调用主菜单函数 
		cout<<"\t\t\t请选择:";
		cin>>choise; 
		switch(choise){
			case 1:
				OpenFile();		    //1. 导入学生信息 
				break;
			case 2:
				PrintAll();		    //2. 显示学生信息 
				break;
			case 3:
				SearchMenu();		//3. 查询学生信息 
				break;
			case 4:
				AddStuData();		//4. 添加学生信息 
				break;		
			case 5:
				DeleteMenu();		//5. 删除学生信息
				break;
			case 6:
				ModifyData();		//6. 修改学生信息
				break;
			case 7:
				ListSort();			//7. 按学号进行排序
				break;
			case 8:
				SaveData();			//8. 保存到文件
				break;
			default:
				break;	
		}
	}
	return 0;
}

3. 函数声明部分
void menu();			    //      主菜单
void CreateList();			//      创建链表
void OpenFile();			//1.	打开文件并导入学生信息
void PrintAll();			//2.	显示学生信息
void SearchMenu();			//3.	查询学生信息主函数
void SearchName();			//3.1	按姓名查找
void SearchNum();		    //3.2	按学号查找
void SearchCnt();			//3.3	查看总人数
void SearchMaxScore();		//3.4   查看最高分
void AddStuData();			//4.	添加学生信息
void DeleteMenu();			//5.	删除学生信息主函数
void DeleteLocation();		//5.1	按位置删除
void DeleteNum();			//5.2	按学号删除
void DeleteName();			//5.3	按姓名删除
void DeleteScore();	        //5.4	按成绩删除
void ModifyData();			//6.	修改学生信息
void ListSort();			//7.    按学号进行排序
void SaveData();			//8.	保存到文件	
4. 主菜单函数
void menu() {
	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|       5.删除学生信息         |\n";
	cout << "\t\t\t|       6.修改学生信息         |\n";
	cout << "\t\t\t|       7.按学号来排序         |\n";
	cout << "\t\t\t|       8.保存学生信息         |\n";
	cout << "\t\t\t|       0.退出管理系统         |\n";
	cout << "\t\t\t ------------------------------\n";
}
5. 链表初始化
//链表初始化成一个空链表,没有数据
void CreateList() {
	L = (LNode*)malloc(sizeof(LNode));
	L->next = NULL;
}
6. 打开文件
void OpenFile() {
	CreateList();			//先初始化链表
	LNode * 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 = (LNode*)malloc(sizeof(LNode));				//为新创建的结点p分配空间
		if (fscanf(fp, "%d\t%s\t%f\n" , &p->data.num, p->data.name ,&p->data.score) == EOF){	//从文件读入信息
			free(p);									//没有读出来,需要释放掉该结点空间
			cout << "\t\t\t读入成功!";
			system("pause");
			break;
		}
		//尾插法创建链表	①新创建的结点p指针域置为空 ②将头结点指向p ③q向右移一位
		p->next = NULL;
		q->next = p;
		q = q->next;
	}
	fclose(fp);											//关闭文件
}

读取文件格式:学号 姓名 分数

//student.txt
1	张小辉	91.00
2	赵子龙	90.00
3	宇文拓	83.00
4	韩非子	99.00
7. 显示学生信息
void PrintAll() {
	system("cls");
	cout << "\n\n\t\t\t-----已显示学生信息----\n";
	LinkList p;
	p = L->next;								//p指向第一个有数据的结点
	cout << "\t\t\t学号\t姓名\t成绩\n";
	if (p == NULL) {
		cout << "\t\t\t没有数据!";
		system("pause");
		return;
	}
	while (p!=NULL) {
		printf("\t\t\t%d\t%s\t%.2f\n", p->data.num, p->data.name,  p->data.score);
		p = p->next;
	}
	cout << "\t\t\t-----------------------\n";
	cout << "\t\t\t";
	system("pause");
}
8. 查询主函数
void SearchMenu() {
	int choise = -1;
	while (choise != 5) {
		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|       5.返回主菜单      |\n";
		cout << "\t\t\t -------------------------\n";
		cout << "\t\t\t请选择:";
		cin >> choise;
		switch (choise)
		{
			case 1:
				SearchName();			//3.1 按姓名查找
				break;
			case 2:
				SearchNum();			//3.2 按学号查找
				break;
			case 3:
				SearchCnt();			//3.3 查看总人数
				break;
			case 4:
				SearchMaxScore();	    //3.4 查看最高分
				break;
			default:
				break;
		}
	}

}
8.1 按姓名查询
//结果可能不止一个
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成绩" << endl;
			printf("\t\t\t%d\t%s\t%f\n", q->data.num, q->data.name, q->data.score);
			n++;
		}
		q = q->next;
	}
	cout << "\t\t\t----------------------------\n";
	if (n == 0)
		cout << "\t\t\t查无此人,\n";
	cout << "\t\t\t";
	system("pause");
}
8.2 按学号查询
void SearchNum() {
	system("cls");
	cout << endl << endl;
	cout << "\t\t\t-------正在查询学生信息----- \n";
	cout << "\t\t\t请输入学号:";
	int num; cin >> num;
	LinkList q = L->next;
	while (q != NULL) {
		if (q->data.num == num) {
			cout << "\t\t\t学号\t姓名\t成绩" << endl;
			printf("\t\t\t%d\t%s\t%f\n", q->data.num, q->data.name, q->data.score);
			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");
}
8.3 查看总人数
void SearchCnt() {
	system("cls");
	cout << endl << endl;
	cout << "\t\t\t-------正在查询学生信息----- \n";
	cout << "\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");
}
8.4 查看最高分
void SearchMaxScore() {
	system("cls");
	cout << endl << endl;
	cout << "\t\t\t-------正在查询学生信息----- \n";
	LinkList p, q;					//p是指向成绩最高学生结点的指针
	p = NULL;
	q = L->next;
	while (q->next != NULL) {
		if (q->data.score > q->next->data.score) {
			p = q;
		}
		else p = q->next;
		q = q->next;
	}
	if (p != NULL) {
		cout << "\t\t\t学号\t姓名\t成绩" << endl;
		printf("\t\t\t%d\t%s\t%f\n", p->data.num, p->data.name, p->data.score);
	}
	cout << "\t\t\t----------------------------\n";
	cout << "\t\t\t";
	system("pause");
}
9. 删除主函数
void DeleteMenu() {
	int choise = -1;
	while (choise != 5) {
		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|       5.返回主界面      |\n";
		cout << "\t\t\t -------------------------\n";
		cout << "\t\t\t请选择:";
		cin >> choise;
		switch (choise)
		{
			case 1:
				DeleteLocation();			//按位置删除
				break;
			case 2:
				DeleteNum();				//按学号删除
				break;
			case 3:
				DeleteName();				//按姓名删除
				break;
			case 4:
				DeleteScore();				//按成绩删除
				break;
			default:
				break;
		}
	}
}
9.1 按位置删除
void DeleteLocation() {		
	cout << endl << endl;
	cout << "\t\t\t请输入位置:";
	int location ; cin >> location;
	LinkList q = L;
	int j = 0;
	while (q != NULL&&j<location-1) { 				//找p结点前一位置
		q = q->next;
		j++;
	}
	if (!q ||  j >location - 1) {
		cout << "\t\t\t位置输入错误,删除失败\n";
		cout << "\t\t\t----------------------------\n";
		cout << "\t\t\t";
		system("pause");
		return;
	}
	
	//删除结点q下一结点q:①p指向q下一结点 ②将q的next指向p的next ③释放结点p
	LinkList p = q->next;
	q->next = p->next;
	free(p);
	cout << "\t\t\t----------------------------\n";
	cout << "\t\t\t删除成功,";
	system("pause");
}
9.2 按学号删除
//不会重复
void DeleteNum() {
	cout << endl << endl;
	cout << "\t\t\t请输入学号:";
	int num; cin >> num;
	LinkList q = L;							//删除结点的前一结点q
	while (q != NULL) {
		if (q->next->data.num == num) {		//找到要删除的前一结点q
			LinkList p = q->next;
			q->next = p->next;
			free(p);
			cout << "\t\t\t----------------------------\n";
			cout << "\t\t\t删除成功,";
			system("pause");
			return;
		}
		q = q->next;
	}
	cout << "\t\t\t查无此人或输入错误,";
	system("pause");
}
9.3 按姓名删除
void DeleteName() {
	cout << endl << endl;
	cout << "\t\t\t请输入姓名:";
	char name[10]; cin >> name;
	LinkList q = L;
	int n = 0;
	while (q->next != NULL) {
		if (strcmp(q->next->data.name, name) == 0) {
			LinkList p = q->next;
			q->next = p->next;
			free(p);
			n++;
		}
		q = q->next;
	}
	cout << "\t\t\t----------------------------\n";
	if (n == 0) {
		cout << "\t\t\t删除失败";
		system("pause");
	}
	else {
		cout << "\t\t\t删除成功,";
		system("pause");
	}
}
9.4 按成绩删除
void DeleteScore() {
	cout << endl << endl;
	cout << "\t\t\t请输入成绩:";
	float score; cin >> score;
	LinkList q = L;
	int n=0;
	while (q->next != NULL) {
		if (q->next->data.score == score) {
			LinkList p = q->next;
			q->next = p->next;
			free(p);
			n++;
		}
		q = q->next;
	}
	cout << "\t\t\t----------------------------\n";
	if (n == 0) {
		cout << "\t\t\t删除失败";
		system("pause");
	}
	else {
		cout << "\t\t\t删除成功,";
		system("pause");
	}
}
10. 添加学生信息
//添加学生信息到合适的位置
void AddStuData() {
	system("cls");
	cout << endl << endl;
	cout << "\t\t\t-------正在添加学生信息----- \n";
	cout << "\t\t\t请输入添加学员人数:";
	int n; cin >> n;
	LinkList p, q;								//p是新添加的结点,q是指向L的指针
	for (int i = 0; i < n; i++) {
		p = (LNode*)malloc(sizeof(LNode));		//为p分配空间,写入数据
		printf("\t\t\t正在添加第%d个学生的信息:\n", i + 1);
		cout << "\t\t\t请输入学号:";
		cin >> p->data.num;
		q = L->next;
		while (q != NULL) {						//判断学号是否重复
			if (q->data.num == p->data.num) {
				cout << "\t\t\t学号重复,请重新输入:";
				cin >> p->data.num;
				q = L->next;
				continue;
			}
			else q=q->next;
		}

		cout << "\t\t\t请输入姓名:";       		//输入姓名,成绩
		cin >> p->data.name;
		cout << "\t\t\t请输入成绩:";
		cin >> p->data.score;
												//开始将p结点插入到链表中
		if (L->next == NULL) {					//如果是空链表,没有数据,直接插入
			p->next = NULL;
			L->next = p;
		}
		else {									//有数据,插入合适位置
			q = L->next;						//q指向L第一个有数据的位置
			while (q != NULL) {
				if (q->next != NULL) {
					if (p->data.num > q->data.num && p->data.num < q->next->data.num) {	//找到插入点q结点的后方
						p->next = q->next;    	//将p插入到q后面的结点 :①p的next 指向q后面的结点
						q->next = p;			// ②q的next指向p
						break;
					}
				}
				else {							//q 在尾部 没有后一个,将p插入到q的后面
					p->next = NULL;
					q->next = p;
					break;
				}
				q = q->next;					//q指向下一个结点
			}
		}
	}
	cout << "\t\t\t----------------------------\n";
	cout << "\t\t\t";
	system("pause");
}
11. 修改学生信息
void ModifyData() {
	system("cls");
	cout << endl << endl;
	cout << "\t\t\t-------正在修改学生信息----- \n";
	cout << "\t\t\t请输入需要修改学生的学号:";
	int num,n=0 ; cin >> num;
	LinkList q = L ;

	while (q != NULL) {							//判断学号是否存在
		q = q->next;
		if (q->data.num == num) {
			break;
		}	
		if (q->next == NULL) {
			cout << "\t\t\t学号不存在,请重新输入:";
			cin >> num;
			q = L->next;
			continue;
		}
	}
	LinkList pnew = (LNode*)malloc(sizeof(LNode));
	pnew->next = NULL;
	cout << "\t\t\t请输入修改后的学号:";	
	cin >> pnew->data.num;

	LinkList p = L->next;
	while (p != NULL) {							//判断学号是否重复
		if (pnew->data.num == p->data.num) {
			cout << "\t\t\t学号重复,请重新输入:";
			cin >> pnew->data.num;
			p = L->next;
			continue;
		}
		else p = p->next;
	}

	cout << "\t\t\t请输入修改后的姓名:";
	cin >> pnew->data.name;
	cout << "\t\t\t请输入修改后的成绩:";
	cin >> pnew->data.score;

	q->data.num=pnew->data.num;
	strcpy(q->data.name,pnew->data.name);
	q->data.score = pnew->data.score;
	free(pnew);
	cout << "\t\t\t----------------------------\n";
	cout << "\t\t\t修改成功,";

	system("pause");
}
12.按学号进行排序
//用冒泡或者选择排序,只交换数据域,而不交换结点
void ListSort() {
	system("cls");
	cout << endl << endl;
	cout << "\t\t\t-------正在按学号进行排序----- \n";
	LinkList q = L->next;
	int len = 0;
	while (q != NULL) {						//获取链表长度
		len++;
		q = q->next;
	}

	LNode* 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.num > p2->data.num) {
				Student temp = p1->data;
				p1->data = p2->data;
				p2->data = temp;
			}
			q = q->next;
		}
	}
	cout << "\t\t\t排序完成 " ;
	system("pause");
}
13. 保存到文件
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\n", q->data.num, q->data.name, q->data.score);
			q = q->next;
		}
	}
	fclose(fp);
	cout << "\t\t\t保存成功,";
	system("pause");
}
14. 运行效果

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值