单链表实现学生成绩管理系统的增删改查
程序员文章站
2022-05-06 18:05:14
...
写在前面:这个代码除了实现基本的数据增删改查外,还对数据进行了按学号排序输入,输出到文档中!同时对界面实现了优化!对数据插入方法使用插入排序!以及人数的统计,多种查询方式等!代码是很久之前写的,当时刚好学了单链表这一块,最近碰巧在磁盘里看到了就把它发了出来,顺便把文件操作内容补充了!
//全局定义两个指针变量(头指针和尾指针);头指针用来遍历,尾指针用来添加Student成员;实现结果就不附图了,谢谢阅览!!!
//腾出一点时间顺便把文件处理内容也补充了,读者自行测试!!!!
#pragma warning(disable:4996) //屏蔽某些非标准C库的警告!
//#define _CRT_SECURE_NO_WARNINGS //防止scanf警告,也可直接用scanf_s;
#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
//成绩表结构体
typedef struct stu
{
long num;
char name[10];
char sex[4];
float Math;
float Chinese;
float English;
struct stu* next;
}STU;
FILE *fp;
char filename[20];
STU* Head = NULL; //定义一个指针
STU* End = NULL; //尾结点
//创建头结点和尾结点
void CreatList()
{
Head = (struct stu*)malloc(sizeof(struct stu));
Head->next = NULL;
STU* End = Head;
}
//文件加载
void LoadData()
{
CreatList();
STU* ptr;
printf("\n\n\n\n 请输入文件名:");
scanf("%s", filename);
if ((fp = fopen(filename, "a+")) == NULL)
{
printf("\n Error!!!");
printf("\n Error!!!");
printf("\n Error!!!");
printf("\n 文件打开失败!!!");
exit(0);
}
ptr = (struct stu*)malloc(sizeof(struct stu));
ptr->next = NULL;
while (fscanf(fp, "%ld %s %s %f %f %f\n", &ptr->num, ptr->name, ptr->sex, &ptr->Math, &ptr->Chinese, &ptr->English) != EOF)
{
if (Head->next == NULL)
{
Head->next = ptr;
End = ptr;
}
else
{
End->next = ptr;
End = End->next;
}
ptr = (struct stu*)malloc(sizeof(struct stu));
ptr->next = NULL;
}
free(ptr);
fclose(fp);
}
//写入数据到文件中,并保存文件
void SaveData()
{
STU* ptr = Head->next;
if ((fp = fopen(filename, "w")) == NULL)
{
printf("\n Error!!!");
printf("\n Error!!!");
printf("\n Error!!!");
printf("\n 文件打开失败!!!");
exit(0);
}
while (ptr != NULL)
{
fprintf(fp, "%ld %s %s %6.2f %6.2f %6.2f\n", ptr->num, ptr->name, ptr->sex, ptr->Math, ptr->Chinese, ptr->English);
ptr = ptr->next;
}
fclose(fp);
}
//添加学生成绩信息
void AddStudent()
{
int n, i;
printf("\n请输入您要添加的学生人数:");
scanf("%d", &n);
for (i = 0; i<n; i++)
{
struct stu* pNew = (struct stu*)malloc(sizeof(struct stu));
if (pNew == NULL)
{
printf("\n 空间分配失败,程序异常终止!!!\n\n");
exit(-1);
}
pNew->next = NULL;
printf("\n 要添加的第%d个学生的信息如下:\n", i + 1);
printf("\n请输入第%d个学生学号: ", i + 1);
scanf("%ld", &pNew->num);
//检查学号是否重复
STU* temp = Head->next;
while (temp != NULL)
{
if (temp->num == pNew->num)
{
printf("\n 学号重复,请重新输入!!!\n");
printf("\n请重新输入第%d个学生学号: ", i + 1);
scanf("%ld", &pNew->num);
temp = Head->next; //重新遍历比较
continue;
}
else
temp = temp->next;
}
printf("请输入第%d个学生姓名: ", i + 1);
scanf("%s", pNew->name);
printf("请输入第%d个学生性别: ", i + 1);
scanf("%s", pNew->sex);
printf("请输入第%d个学生数学成绩: ", i + 1);
scanf("%f", &pNew->Math);
while (1)
{
if ((pNew->Math)< 0 || (pNew->Math > 100))
{
printf("\n 输入成绩有误,请检查!!!\n");
printf("\n请重新输入第%d个学生数学成绩: ", i + 1);
scanf("%f", &pNew->Math);
}
else break;
}
printf("请输入第%d个学生语文成绩: ", i + 1);
scanf("%f", &pNew->Chinese);
while (1)
{
if ((pNew->Chinese)< 0 || (pNew->Chinese > 100))
{
printf("\n 输入成绩有误,请检查!!!\n");
printf("\n请重新输入第%d个学生语文成绩: ", i + 1);
scanf("%f", &pNew->Chinese);
}
else break;
}
printf("请输入第%d个学生英语成绩: ", i + 1);
scanf("%f", &pNew->English);
while (1)
{
if ((pNew->English)< 0 || (pNew->English) > 100)
{
printf("\n 输入成绩有误,请检查!!!\n");
printf("\n请重新输入第%d个学生英语成绩: ", i + 1);
scanf("%f", &pNew->English);
}
else break;
}
//按学号排序,边添加边排序;
if (Head->next == NULL)
{
Head->next = pNew; //作为首元素
End = Head->next;
//End->next = NULL;
}
else
{
if (pNew->num > End->num)
{
End->next = pNew;
End = End->next;
//End->next = NULL;
}
else
{
STU* p1 = Head->next;
if (pNew->num > p1->num) //表明链表中已经至少存在2个成员(至少存在首和尾);
{
STU* p2 = p1->next;
while (1)
{
if ((pNew->num > p1->num) && (pNew->num < p2->num))
{
pNew->next = p2;
p1->next = pNew;
break;
}
else
{
p1 = p1->next;
p2 = p2->next;
}
}
}
else
{
pNew->next = p1;
Head->next = pNew;
}
}
}
}
printf("\n\n 学生信息全部添加完成!!!\n");
}
//通过前驱结点删除学生成绩信息
void DeleteStudent()
{
int num;
printf("\n请输入您要删除的学生的学号:");
scanf("%ld", &num);
STU* pre = Head; //表中没有数据时,pre为空;
while (1)
{
if (pre->next && (pre->next->num == num))
{
STU* q = pre->next;
pre->next = pre->next->next;
//pre->next = NULL;
printf("\n\n 删除操作成功!!!\n");
printf("\n 已删除的学生成绩信息如下!!!\n\n");
printf("学号\t\t姓名\t性别\t数学\t语文\t英语\t\n\n");
printf("%ld\t%s\t%s\t%.2f\t%.2f\t%.2f\n", q->num, q->name, q->sex, q->Math, q->Chinese, q->English);
free(q);
return;
}
else
{
if (pre->next != NULL)
pre = pre->next;
else
{
printf("\n\n 信息删除失败!!!\n");
return;
}
}
}
//寻找前驱结点的第二种方法
/*
while (pre->next && (pre->next->num != num))
pre = pre->next;
if (pre->next) //pre为前驱
{
STU* q = pre->next;
pre->next = pre->next->next;
//pre->next = NULL;
printf("\n\n 删除操作成功!!!\n");
printf("\n 已删除的学生成绩信息如下!!!\n\n");
printf("学号\t\t姓名\t性别\t数学\t语文\t英语\t\n\n");
printf("%ld\t%s\t%s\t%.2f\t%.2f\t%.2f\n", q->num, q->name, q->sex, q->Math, q->Chinese, q->English);
free(q);
}
else
printf("\n\n 信息删除失败!!!\n");
*/
}
//更改学生成绩信息
void AlterStudent()
{
int num;
printf("\n请输入您要更改学生的学号:");
scanf("%ld", &num);
STU* change = Head->next;
while (change && (change->num != num))
change = change->next;
if (change)
{
printf("\n更改后的学号:");
scanf("%ld", &change->num);
printf("\n更改后的姓名: ");
scanf("%s", change->name);
printf("\n更改后的性别: ");
scanf("%s", change->sex);
printf("\n更改后的数学成绩: ");
scanf("%f", &change->Math);
printf("\n更改后的语文成绩: ");
scanf("%f", &change->Chinese);
printf("\n更改后的英语成绩: ");
scanf("%f", &change->English);
printf("\n\n 学生信息已经更改完毕!!!\n");
}
else
printf("\n\n 学生信息不存在,无法更改!!!\n");
}
//查询学生成绩信息
void SeekStudent()
{
while (1)
{
printf("\n\n请选择查询方式??? 按学号:1 / 按姓名:2: ");
int k;
scanf("%d", &k);
switch (k)
{
case 1:
{
int num;
printf("\n请输入您要查找学生的学号:");
scanf("%ld", &num);
STU* find = Head->next;
while (find && (find->num != num))
find = find->next;
if (find)
{
printf("\n查询学生信息如下:\n\n");
printf("学号\t\t姓名\t性别\t数学\t语文\t英语\n\n");
printf("%ld\t%s\t%s\t%.2f\t%.2f\t%.2f\n", find->num, find->name, find->sex, find->Math, find->Chinese, find->English);
}
else
printf("\n\n 没有查询到该学生信息!!!\n");
return;
}
case 2:
{
printf("\n请输入您要查找学生的姓名:");
char name1[20];
scanf("%s", name1);
STU* find = Head->next;
while (find && (strcmp(find->name, name1) != 0))
find = find->next;
if (find)
{
printf("\n查询学生信息如下:\n\n");
printf("学号\t\t姓名\t性别\t数学\t语文\t英语\n\n");
printf("%ld\t%s\t%s\t%.2f\t%.2f\t%.2f\n", find->num, find->name, find->sex, find->Math, find->Chinese, find->English);
}
else
printf("\n\n 没有查询到该学生信息!!!\n");
return;
}
default:
{
printf("\n\n查询方式错误!!! 请重新选择查询方式\n");
break;
}
}
}
}
//输出全部学生成绩
void DisplayAll()
{
STU* p = Head->next;
int len = 0;
printf("\n 全部学生成绩信息如下!!!\n\n");
printf("学号\t\t姓名\t性别\t数学\t语文\t英语\n\n");
while (p != NULL)
{
printf("%ld\t%s\t%s\t%.2f\t%.2f\t%.2f\n", p->num, p->name, p->sex, p->Math, p->Chinese, p->English);
p = p->next;
len++;
while (p == NULL)
{
printf("\n\n 成绩系统含学生总人数为:%d 人\n", len);
return;
}
}
printf("\n Error!!!");
printf("\n Error!!!");
printf("\n Error!!!");
printf("\n 成绩表中数据为空!!!\n");
return;
}
//视图界面
void VeiwInterface()
{
system("cls");
printf(" \t***********************************************************\n");
printf(" \t* 欢迎使用学生成绩管理系统 *\n");
printf(" \t***********************************************************\n\n");
printf(" \t*|*\t\t 1.添加学生成绩信息 \t\t*|*\n\n");
printf(" \t*|*\t\t 2.删除学生成绩信息 \t\t*|*\n\n");
printf(" \t*|*\t\t 3.更改学生成绩信息 \t\t*|*\n\n");
printf(" \t*|*\t\t 4.查询学生成绩信息 \t\t*|*\n\n");
printf(" \t*|*\t\t 5.输出全部学生信息 \t\t*|*\n\n");
printf(" \t*|*\t\t 6.--- 退出系统 --- \t\t*|*\n\n");
printf(" \t*-*-----------------------------------------------------*-*\n");
printf("\n请选择功能??? 输入序号:<1--6>:");
}
//需要执行的功能选择
void ChoiceFunction(int k)
{
while (1)
{
switch (k)
{
case 1:
{
while (1)
{
system("cls");
AddStudent();
printf("\n\n是/否继续添加学生成绩信息??? 继续:1 / 退出:0: ");
int select1 = getch() - 48;
switch (select1)
{
case 1: break;
case 0: return;
default:
{
printf("\n\n 输入错误!!! 按任意键回到主界面\n\n");
system("pause");
return;
}
}
}
}
case 2:
{
while (1)
{
system("cls");
DeleteStudent();
printf("\n\n是/否继续删除学生成绩信息??? 继续:1 / 退出:0: ");
int select2 = getch() - 48;
switch (select2)
{
case 1: break;
case 0: return;
default:
{
printf("\n\n 输入错误!!! 按任意键回到主界面\n\n");
system("pause");
return;
}
}
}
}
case 3:
{
while (1)
{
system("cls");
AlterStudent();
printf("\n\n是/否继续更改学生成绩信息??? 继续:1 / 退出:0: ");
int select3 = getch() - 48;
switch (select3)
{
case 1: break;
case 0: return;
default:
{
printf("\n\n 输入错误!!! 按任意键回到主界面\n\n");
system("pause");
return;
}
}
}
}
case 4:
{
while (1)
{
system("cls");
SeekStudent();
printf("\n\n是/否继续查询学生成绩信息??? 继续:1 / 退出:0: ");
int select4 = getch() - 48;
switch (select4)
{
case 1: break;
case 0: return;
default:
{
printf("\n\n 输入错误!!! 按任意键回到主界面\n\n");
system("pause");
return;
}
}
}
}
case 5:
{
while (1)
{
system("cls");
//system("color 17");
DisplayAll();
printf("\n\n是/否退出显示??? 退出:1 / 刷新:0: ");
int select5 = getch() - 48;
switch (select5)
{
case 1: return;
case 0: break;
default:
{
printf("\n\n 输入错误!!! 按任意键回到主界面\n\n");
system("pause");
return;
}
}
}
}
case 6:
{
SaveData();
printf("\n\n再次确认是/否退出系统??? 退出:1 / 取消:0: ");
int select6 = getch() - 48;
switch (select6)
{
case 1: exit(0);
case 0: return;
default: return;
}
}
default:
{
printf("\n\n 输入错误!!! 按任意键回到主界面重新选择\n\n");
system("pause");
return;
}
}
}
}
//主函数
void main()
{
LoadData();
int key;
while (1)
{
VeiwInterface();
key = getch() - 48; //返回的是字符的ASCLL值,‘1’= 49.....;
ChoiceFunction(key);
}
}
添加成员
显示输出:
查找学员:
更改学员:
删除学员:
显示输出:
此外对于存入文件中,博主在这里没有直接给出代码,读者可以自行设计(用文件指针实现),不理解的地方可以留言一起讨论,谢谢指教!
补充:前几天把文件处理内容补充了,今天把代码发了上来,可以试着用“feof”去代替我的“EOF”,看看结果怎样!!!!
上一篇: Java 中对于polymorphism:多态的理解
下一篇: 基于JavaWeb的学生成绩管理系统