学习完C语言之后,我们可以通过简单写一个学生管理系统来检验自己学的怎么样。很多计算机系大学生都会学到C语言,对于C语言课程的设计作业可能会感到困难,该篇博客的核心点就是带领读者单独完成学生管理系统,此篇博客附有整个学生管理系统的源码。
目录
功能描述
设计过程
函数实现
结构体定义(grade,student,teacher,Sys_student,Sys_teacher)
登录函数(login)
信息的增删改查(insert,search,change,delete)
成绩排序函数(bubblenumber_chinese,bubblenumber_c,bubblenumber_math)
名次排序函数(bubblenumber_rank,rank)
成绩平均分计算函数(grade_chinese,grade_c,grade_math)
文件保存读取函数(saveFile_teacher,readFile_teacher,saveFile_student,readFile_student)
按键交互函数
运行效果
源码分享
功能描述
- 1、学生信息:基本信息有学号、姓名、密码、班级和年龄;成绩信息有数学,C语言,语文和名次
-
实现对学生信息基本信息的录入,其中名次根据成绩自动计算(添加),学号不能重复
-
删除学生信息
-
修改学生信息
-
查找学生信息
-
根据姓名查找
-
根据班级群体查找,把属于这个班的学生全部显示
-
根据学号查找
-
- 显示所有学生信息列表
- 按学号顺序显示
-
按名次显示
-
按某学科(可选)成绩顺序显示,并在最后显示出此科平均分
-
保存学生信息
-
修改后的信息保存到文件中。当程序启动后从文件中读取信息存放至内存
-
在做添加删除修改时信息保存至内才中。(在内存中使用链表或数组…保存)
-
- 退出系统
- 如果有修改操作要提示是否保存
- 2、教师信息:教员序号、教员姓名,教员密码和所任班级。
- 对老师信息的添加、删除、修改、显示、保存。教员序号不能重复
- 3、登录功能
- 系统启动后提示登陆界面。使用用户名和密码登陆。学生和老师都可以登陆
- 用户名和密码正确登陆成功。显示欢迎界面:”欢迎 XX 同学(或老师)登陆”显示操作界面
- 如果输入用户名和密码错误接续提示,超过 3 次程序自动退出
- 除老师和学生外,系统有一个特殊用户超级管理员用户。用户名固定(admin),也可以固定
- 超级管理员、老师和学生有不同的操作界面
- 4、管理权限
- 超级管理员:可以对老师学生做所有操作
- 老师:可以查看自己的信息,和修改自己的密码,可以查看所有学生的信息,修改学生的成绩信息
- 学生:可以查看自己的信息,和修改自己的基本信息
设计过程
实现的功能确实有点多,但学完C语言之后理论可以全部做出来的,该学生系统的流程图如下图所示:
函数实现
结构体定义(grade,student,teacher,Sys_student,Sys_teacher)
实现各个函数之前需要先定义学生student和教师teacher结构体
#define TOTAL_student 100
#define TOTAL_teacher 20
struct Grade
{
int math;
int c_language;
int chinese;
int rank;
}Grade[TOTAL_student];
struct Student
{
int number_student;
char name_student[128];
char password_student[32];
int class_student;
int age;
struct Grade grade;
}Student[TOTAL_student];
struct Teacher
{
int number_teacher;
char name_teacher[128];
char password_teacher[32];
int class_teacher;
}Teacher[TOTAL_teacher];
struct Sys_student
{
struct Student data[TOTAL_student];
int curSize_student;
};
struct Sys_teacher
{
struct Teacher data[TOTAL_teacher];
int curSize_teacher;
};
其中学生成绩信息也使用成绩结构体grade来定义,我们就可以定义出上面的三个结构体。同时,我们依然使用给宏定义来决定学生和老师的最大人数。后面的结构体Sys_teacher,Sys_studen是老师和学生信息的存储容器。
菜单函数(menu)
设计过程中我们列出了各个界面的所有功能,我们可以通过流程图写出每个界面相对应的菜单(menu)函数:
选择界面的menu函数:
menu()
{
printf("********** 学生信息关系系统 **********\n");
printf("********** 1、超级用户界面 **********\n");
printf("********** 2、教师用户界面 **********\n");
printf("********** 3、学生用户界面 **********\n");
printf("********** 4、退出该界面 **********\n");
}
超级用户下的教师用户菜单函数(menu_super_teacher):
menu_super_teacher()
{
printf("********** 1、录入老师信息 **********\n");
printf("********** 2、查找老师信息 **********\n");
printf("********** 3、修改老师信息 **********\n");
printf("********** 4、显示老师信息 **********\n");
printf("********** 5、删除老师信息 **********\n");
printf("********** 6、退出该系统 **********\n");
}
超级用户下的学生用户菜单函数(menu_super_student):
menu_super_student()
{
printf("********** 1、录入学生信息 **********\n");
printf("********** 2、查找学生信息 **********\n");
printf("********** 3、修改学生信息 **********\n");
printf("********** 4、显示学生信息 **********\n");
printf("********** 5、删除学生信息 **********\n");
printf("********** 6、退出该系统 **********\n");
}
教师用户界面(menu_teacher):
menu_teacher()
{
printf("********** 1、查看个人信息 **********\n");
printf("********** 2、修改密码 **********\n");
printf("********** 3、查看学生信息 **********\n");
printf("********** 4、修改学生信息 **********\n");
printf("********** 5、修改成绩信息 **********\n");
printf("********** 6、显示学生信息 **********\n");
printf("********** 7、退出该界面 **********\n");
}
学生用户界面(menu_student):
menu_student()
{
printf("********** 1、查看个人信息 **********\n");
printf("********** 2、修改学生信息 **********\n");
printf("********** 3、退出该界面 **********\n");
}
登录函数(login)
对于登录功能,我们一共有三个不同的用户群体(超级用户,教师用户,学生用户),那么就需要要写三个登录函数(login_super,login_teacher,login_student)。先大概讲一下思路:功能需求是只允许三次机会登录,第四次就会登录失败,这种情况很容易实现,实现允许三次循环后退出整个程序(exit函数实现),如果三次之内登录成功则显示登录成功的提示,输入错误则做一定的错误提醒。对于密码的输入,如果你想要有逼格的话,就可以把代码做成不可视(用*号表示密码)。
//实现密码不可视,用*号表示密码
while ((key = _getch()) != '\r') //实现密码不可见的功能
{
password[count++] = key;
printf("*");
}
超级用户的登录函数(login_super):
void login_super()
{
int i = 3;
while (i) //实现只能登录三次的功能
{
char username[20] = "admin";
char password[7] = "000000";
char key = '0';
int count = 0;
printf("\t\t用户名:");
scanf("%s", username);
printf("\t\t密 码:");
while ((key = _getch()) != '\r') //实现密码不可见的功能
{
password[count++] = key;
printf("*");
}
printf("\n");
if (!strcmp(username, "admin") && !strcmp(password, "000000"))
{
printf("登录成功...\n");
system("pause");
system("cls");
break;
}
else
{
printf("你的账号或密码错误!\n");
printf("登录失败...\n");
}
i--;
printf("你还有%d次机会!\n", i);
if (i == 0)
{
exit(0);
}
}
}
对于教师登录函数(login_teacher)和学生登录函数(login_student)这里不提供源码,因为此篇博客核心点是引领读者能单独完成整个程序,其他登录函数的源码可以在评论留言获取。
信息的增删改查(insert,search,change,delete)
超级用户登录成功之后,就可以选择是学生还是教师,通过上面的流程图可以得知老师和学生都有着同样的操作:录入信息,查看信息,修改信息,删除信息,显示信息,那是不是完成一种群体就相当于完成另一种呢?逻辑是非常相似的,那我这里就提供学生信息的增删改查,教师信息的增删改查的功能函数可以根据下面的学生功能函数作适当的修改,利用读者当前的C语言知识,当然,源码也可以在评论中留言获取。
学生信息的录入(insertData_student):
void insertData_student(struct Sys_student* psys_student, struct Student data)
{
//避免重复编号的插入操作
psys_student->data[psys_student->curSize_student++] = data; //数组插入
}
学生信息的查找(searchData_student):
int searchData_student(struct Sys_student* psys_student, int number)
{
//实现查找学生信息功能
for (int i = 0; i < psys_student->curSize_student; i++)
{
if (number == psys_student->data[i].number_student)
{
return i;
}
}
return -1;
}
学生信息的删除(deleteData_student):
void deleteData_student(struct Sys_student* psys_student, int number)
{
//实现删除学生信息功能的函数功能
//1.找到指定位置
int pos = -1;
for (int i = 0; i < psys_student->curSize_student; i++)
{
if (psys_student->data[i].number_student == number)
{
pos = i;
break;
}
}
//分析讨论结果
if (pos == -1)
{
printf("No Find!....\n");
}
else//2.移动覆盖的方式进行删除
{
for (int i = pos; i < psys_student->curSize_student - 1; i++)
{
psys_student->data[i] = psys_student->data[i + 1];
}
psys_student->curSize_student--;
}
}
学生信息的修改(changrData_student):
void changrData_student(struct Sys_student* psys_student, int number)
{
//实现修改学生基本信息的函数功能
for (int i = 0; i < psys_student->curSize_student; i++)
{
if (number == psys_student->data[i].number_student)
{
printf("请重新输入你的学号、姓名、密码、班级、年龄\n");
scanf("%d %s %s %d %d", &psys_student->data[i].number_student, psys_student->data[i].name_student, psys_student->data[i].password_student, &psys_student->data[i].class_student, &psys_student->data[i].age);
}
}
}
学生信息的显示(printfData_student):
void printfData_student(struct Sys_student* psys_student)
{
//实现打印学生信息的函数功能
printf("学号\t姓名\t密码\t班级\t年龄\t数学成绩 c语言成绩 语文成绩 总成绩 名次\n");
for (int i = 0; i < psys_student->curSize_student; i++)
{
printf("%-8d%-8s%-8s%03d\t%-8d%-9d%-10d%-10d%-9d%-10d\n", psys_student->data[i].number_student, psys_student->data[i].name_student, psys_student->data[i].password_student,
psys_student->data[i].class_student, psys_student->data[i].age, psys_student->data[i].grade.math, psys_student->data[i].grade.c_language,
psys_student->data[i].grade.chinese, psys_student->data[i].grade.math + psys_student->data[i].grade.c_language + psys_student->data[i].grade.chinese, psys_student->data[i].grade.rank);
}
}
学生信息的查找和显示合并(searchData1_student):
void searchData1_student(struct Sys_student* psys_student, int number)
{
//实现查找学生和打印的函数功能
for (int i = 0; i < psys_student->curSize_student; i++)
{
if (number == psys_student->data[i].number_student)
{
printf("学号\t姓名\t密码\t班级\t年龄\t数学成绩 c语言成绩 语文成绩 总成绩\n");
printf("%-8d%-8s%-8s%03d\t%-8d%-9d%-10d%-10d%-10d\n", psys_student->data[i].number_student, psys_student->data[i].name_student, psys_student->data[i].password_student, psys_student->data[i].class_student, psys_student->data[i].age, psys_student->data[i].grade.math,
psys_student->data[i].grade.c_language, psys_student->data[i].grade.chinese, psys_student->data[i].grade.math + psys_student->data[i].grade.c_language + psys_student->data[i].grade.chinese);
}
}
}
教师信息的相关类似功能都可以借鉴于上面的代码写出来,这里就不提供了,有需要的话也可以在评论区留言获取相关函数代码
成绩排序函数(bubblenumber_chinese,bubblenumber_c,bubblenumber_math)
看函数名就知道用的是最简单的冒泡排序对三门成绩进行名次的排序,只需要会一个函数就可以理解如何写出另外两个了,既然是用C语言,这里就给出C语言成绩的名次排序函数。其他两个函数可以在评论区留言获得。
C语言成绩的排序函数(bubblenumber_c):
void bubblenumber_c(struct Sys_student* psys_student)
{
//实现学生c语言成绩信息的冒泡排序功能
for (int i = 0; i < psys_student->curSize_student; i++)
{
for (int j = 0; j < psys_student->curSize_student - 1 - i; j++)
{
if (psys_student->data[j].grade.c_language > psys_student->data[j + 1].grade.c_language)
{
struct Student temp = psys_student->data[j];
psys_student->data[j] = psys_student->data[j + 1];
psys_student->data[j + 1] = temp;
}
}
}
}
名次排序函数(bubblenumber_rank,rank)
显而易见,和上面的成绩排序函数是一样的
void bubblenumber_rank(struct Sys_student* psys_student)
{
//实现学生名次的冒泡排序功能
for (int i = 0; i < psys_student->curSize_student; i++)
{
for (int j = 0; j < psys_student->curSize_student - 1 - i; j++)
{
if (psys_student->data[j].grade.rank > psys_student->data[j + 1].grade.rank)
{
struct Student temp = psys_student->data[j];
psys_student->data[j] = psys_student->data[j + 1];
psys_student->data[j + 1] = temp;
}
}
}
}
总分数的冒泡排序和名次赋值的函数(rank):
void rank(struct Sys_student* psys_student)
{
//实现总分数的冒泡排序和名次赋值的函数功能
int sum[TOTAL_student] = { 0 };
for (int i = 0; i < psys_student->curSize_student; i++)
{
for (int j = 0; j < psys_student->curSize_student - 1 - i; j++)
{
if (psys_student->data[j].grade.sum < psys_student->data[j + 1].grade.sum)
{
struct Student temp = psys_student->data[j];
psys_student->data[j] = psys_student->data[j + 1];
psys_student->data[j + 1] = temp;
}
}
}
for (int i = 0; i < psys_student->curSize_student; i++)
{
sum[i] = psys_student->data[i].grade.sum;
}
for (int i = 0; i < psys_student->curSize_student; i++)
{
psys_student->data[i].grade.rank = i + 1;
}
//for (int i = 0; i < psys_student->curSize_student; i++)
//{
// printf("%d\t", sum[i]);
//}
//printf("\n");
//for (int i = 0; i < psys_student->curSize_student; i++)
//{
// printf("%d\t", psys_student->data[i].grade.rank);
//}
//printf("\n");
}
成绩平均分计算函数(grade_chinese,grade_c,grade_math)
三门成绩平均分计算的逻辑是一样的,那么只需要会一个函数就可以理解如何写出另外两个了,既然是用C语言,这里就给出C语言成绩的求平均分函数。其他两个函数可以在评论区留言获得。
void grade_c(struct Sys_student* psys_student)
{
//实现求c语言成绩平均数的函数功能
int ave = 0;
for (int i = 0; i < psys_student->curSize_student; i++)
{
ave = ave + psys_student->data[i].grade.c_language;
}
printf("%d\n", ave / psys_student->curSize_student);
}
文件保存读取函数(saveFile_teacher,readFile_teacher,saveFile_student,readFile_student)
学C语言必不可少的是文件操作,对于程序录入的学生和老师信息,我们不仅仅是单次使用信息,单次使用数据在程序结束之后就会消失,重新运行之后需要我们重新输入信息,这就是一门复杂的工程了,就很需要写文件操作的相关函数,把学生信息和老师信息保存到文件txt中,方便下一次程序运行读取数据。而学生和老师是类似的,通过学生信息的保存读取函数来写出老师的相关类似函数了,其他两个函数可以在评论区留言获得。
学生信息保存函数(saveFile_student):
void saveFile_student(struct Sys_student* psys_student, const char* Student)
{
FILE* fp = fopen(Student, "w");
for (int i = 0; i < psys_student->curSize_student; i++)
{
fprintf(fp, "%d\t%s\t%s\t%d\t%d\t%d\t%d\t%d\t%d\n", psys_student->data[i].number_student, psys_student->data[i].name_student, psys_student->data[i].password_student, psys_student->data[i].class_student, psys_student->data[i].age, psys_student->data[i].grade.math,
psys_student->data[i].grade.c_language, psys_student->data[i].grade.chinese, psys_student->data[i].grade.math + psys_student->data[i].grade.c_language + psys_student->data[i].grade.math);
}
fclose(fp);
}
学生信息读取函数(readFile_student):
void readFile_student(struct Sys_student* psys_student, const char* Student)
{
FILE* fp = fopen(Student, "r");
if (fp == NULL)
{
return;
}
struct Student temp;
while (fscanf(fp, "%d\t%s\t%s\t%d\t%d\t%d\t%d\t%d\t%d\n", &temp.number_student, temp.name_student, temp.password_student, &temp.class_student, &temp.age, &temp.grade.math, &temp.grade.c_language,
&temp.grade.chinese, &temp.grade.sum) != EOF)
{
insertData_student(psys_student, temp);
}
fclose(fp);
}
按键交互函数
通过上面的流程图每个人都有自己的案件交互函数,无非就是while循环配合switch语句来实现,每个人写出的按键交互函数都不一样,所以这里我就不献丑了,读者可以通过自己的C语言知识写出自己的按键交互函数,不过按键交互函数依然可以在评论区留言获取。
运行效果
此截图并非全部功能展示,如有需求可联系博主获得全部源码
源码分享
因为整个管理系统的代码过于冗杂,不便全部放在博客中,所以这里附上我的主函数代码,全部的源码可以在此篇博客下留下你们的邮箱,我看到会一一发送的。
int main()
{
struct Sys_teacher* psys_teacher = createTeacherSystem();
struct Sys_student* psys_student = createStudentSystem();
int key = 0;
int ret = 0;
readFile_student(psys_student, "Student.txt");
readFile_teacher(psys_teacher, "Teacher.txt");
rank(psys_student);
menu();
scanf("%d", &key);
switch (key)
{
case 1:
login_super(); //超级用户账号,密码输入,判断是否登录成功
printf("欢迎超级用户登陆!\n");
printf("\n\n\n");
printf("请选择你要登陆的界面(1为老师,2为学生):");
scanf("%d", &key);
if (key == 1)
{
keybroad_super_teacher(psys_teacher);
}
if (key == 2)
{
keybroad_super_student(psys_student);
}
break;
case 2:
login_teacher(psys_teacher, &ret); //教师用户账号,密码输入,判断是否登录成功
keybroad_teacher(psys_teacher, psys_student, ret);
break;
case 3:
login_student(psys_student, &ret); //学生用户账号,密码输入,判断是否登录成功
keybroad_student(psys_student, ret);
break;
case 4:
printf("退出系统!\n");
exit(0);
break;
default:
printf("输入错误,请输入1到4的数字!\n");
break;
}
return 0;
}