本文主要是介绍链式成绩管理系统,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
/*
名称:成绩管理系统(单链表实现)
功能:学生信息的添加、修改、删除、查找及显示
特点:加入两种查找方式,登录成绩管理系统需要密码
且密码,且有管理员和学生两种权限
(管理员账号:admin,管理员密码:admin
学生账号:student,学生密码:student);
update:
2013.5.20---成绩管理系统beta1(实现基本功能)
2013.5.29---成绩管理系统beta2(加入文件,内置
网工三班前12号成绩(仅作者乱打的数据)
修复删除了人之后不能马上添加的bug)
*/
#include <cstdio>
#include <cstring>
#include <cstdlib>
struct student
{
long long no;//比如学号为:121052030*
char name[20];//比如姓名为:蒲*
float score[3];//数据结构,高数,英语三门学科成绩
float sum;//总分
float ave;//平均分
struct student *next;//指向下一节点的指针
};
//初始化,有头结点
student *Init()
{
student *stu;
stu = (student *)malloc(sizeof(student));//动态分配内存
stu->next = NULL;
return stu;
}
//登陆函数
int Login()
{
char Name[20];//用户名
char Password[20];//密码
printf("|*************************************|\n");
printf("|*****欢迎进入Neusoft成绩管理系统*****|\n");
printf("|***** 登陆 *****|\n");
printf(" 用户名:_____\b\b\b\b\b");
scanf("%s", Name);
printf(" 密码:_____\b\b\b\b\b");
scanf("%s", Password);
printf("|*************************************|\n\n");
//判断用户名和密码是否正确,以及权限
if (!strcmp("admin", Name) && !strcmp("admin", Password))
{
return 2;
}
else if(!strcmp("student", Name) && !strcmp("student", Password))
{
return 1;
}
else
{
return 0;
}
}
//菜单函数
int Menu()
{
int select;
printf("|*************************************|\n");
printf("|*****欢迎进入Neusoft成绩管理系统*****|\n");
printf("|***** 1.录入新学生信息 *****|\n");
printf("|***** 2.查找学生信息 *****|\n");
printf("|***** 3.修改学生信息 *****|\n");
printf("|***** 4.删除学生信息 *****|\n");
printf("|***** 5.显示学生信息 *****|\n");
printf("|***** 6.退出 *****|\n");
printf("|*************************************|\n");
do//如果输入不合法的选项,就一直进行输入,知道输入正确的选项
{
printf("请输入你的选择:");
scanf("%d", &select);
}while (select>6 || select<1);
return select;
}
//载入文件
void load(student *stu)
{
FILE *fp;
student *stuTemp;//哨兵指针
student *stuNew;//新节点指针
stuTemp = stu;
//判断文件是否能正常打开
if ((fp = fopen("student_list", "rb")) == NULL)
{
printf("Can't open file!\n");
exit (0);
}
//到文件结束前,一次读取文件放到链表中
while (!feof(fp))
{
stuNew = (student *)malloc(sizeof(student));
if (fread(stuNew, sizeof(student), 1, fp)!=1)
{
if (feof(fp))
{
fclose(fp);
return ;
}
printf("File read error!\n");
}
else
{
stuTemp->next = stuNew;
stuTemp = stuNew;
}
}
stuTemp = NULL;
fclose(fp);//关闭文件
}
//信息写入文件函数
void save(student *stu)
{
FILE *fp;
student *stuTemp;//哨兵指针
stuTemp = stu->next;//指向第一个信息节点
//判断文件是否能正常打开
if ((fp = fopen("student_list", "wb")) == NULL)
{
printf("Can't open file!\n");
exit (0);
}
//循环到链表,末尾,依次写入到文件
while (stuTemp!=NULL)
{
if (fwrite(stuTemp, sizeof(student), 1, fp)!=1)
{
printf("File write error!\n");
break;
}
else
{
stuTemp = stuTemp->next;
}
}
fclose(fp);//关闭文件
}
//录入学生信息,此实现一次录入一个学生的功能
void Ent(student *stu, long long inNo, char inName[], float inScore[])
{
student *stuTemp;
student *stuTempJ;//检查遍历指针
student *stuNew;//创建一个新学生的节点
stuTemp = stu;
stuNew = (student *)malloc(sizeof(student));//为新学生节点动态分配内存空间
stuNew->next = NULL;
stuTempJ = stu->next;
stuNew->no = inNo;
strcpy(stuNew->name, inName);//姓名是字符串,所以要用strcpy函数,当然c++的string类支持直接=
float inSum = 0.0, inAve;
int i;
for (i=0; i<3; i++)
{
stuNew->score[i] = inScore[i];
inSum += inScore[i];
}
inAve = inSum/3.0;//计算平均分
stuNew->sum = inSum;
stuNew->ave = inAve;
stuTemp->next = stuNew;//将原始链表与新节点连接起来
}
//按学号查找函数
void SearchNo(student *stu, long long inNo)
{
student *stuTemp;
stuTemp = stu->next;//哨兵指针指向第一个有信息的节点
while (stuTemp!=NULL)
{
if (inNo == stuTemp->no)
{
printf("|你查找的学生信息如下: |\n");
printf("|*****************************************************************************|\n");
printf("| 学号 || 姓名 || 数据结构 || 高数 || 英语 || 总分 || 平均分 |\n");
//-代表向左对其,小数左边代表一共多少位占用,右边代表小数点的位置
printf("|%-11lld||%-8s||%-12.2f||%-8.2f||%-8.2f||%-8.2f||%-10.2f|\n",
stuTemp->no, stuTemp->name,
stuTemp->score[0], stuTemp->score[1], stuTemp->score[2],
stuTemp->sum, stuTemp->ave);
printf("|*****************************************************************************|\n");
break;
}
else
{
stuTemp = stuTemp->next;
}
}
//查找到链表末尾都没找到,即不存在
if (stuTemp==NULL)
{
printf("|*****************************************************************************|\n");
printf("|你查找的学生不存在! |\n");
printf("|*****************************************************************************|\n");
}
stuTemp = NULL;
}
//按姓名查找函数
void SearchName(student *stu, char inName[])
{
student *stuTemp;
stuTemp = stu->next;//哨兵指针
while (stuTemp!=NULL)
{
if (!strcmp(stuTemp->name, inName))
{
printf("|你查找的学生信息如下: |\n");
printf("|*****************************************************************************|\n");
printf("| 学号 || 姓名 || 数据结构 || 高数 || 英语 || 总分 || 平均分 |\n");
//-代表向左对其,小数左边代表一共多少位占用,右边代表小数点的位置
printf("|%-11lld||%-8s||%-12.2f||%-8.2f||%-8.2f||%-8.2f||%-10.2f|\n",
stuTemp->no, stuTemp->name,
stuTemp->score[0], stuTemp->score[1], stuTemp->score[2],
stuTemp->sum, stuTemp->ave);
printf("|*****************************************************************************|\n");
break;
}
else
{
stuTemp = stuTemp->next;
}
}
//查找到链表末尾都没找到,即不存在
if (stuTemp==NULL)
{
printf("|*****************************************************************************|\n");
printf("|你查找的学生不存在! |\n");
printf("|*****************************************************************************|\n");
}
stuTemp = NULL;
}
//查找选择函数
void Search(student *stu)
{
int sel;
printf("|~~~~~~~~~~~~~~~~~~|\n");
printf("| 1.按学号查找 |\n");
printf("| 2.按姓名查找 |\n");
printf("|~~~~~~~~~~~~~~~~~~|\n");
do//如果输入不合法的选项,就一直进行输入,知道输入正确的选项
{
printf("请输入你的选择:");
scanf("%d", &sel);
} while (sel<1 || sel>2);
long long inNo;
char inName[20];
//选择1就按学号查找
if (sel == 1)
{
printf("请输入学生的学号(eg:1231052030*):");
scanf("%lld", &inNo);
//printf("inNo==%lld\n", inNo);
SearchNo(stu, inNo);
}
//选择2按姓名查找
else if (sel == 2)
{
getchar();//由于gets要吃回车符,所以在sel==2时,输入sel2会产生一个回车符,要在gets输入之前被吃掉
printf("请输入学生的姓名(eg:蒲*):");
gets(inName);
SearchName(stu, inName);
}
}
//学生信息的修改函数,由于学号的唯一性,所以我们修改就只按照学号修改
void Mod(student *stu, long long inNo, char inName[], float inScore[])
{
student *stuTemp;
stuTemp = stu->next;//哨兵指针
float inSum = 0.0, inAve;
int i;
while (stuTemp!=NULL)
{
//学号相等判断
if (inNo == stuTemp->no)
{
strcpy(stuTemp->name, inName);//姓名是字符串,所以要用strcpy函数,当然c++的string类支持直接=
for (i=0; i<3; i++)
{
stuTemp->score[i] = inScore[i];//循环赋值
inSum += inScore[i];//求和
}
inAve = inSum/3.0;//求平均
stuTemp->sum = inSum;
stuTemp->ave = inAve;
break;
}
else
{
stuTemp = stuTemp->next;//哨兵指针遍历
}
}
//查找到链表末尾都没找到,即不存在
if (stuTemp==NULL)
{
printf("|*****************************************************************************|\n");
printf("|你要修改的学生不存在! |\n");
printf("|*****************************************************************************|\n");
}
stuTemp = NULL;
}
//学生信息删除函数
void Delete(student *stu, long long inNo)
{
student *stuTemp;
student *stuFront;
stuTemp = stu->next;//哨兵指针
stuFront = stu;
while (stuTemp!=NULL)
{
if (stuTemp->no == inNo)
{
stuFront->next = stuTemp->next;
free(stuTemp);//释放内存
stuTemp = stu;//由于后面要判断是否删除不存在的人,所以让哨兵指针指向一个地址
break;
}
else
{
stuFront = stuTemp;
stuTemp = stuTemp->next;
}
}
if (stuTemp==NULL)
{
printf("|*****************************************************************************|\n");
printf("|你要删除的学生不存在! |\n");
printf("|*****************************************************************************|\n");
}
}
//按学号排序,使用的是冒泡排序,当然你有其他更好的选择
void Sort(student *stu)
{
student *p, *q;
//凡是以t打头的都是零时变量,后面交换用
long long tNo;
char tName[20];
float tScore[3];
float tSum, tAve;
p=stu->next;
q=stu->next;
for (; p->next!=NULL; p=p->next)
{
for (q=stu->next; q->next!=NULL; q=q->next)
{
//判断后面的学号是否比前面学号小
if (q->no>q->next->no)
{
//赋值给零时变量
tNo = q->no;
strcpy(tName, q->name);
for (int i=0; i<3; i++)
{
tScore[i] = q->score[i];
}
tSum = q->sum;
tAve = q->ave;
//下面三段代码都是交换操作,可能冒泡有点繁琐,当然推荐使用其他
q->no = q->next->no;
strcpy(q->name, q->next->name);
for (int i=0; i<3; i++)
{
q->score[i] = q->next->score[i];
}
q->sum = q->next->sum;
q->ave = q->next->ave;
q->next->no = tNo;
strcpy(q->next->name, tName);
for (int i=0; i<3; i++)
{
q->next->score[i] = tScore[i];
}
q->next->sum = tSum;
q->next->ave = tAve;
}
}
}
}
//显示学生信息
void Print(student *stu)
{
student *stuTemp;
Sort(stu);
stuTemp = stu->next;
printf("|*****************************************************************************|\n");
printf("| 学号 || 姓名 || 数据结构 || 高数 || 英语 || 总分 || 平均分 |\n");
//循环到链表末尾,显示所有信息
while (stuTemp!=NULL)
{
//-代表向左对其,小数左边代表一共多少位占用,右边代表小数点的位置
printf("|%-11lld||%-8s||%-12.2f||%-8.2f||%-8.2f||%-8.2f||%-10.2f|\n",
stuTemp->no, stuTemp->name,
stuTemp->score[0], stuTemp->score[1], stuTemp->score[2],
stuTemp->sum, stuTemp->ave);
stuTemp = stuTemp->next;//指针遍历
}
printf("|*****************************************************************************|\n");
}
//主函数入口
int main()
{
student *stu;//声名一个student的指针变量(本人习惯使用指针变量,当然你可以直接声名一个student的变量)
stu = Init();//初始化学生信息链表
load(stu);//载入文件
student *stuTemp;
int sel;
long long inNo;
char inName[20];
float inScore[3];
int lg;
while (1)
{
lg = Login();
if (lg == 2)
{
printf("登陆成功,你的权限为:管理员.\n");
break;
}
else if (lg == 1)
{
printf("登陆成功,你的权限为:学生.\n");
break;
}
else
{
printf("账号密码错误,请重新输入!\n");
}
}
//死循环,进行多次操作,退出可选择6即可
while (1)
{
sel = Menu();//sel接收菜单函数的返回值,然后进入switch case语句判断
//管理员权限
if (lg == 2)
{
switch (sel)
{
case 1:
printf("请输入学生的学号(eg:1231052030*):");
scanf("%lld", &inNo);
getchar();
printf("请输入学生的姓名(eg:蒲*):");
gets(inName);
printf("请输入学生的数据结构成绩(eg:98.5):");
scanf("%f", &inScore[0]);
printf("请输入学生的高数成绩(eg:98.5):");
scanf("%f", &inScore[1]);
printf("请输入学生的英语成绩(eg:98.5):");
scanf("%f", &inScore[2]);
for (stuTemp = stu; stuTemp->next!=NULL; stuTemp=stuTemp->next);//扫描到最后一个信息节点
Ent(stuTemp, inNo, inName, inScore);//把指向最后一个节点的指针传入录入信息函数
break;
case 2:
Search(stu);
break;
case 3:
printf("请输入要修改的学生的学号(eg:1231052030*):");
scanf("%lld", &inNo);
getchar();
printf("请输入修改后的学生的姓名(eg:蒲*):");
gets(inName);
printf("请输入修改后的学生的数据结构成绩(eg:98.5):");
scanf("%f", &inScore[0]);
printf("请输入修改后的学生的高数成绩(eg:98.5):");
scanf("%f", &inScore[1]);
printf("请输入修改后的学生的英语成绩(eg:98.5):");
scanf("%f", &inScore[2]);
Mod(stu, inNo, inName, inScore);
break;
case 4:
printf("请输入要删除的学生的学号(eg:1231052030*):");
scanf("%lld", &inNo);
Delete(stu, inNo);
break;
case 5:
Print(stu);
break;
case 6:
save(stu);
exit(0);//结束,需要包含头文件stdlib.h
}
}
else if (lg == 1)
{
switch (sel)
{
case 1:
printf("您没有权限\n");
break;
case 2:
Search(stu);
break;
case 3:
printf("您没有权限\n");
break;
case 4:
printf("您没有权限\n");
break;
case 5:
Print(stu);
break;
case 6:
save(stu);
exit(0);//结束,需要包含头文件stdlib.h
}
}
}
return 0;
}
这篇关于链式成绩管理系统的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!