从零开始的学生管理系统
主要功能
学生能够登陆系统查询语文、数学、英语三科成绩,及三科的平均分、总分、排名
教师能够管理学生、录入学生考试成绩。
管理员能够管理教师,超级管理员有且只有一个,只为管理普通管理员。
除超级管理员外,所有用户连续登陆三次帐号被锁定,需要上级用户才能解锁。
除超级管理员外,所有用户id要求有序且唯一。
除超级管理员外,所有用户登陆必须修改密码。
学生功能
学生信息包括:学号、密码、姓名、性别、年龄、语文、数学、英语、平均、总分、
排名
登陆后显示姓名、语文、数据、英语、平均分、总分
可选择查看单科成绩排名、总分成绩排名
修改登陆密码
教师功能
教师信息包括:工号、密码、姓名、性别、年龄、工龄
学生信息管理:
添加学生,单个添加或批量添加
删除学生,删除后的学生记作退学学生
修改学生基本信息
重置学生密码
解锁学生帐号
根据姓名查询学生基本信息
显示所有在读学生
显示所有退学学生
学生成绩管理:
录入学生成绩,单个录入或指导入
修改学生成绩
根据学号或姓名查询学生成绩
前言
主要功能:
学生功能:
教师功能:
按各科分数和部分排序
修改登陆密码
管理员功能
添加教师,单个添加或批量添加
删除教师,删除后的老师记作离职
修改教师基本信息
重置教师密码
解锁教师帐号
根据姓名查询教师基本信息
显示所有在职教师
显示所有离职教师
修改登陆密码
超级管理员系统
添加管理员
删除管理员
重置管理员密码
解锁管理员帐号
显示所有管理员
Makefile
#source file
SRC :=$(wildcard *.c)
OBJ :=$(patsubst %.c,%.o,$(SRC))
#target you can change test to what you want
TARGET :=sams
#compile and lib parameter
CC :=gcc
STD :=-std=c99
CFLAGS :=-g -Wall -03
all:obj
$(CC) $(OBJ) -o $(TARGET)
obj:
$(CC) $(STD) -c $(SRC) $(STD)
clean:
rm -fr *.o
sams.h
#ifndef SAMS_H
#define SAMS_H
#include "tools.h"
#define ID_PATH "data/id.bin"
// 申请内存加载数据
void sams_init (void);
// 开始运行管理系统
void sams_start (void);
// 保存数据释放内存
void sams_exit (void);
extern uint32_t* id_a;
#endif//SAMS_H
status.h
#ifndef STATUS_H
#define STATUS_H
typedef enum
{
EXCEP = 1, // 执行异常
RIGHT = 0, // 执行成功
ERROR = -1, // 执行错误
PRNIL = -2, // 参数为空
SPILL = -3, // 参数过界
IDERR = -4, // 帐号错误
PDERR = -5 // 密码错误
}Status;
#define nil (0)
#endif//STATUS_H
tool.h
#ifndef TOOLS_H
#define TOOLS_H
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <stdbool.h>
#include <time.h>
#include "get_keyboard.h"
#define pf printf
#define sf scanf
// 获取当前年份
uint16_t get_current_year(void);
// 清理屏幕
void clear_src(void);
// 任意键继续
void anykey_continue(void);
// 显示提示信息
void show_msg(const char* msg,time_t t);
// 从键盘获取指令
char get_cmd(char begin_cmd,char end_cmd);
// 获取性别
char get_sex(void);
// 获取年份
uint16_t get_year(void);
// 获取成绩
bool get_score(float* score_p);
// 从键盘获取密码
char* get_passwd(char* pd,size_t hope_len,bool is_show);
// 从键盘获取字符串
char* get_str(char* str,size_t hope_len);
// 从文件加载数据
int load_data(const char* path,void* ptr,size_t node_size);
// 保存数据到文件
int save_data(const char* path,const void* ptr,size_t node_size,size_t num);
#endif//TOOLS_H
student.h
#ifndef STUDENT_H
#define STUDENT_H
#include "tools.h"
#define S_DATA_PATH "data/s_data.bin"
#define SD_DATA_PATH "data/sd_data.bin"
#define STU_MAX 50
typedef struct Student
{
uint32_t id; // 学号
uint32_t pd; // 密码
char name[20]; // 姓名
char sex; // 性别
uint16_t age; // 年龄
float score_c; // 语文
float score_m; // 数学
float score_e; // 英语
float score_s; // 总分
float score_a; // 平均
int8_t rank; // 排名
bool is_stop; // 是否禁用
}Student;
// 学生数组指针
extern Student* stu_a;
// 学生数组使用量
extern size_t stu_n;
// 学生登陆
int stu_login(const char* id_p,const char* pd_p);
// 进入学生子系统
void stu_enter(Student* stu_p);
// 显示学生信息
void stu_show(Student* stu_p);
// 显示学生成绩
void stu_show_score(Student* stu_p);
// 语文成绩排名
void stu_rank_c(void);
// 数学成绩排名
void stu_rank_m(void);
// 英语成绩排名
void stu_rank_e(void);
// 总分成绩排名
void stu_rank_s(void);
#endif//STUDENT_H
teacher.h
#ifndef TEACHER_H
#define TEACHER_H
#include "tools.h"
#define T_DATA_PATH "data/t_data.bin"
#define TD_DATA_PATH "data/td_data.bin"
#define TCH_MAX 10
typedef struct Teacher
{
uint32_t id; // 工号
uint32_t pd; // 密码
char name[20]; // 姓名
char sex; // 性别
uint16_t age; // 年龄
uint16_t age_w; // 工龄
bool is_stop; // 是否停用
}Teacher;
extern Teacher* tch_a;
extern size_t tch_n;
// 教师登陆
int tch_login(const char* id_p,const char* pd_p);
// 进入教师子系统
void tch_enter(Teacher* tch_p);
// 显示老师基本信息
void tch_show(Teacher* tch_p);
#endif//TEACHER_H
manager.h
#ifndef MANAGER_H
#define MANAGER_H
#include "tools.h"
#define M_DATA_PATH "data/m_data.bin"
#define MD_DATA_PATH "data/md_data.bin"
#define MGR_MAX 5
typedef struct Manager
{
uint32_t id; // 帐号
uint32_t pd; // 密码
bool is_stop; // 是否停用
}Manager;
// 管理员数组指针
extern Manager* mgr_a;
// 管理员数组使用量
extern size_t mgr_n;
// 管理员登陆
int mgr_login(const char* id_p,const char* pd_p);
// 进行管理员子系统
void mgr_enter(Manager* mgr_p);
// 显示管理员
void mgr_show(Manager* mgr_p);
#endif//MANAGER_H
admin.h
#ifndef ADMIN_H
#define ADMIN_H
// 登陆超级管理员
int admin_login (const char* id,const char* pd);
// 进入超级管理员子系统
void admin_enter (void);
#endif//ADMIN_H
admin.c
#include "admin.h"
#include "sams.h"
#include "manager.h"
#include "tools.h"
#include "status.h"
// 根据帐号查找管理员对象的下标
int admin_find_mgr(uint32_t id)
{
for(int i=0; i<mgr_n; i++)
{
if(id == mgr_a[i].id) return i;
}
return ERROR;
}
// 添加管理员
static void admin_add_mgr (void)
{
if(mgr_n >= MGR_MAX)
{
show_msg("*** 管理员已满,无法添加! ***",1);
return;
}
mgr_a[mgr_n].id = id_a[0]++;
mgr_a[mgr_n].pd = 111111;
mgr_a[mgr_n].is_stop = false;
pf("*** 管理员:%u 添加成功! ***",mgr_a[mgr_n].id);
show_msg("",1);
mgr_n++;
}
// 删除管理员
static void admin_del_mgr (void)
{
if(0 >= mgr_n)
{
show_msg("*** 系统内无管理员! ***",1);
return;
}
uint32_t id = 0;
pf("请输入要删除的管理员帐号:");
sf("%u",&id);
int index = admin_find_mgr(id);
if(ERROR == index)
{
show_msg("*** 不存在此帐号! ***",1);
return;
}
pf("请再次输入要删除的管理员帐号:");
sf("%u",&id);
if(id != mgr_a[index].id)
{
show_msg("*** 两次输入的帐号不符,删除失败! ***",1);
return;
}
memcpy(mgr_a+index,mgr_a+index+1,(mgr_n-index-1)*sizeof(Manager));
show_msg("*** 删除帐号成功! ***",1);
mgr_n--;
}
// 解锁管理员
static void admin_unlock_mgr (void)
{
if(0 >= mgr_n)
{
show_msg("*** 系统内无管理员! ***",1);
return;
}
uint32_t id = 0;
pf("请输入要解锁的管理员帐号:");
sf("%u",&id);
int index = admin_find_mgr(id);
if(ERROR == index)
{
show_msg("*** 不存在此帐号! ***",1);
return;
}
if(!mgr_a[index].is_stop)
{
show_msg("*** 此帐号未被锁! ***",1);
return;
}
mgr_a[index].is_stop = false;
show_msg("*** 解锁帐号成功! ***",1);
}
// 重置管理员密码
static void admin_reset_mgr (void)
{
if(0 >= mgr_n)
{
show_msg("*** 系统内无管理员! ***",1);
return;
}
uint32_t id = 0;
pf("请输入要重置的管理员帐号:");
sf("%u",&id);
int index = admin_find_mgr(id);
if(ERROR == index)
{
show_msg("*** 不存在此帐号! ***",1);
return;
}
pf("请再次输入要重置的管理员帐号:");
sf("%u",&id);
if(id != mgr_a[index].id)
{
show_msg("*** 两人些输入的帐号不符,重置失败! ***",1);
return;
}
mgr_a[index].pd = 111111;
show_msg("*** 重置密码成功! ***",1);
}
// 列出所有管理员
static void admin_list_mgr (void)
{
clear_src();
puts("******显示所有管理员******");
for(int i=0; i<mgr_n; i++)
{
mgr_show(mgr_a+i);
}
anykey_continue();
}
// 登陆超级管理员
int admin_login(const char* id,const char* pd)
{
if(NULL == id || NULL == pd) return PRNIL;
if(strcmp(id,"zhizhen")) return IDERR;
if(strcmp(pd,"zzxxwyz")) return PDERR;
admin_enter ();
return RIGHT;
}
// 进入超级管理员子系统
void admin_enter (void)
{
while(true)
{
clear_src();
puts("***超级管理员子系统***");
puts(" 0.添加管理员");
puts(" 1.删除管理员");
puts(" 2.重置管理员密码");
puts(" 3.解锁管理员");
puts(" 4.列出所有管理员");
puts(" 5.退出超级管理员");
puts("---------------------");
switch(get_cmd('0','5'))
{
case '0': admin_add_mgr(); break;
case '1': admin_del_mgr(); break;
case '2': admin_reset_mgr(); break;
case '3': admin_unlock_mgr(); break;
case '4': admin_list_mgr(); break;
case '5': return;
}
}
}
manager.c
#include <strings.h>
#include "manager.h"
#include "teacher.h"
#include "sams.h"
#include "status.h"
#include "tools.h"
// 管理员数组指针
Manager* mgr_a;
// 管理员数组使用量
size_t mgr_n;
int mgr_find_tch(uint32_t id)
{
for(int i=0; i<tch_n; i++)
{
if(id == tch_a[i].id) return i;
}
return ERROR;
}
// 添加一个教师
void mgr_add_one_tch(void)
{
bzero(tch_a+tch_n,sizeof(Teacher));
pf("请输入教师姓名:");
get_str(tch_a[tch_n].name,20);
pf("请输入教师性别:");
tch_a[tch_n].sex = get_sex();
pf("请输入教师出生年份:");
tch_a[tch_n].age = get_year();
pf("请输入教师入职年份:");
tch_a[tch_n].age_w = get_year();
tch_a[tch_n].id = id_a[1]++;
tch_a[tch_n].pd = 222222;
tch_n++;
show_msg("*** 添加教师成功! ***",1);
}
// 批量添加教师
void mgr_add_multi_tch(void)
{
char path[30] = {};
pf("请输入要导入的文件名:");
get_str(path,30);
FILE* frp = fopen(path,"r");
if(NULL == frp)
{
show_msg("*** 输入的路径有误! ***",1);
}
Teacher* tch_p = tch_a+tch_n;
size_t num_r = 0;
size_t num_s = 0;
while(tch_n<TCH_MAX)
{
bzero(tch_p,sizeof(Teacher));
if(!fscanf(frp,"%s %c %hu %hu\n",
tch_p->name,&tch_p->sex,&tch_p->age,&tch_p->age_w))
break;
num_r++;
if('f' != tch_p->sex && 'm' != tch_p->sex) continue;
if(1950 > tch_p->age || tch_p->age > get_current_year()-18) continue;
if(tch_p->age+18 > tch_p->age_w ||
tch_p->age_w > get_current_year()) continue;
tch_p->id = id_a[1]++;
tch_p->pd = 222222;
tch_p->is_stop = false;
tch_show(tch_p);
tch_n++;
tch_p++;
num_s++;
}
printf("*** 共读取到%u条数据,成功添加%u位教师! ***",num_r,num_s);
anykey_continue();
}
// 添加教师
void mgr_add_tch(void)
{
if(tch_n >= TCH_MAX)
{
show_msg("*** 教师已满,无法添加! ***",1);
return;
}
clear_src();
puts("***添加教师***");
puts(" 0.单个添加");
puts(" 1.批量添加");
puts("-------------");
switch(get_cmd('0','1'))
{
case '0': mgr_add_one_tch(); break;
case '1': mgr_add_multi_tch(); break;
}
}
// 删除教师
void mgr_del_tch(void)
{
if(0 >= tch_n)
{
show_msg("*** 系统内无教师! ***",1);
return;
}
uint32_t id = 0;
pf("请输入要删除的教师帐号:");
sf("%u",&id);
int index = mgr_find_tch(id);
if(ERROR == index)
{
show_msg("*** 不存在此帐号! ***",1);
return;
}
pf("请再次输入要删除的管理员帐号:");
sf("%u",&id);
if(id != tch_a[index].id)
{
show_msg("*** 两次输入的帐号不符,删除失败! ***",1);
return;
}
FILE* fap = fopen(TD_DATA_PATH,"a");
fwrite(tch_a+index,sizeof(Teacher),1,fap);
fclose(fap);
memcpy(tch_a+index,tch_a+index+1,(tch_n-index-1)*sizeof(Teacher));
show_msg("*** 删除帐号成功! ***",1);
tch_n--;
}
// 修改教师信息
void mgr_mod_tch(void)
{
uint32_t id;
pf("请输入要修改的教师帐号:");
sf("%u",&id);
int index = mgr_find_tch(id);
if(ERROR == index)
{
show_msg("*** 不存在此帐号! ***",1);
return;
}
while(true)
{
clear_src();
tch_show(tch_a+index);
puts("***请选择要修改的教师信息***");
puts(" 0.修改教师姓名");
puts(" 1.修改教师性别");
puts(" 2.修改教师出生年份");
puts(" 3.修改教师入职年份");
puts(" 4.返回上一级");
puts("-------------------------");
switch(get_cmd('0','4'))
{
case '0':
pf("请输入教师姓名:");
get_str(tch_a[index].name,20); break;
case '1':
pf("请输入教师性别:");
tch_a[index].sex = get_sex(); break;
case '2':
pf("请输入教师出生年份:");
tch_a[index].age = get_year(); break;
case '3':
pf("请输入教师入职年份:");
tch_a[index].age_w = get_year(); break;
case '4': return;
}
show_msg("*** 修改成功! ***",1);
}
}
// 重置教师密码
void mgr_reset_tch(void)
{
if(0 >= mgr_n)
{
show_msg("*** 系统内无教师! ***",1);
return;
}
uint32_t id = 0;
pf("请输入要重置的教师帐号:");
sf("%u",&id);
int index = mgr_find_tch(id);
if(ERROR == index)
{
show_msg("*** 不存在此帐号! ***",1);
return;
}
pf("请再次输入要重置的教师帐号:");
sf("%u",&id);
if(id != tch_a[index].id)
{
show_msg("*** 两人些输入的帐号不符,重置失败! ***",1);
return;
}
tch_a[index].pd = 222222;
show_msg("*** 重置密码成功! ***",1);
}
// 解锁教师帐号
void mgr_nulock_tch(void)
{
if(0 >= tch_n)
{
show_msg("*** 系统内无教师! ***",1);
return;
}
uint32_t id = 0;
pf("请输入要解锁的教师帐号:");
sf("%u",&id);
int index = mgr_find_tch(id);
if(ERROR == index)
{
show_msg("*** 不存在此帐号! ***",1);
return;
}if(!tch_a[index].is_stop)
{
show_msg("*** 此帐号未被锁! ***",1);
return;
}
tch_a[index].is_stop = false;
show_msg("*** 解锁帐号成功! ***",1);
}
// 查询教师基本信息
void mgr_query_tch(void)
{
char name[20] = {};
pf("请输入要查询的老师姓名:");
get_str(name,20);
bool flag = true;
for(int i=0; i<tch_n; i++)
{
if(!strcmp(name,tch_a[i].name))
{
tch_show(tch_a+i);
flag = false;
}
}
flag ? show_msg("*** 查无此人! ***",1) : anykey_continue();
}
// 显示所有在职教师
void mgr_job_tch(void)
{
clear_src();
puts("******所有在职教师******");
for(int i=0; i<tch_n; i++)
{
tch_show(tch_a+i);
}
anykey_continue();
}
// 显示所有离职教师
void mgr_quit_tch(void)
{
FILE* frp = fopen(TD_DATA_PATH,"r");
if(NULL == frp)
{
show_msg("*** 斩无离职教师! ***",1);
return;
}
clear_src();
puts("******所有离职教师******");
Teacher tch;
while(fread(&tch,sizeof(tch),1,frp)) tch_show(&tch);
fclose(frp);
anykey_continue();
}
// 修改管理员登陆密码
void mgr_mod_pd(Manager* mgr_p)
{
pf("请输入新密码:");
char pd[20] = {};
get_passwd(pd,20,true);
char re_pd[20] = {};
pf("请再次输入新密码:");
get_passwd(re_pd,20,true);
if(strcmp(pd,re_pd))
{
show_msg("*** 两次输入密码不一致,修改密码失败! ***",1);
return;
}
mgr_p->pd = atoi(pd);
show_msg("*** 修改密码成功! ***",1);
}
// 管理员登陆
int mgr_login(const char* id_p,const char* pd_p)
{
if(NULL == id_p || NULL == pd_p) return PRNIL;
uint32_t id = atoi(id_p);
uint32_t pd = atoi(pd_p);
int i = 0;
for(; i<mgr_n; i++)
{
if(id == mgr_a[i].id) break;
}
if(i == mgr_n) return IDERR;
if(mgr_a[i].is_stop)
{
show_msg("***此帐号被锁,请联系超级管理员解锁!***",1);
return RIGHT;
}
if(pd != mgr_a[i].pd) return PDERR;
mgr_enter(mgr_a+i);
return RIGHT;
}
// 进行管理员子系统
void mgr_enter(Manager* mgr_p)
{
while(true)
{
clear_src();
pf("管理员:%u\n",mgr_p->id);
puts("***进入管理员子系统***");
puts(" 0.添加教师");
puts(" 1.删除教师");
puts(" 2.修改教师信息");
puts(" 3.重置教师密码");
puts(" 4.解锁教师帐号");
puts(" 5.查询教师基本信息");
puts(" 6.显示所有在职教师");
puts(" 7.显示所有离职教师");
puts(" 8.修改管理员密码");
puts(" 9.退出管理员子系统");
puts("---------------------");
switch(get_cmd('0','9'))
{
case '0': mgr_add_tch(); break;
case '1': mgr_del_tch(); break;
case '2': mgr_mod_tch(); break;
case '3': mgr_reset_tch(); break;
case '4': mgr_nulock_tch(); break;
case '5': mgr_query_tch(); break;
case '6': mgr_job_tch(); break;
case '7': mgr_quit_tch(); break;
case '8': mgr_mod_pd(mgr_p); break;
case '9': return;
}
}
}
// 显示管理员
void mgr_show(Manager* mgr_p)
{
pf("帐号:%u 状态:%s\n",mgr_p->id,mgr_p->is_stop?"锁定":"正常");
}
teacher.c
#include <strings.h>
#include "sams.h"
#include "teacher.h"
#include "student.h"
#include "status.h"
Teacher* tch_a;
size_t tch_n;
int tch_find_stu(uint32_t id)
{
for(int i=0; i<stu_n; i++)
{
if(id == stu_a[i].id) return i;
}
return ERROR;
}
// 单个添加学生
void tch_add_one_stu()
{
bzero(stu_a+stu_n,sizeof(Student));
pf("请输入学生姓名:");
get_str(stu_a[stu_n].name,20);
pf("请输入学生性别:");
stu_a[stu_n].sex = get_sex();
pf("请输入学生出生年份:");
stu_a[stu_n].age = get_year();
stu_a[stu_n].id = id_a[2]++;
stu_a[stu_n].pd = 222222;
stu_n++;
show_msg("*** 添加学生成功! ***",1);
}
// 批量添加学生
void tch_add_multi_stu()
{
char path[30] = {};
pf("请输入要导入的文件名:");
get_str(path,30);
FILE* frp = fopen(path,"r");
if(NULL == frp)
{
show_msg("*** 输入的路径有误! ***",1);
}
Student* stu_p = stu_a+stu_n;
size_t num_r = 0;
size_t num_s = 0;
while(stu_n<STU_MAX)
{
bzero(stu_p,sizeof(Student));
if(!fscanf(frp,"%s %c %hu\n",
stu_p->name,&stu_p->sex,&stu_p->age))
break;
num_r++;
if('f' != stu_p->sex && 'm' != stu_p->sex) continue;
if(1950 > stu_p->age || stu_p->age > get_current_year()-5) continue;
stu_p->id = id_a[1]++;
stu_p->pd = 333333;
stu_show(stu_p);
stu_n++;
stu_p++;
num_s++;
}
printf("*** 共读取到%u条数据,成功添加%u位教师! ***",num_r,num_s);
anykey_continue();
}
// 添加学生
void tch_add_stu(void)
{
if(stu_n >= STU_MAX)
{
show_msg("*** 学生已满,无法添加! ***",1);
return;
}
clear_src();
puts("***添加学生***");
puts(" 0.单个添加");
puts(" 1.批量添加");
puts("-------------");
switch(get_cmd('0','1'))
{
case '0': tch_add_one_stu(); break;
case '1': tch_add_multi_stu(); break;
}
}
// 删除学生
void tch_del_stu(void)
{
if(0 >= stu_n)
{
show_msg("*** 系统内无学生! ***",1);
return;
}
uint32_t id = 0;
pf("请输入要删除的学生帐号:");
sf("%u",&id);
int index = tch_find_stu(id);
if(ERROR == index)
{
show_msg("*** 不存在此帐号! ***",1);
return;
}
pf("请再次输入要删除的管理员帐号:");
sf("%u",&id);
if(id != stu_a[index].id)
{
show_msg("*** 两次输入的帐号不符,删除失败! ***",1);
return;
}
FILE* fap = fopen(SD_DATA_PATH,"a");
fwrite(stu_a+index,sizeof(Student),1,fap);
fclose(fap);
memcpy(stu_a+index,stu_a+index+1,(stu_n-index-1)*sizeof(Student));
show_msg("*** 删除帐号成功! ***",1);
stu_n--;
}
// 修改学生信息
void tch_mod_stu(void)
{
uint32_t id;
pf("请输入要修改的学生帐号:");
sf("%u",&id);
int index = tch_find_stu(id);
if(ERROR == index)
{
show_msg("*** 不存在此帐号! ***",1);
return;
}
while(true)
{
clear_src();
stu_show(stu_a+index);
puts("***请选择要修改的学生信息***");
puts(" 0.修改学生姓名");
puts(" 1.修改学生性别");
puts(" 2.修改学生出生年份");
puts(" 3.返回上一级");
puts("-------------------------");
switch(get_cmd('0','4'))
{
case '0':
pf("请输入学生姓名:");
get_str(stu_a[index].name,20); break;
case '1':
pf("请输入学生性别:");
stu_a[index].sex = get_sex(); break;
case '2':
pf("请输入学生出生年份:");
stu_a[index].age = get_year(); break;
case '3': return;
}
show_msg("*** 修改成功! ***",1);
}
}
// 重置学生密码
void tch_reset_stu(void)
{
if(0 >= stu_n)
{
show_msg("*** 系统内无学生! ***",1);
return;
}
uint32_t id = 0;
pf("请输入要重置的学生帐号:");
sf("%u",&id);
int index = tch_find_stu(id);
if(ERROR == index)
{
show_msg("*** 不存在此帐号! ***",1);
return;
}
pf("请再次输入要重置的教师帐号:");
sf("%u",&id);
if(id != stu_a[index].id)
{
show_msg("*** 两人些输入的帐号不符,重置失败! ***",1);
return;
}
stu_a[index].pd = 333333;
show_msg("*** 重置密码成功! ***",1);
}
// 解锁学生帐号
void tch_nulock_stu(void)
{
if(0 >= stu_n)
{
show_msg("*** 系统内无学生! ***",1);
return;
}
uint32_t id = 0;
pf("请输入要解锁的学生帐号:");
sf("%u",&id);
int index = tch_find_stu(id);
if(ERROR == index)
{
show_msg("*** 不存在此帐号! ***",1);
return;
}
if(!stu_a[index].is_stop)
{
show_msg("*** 此帐号未被锁! ***",1);
return;
}
stu_a[index].is_stop = false;
show_msg("*** 解锁帐号成功! ***",1);
}
// 查询学生信息
void tch_query_stu(void)
{
char name[20] = {};
pf("请输入要查询的学生姓名:");
get_str(name,20);
bool flag = true;
for(int i=0; i<stu_n; i++)
{
if(!strcmp(name,stu_a[i].name))
{
stu_show(stu_a+i);
flag = false;
}
}
flag ? show_msg("*** 查无此人! ***",1) : anykey_continue();
}
// 显示在读学生
void tch_inshl_stu(void)
{
if(0 >= stu_n)
{
show_msg("*** 系统内无学生! ***",1);
return;
}
clear_src();
puts("******在读学生******");
for(int i=0; i<stu_n; i++)
{
stu_show(stu_a+i);
}
anykey_continue();
}
// 显示退学学生
void tch_drop_stu(void)
{
FILE* frp = fopen(SD_DATA_PATH,"r");
if(NULL == frp)
{
show_msg("*** 斩无退学学生! ***",1);
return;
}
clear_src();
puts("******所有退学学生******");
Student stu;
while(fread(&stu,sizeof(stu),1,frp)) stu_show(&stu);
fclose(frp);
anykey_continue();
}
// 录入单个学生的成绩
void tch_input_one_stu()
{
if(0 >= stu_n)
{
show_msg("*** 系统内无学生! ***",1);
return;
}
uint32_t id = 0;
pf("请输入要修改成绩的学生帐号:");
sf("%u",&id);
int index = tch_find_stu(id);
if(ERROR == index)
{
show_msg("*** 不存在此帐号! ***",1);
return;
}
pf("请输入语文,数学,英语成绩:");
float sc = 0 , sm = 0 , se = 0;
sf("%f%f%f",&sc,&sm,&se);
if(sc < 0 || sc > 100 || sm < 0 || sm > 100 || se < 0 || se > 100)
{
show_msg("*** 输入的成绩有误! ***",1);
return;
}
stu_a[index].score_c = sc;
stu_a[index].score_m = sm;
stu_a[index].score_e = se;
stu_a[index].score_s = sc + sm + se;
stu_a[index].score_a = stu_a[index].score_s /3;
stu_show_score(stu_a+index);
show_msg("*** 录入成功! ***",1);
}
void tch_input_multi_stu()
{
char path[30] = {};
pf("请输入要导入的文件名:");
get_str(path,30);
FILE* frp = fopen(path,"r");
if(NULL == frp)
{
show_msg("*** 输入的路径有误! ***",1);
}
size_t num_r = 0;
size_t num_s = 0;
uint32_t id = 0;
int index = 0;
float sc = 0 , sm = 0 , se = 0;
while(fscanf(frp,"%u %f %f %f\n",&id,&sc,&sm,&se))
{
num_r++;
if(ERROR == (index = tch_find_stu(id))) continue;
if(sc < 0 || sc > 100 || sm < 0 || sm > 100 || se < 0 || se > 100)
continue;
stu_a[index].score_c = sc;
stu_a[index].score_m = sm;
stu_a[index].score_e = se;
stu_a[index].score_s = sc + sm + se;
stu_a[index].score_a = stu_a[index].score_s /3;
stu_show_score(stu_a+index);
num_s++;
}
printf("*** 共读取到%u条数据,成功添加%u位教师! ***",num_r,num_s);
anykey_continue();
}
// 录入学生成绩
void tch_input_scr(void)
{
if(0 >= stu_n)
{
show_msg("*** 系统内无学生! ***",1);
return;
}
clear_src();
puts("***添加学生***");
puts(" 0.单个录入");
puts(" 1.批量录入");
puts("-------------");
switch(get_cmd('0','1'))
{
case '0': tch_input_one_stu(); break;
case '1': tch_input_multi_stu(); break;
}
}
// 修改学生成绩
void tch_mod_scr(void)
{
if(0 >= stu_n)
{
show_msg("*** 系统内无学生! ***",1);
return;
}
uint32_t id = 0;
pf("请输入要修改成绩的学生帐号:");
sf("%u",&id);
int index = tch_find_stu(id);
if(ERROR == index)
{
show_msg("*** 不存在此帐号! ***",1);
return;
}
while(true)
{
clear_src();
stu_show_score(stu_a+index);
puts("***请选择要修改的成绩的科目**");
puts(" 0.修改语文成绩");
puts(" 1.修改数学成绩");
puts(" 2.修改英语成绩");
puts(" 3.返回上一级");
puts("-------------------------");
switch(get_cmd('0','3'))
{
case '0':
pf("请输入语文成绩:");
if(!get_score(&stu_a[index].score_c)) continue;
break;
case '1':
pf("请输入数学成绩:");
if(!get_score(&stu_a[index].score_m)) continue;
break;
case '2':
pf("请输入英语成绩:");
if(!get_score(&stu_a[index].score_e)) continue;
break;
case '3': return;
}
stu_a[index].score_s = stu_a[index].score_c +
stu_a[index].score_m + stu_a[index].score_e;
stu_a[index].score_a = stu_a[index].score_s /3;
show_msg("*** 修改成功! ***",1);
}
}
// 查询学生成绩
void tch_query_scr(void)
{
char name[20] = {};
pf("请输入要查询的学生姓名:");
get_str(name,20);
bool flag = true;
for(int i=0; i<stu_n; i++)
{
if(!strcmp(name,stu_a[i].name))
{
stu_show_score(stu_a+i);
flag = false;
}
}
flag ? show_msg("*** 查无此人! ***",1) : anykey_continue();
}
// 各科成绩排名
void tch_rank_scr(void)
{
while(true)
{
clear_src();
puts("***查看各科成绩排名***");
puts(" 0.语文成绩排名");
puts(" 1.数学成绩排名");
puts(" 2.英语成绩排名");
puts(" 3.总分成绩排名");
puts(" 4.退出");
puts("------------------");
switch(get_cmd('0','4'))
{
case '0': stu_rank_c(); break;
case '1': stu_rank_m(); break;
case '2': stu_rank_e(); break;
case '3': stu_rank_s(); break;
case '4': return;
}
for(int i=0; i<stu_n; i++)
{
stu_show_score(stu_a+i);
}
anykey_continue();
}
}
// 修改登陆密码
void tch_mod_pd(Teacher* tch_p)
{
pf("请输入新密码:");
char pd[20] = {};
get_passwd(pd,20,true);
char re_pd[20] = {};
pf("请再次输入新密码:");
get_passwd(re_pd,20,true);
if(strcmp(pd,re_pd))
{
show_msg("*** 两次输入密码不一致,修改密码失败! ***",1);
return;
}
tch_p->pd = atoi(pd);
show_msg("*** 修改密码成功! ***",1);
}
// 教师登陆
int tch_login(const char* id_p,const char* pd_p)
{
uint32_t id = atoi(id_p);
uint32_t pd = atoi(pd_p);
int i = 0;
for(; i<tch_n; i++)
{
if(id == tch_a[i].id) break;
}
if(i == tch_n) return IDERR;
if(tch_a[i].is_stop)
{
show_msg("***此帐号被锁,请联系管理员解锁!***",1);
return RIGHT;
}
if(pd != tch_a[i].pd) return PDERR;
tch_enter(tch_a+i);
return RIGHT;
}
// 进入教师子系统
void tch_enter(Teacher* tch_p)
{
while(true)
{
clear_src();
pf("教师:%u 姓名:%s\n",tch_p->id,tch_p->name);
puts("***进入教师子系统***");
puts(" 0.添加学生");
puts(" 1.删除学生");
puts(" 2.修改学生信息");
puts(" 3.重置学生密码");
puts(" 4.解锁学生帐号");
puts(" 5.查询学生信息");
puts(" 6.显示在读学生");
puts(" 7.显示退学学生");
puts(" 8.录入学生成绩");
puts(" 9.修改学生成绩");
puts(" a.查询学生成绩");
puts(" b.各科成绩排名");
puts(" c.修改登陆密码");
puts(" d.退出教师子系统");
puts("------------------");
switch(get_cmd('0','d'))
{
case '0': tch_add_stu(); break;
case '1': tch_del_stu(); break;
case '2': tch_mod_stu(); break;
case '3': tch_reset_stu(); break;
case '4': tch_nulock_stu(); break;
case '5': tch_query_stu(); break;
case '6': tch_inshl_stu(); break;
case '7': tch_drop_stu(); break;
case '8': tch_input_scr(); break;
case '9': tch_mod_scr(); break;
case 'a': tch_query_scr(); break;
case 'b': tch_rank_scr(); break;
case 'c': tch_mod_pd(tch_p); break;
case 'd': return;
}
}
}
// 显示老师基本信息
void tch_show(Teacher* tch_p)
{
pf("帐号:%u 姓名:%s 性别:%s 年龄:%hhu 工龄:%hhu 状态:%s\n",
tch_p->id,tch_p->name,'m' == tch_p->sex ? "男" : "女",
get_current_year() - tch_p->age,get_current_year() - tch_p->age_w,
tch_p->is_stop ? "锁定" : "正常");
}
student.c
#include "student.h"
#include "status.h"
// 学生数组指针
Student* stu_a;
// 学生数组使用量
size_t stu_n;
// 语言成绩比较
int stu_cmp_c(const void* stu_p1,const void* stu_p2)
{
return ((Student*)stu_p1)->score_c < ((Student*)stu_p2)->score_c;
}
// 数学成绩比较
int stu_cmp_m(const void* stu_p1,const void* stu_p2)
{
return ((Student*)stu_p1)->score_m < ((Student*)stu_p2)->score_m;
}
// 英语成绩比较
int stu_cmp_e(const void* stu_p1,const void* stu_p2)
{
return ((Student*)stu_p1)->score_e < ((Student*)stu_p2)->score_e;
}
// 总分成绩比较
int stu_cmp_s(const void* stu_p1,const void* stu_p2)
{
return ((Student*)stu_p1)->score_s < ((Student*)stu_p2)->score_s;
}
// 学生登陆
int stu_login(const char* id_p,const char* pd_p)
{
uint32_t id = atoi(id_p);
uint32_t pd = atoi(pd_p);
int i = 0;
for(; i<stu_n; i++)
{
if(id == stu_a[i].id) break;
}
if(i == stu_n) return IDERR;
if(stu_a[i].is_stop)
{
show_msg("***此帐号被锁,请联系教师解锁!***",1);
return RIGHT;
}
if(pd != stu_a[i].pd) return PDERR;
stu_enter(stu_a+i);
return RIGHT;
}
// 语文成绩排名
void stu_rank_c(void)
{
qsort(stu_a,stu_n,sizeof(Student),stu_cmp_c);
for(int i=0; i<stu_n; i++)
stu_a[i].rank = i+1;
}
// 数学成绩排名
void stu_rank_m(void)
{
qsort(stu_a,stu_n,sizeof(Student),stu_cmp_m);
for(int i=0; i<stu_n; i++)
stu_a[i].rank = i+1;
}
// 英语成绩排名
void stu_rank_e(void)
{
qsort(stu_a,stu_n,sizeof(Student),stu_cmp_e);
for(int i=0; i<stu_n; i++)
stu_a[i].rank = i+1;
}
// 总分成绩排名
void stu_rank_s(void)
{
qsort(stu_a,stu_n,sizeof(Student),stu_cmp_s);
for(int i=0; i<stu_n; i++)
stu_a[i].rank = i+1;
}
// 修改登陆密码
void stu_mod_pd(Student* stu_p)
{
pf("请输入新密码:");
char pd[20] = {};
get_passwd(pd,20,true);
char re_pd[20] = {};
pf("请再次输入新密码:");
get_passwd(re_pd,20,true);
if(strcmp(pd,re_pd))
{
show_msg("*** 两次输入密码不一致,修改密码失败! ***",1);
return;
}
stu_p->pd = atoi(pd);
show_msg("*** 修改密码成功! ***",1);
}
// 进入学生子系统
void stu_enter(Student* stu_p)
{
while(true)
{
clear_src();
puts("***进入学生子系统***");
puts(" 0.语文成绩排名");
puts(" 1.数学成绩排名");
puts(" 2.英语成绩排名");
puts(" 3.总分成绩排名");
puts(" 4.修改登陆密码");
puts(" 5.退出学生子系统");
puts("------------------");
switch(get_cmd('0','5'))
{
case '0':
stu_rank_c();
pf("语文成绩:%g",stu_p->score_c);
break;
case '1':
stu_rank_m();
pf("数学成绩:%g",stu_p->score_m);
break;
case '2':
stu_rank_e();
pf("英语成绩:%g",stu_p->score_e);
break;
case '3':
stu_rank_s();
pf("总分成绩:%g",stu_p->score_s);
break;
case '4': stu_mod_pd(stu_p); continue;
case '5': return;
}
pf(" 排名第%u \n",stu_p->rank);
anykey_continue();
}
}
// 显示学生信息
void stu_show(Student* stu_p)
{
pf("学号:%u 姓名:%s 性别:%s 年龄:%hu\n",stu_p->id,stu_p->name,
'm' == stu_p->sex ? "男" : "女",get_current_year() - stu_p->age);
}
// 显示学生成绩
void stu_show_score(Student* stu_p)
{
pf("学号:%u 姓名:%s 语文:%g 数学%g 英语:%g 平均%g 总分%g\n",
stu_p->id,stu_p->name,stu_p->score_c,stu_p->score_m,
stu_p->score_e,stu_p->score_a,stu_p->score_s);
}
tools.c
#include <get_keyboard.h>
#include "tools.h"
#include "status.h"
// 获取当前年份
uint16_t get_current_year(void)
{
time_t sec = time(NULL);
struct tm* gmt = gmtime(&sec);
return 1900 + gmt->tm_year;
}
// 清理输入缓冲区
static void clear_stdin(void)
{
stdin->_IO_read_ptr = stdin->_IO_read_end;
}
// 清理屏幕
void clear_src(void)
{
system("clear");
}
// 任意键继续
void anykey_continue(void)
{
pf("按任意键继续...");
get_keyboard();
pf("\n");
}
// 显示提示信息
void show_msg(const char* msg,time_t t)
{
pf("%s\n",msg);
sleep(t);
}
// 获取性别
char get_sex(void)
{
while(true)
{
char sex = get_keyboard();
if('f' == sex || 'm' == sex)
{
pf("%c\n",sex);
return sex;
}
}
}
// 获取年份
uint16_t get_year(void)
{
while(true)
{
uint16_t year = 0;
for(int i=0; i<4; i++)
{
year *= 10;
char ch = get_keyboard();
pf("%c",ch);
year += ch-'0';
}
if(year > 1950 && year < get_current_year())
{
pf("\n");
return year;
}
pf("\b\b\b\b \b\b\b\b");
}
}
// 获取成绩
bool get_score(float* score_p)
{
float score = 0;
sf("%f",&score);
if(score < 0 || score > 100)
{
show_msg("*** 输入的数据有误,请重新输入! ***",1);
return false;
}
*score_p = score;
return true;
}
// 从键盘获取密码
char* get_passwd(char* pd,size_t hope_len,bool is_show)
{
if(NULL == pd) return NULL;
size_t index = 0;
while(index < hope_len-1)
{
int32_t key_val = get_keyboard();
if(KEY_BACKSPACE == key_val)
{
if(index > 0)
{
index--;
is_show ? pf("\b \b") : nil;
}
}
else if(KEY_ENTER == key_val)
{
break;
}
else
{
pd[index++] = key_val;
is_show ? pf("*") : nil;
}
}
pd[index] = '\0';
pf("\n");
clear_stdin();
return pd;
}
// 从键盘获取指令
char get_cmd(char begin_cmd,char end_cmd)
{
if( begin_cmd > end_cmd) return SPILL;
pf(" 请输入指令:");
while(true)
{
char key_val = get_keyboard() ;
if(key_val >= begin_cmd && key_val <= end_cmd)
{
pf("%c\n",key_val);
return key_val;
}
}
}
// 从键盘获取字符串
char* get_str(char* str,size_t hope_len)
{
if(NULL == str || 0 == hope_len) return NULL;
size_t index = 0;
while(index < hope_len-1)
{
int8_t key_val = get_keyboard();
if(KEY_ESC == key_val) return NULL;
if(KEY_ENTER == key_val) break;
if(KEY_BACKSPACE == key_val)
{
if(index > 0)
{
pf("\b \b");
index--;
}
continue;
}
pf("%c",key_val);
str[index++] = key_val;
}
str[index] = '\0';
pf("\n");
clear_stdin();
return str;
}
// 从文件加载数据
int load_data (const char* path,void* ptr,size_t node_size)
{
if(NULL == path || NULL == ptr) return PRNIL;
FILE* frp = fopen (path,"r");
if(NULL == frp) return ERROR;
size_t cnt = 0,num = 0;
while ((cnt = fread(ptr+num*node_size,node_size,1,frp))) num += cnt;
fclose(frp);
return num;
}
// 保存数据到文件
int save_data (const char* path,const void* ptr,size_t node_size,size_t num)
{
if(NULL == path || NULL == ptr) return PRNIL;
FILE* fwp = fopen(path,"w");
if(NULL == fwp) return ERROR;
size_t cnt = fwrite(ptr,node_size,num,fwp);
fclose(fwp);
return cnt;
}
sams_main.c
#include "sams.h"
int main(void)
{
// 申请内存加载数据
sams_init ();
// 开始运行管理系统
sams_start ();
// 保存数据释放内存
sams_exit ();
}
sams.c
#include <malloc.h>
#include "admin.h"
#include "manager.h"
#include "teacher.h"
#include "student.h"
#include "sams.h"
#include "tools.h"
#include "status.h"
uint32_t* id_a;
static int sams_login(const char* id,const char* pd)
{
Status ret = admin_login(id,pd);
if(RIGHT == ret) return RIGHT;
if(PDERR == ret) return IDERR;
ret = mgr_login(id,pd);
if(IDERR != ret) return ret;
ret = tch_login(id,pd);
if(IDERR != ret) return ret;
ret = stu_login(id,pd);
return ret;
}
// 锁定帐号
static void sams_lock(const char* id_p)
{
uint32_t id = atoi(id_p);
for(int i=0; i<mgr_n; i++)
{
if(id == mgr_a[i].id)
{
pf("---------------\n");
mgr_a[i].is_stop = true;
return;
}
}
for(int i=0; i<tch_n; i++)
{
if(id == tch_a[i].id)
{
tch_a[i].is_stop = true;
return;
}
}
for(int i=0; i<stu_n; i++)
{
if(id == stu_a[i].id)
{
stu_a[i].is_stop = true;
return;
}
}
}
// 申请内存加载数据
void sams_init(void)
{
mgr_a = malloc(sizeof(Manager)*MGR_MAX);
mgr_n = load_data(M_DATA_PATH,mgr_a,sizeof(Manager));
tch_a = malloc(sizeof(Teacher)*TCH_MAX);
tch_n = load_data(T_DATA_PATH,tch_a,sizeof(Teacher));
stu_a = malloc(sizeof(Student)*STU_MAX);
stu_n = load_data(S_DATA_PATH,stu_a,sizeof(Student));
id_a = malloc(sizeof(uint32_t)*3);
load_data(ID_PATH,id_a,sizeof(uint32_t));
}
// 开始运行管理系统
void sams_start(void)
{
char id[20] = {};
char pd[20] = {};
char prev_id[20] = {};
size_t login_num = 3;
while(true)
{
clear_src();
pf("***欢迎使用指针成绩管理系统***\n");
pf("请输入帐号:");
if(NULL == get_str(id,20)) break;
pf("请输入密码:");
get_passwd(pd,20,true);
login_num--;
switch(sams_login(id,pd))
{
case RIGHT:
login_num = 3; break;
case IDERR:
show_msg("*** 帐号或密码错误,请重新登陆! ***",1);
break;
case PDERR:
if(0 == login_num)
{
sams_lock(id);
login_num = 3;
show_msg("*** 此帐号被锁,请联系上级解锁! ***",1);
break;
}
if(strcmp(id,prev_id))
{
strcpy(prev_id,id);
login_num = 2;
}
pf("密码错误,你还有%d次机会",login_num);
show_msg("",1);
}
}
}
// 保存数据释放内存
void sams_exit(void)
{
pf("\n已退出管理系统\n");
save_data(M_DATA_PATH,mgr_a,sizeof(Manager),mgr_n);
free(mgr_a);
save_data(T_DATA_PATH,tch_a,sizeof(Teacher),tch_n);
free(tch_a);
save_data(S_DATA_PATH,stu_a,sizeof(Student),stu_n);
free(stu_a);
}