文章目录
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. 运行效果