😁经历了一个月的C语言学习,将学习成果奉上,学生成绩管理系统,涵盖了很多C语言的知识点,做法很多,链表和结构体的都有,我是用的结构体,但巧妙的利用动态存储的方式将学生的信息存储到文件中。------结尾附上代码😀
一、实现效果
👏登录界面
采用密码验证方式进入系统,错误则重复输入,隐藏密码
👋主菜单页面
******************通过输入对应的数字进到对应的系统************************
✍学生个人信息管理页面
******************输入对应数字进行对应的操作***************************
💪学生成绩管理系统
二、实现思路
- 利用结构体的特点,将增加的学生信息先保存在结构体中
- 分模块编写,增删改查,分函数写,再调用
- 利用动态存储的方式分配空间
- 考虑细节,判断输入的各种情况,比如学号唯一,指针空等
- 文件操作,写入和读取,利用结构体变量来接
三、功能说明
- 👉主菜单进入子系统时,会进行初始化,结构体清空,经文件里的学生信息读取到结构体中,并进行容量检查
- 👉增加学生信息:将学生信息添加到系统中(学号唯一判断,容量判断)
- 👉删除学生信息:输入你要修改的学生学号删除对应学生信息
- 👉修改学生信息:输入你要修改的学生学号删除对应学生信息
- 👉查询学生成绩:输入你要查询的学生学号输出对应学生信息
- 👉输出学生信息:输出表中所有的学生信息
- 👉排序学生信息:根据学号进行降序排序
- 👉退出系统:先将学生信息保存到文件中方便下次读取,然后释放内存,回到主菜单
四、实现讲解
♈基本框架的搭建
**************************创建三个文件*****************************
给大家解释下为什么要创建三个文件,首先,做项目,讲究的是编程手法和代码的简洁化,为我们在写代码时,需要将代码模块化,所谓的模块化就是,将函数封装,在主函数调用,这样搭建框架有助于大家思考下一步怎么做,所以博主建议大家在写时像上图这样,main.c里放主函数和主界面,student.h放函数的声明,结构体和枚举声明以及宏定义,而student.c编写要封装的函数和功能,通过main函数进行调用,这样子我们思路就会非常的清晰,一步一步完善我们的模块。
****************************************** 开始啦 **********************************************************
🌎1.定义两个结构体,一个用来存放学生的个人信息,一个用来嵌套成员人数,记录表中成员的个数和容量,为待会写动态存储做准备
🌍2. 定义各个模块的函数,在.h文件里定义,模块化编程
声明好需要的函数,然后再分模块编写,
这里提一点,大家要养成好的习惯,函数命名时尽量用翻译,将中文翻译好这个模块是什么功能的进行命名,不然久了回来看项目时,就不知道那个模块是什么功能了,包括定义变量也一样,,不要总是 i, j, a, b这样声明很容易弄混,因为代码量很多,有时候会冲突导致你找很久,所以尽量将功能翻译成中文使用。
![]()
🌏3.菜单页面的编写
这个就没什么好说的,大家的美化技能应该比我的强大吧,可以根据自己的想法来哦
🌕4.主函数的排布
- 这里的登录界面我们后面再讲,因为会涉及到密码的处理
- 定义静态全局变量input用来存储输入的指令数字
- 通过do--while 来嵌套switch来循环输入指令来处理
- system函数的用法很多,这里是冻结窗口的意思,可以停下来让你观察打印的变化
- 这里的switch就是输入相应的数字进入不同的系统了
♉编写初始化的函数
*********************************增容函数***********************************
- 解释下,这里的函数的传进来的参数是存放学生人数的结构体变量,在主函数有定义的
- 往下,比较容量和sz的数值是否相等来判断是否需要增容
- realloc是调整空间的函数,返回的是调整后空间的大小
- 再往下就是增容部分的赋值,将扩容后的空间给到结构体
*********************************初始化函数***********************************
进行系统运行时的初始化,首先会开辟3个结构体大小的空间来存放数据,然后读取文件的数据存放进来,期间会进行一个容量的判断
//*****初始化个人信息--动态分配内存,先分配3个,超过3个再给2个****** int InitContact(Contact *pc) { assert(pc); //如果指针为空就会返回信息 pc->sz = 0; pc->data = (PeoInfo*)calloc(DEFAULT_SZ, sizeof(PeoInfo)); if (pc->data == NULL) { printf("InitContact::%s\n", strerror(errno)); return 1; } pc->capacity = DEFAULT_SZ; //加载文件的信息到通讯录中 LoadStudent(pc); // LoadScore(qs); //读取成绩信息 return 0; }
*********************************文件读取函数***********************************
- 文件读取,一块一块读,定义一个临时的结构体变量来存放读取过来的数据,这样我们就不用考虑格式,用结构体变量存,顺序存储排放。
- perror是检测到为空就会返回信息,防御式编程
- 容量检测,超过3个后就会扩容两个,往后就判断,满了就扩容两个
*********************************释放内存函数***********************************
♊功能函数的编写
*********************************增加信息函数***********************************
- 先检测容量是否足够,不够就进行扩容,这里封装好了,直接调用就行
- 学号不能重复,这里进行判断,通过goto 语句进行跳转
- 将输入的值放进结构体就行,这里就不多说了
*********************************增加信息函数***********************************
- 这里封装好一个查找函数,返回下标,为后面的函数做准备
*********************************删除信息函数***********************************
- 这里就用到了上面封装的函数,通过接收返回值进行判断,是否存在
- 存在就执行删除,覆盖结构体的整个值
*********************************排序函数***********************************
- 根据学号排序,比较数值的大小
- 用了字符转换整型的函数,因为学号前面定义类型错了,改的话比较麻烦
*********************************写文件函数***********************************
- 这个也没啥好说的,封装好的,但时候主函数调用,退出指令的时候自动将结构体的信息保存到外部文件中
剩下的一些查询函数大同小异,就不一一罗列了,大家可以看下代码。放在了结尾。
♋登录界面
- 这里调用了#include <conio.h> 这个头文件,里面有个函数用来密码隐藏
- 无非就是一些输入的判断,错误就循环输入
- 可添加输入次数的判断
//**********************登录界面*********************
void Log_In()
{
char password[MAX_PASSWORD_LENGTH];
// 存储预定义的用户名和密码
char predefined_password[] = "password";
char input[10];
printf("\n");
printf("\033[1;34m███╗ ██╗ ███████╗ ██████╗ ██████╗ ██╗ ██╗\033[0m\n");
printf("\033[1;34m████╗ ██║ ██╔════╝██╔═══██╗██╔══██╗╚██╗ ██╔╝\033[0m\n");
printf("\033[1;34m██╔██╗ ██║ ███████╗██║ ██║██████╔╝ ╚████╔╝\033[0m\n");
printf("\033[1;34m██║╚██╗██║ ╚════██║██║ ██║██╔══██╗ ╚██╔╝\033[0m\n");
printf("\033[1;34m██║ ╚████║ ███████║╚██████╔╝██████╔╝ ██║\033[0m\n");
printf("\033[1;34m╚═╝ ╚═══╝ ╚══════╝ ╚═════╝ ╚═════╝ ╚═╝\033[0m\n");
printf("\n");
printf("\033[36m欢迎使用学生管理系统\n\n");
printf("用户名:admin \n\n");
int j = 100,i;
while (j--) {
printf("请输入密码 : " );
// 隐藏密码输入
int index = 0;
char ch;
for(i=0;i<100;i++)
{
ch = getch();
if (ch == 13) // 如果用户按下回车键
break;
if (ch == 8 && index > 0) { // 如果用户按下退格键
putchar('\b');
putchar(' ');
putchar('\b');
index--;
continue;
}
if (ch != 8) { // 忽略退格键
putchar('*'); // 显示'*'而不是实际输入的字符
password[index] = ch;
index++;
}
}
password[index] = '\0'; // 在密码末尾添加null终止符
if (strcmp(password, predefined_password) == 0) {
printf("\n\033[1;32m正在登录...\033[0m\n");
Sleep(2000);
printf("\n登录成功!\n");
return;
} else {
printf("\n密码错误,请重试。\n");
}
}
}
代码分享 :
存放信息的 文件会在执行文件时自动创建,有些编辑器需要创建项目才能同时运行多个.c文件,大家可以根据自己的编辑器类型来创建,我用的是vscode, c-free
main.c
#include <stdio.h> #include <stdlib.h> #include "student.h" // 学生个人信息菜单 void menu_a() { system("cls"); // 清屏 printf("\t\t****************************************************************\n"); printf("\t\t\033[37m*********** \033[34m学生个人信息管理 \033[37m ************\n"); printf("\t\t----------------------------------------------------------------\n"); printf("\t\t*********** \033[32m 1 \033[37m---- 增加学生信息 ***********\n"); printf("\t\t*********** \033[32m 2 \033[37m---- 删除学生信息 ***********\n"); printf("\t\t*********** \033[32m 3 \033[37m---- 修改学生信息 ***********\n"); printf("\t\t*********** \033[32m 4 \033[37m---- 查询学生信息 ***********\n"); printf("\t\t*********** \033[32m 5 \033[37m---- 输出学生信息 ***********\n"); printf("\t\t*********** \033[32m 6 \033[37m---- 排序学生信息 ***********\n"); printf("\t\t*********** \033[32m 0 \033[37m---- 退出管理系统 ***********\n"); printf("\t\t***************************************************************\n"); printf("\033[35m"); printf("\t\t请选择你的操作(数字):"); } // 成绩管理 void menu_b() { system("cls"); // 清屏 printf("\033[37m=======================\033[34m学生成绩信息管理\033[37m============================\n"); printf("---------------------------功能菜单------------------------------\n"); printf("\t\t\t\033[32m1\033[37m--录入学生成绩信息\n"); printf("\t\t\t\033[32m2\033[37m--删除学生成绩信息\n"); printf("\t\t\t\033[32m3\033[37m--修改学生成绩\n"); printf("\t\t\t\033[32m4\033[37m--查询单个学生的成绩\n"); printf("\t\t\t\033[32m5\033[37m--查询所有学生成绩\n"); printf("\t\t\t\033[32m6\033[37m--学生成绩排序\n"); printf("\t\t\t\033[32m7\033[37m--根据学号排序\n"); printf("\t\t\t\033[32m8\033[37m--保存学生信息\n"); printf("\t\t\t\033[32m9\033[37m--查看班级平均分\n"); printf("\t\t\t\033[32m0\033[37m--退出系统\n"); printf("------------------------------------------------------------------\n"); printf("\033[35m"); printf("\t\t请选择你的操作(数字):"); } // 总菜单页面 void menuAll() { system("cls"); // 清屏 printf("\t\t****************************************************************\n"); printf("\t\t\033[37m*********** \033[34m学生信息管理系统V3.0版 \033[37m ********\n"); printf("\t\t----------------------------------------------------------------\n"); printf("\t\t*********** \033[32m 1 \033[37m---- 个人信息管理系统-》 *********\n"); printf("\t\t*********** \033[32m 2 \033[37m---- 成绩信息管理系统-》 **********\n"); printf("\t\t*********** \033[32m 0 \033[37m---- 退出管理系统 **********\n"); printf("\t\t****************************************************************\n"); printf("\033[35m"); printf("\t\t请选择你要进入的系统(数字):"); } // 创建个人信息结构体变量 Contact con; // 创建成绩信息结构体变量 Crowd str; //**************************************************************** //************** 个人信息菜单 **************** //**************************************************************** void Information() { short input_a = 0; do { menu_a(); // 菜单 scanf("%d", &input_a); switch (input_a) { case ADD: // 增加 add_student(&con); break; case DEL: // 删除 delete_student(&con); break; case MODIFY: // 修改 modify_student(&con); break; case QUERY: // 查询 query_student(&con); break; case OUTPUT: // 输出 output_student(&con); break; case SORT: // 学号排序 sort_student(&con); break; case EXIT: // 退出--保存文件 save_student(&con); DestroyContact(&con); break; default: printf("\t\t\033[31m输入错误,请重新输入!\033[37m\n"); input_a = 1; break; } system("pause"); } while (input_a); } //**************************************************************** //************** 成绩信息菜单 **************** //**************************************************************** void Score() { short input_b = 0; do { menu_b(); // 菜单 scanf("%d", &input_b); switch (input_b) { case ADD: // 增加 add_score(&str); break; case DEL: // 删除 delete_score(&str); break; case MODIFY: // 修改 modify_score(&str); break; case QUERY: // 查询个人 query_score(&str); break; case OUTPUT: // 查询所有 output_score(&str); break; case SORT: // 成绩排序 sort_avge_score(&str); break; case SORT_ID: // 学号排序 sort_ID_score(&str); break; case Save_score: // 保存信息 Save_Score_File(&str); break; case Examine: // 查看班级平均分 Class_avge_score(&str); break; case EXIT: // 退出--保存文件 Save_Score_File(&str); Destroy_Crowd(&str); printf("\t\t 感谢使用!!!!!!!\n"); return; default: printf("\t\t\033[31m输入错误,请重新输入!\033[37m\n"); break; } system("pause"); } while (input_b); } //**************************************************************** //********** 主函数 **************** //**************************************************************** static int input; // 静态全局 int main() { // 登录界面 Log_In(); //system("color 8A"); do { menuAll(); // 总菜单 scanf("%d", &input); switch (input) { case 1: // 个人信息管理 InitContact(&con); // 初始化 system("pause"); Information(); continue; case 2: // 成绩信息管理 InitContact_grade(&str); // 初始化 system("pause"); Score(); continue; case 0: // 退出系统 // Exit(); break; default: printf("\t\t\033[31m输入的指令有误,请重新输入\n"); break; } system("pause"); } while (input); return 0; }
student.c
#include <stdio.h> #include "student.h" #include <stdlib.h> #include <assert.h> #include <string.h> #include <conio.h> // 用于隐藏密码输 #include <windows.h> //***********增容的函数************判断是否需要增容**************** void CheckCapacity(Contact* pc) { if (pc->sz == pc->capacity) { PeoInfo* ptr = (PeoInfo*)realloc(pc->data, (pc->capacity + INC_SZ) * sizeof(PeoInfo)); if (ptr == NULL) { printf("AddContact::%s\n", strerror(errno)); return; } else { pc->data = ptr; pc->capacity += INC_SZ; printf("\t\t\033[31m增容成功\n"); } } //system("pause"); } //*************个人信息文件读取*************** void LoadStudent(Contact *pc) { FILE *fp = fopen("student.txt", "rb"); if (fp == NULL) { perror("LoadStudent"); return; } PeoInfo temp = {0}; // 定义结构体变量对读出的文件进行接收 // 读文件 while (fread(&temp, sizeof(PeoInfo), 1, fp) == 1) // 成功返回读写的块数,失败返回0 { CheckCapacity(pc); pc->data[pc->sz] = temp; pc->sz++; } // 关闭文件 fclose(fp); fp = NULL; printf("\t\t\033[33m1--个人信息读取成功\n"); } //***********成绩信息文件读取******************* void LoadScore(Crowd *qs) { // 打开文件 FILE *fp = fopen("student_score.txt","rb"); if(fp == NULL) { perror("LoadScore"); return; } Result tmp = {0}; //定义一个新的结构体变量进行接收 while(fread(&tmp,sizeof(Result),1,fp) == 1) //成功返回写的数量 失败返回0 { CheckCapacity_grade(qs); qs->data[qs->count] = tmp; qs->count++; } //关闭文件 fclose(fp); fp = NULL; printf("\t\t\033[33m2--成绩信息读取成功\n"); } //*****初始化个人信息--动态分配内存,先分配3个,超过3个再给2个****** int InitContact(Contact *pc) { assert(pc); //如果指针为空就会返回信息 pc->sz = 0; pc->data = (PeoInfo*)calloc(DEFAULT_SZ, sizeof(PeoInfo)); if (pc->data == NULL) { printf("InitContact::%s\n", strerror(errno)); return 1; } pc->capacity = DEFAULT_SZ; //加载文件的信息到通讯录中 LoadStudent(pc); // LoadScore(qs); //读取成绩信息 return 0; } //*********释放掉内存*********** void DestroyContact(Contact* pc) { assert(pc); free(pc->data); pc->data = NULL; printf("\t\t内存释放成功!\n"); } //********动态 增加学生******** void add_student(Contact *pc) { assert(pc); int i; //增容 CheckCapacity(pc); dir: printf("\t\t\033[32m请输入学生学号:"); scanf("%s", pc->data[pc->sz].ID); // 判断学号是否重复 for (i = 0; i < pc->sz; i++) { if (strcmp(pc->data[i].ID, pc->data[pc->sz].ID) == 0) { printf("\t\t\033[31m学号已存在\n"); goto dir; } } printf("\t\t请输入学生的姓名: "); scanf("%s", pc->data[pc->sz].name); printf("\t\t请输入学生性别:"); scanf("%s", pc->data[pc->sz].sex); printf("\t\t请输入学生专业:"); scanf("%s", pc->data[pc->sz].major); printf("\t\t请输入学生的班级: "); scanf("%s", pc->data[pc->sz].grade); printf("\t\t请输入学生的电话:"); scanf("%s", pc->data[pc->sz].phone); pc->sz++; // 位移一位 printf("\t\t添加成功\n"); } // **********输出全部学生信息**************** void output_student(Contact *pc) { assert(pc); int i; if (pc->sz == 0) { printf("\t\t\033[31m学生信息表为空,请增加学生信息!\n\n"); return; } printf("\t ===================================================================================\n"); for (i = 0; i < pc->sz; i++) { printf("\t\033[33m |%-10s\t%-15s\t%-12s\t%-15s\t%-12s\t%-12s\n", "学号", "姓名", "性别", "专业", "班级", "电话"); printf("\t\033[37m |%-10s\t%-15s\t%-12s\t%-15s\t%-12s\t%-12s\n", pc->data[i].ID, pc->data[i].name, pc->data[i].sex, pc->data[i].major, pc->data[i].grade, pc->data[i].phone); } printf("\t ===================================================================================\n"); } // *********查找函数--通过学号查找************* int FindByName(Contact *pc, char *num) { assert(pc); int i; for (i = 0; i < pc->sz; i++) { if (strcmp(pc->data[i].ID, num) == 0) { return i; // 返回位置下标 } } return -1; // 没有则返回-1 } //************ 删除学生信息******************* void delete_student(Contact *pc) { assert(pc); int i; char num[20]; if (pc->sz == 0) { printf("\t\t\033[31m学生信息表为空,无删除\n\n"); return; } printf("\t\t请输入要删除的学号:"); scanf("%s", num); // 1.查找学生 int pos = FindByName(pc, num); // 接收返回值 if (pos == -1) { printf("\t\t该学号不存在\n"); return; } // 2.删除 for (i = pos; i < pc->sz - 1; i++) { pc->data[i] = pc->data[i + 1]; } pc->sz--; printf("\t\t删除成功\n"); } // ****************根据学号查询信息************ void query_student(Contact *pc) { assert(pc); int i; if (pc->sz == 0) { printf("\t\t\033[31m学生信息表为空,无查询\n\n"); return; } char num[20]; printf("\t\t请输入要查询的学号:"); scanf("%s", num); int pos = FindByName(pc, num); if (pos == -1) { printf("\t\t该学号不存在\n"); return; } printf("\n\t\t \033[34m 你要查询学号为 %s学生信息如下:\n", pc->data[pos].ID); printf("\t\t%-10s\t%-15s\t%-12s\t%-15s\t%-12s\t%-12s\n", "学号", "姓名", "性别", "专业", "班级", "电话"); printf("\t\t%-10s\t%-15s\t%-12s\t%-15s\t%-12s\t%-12s\n", pc->data[pos].ID, pc->data[pos].name, pc->data[pos].sex, pc->data[pos].major, pc->data[pos].grade, pc->data[pos].phone); } //************* 修改***************** void modify_student(Contact *pc) { assert(pc); int i; if (pc->sz == 0) { printf("\t\t\033[31m学生信息表为空,无法修改\n\n"); return; } char num[20]; printf("\t\t请输入要修改的学生的学号:"); scanf("%s", num); int pos = FindByName(pc, num); if (pos == -1) { printf("\t\t查询不到,没有该学生"); return; } char str[20]; //输入信息更改表里的信息 dir: printf("\t\t请输入学生学号:"); scanf("%s", str); // 判断学号是否重复 for (i = 0; i < pc->sz; i++) { if (strcmp(pc->data[i].ID, str) == 0) { printf("\t\t\033[31m学号已存在\n"); goto dir; } } strcpy(pc->data[pos].ID, str); // 将学号写进去 // 继续写入信息 printf("\t\t请输入学生的姓名: "); scanf("%s", pc->data[pos].name); printf("\t\t请输入学生性别:"); scanf("%s", pc->data[pos].sex); printf("\t\t请输入学生专业:"); scanf("%s", pc->data[pos].major); printf("\t\t请输入学生的班级: "); scanf("%s", pc->data[pos].grade); printf("\t\t请输入学生的电话:"); scanf("%s", pc->data[pos].phone); printf("\t\t修改成功!\n"); } // *********比较大小交换两个数值************* void cmp_by_num(PeoInfo *str1, PeoInfo *str2) { PeoInfo temp; // 定义一个第三结构体变量 temp = *str1; *str1 = *str2; *str2 = temp; } //*********** 排序 ************************ void sort_student(Contact *pc) { assert(pc); int i, j; if (pc->sz == 0) { printf("\n\t\t \033[31m无学生信息,无法排序\n"); return; } for (i = 0; i < pc->sz - 1; i++) // 通过学号进行冒泡排序 { for (j = 0; j < pc->sz - i - 1; j++) { if (atoi(pc->data[j].ID) > atoi(pc->data[j+1].ID)) //将字符串转换成整数进行比较 { cmp_by_num(&pc->data[j], &pc->data[j + 1]); } } } printf("\t\t排序成功\n"); } // ****************写文件********************** void save_student(Contact *pc) { assert(pc); // 打开文件 FILE *fp = fopen("student.txt", "wb"); // 二进制写入 if (fp == NULL) { perror("save_student"); return; } // 写文件 int i; for (i = 0; i < pc->sz; i++) { fwrite(&pc->data[i], sizeof(PeoInfo), 1, fp); } // 关闭文件 fclose(fp); fp = NULL; printf("\t\t\033[33m保存成功,可安全退出\n"); } //********************************************************************************8 //******************* 成绩信息管理 *******************************8 //********************************************************************************8 //*****初始化个人信息--动态分配内存,先分配3个,超过3个再给2个******* int InitContact_grade(Crowd *qs) { assert(qs); qs->count = 0; qs->data = (Result*)calloc(DEFAULT_SZ, sizeof(Result)); if (qs->data == NULL) { printf("InitContact::%s\n", strerror(errno)); return 1; } qs->capacity = DEFAULT_SZ; //加载文件的信息 LoadScore(qs); //读取成绩信息 return 0; } //*****************释放掉内存************ void Destroy_Crowd(Crowd* qs) { assert(qs); free(qs->data); qs->data = NULL; printf("\t\t内存释放成功!\n"); system("pause"); } //*********************检测增容的函数*********************** void CheckCapacity_grade(Crowd* qs) { if (qs->count == qs->capacity) { Result* ptr = (Result*)realloc(qs->data, (qs->capacity + INC_SZ) * sizeof(Result)); if (ptr == NULL) { printf("AddContact::%s\n", strerror(errno)); return; } else { qs->data = ptr; qs->capacity += INC_SZ; printf("\t\t\033[31m增容成功\n"); } } } //********************* 增加成绩信息************************ void add_score(Crowd *qs) { assert(qs); int i; CheckCapacity_grade(qs); dir: printf("\t\t\033[32m请输入该学生的学号: "); scanf("%s", qs->data[qs->count].ID); for (i = 0; i < qs->count; i++) { if (strcmp(qs->data[i].ID, qs->data[qs->count].ID) == 0) { printf("\t\t\033[31m学号已存在\n"); goto dir; } } printf("\t\t请输入学生的姓名:"); scanf("%s", qs->data[qs->count].name); printf("\t\t请输入该学生的语文成绩:"); scanf("%d", &qs->data[qs->count].language); printf("\t\t请输入该学生的数学成绩:"); scanf("%d", &qs->data[qs->count].math); printf("\t\t请输入该学生的英语成绩:"); scanf("%d", &qs->data[qs->count].English); All_avse(qs, qs->count); //总分和平均分的处理 qs->count++; //位移一位 printf("\t\t添加成功\n"); } //*********************平均分和总分的处理******************** void All_avse(Crowd *qs,int num) { assert(qs); //总分 qs->data[num].Total=(qs->data[num].language)+ (qs->data[num].English)+ (qs->data[num].math); //平均分 qs->data[num].average=((qs->data[num].Total)/3); } //********************* 输出所有学生成绩信息******************* void output_score(Crowd *qs) { assert(qs); int i; if (qs->count == 0) { printf("\t\t\033[31m无学生成绩信息,请添加后再尝试出输出\n"); return; } printf(" \t ============================================================================\n"); for (i = 0; i < qs->count; i++) { printf(" \t\033[33m |%-10s\t%-15s\t%-12s\t%-15s\t%-12s\t%-12s\t%-12s\n", "学号", "姓名", "语文成绩", "数学成绩", "英语成绩","总分","平均分"); printf(" \t\033[37m |%-10s\t%-15s\t%-12d\t%-15d\t%-12d\t%-12d\t%-12d\n", qs->data[i].ID, qs->data[i].name, qs->data[i].language, qs->data[i].math, qs->data[i].English,qs->data[i].Total, qs->data[i].average); } printf(" \t ============================================================================\n"); } //************ 封装的查询函数********************** int FindByNumber(Crowd *qs, char *num) { assert(qs); int i; for (i = 0; i < qs->count; i++) { if (strcmp(qs->data[i].ID, num) == 0) { return i; // 返回位置下标 } } return -1; // 没有则返回-1 } // ************删除成绩********************* void delete_score(Crowd *qs) { assert(qs); int i; char num[20]; if (qs->count == 0) { printf("\t\t\033[31m表里无学生成绩信息,删除失败\n"); return; } printf("\t\t请输入你要删除的学生的学号:"); scanf("%s", num); int pos = FindByNumber(qs, num); // 获取返回值进行判断 if (pos == -1) { printf("t\t\033[31m要删除的人不存在"); return; } for (i = pos; i < qs->count - 1; i++) { qs->data[i] = qs->data[i + 1]; // 将元素往前移将要删除的覆盖 } qs->count--; printf("\t\t删除成功\n"); } //***************** 修改信息 *************************** void modify_score(Crowd *qs) { assert(qs); char num[20]; if (qs->count == 0) { printf("\t\t\033[31m无学生成绩信息,修改失败\n"); return; } printf("\t\t请输入你要修改的学生的学号:"); scanf("%s", num); int pos = FindByNumber(qs, num); // 获取返回值进行判断 if (pos == -1) { printf("t\t\033[31m要修改的人不存在"); return; } int i; char clos[20]; dir: printf("\t\t\033[32m请输入该学生的学号: "); scanf("%s", clos); for (i = 0; i < qs->count; i++) { if (strcmp(qs->data[i].ID, clos) == 0) { printf("\t\t\033[31m学号已存在\n"); goto dir; } } strcpy(qs->data[pos].ID,clos); printf("\t\t请输入学生的姓名:"); scanf("%s", qs->data[pos].name); printf("\t\t请输入该学生的语文成绩:"); scanf("%d", &qs->data[pos].language); printf("\t\t请输入该学生的数学成绩:"); scanf("%d", &qs->data[pos].math); printf("\t\t请输入该学生的英语成绩:"); scanf("%d", &qs->data[pos].English); All_avse(qs,pos); //总分和平均分的处理 printf("\t\t修改成功\n"); } //********************* 查询个人成绩*********************** void query_score(Crowd *qs) { assert(qs); char num[20]; if (qs->count == 0) { printf("\t\t\033[31m无学生成绩信息,查询失败\n"); return; } printf("\t\t请输入你要查询的学生的学号:"); scanf("%s", num); int pos = FindByNumber(qs, num); // 获取返回值进行判断 if (pos == -1) { printf("t\t\033[31m要查询的人不存在"); return; } printf(" \t ============================================================================\n"); printf(" \t\033[33m |%-10s\t%-15s\t%-12s\t%-15s\t%-12s\n", "学号", "姓名", "语文成绩", "数学成绩", "英语成绩"); printf(" \t\033[37m |%-10s\t%-15s\t%-12d\t%-15d\t%-12d\n", qs->data[pos].ID, qs->data[pos].name, qs->data[pos].language, qs->data[pos].math, qs->data[pos].English); printf(" \t ============================================================================\n"); } //*****************交换位置****************** void Exchange_num(Result *arr1 , Result *arr2) { Result temp;//定义第三个结构体变量 temp=*arr1; *arr1=*arr2; *arr2=temp; } //************根据--平均分排序************* void sort_avge_score(Crowd *qs) { assert(qs); int i, j; if (qs->count == 0) { printf("\n\t\t \033[31m无学生信息,无法排序\n"); return; } for (i = 0; i < qs->count - 1; i++) // 通过平均分进行冒泡排序 { for (j = 0; j < qs->count - i - 1; j++) { if (qs->data[j].average < qs->data[j + 1].average) { Exchange_num(&qs->data[j],&qs->data[j+1]); } } } printf("\t\t排序成功\n"); } //************根据--学号排序************** void sort_ID_score(Crowd *qs) { assert(qs); int i, j; if (qs->count == 0) { printf("\n\t\t \033[31m无学生信息,无法排序\n"); return; } for (i = 0; i < qs->count - 1; i++) // 通过学号进行冒泡排序 { for (j = 0; j < qs->count - i - 1; j++) { if (strcmp(qs->data[j].ID,qs->data[j+1].ID) > 0) { Exchange_num(&qs->data[j],&qs->data[j+1]); } } } printf("\t\t排序成功\n"); } //************保存信息到文件************** void Save_Score_File(Crowd *qs) { assert(qs); //打开文件 FILE *fp = fopen("student_score.txt","wb"); if(fp == NULL) { perror("Save_score_File"); return; } //写文件 int i; for(i=0;i<qs->count;i++) { fwrite(&qs->data[i],sizeof(Result),1,fp); } //关闭文件 fclose(fp); fp = NULL; printf("\t\t信息保存成功\n"); } //*****************查看班级平均分******************** void Class_avge_score(Crowd *qs) { assert(qs); if(qs->count==0) { printf("\t\t无成绩信息,请重新选择\n"); return; } short i,all_avge1=0,all_avge2=0,all_avge3=0; for(i=0;i<qs->count;i++) { all_avge1+=qs->data[i].language; all_avge2+=qs->data[i].math; all_avge3+=qs->data[i].English; } printf(" \t ============================================================================\n"); printf(" \t\033[33m |%-10s\t%-15s\t%-12s\n", "语文平均分", "数学平均分", "英语平均分"); printf(" \t\033[33m |%-10d\t%-15d\t%-12d\n",all_avge1/qs->count,all_avge2/qs->count,all_avge3/qs->count); printf(" \t ============================================================================\n"); } //**********************登录界面********************* void Log_In() { char password[MAX_PASSWORD_LENGTH]; // 存储预定义的用户名和密码 char predefined_password[] = "password"; char input[10]; printf("\n"); printf("\033[1;34m███╗ ██╗ ███████╗ ██████╗ ██████╗ ██╗ ██╗\033[0m\n"); printf("\033[1;34m████╗ ██║ ██╔════╝██╔═══██╗██╔══██╗╚██╗ ██╔╝\033[0m\n"); printf("\033[1;34m██╔██╗ ██║ ███████╗██║ ██║██████╔╝ ╚████╔╝\033[0m\n"); printf("\033[1;34m██║╚██╗██║ ╚════██║██║ ██║██╔══██╗ ╚██╔╝\033[0m\n"); printf("\033[1;34m██║ ╚████║ ███████║╚██████╔╝██████╔╝ ██║\033[0m\n"); printf("\033[1;34m╚═╝ ╚═══╝ ╚══════╝ ╚═════╝ ╚═════╝ ╚═╝\033[0m\n"); printf("\n"); printf("\033[36m欢迎使用学生管理系统\n\n"); printf("用户名:admin \n\n"); int j = 100,i; while (j--) { printf("请输入密码 : " ); // 隐藏密码输入 int index = 0; char ch; for(i=0;i<100;i++) { ch = getch(); if (ch == 13) // 如果用户按下回车键 break; if (ch == 8 && index > 0) { // 如果用户按下退格键 putchar('\b'); putchar(' '); putchar('\b'); index--; continue; } if (ch != 8) { // 忽略退格键 putchar('*'); // 显示'*'而不是实际输入的字符 password[index] = ch; index++; } } password[index] = '\0'; // 在密码末尾添加null终止符 if (strcmp(password, predefined_password) == 0) { printf("\n**正在登录...\n"); Sleep(2000); printf("\n登录成功!\n"); return; } else { printf("\n密码错误,请重试。\n"); } } }
student.h
#ifndef __STUDENT_H #define __STUDENT_H #include <string.h> #include <stdio.h> #include <assert.h> #include <stdlib.h> #define MAX_PATH 20 #define MAX_SEX 5 #define MAX_major 50 #define MAX_date 100 #define MAX_PASSWORD_LENGTH 50 #define DEFAULT_SZ 3 #define INC_SZ 2 enum Option //学生个人信息 { EXIT, //退出--0 ADD, //增加--1 DEL, //删除--2 MODIFY, //修改--3 QUERY, //查询--4 OUTPUT, //输出--5 SORT, //排序--6 SORT_ID, //--7 Save_score, //--8 Examine //--9 }; // *****************存放个人学生信息******************** typedef struct { char ID[MAX_PATH]; // 学号 char name[MAX_PATH]; // 姓名 char sex[MAX_SEX]; // 性别 char major[MAX_major]; // 专业 char grade[MAX_PATH]; // 班级 char phone[MAX_PATH]; // 电话 } PeoInfo; //动态的版本 typedef struct Contact { PeoInfo* data;//存放人的信息 int sz;//记录当前通讯录中实际人的个数 int capacity;//当前通讯录的容量 }Contact; // *********************存放学生成绩信息********************** typedef struct { char ID[MAX_PATH]; // 学号 char name[MAX_PATH]; // 姓名 short language; //语文成绩 short math; //数学成绩 short English;//英语成绩 short Total; //三科成绩 short average;//平均分 }Result; // 成绩人数 typedef struct Crowd { Result* data;//存放人的信息 int count;//记录当前通讯录中实际人的个数 int capacity;//当前通讯录的容量 }Crowd; //**************************************************** //***************登录界面****************************** void Log_In(); //******************************************************** //***************学生个人信息****************************** void Information(); // 初始化 int InitContact(Contact *pc); //释放掉内存 void DestroyContact(Contact* pc); // 增加学生信息 void add_student(Contact *pc); // 输出学生信息 void output_student(Contact *pc); //删除学生信息 void delete_student(Contact *pc); //查询学生信息 void query_student(Contact *pc); //修改学生信息 void modify_student(Contact *pc); //排序 void sort_student(Contact *pc); //保存文件 void save_student(Contact *pc); //********************************************************** //********************************************************** //***************学生成绩管理******************************** //初始化 int InitContact_grade(Crowd *qs); //增容函数 void CheckCapacity_grade(Crowd* qs); //释放内存 void Destroy_Crowd(Crowd* pc); // 增加学生成绩信息 void add_score(Crowd *qs); //输出学生成绩信息 void output_score(Crowd *qs); //删除学生成绩信息 void delete_score(Crowd *qs); //修改学生成绩信息 void modify_score(Crowd *qs); //查询个人成绩 void query_score(Crowd *qs); //总分和平均分处理 void All_avse(Crowd *qs,int num); //根据平均分排序 void sort_avge_score(Crowd *qs); //根据学号排序 void sort_ID_score(Crowd *qs); //保存信息到文件 void Save_Score_File(Crowd *qs); //查看班级平均分 void Class_avge_score(Crowd *qs); #endif