学生管理系统
一.平台开发环境
Linux 系统 + gcc + gdb + make
二. 相关结构信息学生信息:
基本数据信息:学号: int
姓名: char 128
密码: char 32
年龄: int
班级: int成绩信息:
数学成绩: int
C语言成绩:int
语文成绩:int
名次:int
三.功能描述
使用终端命令界面,作为系统的输入输出界面3.1登录功能
登录功能:
学生的账户,密码
老师的账户,密码1.系统启动后提示登录界面。使用用户名和密码登录。学生和老师都可登录
2.用户名和密码正确登录成功,显示欢迎界面:"欢迎 XX 同学(老师)登录"显示操作界面
3.如果输入用户名和密码错误连续提示,超过3次自动退出
3.2学生功能:
1.实现对学生信息基本信息的录入,其中名次根据成绩自动计算(添加).学号不能重复2.删除学生信息
3.修改学生信息
4.查找学生信息a .根据学号查找
b .根据姓名查找
c .根据班级群体查找,把属于这个班的学生全部显示5.显示所有学生信息列表
a .按学号顺序显示
b .按名次显示
c .按某学科(可选)成绩顺序显示,并在最后显示出此科平均分6.退出系统
四.项目实施计划
a .完成学生信息管理的部分
五.项目要求
1.使用 Makefile 对项目进行编译2.参考代码存放到不同文件中
3.main. c 、 menu . c 、 student . c 、 student . h 、 Makefile
4.完成作业后,运行程序展示结果,录屏对结果进行讲解
5.上交内容:
程序,视频讲解
验收时间:6月16号项目验收报告:
01.流程图
02.项目代码截图
03.项目代码源码:
03_01main.c
#include "student.h" int main(){ //手动申请教师系统和学生系统内存 p_TeacherManager p_T=create_teachermanager(); p_StudentManager p_S=create_studentmanager(); //初始化教师系统和学生系统 init_teacher_manager(p_T); init_student_manager(p_S); //输入教师和学生的信息 p_T=input_teacher(p_T); p_S=input_student(p_S); login_menu(p_S,p_T); // 释放教师系统和学生系统内存 #if 1 destroy_teachermanager(p_T); destroy_studentmanager(p_S); #endif return 0; }
03_02.menu.c
#include "student.h" void login_menu(p_StudentManager p_S,p_TeacherManager p_T) { int attempts=0; char username[MAX_NAME_LEN]; char password[MAX_PASSWORD_LEN]; while(attempts<3){ printf("请输入用户名:"); scanf("%s",username); printf("请输入密码:"); scanf("%s",password); if(authenticate_student(p_S,username,password)){ printf("欢迎%s同学登录\n",username); student_menu(p_S); return; }else if(authenticate_teacher(p_T,username,password)){ printf("欢迎%s老师登录\n",username); student_menu(p_S); return; }else{ attempts++; printf("用户名或者密码错误,您还有%d次尝试机会!\n",3-attempts); } } printf("尝试次数过多,自动退出系统!\n"); } //用来验证学生身份 int authenticate_student(p_StudentManager p_S,const char*username,const char*password) { for(int i=0;i<p_S->count;++i){ if(strcmp(p_S->students[i].name,username)==0&&strcmp(p_S->students[i].password,password)==0){ return 1; } } return 0; } //用来验证教师身份 int authenticate_teacher(p_TeacherManager p_T,const char*username,const char*password){ for(int i=0;i<p_T->count;++i){ if(strcmp(p_T->teachers[i].username,username)==0&&strcmp(p_T->teachers[i].password,password)==0){ return 1; } } return 0; }
03_03.student.c
#include "student.h" //手动申请教师系统内存 p_TeacherManager create_teachermanager() { p_TeacherManager p_T=(p_TeacherManager)malloc(sizeof(TeacherManager)); if(p_T==NULL){ return NULL; } memset(p_T,0,sizeof(TeacherManager)); return p_T; } //手动申请学生系统内存 p_StudentManager create_studentmanager() { p_StudentManager p_S=(p_StudentManager)malloc(sizeof(StudentManager)); if(p_S==NULL){ return NULL; } memset(p_S,0,sizeof(StudentManager)); return p_S; } int empty_teachermanager(p_TeacherManager p_T) { if(p_T==NULL){ printf("入参为空\n"); return -2; } return p_T->count==0?1:0; } int full_teachermanager(p_TeacherManager p_T) { if(p_T==NULL){ printf("入参为空\n"); return -2; } return p_T->count==MAX_TEACHERS?1:0; } int empty_studentmanager(p_StudentManager p_S) { if(p_S==NULL){ printf("入参为空\n"); return -2; } return p_S->count==0?1:0; } int full_studentmanager(p_StudentManager p_S) { if(p_S==NULL){ printf("入参为空\n"); return -2; } return p_S->count==MAX_STUDENTS?1:0; } //输入老师的信息 p_TeacherManager input_teacher(p_TeacherManager p_T) { printf("请向教师列表中填入需要填入教师信息的个数:"); scanf("%d",&p_T->len); for(int i=0;i<p_T->len;++i){ printf("请输入教师的用户名:"); scanf("%s",p_T->teachers[i].username); printf("请输入教师的密码:"); scanf("%s",p_T->teachers[i].password); p_T->count++; } return p_T; } //输入学生的信息 p_StudentManager input_student(p_StudentManager p_S) { printf("请向学生列表中填入需要填入学生信息的个数:"); scanf("%d",&p_S->len); for(int i=0;i<p_S->len;++i){ printf("请输入学生学号:"); scanf("%d",&p_S->students[i].student_id); printf("请输入学生姓名:"); scanf("%s",p_S->students[i].name); printf("请输入学生密码:"); scanf("%s",p_S->students[i].password); printf("请输入学生年龄:"); scanf("%d",&p_S->students[i].age); printf("请输入学生班级:"); scanf("%d",&p_S->students[i].sclass); printf("请输入学生数学成绩:"); scanf("%d",&p_S->students[i].score.math); printf("请输入学生C语言成绩:"); scanf("%d",&p_S->students[i].score.c_language); printf("请输入学生语文成绩:"); scanf("%d",&p_S->students[i].score.chinese); p_S->count++; //应该添加 calculate_ranks函数 增加学生的排名 calculate_ranks(p_S); } return p_S; } //初始化学生管理系统结构体 void init_student_manager(p_StudentManager p_S) { p_S->count=0; } //初始化教师管理系统 void init_teacher_manager(p_TeacherManager p_T) { p_T->count=0; } //检查学生学号是否重复 int is_student_id_duplicate(p_StudentManager p_S,int student_id) { for(int i=0;i<p_S->count;++i){ if(p_S->students[i].student_id==student_id){ return 1; } } return 0; } //学生操作菜单 void student_menu(p_StudentManager p_S) { int choice; do{ printf("---------------------学生操作菜单------------------------\n"); printf("1.录入学生信息\n"); printf("2.删除学生信息\n"); printf("3.修改学生信息\n"); printf("4.查找学生信息\n"); printf("5.显示所有信息\n"); printf("6.退出系统\n"); scanf("%d",&choice); switch(choice){ case 1: add_student(p_S); break; case 2: delete_student(p_S); break; case 3: modify_student(p_S); break; case 4: find_student(p_S); break; case 5: display_all_student(p_S); break; case 6: printf("退出操作系统!\n"); break; default: printf("无效选择,请重新输入!\n"); } }while(choice!=6); } //添加学生信息 p_StudentManager add_student(p_StudentManager p_S) { if(p_S->count>=MAX_STUDENTS){ printf("学生信息已满,无法添加.\n"); return p_S; } //添加新学生信息 p_Student q_S=&p_S->students[p_S->count]; printf("请输入学号:"); scanf("%d",&q_S->student_id); if(is_student_id_duplicate(p_S,q_S->student_id)){ printf("学号重复,添加失败\n"); return p_S; } printf("请输入学生姓名:"); scanf("%s",q_S->name); printf("请输入学生密码:"); scanf("%s",q_S->password); printf("请输入学生年龄:"); scanf("%d",&q_S->age); printf("请输入学生班级:"); scanf("%d",&q_S->sclass); printf("请输入学生数学成绩:"); scanf("%d",&q_S->score.math); printf("请输入学生C语言成绩:"); scanf("%d",&q_S->score.c_language); printf("请输入学生语文成绩:"); scanf("%d",&q_S->score.chinese); p_S->count++; //应该添加 calculate_ranks函数 增加学生的排名 calculate_ranks(p_S); printf("学生信息添加成功.\n"); return p_S; } p_StudentManager calculate_ranks(p_StudentManager p_S) { if(p_S->count==0)return p_S; Student temp[MAX_STUDENTS]; memcpy(temp,p_S->students,sizeof(Student)*p_S->count); //按总分排名 for(int i=0;i<p_S->count-1;++i){ for(int j=i+1;j<p_S->count;++j){ int total_i=temp[i].score.math+temp[i].score.c_language+temp[i].score.chinese; int total_j=temp[j].score.math+temp[j].score.c_language+temp[j].score.chinese; if(total_i<total_j){ Student swap=temp[i]; temp[i]=temp[j]; temp[j]=swap; } } } //分配名次 for(int i=0;i<p_S->count;++i){ for(int j=0;j<p_S->count;++j){ if(p_S->students[j].student_id==temp[i].student_id){ p_S->students[j].score.rank=i+1; break; } } } return p_S; } //删除学生信息 p_StudentManager delete_student(p_StudentManager p_S) { int student_id; printf("请输入要删除的学生号:"); scanf("%d",&student_id); while(getchar()!='\n'); for(int i=0;i<p_S->count;++i){ if(p_S->students[i].student_id==student_id){ for(int j=i;j<p_S->count-1;j++){ p_S->students[j]=p_S->students[j+1]; } p_S->count--; calculate_ranks(p_S); printf("学生信息删除成功\n"); return p_S; } } printf("未找到该学号的学生信息,删除失败!\n"); return p_S; } //修改学生信息 p_StudentManager modify_student(p_StudentManager p_S) { int student_id; printf("请输入要修改的学生学号:\n"); scanf("%d",&student_id); while(getchar()!='\n'); for(int i=0;i<p_S->count;++i){ if(p_S->students[i].student_id==student_id){ printf("请输入新的名字:"); scanf("%s",p_S->students[i].name); printf("请输入新的密码:"); scanf("%s",p_S->students[i].password); printf("请输入新的年龄:"); scanf("%d",&p_S->students[i].age); printf("请输入新的班级:"); scanf("%d",&p_S->students[i].sclass); printf("请输入新的数学成绩:"); scanf("%d",&p_S->students[i].score.math); printf("请输入新的C语言成绩:"); scanf("%d",&p_S->students[i].score.c_language); printf("请输入新的语文成绩:"); scanf("%d",&p_S->students[i].score.chinese); calculate_ranks(p_S); printf("学生信息修改成功.\n"); return p_S; } printf("未找到该学生的信息,修改失败!\n"); return p_S; } } void find_student(p_StudentManager p_S) { int choice; printf("-------------------请选择查找方式------------------------\n"); printf("1.根据学号查找:\n"); printf("2.根据姓名查找:\n"); printf("3.根据班级群体查找:\n"); scanf("%d",&choice); while(getchar()!='\n'); switch(choice){ case 1:{ int student_id; printf("请输入要查找学生的学号:"); scanf("%d",&student_id); int found=0; while(getchar()!='\n'); for(int i=0;i<p_S->count;i++){ if(p_S->students[i].student_id==student_id){ printf("学号:%d\t姓名:%s\t年龄:%d\t班级:%d\t数学成绩:%d\tC语言成绩:%d\t语文成绩:%d\t名次:%d\n", p_S->students[i].student_id,p_S->students[i].name,p_S->students[i].age, p_S->students[i].sclass,p_S->students[i].score.math, p_S->students[i].score.c_language,p_S->students[i].score.chinese, p_S->students[i].score.rank); found=1; } } if(!found){ printf("未找到该姓名的学生信息.\n"); } break; } case 2:{ char name[MAX_NAME_LEN]; printf("请输入要查找学生的姓名:"); scanf("%s",name); while(getchar()!='\n'); int found=0; for(int i=0;i<p_S->count;++i){ if(strcmp(p_S->students[i].name,name)==0){ printf("学号:%d\t姓名:%s\t年龄:%d\t班级:%d\t数学成绩:%d\tC语言成绩:%d\t语文成绩:%d\t名次:%d\n", p_S->students[i].student_id,p_S->students[i].name,p_S->students[i].age, p_S->students[i].sclass,p_S->students[i].score.math, p_S->students[i].score.c_language,p_S->students[i].score.chinese, p_S->students[i].score.rank); found=1; } } if(!found){ printf("未找到该姓名的学生信息.\n"); } break; } case 3:{ int sclass; printf("请输入要查找的班级:"); scanf("%d",&sclass); int found=0; while(getchar()!='\n'); for(int i=0;i<p_S->count;i++){ if(p_S->students[i].sclass==sclass){ printf("学号:%d\t姓名:%s\t年龄:%d\t班级:%d\t数学成绩:%d\tC语言成绩:%d\t语文成绩:%d\t名次:%d\n", p_S->students[i].student_id,p_S->students[i].name,p_S->students[i].age, p_S->students[i].sclass,p_S->students[i].score.math, p_S->students[i].score.c_language,p_S->students[i].score.chinese, p_S->students[i].score.rank); found=1; } } if(!found){ printf("未找到该学生的信息.\n"); } break; } default: printf("无效的选择.\n"); } } //比较函数,用于qsort //根据student_id int compare_by_id(const void*a,const void*b) { p_Student s1=(p_Student)a; p_Student s2=(p_Student)b; return s1->student_id-s2->student_id; } //根据名次 int compare_by_rank(const void*a,const void*b) { p_Student s1=(p_Student)a; p_Student s2=(p_Student)b; return s1->score.rank-s2->score.rank; } //根据学科成绩顺序显示,并显示次科平均分 int compare_by_math(const void*a,const void*b) { p_Student s1=(p_Student)a; p_Student s2=(p_Student)b; return s2->score.math-s1->score.math; } int compare_by_c_language(const void*a,const void*b) { p_Student s1=(p_Student)a; p_Student s2=(p_Student)b; return s2->score.c_language-s1->score.c_language; } int compare_by_chinese(const void*a,const void*b) { p_Student s1=(p_Student)a; p_Student s2=(p_Student)b; return s2->score.chinese-s1->score.chinese; } void display_all_student(p_StudentManager p_S) { int choice; printf("------------请选择显示方式--------------\n"); printf("1.按学号顺序显示\n"); printf("2.按名次显示\n"); printf("3.按某学科成绩顺序显示\n"); scanf("%d",&choice); while(getchar()!='\n'); Student temp[MAX_STUDENTS]; memcpy(temp,p_S->students,sizeof(Student)*p_S->count); switch(choice){ case 1: qsort(temp,p_S->count,sizeof(Student),compare_by_id); break; case 2: qsort(temp,p_S->count,sizeof(Student),compare_by_rank); break; case 3:{ int subject_choice; printf("--------------请选择学科------------\n"); printf("1.数学\n"); printf("2.C语言\n"); printf("3.语文\n"); scanf("%d",&subject_choice); switch(subject_choice){ case 1: qsort(temp,p_S->count,sizeof(Student),compare_by_math); break; case 2: qsort(temp,p_S->count,sizeof(Student),compare_by_c_language); break; case 3: qsort(temp,p_S->count,sizeof(Student),compare_by_chinese); break; default: printf("无效选择.\n"); return; } int sum=0; for(int i=0;i<p_S->count;++i) { switch(subject_choice){ case 1: sum+=temp[i].score.math; break; case 2: sum+=temp[i].score.c_language; break; case 3: sum+=temp[i].score.chinese; break; } } printf("该学科的平均分:%.2f\n",(float)sum/p_S->count); break; } default: printf("无效选择.\n"); return; } printf("--------------------------学生统计列表-----------------------\n"); for(int i=0;i<p_S->count;++i) { printf("学号:%d\t姓名:%s\t年龄:%d\t班级:%d\t数学成绩:%d\tC语言成绩:%d\t语文成绩:%d\t名次:%d\n", temp[i].student_id,temp[i].name,temp[i].age,temp[i].sclass,temp[i].score.math, temp[i].score.c_language,temp[i].score.chinese,temp[i].score.rank); } } void destroy_teachermanager(p_TeacherManager p_T) { // 检查指针是否为空,避免对空指针进行 free 操作 if (p_T != NULL) { // 释放动态分配的内存 free(p_T); // 将指针置为 NULL,防止悬空指针 p_T = NULL; } } void destroy_studentmanager(p_StudentManager p_S) { // 检查指针是否为空,避免对空指针进行 free 操作 if (p_S != NULL) { // 释放动态分配的内存 free(p_S); // 将指针置为 NULL,防止悬空指针 p_S = NULL; } }
03_04.student.h
#ifndef __STUDENT_H__ #define __STUDENT_H__ #include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX_NAME_LEN 128 #define MAX_PASSWORD_LEN 32 #define MAX_STUDENTS 1000 #define MAX_TEACHERS 100 #define MAX_ATTEMPTS 3 //每个学生的成绩结构 typedef struct{ int math; int c_language; int chinese; int rank; }Score,*p_Score; //每个学生的基本信息 typedef struct{ int student_id; char name[MAX_NAME_LEN]; char password[MAX_PASSWORD_LEN]; int age; int sclass; Score score; }Student,*p_Student; //每个老师登录信息 typedef struct{ char username[MAX_NAME_LEN]; char password[MAX_PASSWORD_LEN]; }Teacher,*p_Teacher; //学生信息管理系统 typedef struct{ Student students[MAX_STUDENTS]; int count;//统计学生的人数 int len; }StudentManager,*p_StudentManager; //教师信息管理系统 typedef struct{ Teacher teachers[MAX_TEACHERS]; int count;//统计教师的人数 int len; }TeacherManager,*p_TeacherManager; //统计用户登录的状态,没有登录,学生登录,教师登录用枚举 typedef enum{ USER_TYPE_NONE, USER_TYPE_STUDENT, USER_TYPE_TEACHER }UserType; //登录信息表 typedef struct{ UserType user_type;//调用枚举数据 union{ struct{ int student_id; }student; struct{ char username[MAX_NAME_LEN]; }teacher; }user_info;//每个终端只能登录一个用户,用共用体 }SystemState,*p_SystemState; //手动申请教师系统和学生系统内存 p_TeacherManager create_teachermanager(); p_StudentManager create_studentmanager(); //释放教师系统和学生系统内存 void destroy_teachermanager(p_TeacherManager p_T); void destroy_studentmanager(p_StudentManager p_S); int empty_teachermanager(p_TeacherManager p_T); int full_teachermanager(p_TeacherManager p_T); int empty_studentmanager(p_StudentManager p_S); int full_studentmanager(p_StudentManager p_S); //老师输入信息 p_TeacherManager input_teacher(p_TeacherManager p_T); //学生输入信息 p_StudentManager input_student(p_StudentManager p_S); //初始化学生系统和教师管理系统结构体 void init_student_manager(p_StudentManager p_S); void init_teacher_manager(p_TeacherManager p_T); //检查学号是否重复 int is_student_id_duplicate(p_StudentManager p_S,int student_id); //登录功能 int login(p_StudentManager p_S,p_TeacherManager p_T,p_SystemState p_A); //学生操作菜单 入口02 void student_menu(p_StudentManager p_S); //学生信息管理系统 p_StudentManager add_student(p_StudentManager p_S); p_StudentManager delete_student(p_StudentManager p_S); p_StudentManager modify_student(p_StudentManager p_S); void find_student(p_StudentManager p_S); void display_all_student(p_StudentManager p_S); //计算名次 p_StudentManager calculate_ranks(p_StudentManager p_S); //根据名次显示 int compare_by_id(const void*a,const void*b); int compare_by_rank(const void*a,const void*b); int compare_by_math(const void*a,const void*b); int compare_by_c_language(const void*a,const void*b); int compare_by_chinese(const void*a,const void*b); //学生认证 int authenticate_student(p_StudentManager p_S,const char *username,const char *password); //老师认证 int authenticate_teacher(p_TeacherManager p_T,const char *username,const char *password); //登录菜单 入口01 void login_menu(p_StudentManager p_S,p_TeacherManager p_T); #endif
03_05.makefile文件
04.完成学生管理系统的心得
第一:学会两个函数的用法memcpy()和qsort的用法
qsort的用法:
qsort 是 C 标准库 <stdlib.h> 里的一个通用排序函数,用于对数组进行快速排序。它基于快速排序算法实现,平均时间复杂度为 $O(n log n)$,最坏情况下为 $O(n^2)$。 void qsort(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *)); 参数解释 base:指向要排序的数组的第一个元素的指针,类型为 void *,这让 qsort 能处理任意类型的数组。 nmemb:数组中元素的个数,类型为 size_t。 size:数组中每个元素的大小(以字节为单位),类型为 size_t。 compar:一个指向比较函数的指针,用于定义元素间的排序规则。比较函数接收两个 const void * 类型的参数,返回一个整数表示两个元素的大小关系。 比较函数的原型如下:
比较函数的原型如下:
int compar(const void *a, const void *b); 若 a 小于 b,返回负整数。 若 a 等于 b,返回 0。 若 a 大于 b,返回正整数。
#include <stdio.h> #include <stdlib.h> // 比较函数,用于对整数数组排序 int compare_ints(const void *a, const void *b) { const int *pa = (const int *)a; const int *pb = (const int *)b; return (*pa - *pb); } int main() { int arr[] = {5, 3, 8, 4, 2}; int n = sizeof(arr) / sizeof(arr[0]); // 调用 qsort 对数组进行排序 qsort(arr, n, sizeof(int), compare_ints); // 输出排序后的数组 for (int i = 0; i < n; i++) { printf("%d ", arr[i]); } printf("\n"); return 0; }
//示例01:赋值整个数组 #include <stdio.h> #include <string.h> int main() { int src[] = {1, 2, 3, 4, 5}; int dest[5]; // 复制 src 数组到 dest 数组 memcpy(dest, src, sizeof(src)); // 输出复制后的数组 for (int i = 0; i < 5; i++) { printf("%d ", dest[i]); } printf("\n"); return 0; }
//示例02:赋值结构体 #include <stdio.h> #include <string.h> typedef struct { int id; char name[20]; } Person; int main() { Person src = {1, "Alice"}; Person dest; // 复制 src 结构体到 dest 结构体 memcpy(&dest, &src, sizeof(Person)); // 输出复制后的结构体信息 printf("ID: %d, Name: %s\n", dest.id, dest.name); return 0; }
示例 1:定义了一个整数数组 src,使用 memcpy 函数将其内容复制到 dest 数组,复制的字节数为 sizeof(src),即整个数组的大小。
示例 2:定义了一个 Person 结构体,创建 src 结构体实例并初始化,使用 memcpy 函数将 src 结构体的内容复制到 dest 结构体,复制的字节数为 sizeof(Person)。第二:学会一个windows和虚拟机传文件的技巧
sudo cp -r hm /mnt/hgfs/VMshare