教务管理系统
一、项目需求
本项目管理三种身份人员的信息:
- 管理员(仅一个):姓名:admin 密码:
- 教师(多个):姓名、密码、工号、性别、出生日期、
- 学生(多个):姓名、密码、学号、性别、出生日期、数学、语文、英语三门功课成绩
管理员登录后可以进行如下操作:
- 修改自身登录密码
- 添加新教师
- 查看所有教师
- 删除教师
- 修改教师信息
教师登录后可以进行如下操作:
- 修改自身登录密码
- 查阅自身信息
- 添加新学生
- 删除学生
- 查阅指定学生信息
- 修改学生信息(姓名、性别、出生日期、三门功课成绩)
- 按学号从低到高查看所有学生信息
- 按数学成绩从高到低查看所有学生信息
- 按语文成绩从高到低查看所有学生信息
- 按英语成绩从高到低查看所有学生信息
- 按总分从高到低查看所有学生信息
学生登录后可以进行如下操作:
- 修改自身登录密码
- 查阅自身信息
二、设计思路
- 可以先设计管理员的功能
- 设计老师的功能
- 设计学生的功能`
三、功能实现
1、数据类型可以选择结构体
2、数据结构可以选用带头结点的链表来存储
一、管理员功能实现
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
struct adm
{
char name[20];
char ser[20];
};
struct teacher
{
char name[20];
char ser[20];
int num;
char sex[10];
char bir[20];
struct teacher*next;
};
上面就是我们定义好的结构体,定义好了数据类型我们可以开始搭建框架了。
二、管理员分支函数框架
void adm_info(void)
{
int x=1;
struct adm s = my_read();
struct teacher *head = NULL;
head = create_node();
head = teacher_read();
while(x)
{
printf("———————————————————————————————————————\n");
printf("欢迎来到管理员登陆界面!\n");
printf("请输入姓名:");
char name[20];
scanf("%s",name);
while(getchar() !='\n');
printf("请输入密码:");
char ser[20];
scanf("%s",ser);
while(getchar() !='\n');
printf("身份确认中...\n");
if(strcmp(s.name,name)==0&&strcmp(s.ser,ser)==0)
{
printf("登陆成功!\n");
break;
}
printf("信息有误,请核实姓名和密码!\n");
printf("———————————————————————————————————————\n");
return;
}
int flag = 1,set,n;
while(flag)
{
printf("——————————————————————————————————\n");
printf("| 管理员功能菜单! |\n");
printf("——————————————————————————————————\n");
printf("|1、修改自身登陆密码 |\n");
printf("——————————————————————————————————\n");
printf("|2、添加新教师信息 |\n");
printf("——————————————————————————————————\n");
printf("|3、查看所有教师 |\n");
printf("——————————————————————————————————\n");
printf("|4、删除教师 |\n");
printf("——————————————————————————————————\n");
printf("|5、修改教师信息 |\n");
printf("——————————————————————————————————\n");
printf("|0、返回上一层! |\n");
printf("+————————————————————————————————+\n");
printf("输入您的选择: |\n");
printf("——————————————————————————————————\n");
scanf("%d",&set);
while(getchar() != '\n');
switch(set)
{
case 1:mod_ser(&s);break;
case 2:add_teacher(head);break;
case 3:show_teacher(head);
printf("任意健退出显示,返回上一层!\n");
scanf("%d",&n);
while(getchar() != '\n');
break;
case 4:del_teacher(head);break;
case 5:mod_teacher(head);break;
case 0:flag = 0;break;
default:printf("无该选项!\n");break;
}
}
adm_write(s);
teacher_write(head);
return;
}
2.1 函数分析
1、函数的框架是先进入登陆界面
2、利用分支结构实现管理员的功能
2.2、登录功能实现
1、想实现登录功能我们需要记住管理员的账号和密码,通过比较是否相等,从而实现这个功能。
2、此处就需要用到文件I/O的相关知识了,
2.3、管理员信息的文件保存与读写函数
//保存管理员密码信息 0成功-1失败
int adm_write(struct adm s)
{
FILE*fp = NULL;
fp = fopen("./adm.txt","w");//打开文件
assert(fp != NULL);
int ret;
ret = fprintf(fp,"%s %s\n",s.name,s.ser);//把数据传到文件中
if(ret != EOF)
{
printf("保存管理员数据成功!\n");
fclose(fp);//关闭文件
return 0;
}
return -1;
}
//读管理员密码
struct adm my_read()
{
FILE*fp = NULL;
fp = fopen("./adm.txt","r");//打开文件
assert(fp != NULL);
struct adm a;
int ret;
ret = fscanf(fp,"%s%s",a.name,a.ser);//读文件
if(ret != EOF)
printf("读取管理员数据成功!\n");
fclose(fp);//关闭文件
return a;//返回数据
}
2.4、修改管理员密码
//修改管理员密码
void mod_ser(struct adm*s)
{
printf("请输入想修改的密码:");
scanf("%s",s->ser);
while(getchar() !='\n');
printf("修改成功!\n");
return;
}
下一步就是设置跟老师相关的参数了,我们需要写一个创建老师信息的节点函数和使用头插法插入老师信息的函数。
2.5、添加老师信息
//创建老师结构体节点
struct teacher *create_node()
{
struct teacher *p = NULL;
p = (struct teacher*)malloc(sizeof(struct teacher));//申请堆空间
assert(p != NULL);//条件为真执行否则段错误
p->next = NULL;
return p;//返回地址
}
//带头节点的链表来添加老师信息
void add_teacher(struct teacher*head)
{
int flag = 1;
struct teacher *p = NULL;
p = head->next;
struct teacher *pnew = NULL;
pnew = create_node();
printf("请输入老师姓名:");
scanf("%s",pnew->name);
while(getchar() != '\n');
printf("请输入老师密码:");
scanf("%s",pnew->ser);
while(getchar() != '\n');
while(flag) //防止工号重复
{
printf("请输入工号:");
scanf("%d",&pnew->num);
while(getchar() != '\n');
p = head->next;
while(p!= NULL)
{
if(p->num == pnew->num)//找到相等的工号p就停止
{
break;
}
p = p->next;
}
if(NULL != p)//说明重复
{
flag = 1;
}
else
{
break;
}
}
printf("请输入性别:");
scanf("%s",pnew->sex);
while(getchar() != '\n');
printf("请输入出生日期例如(19980312):");
scanf("%s",pnew->bir);
while(getchar() != '\n');
//头插法插入数据
pnew->next = head->next;
head->next = pnew;
printf("添加老师信息成功!\n");
return;
}
因为涉及到后面的老师登录,和修改老师信息所以我们,还需要做一个读写老师数据到文件的函数。
2.6、老师信息的文件I/O函数
//读取老师信息
struct teacher*teacher_read()
{
FILE*fp = NULL;
fp = fopen("./teacher.txt","r");
assert(fp != NULL);
//开始读取数据
int ret;
struct teacher *pnew = NULL,*head = NULL,*newhead = NULL;
head = create_node();
while(1)
{
pnew = create_node();//创建新的节点
ret = fscanf(fp,"%s%s%d%s%s",pnew->name,pnew->ser,&pnew->num,pnew->sex,pnew->bir);
if(ret == EOF)//ret == EOF读取到末尾
{
break;
}
pnew->next = newhead;
newhead = pnew;
}
free(pnew);//释放多出来的一个节点
fclose(fp);
printf("读取老师数据成功!\n");
head->next = newhead;
return head;
}
//保存老师的数据
int teacher_write(struct teacher*head)
{
FILE*fp = NULL;//打开文件
fp = fopen("./teacher.txt","w");
assert(fp != NULL);
int ret;
struct teacher *p = head->next;
while(p != NULL)
{
ret = fprintf(fp,"%s\t%s\t%d\t%s\t%s\n",p->name,p->ser,p->num,p->sex\
,p->bir);//写操作
if(ret == EOF)
{
break;
}
p = p->next;
}
if(p == NULL)
printf("保存老师数据成功!\n");
fclose(fp);//关闭文件
return 0;
}
添加信息后,当然需要可以显示和查找老师的信息咯。所以接下来就来实现这两个功能吧
2.7、老师信息的查找和显示
//带头节点显示老师的信息
void show_teacher(struct teacher *head)
{
if(head->next == NULL)//入参检测
{
printf("无老师信息!\n");
}
struct teacher *p = head->next;
while(p!= NULL)
{
printf("姓名:%s\t密码:%s\t工号:%d\t性别:%s\t出生:%s\n",p->name,\
p->ser,p->num,p->sex,p->bir);
p = p->next;
}
return ;
}
//通过工号查找老师的信息
struct teacher*search_teacher(struct teacher*head,int num)
{
struct teacher *ps = NULL,*p = NULL;
p = head->next;
while(p != NULL)
{
if(p->num == num)
{
ps = p;
}
p = p->next;
}
if(ps == NULL)
{
printf("无该老师信息!\n");
}
return ps;
}
可以添加可以查找可以显示,但是我们还缺少编辑老师信息的函数,所以接下来可以创建删除老师信息,和修改老师信息的函数。
2.8、老师信息的删除
//通过工号删除老师信息
void del_teacher(struct teacher*head)
{
struct teacher *pdel = NULL,*p = NULL;
p = head->next;
if(p ==NULL)
{
printf("无老师信息无法删除!\n");
return;
}
int num;
printf("请输入想删除老师工号:");
scanf("%d",&num);
while(p != NULL)
{
if(p->num == num)
{
pdel = p;
break;
}
p = p->next;
}
//头删
if(pdel == head->next)
{
head->next = pdel->next;
printf("删除成功!\n");
free(pdel);
return ;
}
//尾删中间删
p = head->next;
while(p != NULL)
{
if(p->next == pdel)
{
break;
}
p = p->next;
}
p->next = pdel->next;
free(pdel);//释放删掉的节点
printf("删除成功!\n");
return;
}
2.9、老师信息各项的单独修改
分析:其实从标题就可以看出因为需要有选择的修改,所以需要用到分支结构,然后通过选择实现单独的修改操作,无非就是一个子菜单了。
//修改老师信息
void mod_teacher(struct teacher*head)
{
printf("请输入想修改老师的工号:");
int num;
scanf("%d",&num);
struct teacher *pmod = NULL;
pmod = search_teacher(head,num);
int set,flag = 1;
while(flag)
{
printf("+———————————————————+\n");
printf("| 修改老师信息菜单 |\n");
printf("+———————————————————+\n");
printf("|1 修改姓名 |\n");
printf("+———————————————————+\n");
printf("|2 修改密码 |\n");
printf("+———————————————————+\n");
printf("|3 修改性别 |\n");
printf("+———————————————————+\n");
printf("|4 修改出生日期 |\n");
printf("+———————————————————+\n");
printf("|0 返回上一层 |\n");
printf("+———————————————————+\n");
printf(" 请输入你的选择:");
scanf("%d",&set);
while(getchar() != '\n');
switch(set)
{
case 1:printf("输入新的姓名:");
scanf("%s",pmod->name);
while(getchar() != '\n');
break;
case 2:printf("输入新的密码:");
scanf("%s",pmod->ser);
while(getchar() != '\n');
break;
case 3:printf("输入新的性别:");
scanf("%s",pmod->sex);
while(getchar() != '\n');
break;
case 4:printf("输入新的生日:");
scanf("%s",pmod->bir);
while(getchar() != '\n');
break;
case 0:flag = 0;break;
default:printf("无此功能!\n");break;
}
}
}
小结
到目前为止我们已经写好了管理者这个小分支的所有功能了,目前我们能做到的功能有如下:
1、加载管理员的信息和保存管理员的信息。
2、加载老师和保存老师的信息
3、修改和添加老师的信息。
三、老师分支函数的创建
3.1、函数分析
1.修改自身登录密码
2. 查阅自身信息
2. 添加新学生
3. 删除学生
4. 查阅指定学生信息
5. 修改学生信息(姓名、性别、出生日期、三门功课成绩)
6. 按学号从低到高查看所有学生信息
7. 按数学成绩从高到低查看所有学生信息
8. 按语文成绩从高到低查看所有学生信息
9. 按英语成绩从高到低查看所有学生信息
10. 按总分从高到低查看所有学生信息
从功能上我们不难看出我们需要先进行一个登录,这里就需要加载之前保存好的老师数据,我们已经写好,然后需要对学生进行操作,很明显需要定义关于学生的结构体,整体的框架跟管理员的并没有什么不同,想好了就可以直接动手敲代码了。
3.2、创建学生的结构体
#pragma once
#include"adm.h"
struct stu
{
char name[30];
char ser[30];
int num;
char sex[10];
char bir[15];
float math;
struct stu*next;
float chinese;
float english;
};
typedef struct stu STU;
因为需要用到管理员里面的一些函数所以之前创建好的函数一定要都在管理员.h文件进行声明,这样老师分支这边调用只需要包含管理员那边的头文件即可,避免重复劳动。
3.3、老师分支的函数主框架
void teacher_info()
{
int x=1;
struct teacher *head = NULL;
head = create_node();
head = teacher_read();
STU*stu_head = NULL;
stu_head = create_stu_node();
stu_head = read_stu();
TEACH*s = NULL;
while(x)
{
printf("———————————————————————————————————————\n");
printf("欢迎来到老师登陆界面!\n");
printf("请输入工号:");
int num;
scanf("%d",&num);
while(getchar() !='\n');
printf("请输入密码:");
char ser[20];
scanf("%s",ser);
while(getchar() !='\n');
printf("身份确认中...\n");
s = search_teacher(head,num);
if(NULL == s)
{
printf("登陆失败!\n");
return;
}
if(s->num == num && strcmp(s->ser,ser)==0)
{
printf("登陆成功!\n");
x = 0;
break;
}
else
{
printf("信息有误,请核实工号和密码!\n");
printf("———————————————————————————————————————\n");
return;
}
}
int flag = 1,set,n;
while(flag)
{
printf("——————————————————————————————————————————————\n");
printf("| 老师功能菜单! |\n");
printf("——————————————————————————————————————————————\n");
printf("|1、 修改自身登陆密码 |\n");
printf("——————————————————————————————————————————————\n");
printf("|2、 查阅自身信息 |\n");
printf("——————————————————————————————————————————————\n");
printf("|3、 添加新学生信息 |\n");
printf("——————————————————————————————————————————————\n");
printf("|4、 删除学生 |\n");
printf("——————————————————————————————————————————————\n");
printf("|5、 查阅指定学生信息 |\n");
printf("——————————————————————————————————————————————\n");
printf("|6、 修改学生信息(性别、姓名、出生日期、成绩)|\n");
printf("——————————————————————————————————————————————\n");
printf("|7、 按学号从低到高查看所有学生信息 |\n");
printf("——————————————————————————————————————————————\n");
printf("|8、 按数学成绩从高到低查看所有学生信息 |\n");
printf("——————————————————————————————————————————————\n");
printf("|9、 按语文成绩从高到低查看所有学生信息 |\n");
printf("——————————————————————————————————————————————\n");
printf("|10、按英语成绩从高到低查看所有学生信息 |\n");
printf("——————————————————————————————————————————————\n");
printf("|11、按总分从高到低查看所有学生信息 |\n");
printf("——————————————————————————————————————————————\n");
printf("|0、 返回上一层 |\n");
printf("——————————————————————————————————————————————\n");
printf("输入您的选择:");
scanf("%d",&set);
while(getchar() != '\n');
switch(set)
{
case 1:mod_teacher_ser(s);break;
case 0:flag = 0;break;
case 2:
printf("姓名:%s\t密码:%s\t工号:%d\t性别:%s\t出生:%s\n",\
s->name,s->ser,s->num,s->sex,s->bir);break;
case 3:add_stu_info(stu_head);break;
case 5:show_stu_info_by_num(stu_head);break;
case 4:del_stu_info(stu_head);break;
case 6:mod_stu_info_by_num(stu_head);break;
case 7:sortup_by_num(stu_head);
printf("任意健退出显示,返回上一层!");
scanf("%d",&n);
while(getchar() != '\n');
break;
case 8:sortdown_by_math(stu_head);
printf("任意健退出显示,返回上一层!\n");
scanf("%d",&n);
while(getchar() != '\n');
break;
case 9:sortdown_by_chinese(stu_head);
printf("任意健退出显示,返回上一层!\n");
scanf("%d",&n);
while(getchar() != '\n');
break;
case 10:sortdown_by_english(stu_head);
printf("任意健退出显示,返回上一层!\n");
scanf("%d",&n);
while(getchar() != '\n');
break;
case 11:sortdown_by_allscore(stu_head);
printf("任意健退出显示,返回上一层!\n");
scanf("%d",&n);
while(getchar() != '\n');
break;
default:printf("没有这个功能!\n");break;
}
}
teacher_write(head);
write_stu(stu_head);
return;
}
同样也是先登录成功,然后在进行后续的功能,前面有思路分析这里就不赘述了。
3.4、老师分支修改自身密码
#include "teacher.h"
//修改老师密码
void mod_teacher_ser(TEACH*p)
{
printf("请输入新的密码:");
scanf("%s",p->ser);
while(getchar() != '\n');
printf("修改成功!\n");
return ;
}
3.5、添加学生信息
//创建学生节点
STU*create_stu_node()
{
STU*pnew = NULL;
pnew = (STU*)malloc(sizeof(STU));
assert(pnew != NULL);
pnew->next = NULL;
return pnew;
}
//增加学生信息带头节点
void add_stu_info(STU*stu_head)
{
STU*pnew = NULL;
pnew = create_stu_node();
printf("请输入学生姓名:");
scanf("%s",pnew->name);
while(getchar() != '\n');
printf("请输入学生密码:");
scanf("%s",pnew->ser);
while(getchar() != '\n');
int flag = 1;
STU*p = stu_head->next;
while(flag) //防止学号重复
{
printf("请输入学号:");
scanf("%d",&pnew->num);
while(getchar() != '\n');
p = stu_head->next;
while(p!= NULL)
{
if(p->num == pnew->num)
{
break;//重复就退出循环
}
p = p->next;
}
if(NULL == p)//不重复退出循环
{
break;
}
}
printf("请输入性别:");
scanf("%s",pnew->sex);
while(getchar() != '\n');
printf("请输入出生日期例如(1998-03-12):");
scanf("%s",pnew->bir);
while(getchar() != '\n');
printf("请输入数学成绩:");
scanf("%f",&pnew->math);
while(getchar() != '\n');
printf("请输入语文成绩:");
scanf("%f",&pnew->chinese);
while(getchar() != '\n');
printf("请输入英语成绩:");
scanf("%f",&pnew->english);
while(getchar() != '\n');
// 头插
pnew->next = stu_head->next;
stu_head->next = pnew;
printf("添加学生信息成功!\n");
return ;
}
这里其实有一个比较重要的点就是如何防止学号重复,这里简单的分析一下提供几个思路:
1、可以考虑用全局静态变量,每次读取,或者添加一个学生数据就自增一下,删除就自减。
2、可以考虑添加一个判断,学号重复就递归调用本身,不重复就执行下一步。
3、就是我用的方法,直接循环解决问题。
3.6、学生信息的文件I/O操作
//写学生信息到文件
int write_stu(STU*head)
{
FILE*fp = NULL;//打开文件
fp = fopen("./student.txt","w");
assert(fp != NULL);
int ret;
STU *p = head->next;
while(p != NULL)//写操作
{
ret = fprintf(fp,"%s\t%s\t%d\t%s\t%s\t%.2f\t%.2f\t%.2f\n"\
,p->name,p->ser,p->num,p->sex,p->bir,p->math,p->chinese,p->english);
if(ret == EOF)
{
break;
}
p = p->next;
}
if(p == NULL)
printf("保存学生数据成功!\n");
fclose(fp);//关闭文件
return 0;
}
//读学生文件操作
STU*read_stu()
{
FILE*fp = NULL;//打开文件
fp = fopen("./student.txt","r");
assert(fp != NULL);
int ret;
STU *pnew = NULL,*head = NULL,*newhead = NULL;
head = create_stu_node();//创建一个头节点
while(1)
{
pnew = create_stu_node();//新的节点接受数据
ret = fscanf(fp,"%s%s%d%s%s%f%f%f",\
pnew->name,pnew->ser,&pnew->num,pnew->sex,\
pnew->bir,&pnew->math,&pnew->chinese,&pnew->english);
if(ret == EOF)//读到末尾
{
break;
}
//头插
pnew->next = newhead;
newhead = pnew;
}
free(pnew);//释放多余的节点
fclose(fp);//关闭文件
printf("读取学生数据成功!\n");
head->next = newhead;
return head;
}
3.7、删除学生信息通过学号
//删除学生信息
void del_stu_info(STU*head)
{
STU *pdel = NULL,*p = NULL;
p = head->next;//入参检查
if(p ==NULL)
{
printf("无学生信息无法删除!\n");
return;
}
int num;
printf("请输入想删除学生学号:");
scanf("%d",&num);
while(getchar() != '\n');
while(p != NULL)
{
if(p->num == num)
{
pdel = p;
break;//找到目标
}
p = p->next;
}
// pdel = search_teacher(head,num);
if(pdel == head->next)//头删
{
head->next = pdel->next;
printf("删除学生信息成功!\n");
free(pdel);
return ;
}
p = head->next;
//中间删和尾删
while(p != NULL)
{
if(p->next == pdel)
{
break;
}
p = p->next;
}
p->next = pdel->next;
free(pdel);//释放删除的节点
printf("删除学生信息成功!\n");
return;
}
其实这里只提供了一种方法,还可以考虑通过名字,或者其他的方式,但是因为我们设定学号不可以重复具有唯一性,所以选择了这个方法。
3.8、学生信息的查找
//通过学号显示特定学生的信息
void show_stu_info_by_num(STU*head)
{
if(head->next == NULL)//入参检查
{
printf("还没有这个学生信息!\n");
return;
}
printf("请输入想查找的学生学号:");
int num;
scanf("%d",&num);
while(getchar() != '\n');
STU*p = NULL;
p = head->next;
STU*ps = NULL;
while(p != NULL)
{
if(p->num == num)
{
ps = p;//找到目标
break;
}
p = p->next;
}
//显示
if(ps != NULL)
{
printf("姓名:%s\t密码:%s\t学号:%d\t性别:%s\t出生:%s\t数学分数:%.2f\t语文分数:%.2f\t英语分数%.2f\n",p->name,p->ser,p->num,p->sex,p->bir,\
p->math,p->chinese,p->english);
return ;
}
printf("没有这个学生信息!\n");
return;
}
同样的原因我们还是使用学号作为查找依据。
3.9、学生信息的修改
//修改学生信息通过学号
void mod_stu_info_by_num(STU*head)
{
printf("请输入想修改学生的学号:");
int num;
scanf("%d",&num);
while(getchar() !='\n');
STU *pmod = NULL;
if(head->next == NULL)//入参检测
{
printf("还没有这个学生!\n");
return;
}
STU*p = NULL;
p = head->next;
while(p != NULL)
{
if(p->num == num)
{
pmod = p;//找到目标
break;
}
p = p->next;
}
int set,flag = 1;
while(flag)
{
printf("——————————————————————————\n");
printf("| 修改学生信息菜单! |\n");
printf("——————————————————————————\n");
printf("|1 修改姓名 |\n");
printf("——————————————————————————\n");
printf("|2 修改密码 |\n");
printf("——————————————————————————\n");
printf("|3 修改性别 |\n");
printf("——————————————————————————\n");
printf("|4 修改出生日期 |\n");
printf("——————————————————————————\n");
printf("|5 修改数学成绩 |\n");
printf("——————————————————————————\n");
printf("|6 修改语文成绩 |\n");
printf("——————————————————————————\n");
printf("|7 修改英语成绩 |\n");
printf("——————————————————————————\n");
printf("|0 返回上一层 |\n");
printf("——————————————————————————\n");
printf("|请输入你的选择 |\n");
printf("——————————————————————————\n");
scanf("%d",&set);
switch(set)
{
case 1:printf("输入新的姓名:");
scanf("%s",pmod->name);
while(getchar() != '\n');
break;
case 2:printf("输入新的密码:");
scanf("%s",pmod->ser);
while(getchar() != '\n');
break;
case 3:printf("输入新的性别:");
scanf("%s",pmod->sex);
while(getchar() != '\n');
break;
case 4:printf("输入新的生日:");
scanf("%s",pmod->bir);
while(getchar() != '\n');
break;
case 5:printf("输入新的数学成绩:");
scanf("%f",&pmod->math);
while(getchar() != '\n');
break;
case 6:printf("输入新的语文成绩:");
scanf("%f",&pmod->chinese);
while(getchar() != '\n');
break;
case 7:printf("输入新的英语成绩:");
scanf("%f",&pmod->english);
while(getchar() != '\n');
break;
case 0:flag = 0;break;
default:printf("无此功能!\n");break;
}
}
printf("修改学生信息成功!\n");
return;
}
这个和管理员修改老师信息一样,我们同样做了一个子菜单方便操作。
3.9、排序
其实无论是根据什么排序原理其实都差不多,无非是改变一下判别条件,这边就不做详细的介绍了。
//学号升序
void sortup_by_num(STU*head)
{
if(head->next == NULL)
{
printf("还没有学生信息!\n");
return;
}
STU*head1 = head->next;
STU*p = NULL;
STU*pmax = NULL;
head->next = NULL;
STU*newhead = NULL;
/*排序*/
while(head1 != NULL)
{
p = head1;
pmax = head1;
while(p != NULL)
{
if(pmax->num < p->num)//找出最大值
{
pmax = p;
}
p = p->next;
}
if(pmax == head1)//移除最大值
{
head1 = head1->next;
}
else
{
p = head1;
while(p->next != pmax)
{
p = p->next;
}
p->next = pmax->next;
}
/*插入最大值*/
pmax->next = NULL;
pmax->next = newhead;
newhead = pmax;
}
head->next = newhead;
/*展示排序后的链表*/
p = head->next;
printf("学号从低到高开始显示!\n");
while(p != NULL)
{
printf("姓名:%s\t密码:%s\t学号:%d\t性别:%s\t出生:%s\t数学分数:%.2f\t语文分数:%.2f\t英语分数%.2f\n",\
p->name,p->ser,p->num,p->sex,p->bir,p->math,p->chinese,p->english);
p = p->next;
}
return;
}
//数学成绩降序排列
void sortdown_by_math(STU*head)
{
if(head->next == NULL)
{
printf("还没有学生信息!\n");
return;
}
STU*head1 = head->next;
STU*p = NULL;
STU*pmin = NULL;
head->next = NULL;
STU*newhead = NULL;
/*排序*/
while(head1 != NULL)
{
p = head1;
pmin = head1;
while(p != NULL)
{
if(pmin->math > p->math)//找出最大值
{
pmin = p;
}
p = p->next;
}
if(pmin == head1)//移除最大值
{
head1 = head1->next;
}
else
{
p = head1;
while(p->next != pmin)
{
p = p->next;
}
p->next = pmin->next;
}
/*插入最大值*/
pmin->next = NULL;
pmin->next = newhead;
newhead = pmin;
}
head->next = newhead;
/*展示排序后的链表*/
p = head->next;
printf("数学成绩从高到底开始显示!\n");
while(p != NULL)
{
printf("姓名:%s\t密码:%s\t学号:%d\t性别:%s\t出生:%s\t数学分数:%.2f\t语文分数:%.2f\t英语分数%.2f\n",p->name,p->ser,p->num,p->sex,p->bir,\
p->math,p->chinese,p->english);
p = p->next;
}
return;
}
//语文成绩降序排列
void sortdown_by_chinese(STU*head)
{
if(head->next == NULL)
{
printf("还没有学生信息!\n");
return;
}
STU*head1 = head->next;
STU*p = NULL;
STU*pmin = NULL;
head->next = NULL;
STU*newhead = NULL;
/*排序*/
while(head1 != NULL)
{
p = head1;
pmin = head1;
while(p != NULL)
{
if(pmin->chinese > p->chinese)//找出最大值
{
pmin = p;
}
p = p->next;
}
if(pmin == head1)//移除最大值
{
head1 = head1->next;
}
else
{
p = head1;
while(p->next != pmin)
{
p = p->next;
}
p->next = pmin->next;
}
/*插入最大值*/
pmin->next = NULL;
pmin->next = newhead;
newhead = pmin;
}
head->next = newhead;
/*展示排序后的链表*/
p = head->next;
printf("语文成绩从高到底开始显示!\n");
while(p != NULL)
{
printf("姓名:%s\t密码:%s\t学号:%d\t性别:%s\t出生:%s\t数学分数:%.2f\t语文分数:%.2f\t 英语分数%.2f\n",\
p->name,p->ser,p->num,p->sex,p->bir,p->math,p->chinese,p->english);
p = p->next;
}
return;
}
//英语成绩降序排列
void sortdown_by_english(STU*head)
{
if(head->next == NULL)
{
printf("还没有学生信息!\n");
return;
}
STU*head1 = head->next;
STU*p = NULL;
STU*pmin = NULL;
head->next = NULL;
STU*newhead = NULL;
/*排序*/
while(head1 != NULL)
{
p = head1;
pmin = head1;
while(p != NULL)
{
if(pmin->english > p->english)//找出最大值
{
pmin = p;
}
p = p->next;
}
if(pmin == head1)//移除最大值
{
head1 = head1->next;
}
else
{
p = head1;
while(p->next != pmin)
{
p = p->next;
}
p->next = pmin->next;
}
/*插入最大值*/
pmin->next = NULL;
pmin->next = newhead;
newhead = pmin;
}
head->next = newhead;
/*展示排序后的链表*/
p = head->next;
printf("英语成绩从高到底开始显示!\n");
while(p != NULL)
{
printf("姓名:%s\t密码:%s\t学号:%d\t性别:%s\t出生:%s\t数学分数:%.2f\t语文分数:%.2f\t 英语分数%.2f\n",p->name,p->ser,p->num,p->sex,p->bir,p->math,p->chinese,p->english);
p = p->next;
}
return;
}
//总分降序排列
void sortdown_by_allscore(STU*head)
{
if(head->next == NULL)
{
printf("还没有学生信息!\n");
return;
}
STU*head1 = head->next;
STU*p = NULL;
STU*pmin = NULL;
head->next = NULL;
STU*newhead = NULL;
/*排序*/
while(head1 != NULL)
{
p = head1;
pmin = head1;
while(p != NULL)
{
if(pmin->english+pmin->math+pmin->chinese > p->math+p->chinese+p->english)//找出最大值
{
pmin = p;
}
p = p->next;
}
if(pmin == head1)//移除最大值
{
head1 = head1->next;
}
else
{
p = head1;
while(p->next != pmin)
{
p = p->next;
}
p->next = pmin->next;
}
/*插入最大值*/
pmin->next = NULL;
pmin->next = newhead;
newhead = pmin;
}
head->next = newhead;
/*展示排序后的链表*/
p = head->next;
printf("总成绩从高到底开始显示!\n");
while(p != NULL)
{
printf("姓名:%s\t总分:%.2f\t密码:%s\t学号:%d\t性别:%s\t出生:%s\t数学分数:%.2f\t语文分数:%.2f\t英语分数%.2f\n",p->name,(p->math+p->chinese+p->english),p->ser,p->num,\
p->sex,p->bir,p->math,p->chinese,p->english);
p = p->next;
}
return;
}
小结:
其实很容易可以发现,老师分支的很多操作跟管理员分支差不多,我们只需要让两者很好的联系起来就行了。这边主要就是把握程序的一个整体框架,至于具体每个分支所需要的知识和难点就不做详细介绍了。
四、学生分支函数
学生这边其实就比较简单了,比起前面的老师分支,我们只需要很短的时间就可以做出来。
#include "stu.h"
//修改学生密码
void mod_stu_ser(STU*p)
{
printf("请输入新的密码:");
scanf("%s",p->ser);
while(getchar() != '\n');
printf("修改成功!\n");
return ;
}
//查找学生信息
STU*search_stu(STU*head,int num)
{
STU *ps = NULL,*p = NULL;
p = head->next;
while(p != NULL)
{
if(p->num == num)
{
ps = p;
}
p = p->next;
}
if(ps == NULL)
{
printf("无该学生信息!\n");
}
return ps;
}
void stu_info()
{
STU*head = NULL;
head = create_stu_node();
head = read_stu();
STU*s = NULL;
int flag = 1;
int num;
char ser[20];
while(flag)
{
printf("——————————————————————————\n");
printf(" 欢迎来到学生登陆页面!\n");
printf("请输入您的学号:");
scanf("%d",&num);
while(getchar() != '\n');
printf("请输入您的密码:");
scanf("%s",ser);
while(getchar() != '\n');
printf("登陆中...\n");
printf("——————————————————————————\n");
s = search_stu(head,num);
if(NULL == s)
{
printf("登陆失败!\n");
return;
}
if(s->num == num && strcmp(s->ser,ser)==0)
{
printf("登陆成功!\n");
break;
}
else
{
printf("信息有误,请核实学号和密码!\n");
printf("———————————————————————————————————————\n");
return;
}
}
int x = 1,set;
while(x)
{
printf("————————————————————————————————\n");
printf("| 学生功能菜单! |\n");
printf("————————————————————————————————\n");
printf("|1、修改密码 |\n");
printf("————————————————————————————————\n");
printf("|2、查阅信息 |\n");
printf("————————————————————————————————\n");
printf("|0、返回上一层 |\n");
printf("————————————————————————————————\n");
printf("|请输入您的选择 |\n");
printf("————————————————————————————————\n");
scanf("%d",&set);
while(getchar() != '\n');
switch(set)
{
case 1:mod_stu_ser(s);break;
case 0:x = 0;break;
case 2:
printf("姓名:%s\t密码:%s\t学号:%d\t性别:%s\t出生:%s\t数学分数:%.2f\t语文分数:%.2f\t英语分数%.2f\n",s->name,s->ser,s->num,\
s->sex,s->bir,s->math,s->chinese,s->english);break;
default:printf("还没有这个功能!\n");break;
}
}
write_stu(head);
return;
}
4.1、需要用到的头文件如下
#pragma once
#include "teacher.h"
void stu_info();
到这里差不多就结束了各个分支的函数编写,只需要再来一个主函数,把他们连起来文章来源:https://www.toymoban.com/news/detail-480380.html
五、主函数连接
#include <stdio.h>
#include "teacher.h"
#include "adm.h"
#include "stu.h"
int main(){
int set,flag = 1;
while(flag)
{
printf("————————————————————————————————————\n");
printf("| 欢迎进入教务管理系统! |\n");
printf("————————————————————————————————————\n");
printf("|1、管理员登陆 |\n");
printf("————————————————————————————————————\n");
printf("|2、老师登陆 |\n");
printf("————————————————————————————————————\n");
printf("|3、学生登陆 |\n");
printf("————————————————————————————————————\n");
printf("|0、退出! |\n");
printf("————————————————————————————————————\n");
printf("请输入您的身份选择:");
scanf("%d",&set);
while(getchar() != '\n');
switch(set)
{
case 1:adm_info();break;
case 2:teacher_info();break;
case 3:stu_info();break;
case 0:flag = 0;printf("成功退出系统!\n");break;
default:printf("无此选项!\n");break;
}
}
return 0;
}
总结
通过以上步骤,我们就实现了开头想要实现的功能,这只能算是一个很粗糙的小项目了,还有很多可以完善的地方。总的来说,有了这种基本的思路,想增加什么功能,往里面有序的添加就好。文章来源地址https://www.toymoban.com/news/detail-480380.html
到了这里,关于如何用C语言写一个简单的教务管理系统的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!