学生管理系统的文件总共有 5 个: main.c、stuSystem.h、stuSystem.c、ArrayLib.h 和 ArrayLib.c
其中 ArrayLib.h 和 ArrayLib.c 为程序所用到的数据存储方式:动态数组。具体代码在我的另一篇博客上:C语言实现自己的动态数组库,进去里面把代码拷贝下来就得到 ArrayLib.h 和 ArrayLib.c 这两个代码文件了。
剩下的三个代码文件:main.c、stuSystem.h、stuSystem.c 就在这篇博客中,分别拷贝下来。然后把这 5 个代码文件放在同一个地方(相同的文件夹下),然后进去这个文件夹中,运行编译命令:
gcc main.c -o output |
然后就得到了可执行文件 output,运行它就可以了!
main.c
/***************************************************
* 文件名:main.c
* 文件描述:学生管理系统框架 需要配合stuSystem.c
* stuSystem.h 以及动态数组库函数一起编译
* 编辑人:王廷云
* 编辑日期:2017-10-10
* 修改日期:2018-2-10
****************************************************/
#include
#include
#include "stuSystem.h"
#include "arrayLib.h"
int main(void)
{
int index = 0; // 菜单功能索引
int key; // 用户按键输入
FILE *fp;
Array_t *ar;
char *mainMenu[] = { // 菜单选项
"1.注册学生信息",
"2.查询学生信息",
"3.删除学生信息",
"4.退出管理系统",
};
int NR = sizeof(mainMenu)/sizeof(mainMenu[0]);// 菜单选项数
/* 打开文件获取数据 */
fp = fopen("./stuInfo.db", "r");
if (NULL == fp) // 文件不存在则创建
{
fp = fopen("./stuInfo.db", "w+");
}
if (fread(&key, 1, 1, fp) != 1) // 如果文件为空
{
ar = initArray(sizeof(Student_t));
}
else // 文件不为空
{
fclose(fp); // 先关闭打开的文件
ar = loadArrayFromFile("./stuInfo.db"); // 从文件中加载数据
if (ar == NULL)
{
fprintf(stderr,"load info failed.\n");
return -2;
}
}
/* 初始化学生管理系统 */
initStuSysem();
while (1)
{
/* 显示学生管理系统主菜单 */
showMenu(mainMenu,NR,index);
/* 获取用户输入 */
key = getInput();
/* 根据用户输入进行功能选择 */
switch (key)
{
/* 上移 */
case UP : index -= 1;
if (index == -1) index = NR-1; break;
/* 下移 */
case DOWN : index = (index+1)%NR; break;
/* 功能确认 */
case ENTER :
switch (index)
{
/* 注册学生信息 */
case 0: addStuInfo(ar); break;
/* 查询学生信息 */
case 1: queryStuInfo(ar); break;
/* 删除学生信息 */
case 2: deleteStuInfo(ar); break;
/* 退出学生系统 */
case 3: exitStuSystem(ar); break;
} break;
/* 其它按键 */
default : continue;
}
}
return 0;
}
stuSystem.h
/********************************************
* 文件名: stuSystem.h
* 文件描述: 学生管理系统工程头文件,包含了该工程所有
* 需要用到的枚举,结构体定义,方法函数的声明
* 编辑人:王廷云
* 编辑日期:2017-10-1
* 修改日期:2018-1-10
********************************************/
#ifndef _STUSYSTEM_H_
#define _STUSYSTEM_H_
#include "arrayLib.h"
/* 用户输入按键枚举 */
enum Key_e {
UP, /* 上键 */
DOWN, /* 下键 */
RIGHT, /* 右键 */
LEFT, /* 左键 */
ENTER, /* 确认键 */
YES, /* 肯定键 */
NO, /* 取消键 */
QUIT, /* 退出键 */
UNKNOW, /* 其它未知键 */
};
/* 学生结构体封装 */
typedef struct {
int id; // 学生学号:id
char name[10]; // 学生姓名
float grade; // 学生成绩
} Student_t;
/* 初始化学生管理系统 */
void initStuSysem(void);
/* 显示功能选择菜单 */
void showMenu(char *menu[], int NR, int index);
/* 注册学成信息 */
void addStuInfo(Array_t *ar);
/* 查询学生信息 */
void queryStuInfo(Array_t *ar);
/* 查询所有学生信息 */
void showAllStuInfo(Array_t *ar);
/* 根据学生学号显示信息 */
void showStuInfoById(Array_t *ar);
/* 根据学生姓名显示信息 */
void showStuInfoByName(Array_t *ar);
/* 根据学生成绩显示信息 */
void showStuInfoByGrade(Array_t *ar);
/* 显示学生信息 */
void showStuInfo(void *data);
/* 退出显示学生信息界面 */
void exitStuInfo(void);
/* 用于回调的比较函数 */
/* 1、根据学号 */
int compFunById(const void *data1, const void *data2);
/* 2、根据名字 */
int compFunByName(const void *data1, const void *data2);
/* 3、根据成绩 */
int compFunByGrade(const void *data1, const void *data2);
/* 删除学生信息 */
void deleteStuInfo(Array_t *ar);
/* 删除所有学生信息 */
void deleteAllStu(Array_t *ar);
/* 根据学号删除学生信息 */
void deleteStuById(Array_t *ar);
/* 根据姓名删除学生信息 */
void deleteStuByName(Array_t *ar);
/* 根据成绩删除学生信息 */
void deleteStuByGrade(Array_t *ar);
/* 获取用户输入 */
int getInput(void);
/* 退出学生管理系统 */
void exitStuSystem(Array_t *ar);
#endif // _STUSYSTEM_H_
stySystem.c
/******************************************
* 文件名: stuSystem.c
* 文件描述: 学生管理系统项目里所有方法函数的实现
* 编辑人:王廷云
* 编辑日期:2017-10-1
* 修改日期:2018-1-10
******************************************/
#include
#include
#include
#include
#include "stuSystem.h"
#include "arrayLib.h"
/*
* 函数名: initStuSysem
* 函数功能: 对学生管理系统进行初始化
* 参数: 无
* 返回值: 无
*/
void initStuSysem(void)
{
/* 对终端界面进行配置 */
fprintf(stdout, "\033[2J"); // 清屏
system("stty -icanon"); // 关闭缓冲
system("stty -echo"); // 关闭回显
printf("\033[?25l"); // 隐藏鼠标光标
fflush(stdout); // 刷新
}
/*
* 函数名: showMenu
* 函数描述: 显示学生管理系统功能菜单
* 参数: 1.菜单内容 2.菜单功能数目 3.功能索引值
* 返回值: 无
*/
void showMenu(char *menu[], int NR, int index)
{
int i;
/* 屏幕设置 */
for (i = 0; i < 100; i++) // 清除屏幕
{
printf("\033[%d;1H\033[K", i);
}
printf("\033[1;1H"); // 定位到第一行第一列
fflush(stdout);
/* 打印菜单 */
for (i = 0; i < NR; i++)
{
if (i == index)
{
/* 显示绿底黑字 */
printf("\033[42;30m%s\033[0m\n",menu[i]);
}
else
{
/* 显示白底黑字 */
printf("\033[47;30m%s\033[0m\n",menu[i]);
}
}
}
/*
* 函数名: getInput
* 函数功能: 获取用户输入
* 参数: 无
* 返回值: 返回用户输入对应值
*/
int getInput(void)
{
int key;
char ch;
ch = getchar();
if (ch == '\033' && getchar() == '[') // 方向键
{
ch = getchar();
switch (ch)
{
case 'A': key = UP; break;
case 'B': key = DOWN; break;
default : key = UNKNOW; break;
}
}
else if (ch == '\n') // 确认键
{
key = ENTER;
}
else if (ch == 'y' && getchar() == '\n')
{
key = YES;
}
else if (ch == 'n' && getchar() == '\n')
{
key = NO;
}
else
{
key = UNKNOW;
}
return key;
}
/*
* 函数名: addStuInfo
* 函数功能: 注册学生信息菜单功能
* 参数: 保存数据的数组指针
* 返回值: 无
*/
void addStuInfo(Array_t *ar)
{
Student_t stu;
int key;
/* 开启缓冲、显示和鼠标闪烁 */
system("stty echo");
system("stty icanon");
printf("\033[?25h");
fflush(stdout);
/* 注册学生 */
printf("\n******\033[34m学生信息注册\033[0m*******\n");
fprintf(stdout,"学生学号:\033[32m ");
fscanf(stdin,"%d",&(stu.id));
printf("\033[0m");
fflush(stdout);
fprintf(stdout,"学生姓名: \033[32m");
fscanf(stdin,"%s",(stu.name));
printf("\033[0m");
fflush(stdout);
fprintf(stdout,"学生成绩: \033[32m");
fscanf(stdin,"%f",&(stu.grade));
printf("\033[0m");
fflush(stdout);
/* 确认是否录入学生注册信息 */
getchar(); /* 去除回车符 */
while (1)
{
printf("\033[34m确认是否录入学生注册信息(y/n):\033[0m");
key = getInput();
if (key == YES) /* 确认注册 */
{
int ret;
ret = appendArrayTail(ar,&stu);
if (ret != 0)
{
fprintf(stdout,"\033[31m录入信息失败\033[0m\n");
}
else
{
fprintf(stdout,"\033[32m录入信息成功\033[0m\n");
}
break;
}
else if (key == NO) /* 取消注册 */
{
printf("\033[32m录入信息取消\033[0m\n");
break;
}
else /* 输入错误 */
{
printf("\033[31m输入错误!\033[0m\n");
while(getchar() != '\n'); /* 去掉多余字符 */
sleep(1);
}
}
system("stty -echo");
system("stty -icanon");
printf("\033[?25l");
fflush(stdout);
sleep(1); /* 稍等1秒 */
}
/*
* 函数名: queryStuInfo
* 函数功能: 查询学生信息子菜单
* 参数: 存储数据的数组指针
* 返回值: 无
*/
void queryStuInfo(Array_t *ar)
{
int index = 0;
int i;
int key;
/* 如果没有任何学生信息则没有必要进行下一步 */
if (ar->n == 0)
{
printf("*****\033[31m没有任何注册学生信息\033[0m****\n");
sleep(1);
return;
}
char *childMenu[] = {
"**查询所有**",
"*按学号查询*",
"*按名字查询*",
"*按成绩查询*",
"*返回主菜单*",
};
/* 计算菜单功能选项数 */
int NR = sizeof(childMenu)/sizeof(childMenu[0]);
/* 进入子菜单 */
while (1)
{
showMenu(childMenu,NR,index);
key = getInput();
/* 根据用户输入进行功能选择 */
switch (key)
{
/* 上移 */
case UP : index -= 1;
if (index == -1) index = NR-1; break;
/* 下移 */
case DOWN : index = (index+1)%NR; break;
/* 功能确认 */
case ENTER :
switch (index)
{
/* 显示所有学生信息 */
case 0: showAllStuInfo(ar); break;
/* 根据学号显示学生信息 */
case 1: showStuInfoById(ar); break;
/* 根据姓名显示学生信息 */
case 2: showStuInfoByName(ar); break;
/* 根据成绩显示学生信息 */
case 3: showStuInfoByGrade(ar); break;
/* 返回上一层菜单 */
case 4: return;
} break;
/* 其它按键 */
case UNKNOW: continue;
}
}
}
/*
* 函数名:showAllStuInfo
* 函数功能:显示所有学生信息
* 参数:学生信息数据指针
* 返回值:无
*/
void showAllStuInfo(Array_t *ar)
{
printf("\n*********以下为全部学生信息*********\n");
travelArray(ar,showStuInfo);
exitStuInfo();
}
/*
* 函数名:exitStuInfo
* 函数功能:退出显示学生信息界面
* 参数:无
* 返回值:无
*/
void exitStuInfo(void)
{
int key;
printf("***********\033[32m请按确认键返回\033[0m***********\n");
/* 关缓冲回显和鼠标闪烁 */
system("stty -echo");
system("stty -icanon");
printf("\033[?25l");
fflush(stdout);
while (1) /* 等待的确认键 */
{
key = getInput();
if (key == ENTER)
{
return;
}
}
}
/*
* 函数名:showStuInfoById
* 函数功能:根据学号显示学生信息
* 参数:学生信息数组
* 返回值:无
*/
void showStuInfoById(Array_t *ar)
{
void *temp;
int id;
/* 开启回显、缓冲和鼠标闪烁 */
system("stty echo");
system("stty icanon");
printf("\033[?25h");
fflush(stdout);
printf("请输入学生学号:\033[32m");
scanf("%d",&id);
printf("\033[0m");
fflush(stdout);
temp = searchArrayOneByCond(ar,compFunById,&id);
if (temp == NULL)
{
printf("***********\033[31m没有该学生信息\033[0m***********\n");
}
else
{
printf("***********以下为查询结果***********\n");
showStuInfo(temp);
}
getchar(); /* 去掉输入id时所输入的回车符 */
exitStuInfo();
}
/*
* 函数名:showStuInfoByName
* 函数功能:根据姓名显示学生信息
* 参数:学生信息数组
* 返回值:无
*/
void showStuInfoByName(Array_t *ar)
{
void *temp;
char name[10];
system("stty echo");
system("stty icanon");
printf("\033[?25h");
fflush(stdout);
printf("请输入学生姓名:\033[32m");
scanf("%s",name);
printf("\033[0m");
fflush(stdout);
temp = searchArrayOneByCond(ar,compFunByName,name);
if (temp == NULL)
{
printf("***********\033[31m没有该学生信息\033[0m***********\n");
}
else
{
printf("***********以下为查询结果***********\n");
showStuInfo(temp);
}
getchar(); /* 去掉输入name时所输入的回车符 */
exitStuInfo();
}
/*
* 函数名:showStuInfoByGrade
* 函数功能:根据成绩显示学生信息
* 参数:学生信息数组
* 返回值:无
*/
void showStuInfoByGrade(Array_t *ar)
{
void *temp;
float grade;
system("stty echo");
system("stty icanon");
printf("\033[?25h");
fflush(stdout);
printf("请输入学生成绩:\033[32m");
scanf("%f",&grade);
printf("\033[0m");
fflush(stdout);
temp = searchArrayOneByCond(ar,compFunByGrade,&grade);
if (temp == NULL)
{
printf("***********\033[31m没有该学生信息\033[0m***********\n");
}
else
{
printf("***********以下为查询结果***********\n");
showStuInfo(temp);
}
getchar(); /* 去掉输入grade时所输入的回车符 */
exitStuInfo();
}
/*
* 函数名:showStuInfo
* 函数功能:显示学生信息
* 参数:数据地址指针
* 返回值:无
*/
void showStuInfo(void *data)
{
Student_t *stu;
stu = (Student_t *)data;
printf("id: \033[32m%03d\033[0m name: \033[32m%-6s" \
"\033[0m grade: \033[32m%.2f\033[0m\n",\
stu->id,stu->name,stu->grade);
}
/*
* 函数名:compFunById
* 函数功能:比较回调函数,根据条件比较结果
* 参数:需要比较的两个数据指针
* 返回值:无
*/
int compFunById(const void *data1, const void *data2)
{
Student_t *stu = (Student_t *)data1;
if (stu->id == *(int *)data2)
{
return 1;
}
else
return 0;
}
/*
* 函数名:compFunByIdName
* 函数功能:比较回调函数,根据条件比较结果
* 参数:需要比较的两个数据指针
* 返回值:无
*/
int compFunByName(const void *data1, const void *data2)
{
Student_t *stu = (Student_t *)data1;
if (strcmp(stu->name,(char*)data2) == 0)
{
return 1;
}
else
return 0;
}
/*
* 函数名:compFunByGrade
* 函数功能:比较回调函数,根据条件比较结果
* 参数:需要比较的两个数据指针
* 返回值:无
*/
int compFunByGrade(const void *data1, const void *data2)
{
Student_t *stu = (Student_t *)data1;
if (stu->grade == *(float *)data2)
{
return 1;
}
else
return 0;
}
/*
* 函数名: deleteStuInfo
* 函数功能: 删除学生信息
* 参数: 1.子菜单的行坐标 2.子菜单的列坐标
* 返回值: 无
*/
void deleteStuInfo(Array_t *ar)
{
int index = 0;
int i;
int key;
/* 如果没有任何学生信息则没有必要进行下一步 */
if (ar->n == 0)
{
printf("*****\033[31m没有任何注册学生信息\033[0m****\n");
sleep(1);
return;
}
char *childMenu[] = {
"**删除所有**",
"*按学号删除*",
"*按名字删除*",
"*按成绩删除*",
"*返回主菜单*",
};
int NR = sizeof(childMenu)/sizeof(childMenu[0]);
while (1)
{
showMenu(childMenu,NR,index);
key = getInput();
/* 根据用户输入进行功能选择 */
switch (key)
{
/* 上移 */
case UP : index -= 1;
if (index == -1) index = NR-1; break;
/* 下移 */
case DOWN : index = (index+1)%NR; break;
/* 功能确认 */
case ENTER : switch (index)
{
case 0: deleteAllStu(ar); break;
case 1: deleteStuById(ar); break;
case 2: deleteStuByName(ar); break;
case 3: deleteStuByGrade(ar);break;
case 4: return;
} break;
/* 其它按键 */
case UNKNOW: continue;
}
}
}
/*
* 函数名:deleteAllStu
* 函数功能:删除所有学生信息
* 参数:存储数据的数组指针
* 返回值:无
*/
void deleteAllStu(Array_t *ar)
{
int key; // 用户输入按键
int sum = ar->n; // 学生总数
int i, ret;
system("stty icanon");
system("stty echo");
printf("\033[?25h");
fflush(stdout);
printf("\033[31m是否确定要删除所有学生信息(y/n):\033[0m");
key = getInput();
if (key == YES)
{
for (i = 0; i < sum; i++)
{
ret = deleteArrayByIndex(ar, 0);
if (ret != 0)
{
printf("***********\033[31m删除失败,请重试\033[0m**********\n");
exitStuInfo();
}
}
printf("\033[32m成功删除所有学生信息\033[0m\n");
exitStuInfo();
}
else if (key == NO)
{
printf("*************\033[32m删除已取消\033[0m*************\n");
exitStuInfo();
}
}
/*
* 函数名:deleteStuById
* 函数功能:根据学号删除学生信息
* 参数:存储数据的数组指针
* 返回值:无
*/
void deleteStuById(Array_t *ar)
{
int key;
int id;
void *temp;
system("stty icanon");
system("stty echo");
printf("\033[?25h");
fflush(stdout);
printf("请输入要删除学生的学号:\033[32m");
scanf("%d",&id);
printf("\033[0m");
fflush(stdout);
getchar(); /* 去掉回车符 */
temp = searchArrayOneByCond(ar,compFunById,&id);
if (temp == NULL)
{
printf("\033[31m没有该学生\033[0m\n");
exitStuInfo();
return;
}
printf("\033[31m是否确定要删除该学生信息(y/n):\033[0m");
key = getInput();
if (key == YES)
{
int ret;
ret = deleteArrayOneByCond(ar,compFunById,&id);
if (ret != 0)
{
printf("***********\033[31m删除失败,请重试\033[0m**********\n");
exitStuInfo();
return;
}
printf("\033[32m成功删除该学生信息\033[0m\n");
exitStuInfo();
}
else if (key == NO)
{
printf("*************\033[32m删除已取消\033[0m*************\n");
exitStuInfo();
}
}
/*
* 函数名:deleteStuByName
* 函数功能:根据姓名删除学生信息
* 参数:存储数据的数组指针
* 返回值:无
*/
void deleteStuByName(Array_t *ar)
{
int key;
char name[10];
void *temp;
system("stty icanon");
system("stty echo");
printf("\033[?25h");
fflush(stdout);
printf("请输入要删除学生的姓名:\033[32m");
scanf("%s",name);
printf("\033[0m");
fflush(stdout);
getchar(); /* 去掉回车符 */
temp = searchArrayOneByCond(ar,compFunByName,name);
if (temp == NULL)
{
printf("\033[31m没有该学生\033[0m\n");
exitStuInfo();
return;
}
printf("\033[31m是否确定要删除该学生信息(y/n):\033[0m");
key = getInput();
if (key == YES)
{
int ret;
ret = deleteArrayOneByCond(ar,compFunByName,name);
if (ret != 0)
{
printf("***********\033[31m删除失败,请重试\033[0m**********\n");
exitStuInfo();
}
printf("\033[32m成功删除该学生信息\033[0m\n");
exitStuInfo();
}
else if (key == NO)
{
printf("*************\033[32m删除已取消\033[0m*************\n");
exitStuInfo();
}
}
/*
* 函数名:deleteStuByGrade
* 函数功能:根据成绩删除学生信息
* 参数:存储数据的数组指针
* 返回值:无
*/
void deleteStuByGrade(Array_t *ar)
{
int key;
float grade;
void *temp;
system("stty icanon");
system("stty echo");
printf("\033[?25h");
fflush(stdout);
printf("请输入要删除学生的成绩:\033[32m");
scanf("%f",&grade);
printf("\033[0m");
fflush(stdout);
getchar(); /* 去掉回车符 */
temp = searchArrayOneByCond(ar,compFunByGrade,&grade);
if (temp == NULL)
{
printf("\033[31m没有该学生\033[0m\n");
exitStuInfo();
return;
}
printf("\033[31m是否确定要删除该学生信息(y/n):\033[0m");
key = getInput();
if (key == YES)
{
int ret;
ret = deleteArrayOneByCond(ar,compFunByGrade,&grade);
if (ret != 0)
{
printf("***********\033[31m删除失败,请重试\033[0m**********\n");
exitStuInfo();
}
printf("\033[32m成功删除该学生信息\033[0m\n");
exitStuInfo();
}
else if (key == NO)
{
printf("*************\033[32m删除已取消\033[0m*************\n");
exitStuInfo();
}
}
/*
* 函数名: exitStuSystem
* 函数功能: 退出学生管理系统前进行一些终端配置
* 参数: 无
* 返回值: 无
*/
void exitStuSystem(Array_t *ar)
{
char ch;
/* 恢复终端配置 */
system("stty icanon"); // 恢复缓冲
system("stty echo"); // 恢复回显示
printf("\033[?25h"); // 显示鼠标
fflush(stdout); // 刷新
/* 询问是否保存修改 */
fprintf(stdout, "是否保存修改?(y/n):");
ch = getchar();
if (ch == 'y') // 确认保存
{
saveArrayToFile(ar, "stuInfo.db");
}
exit(0); // 退出程序
}