C语言学生管理系统
目录
头文件
一、读取教师学生文件
1.读取教师信息文件
2. 读取学生文件
二、开始菜单
三、教师功能实现
1.教师登录
2.教师页面菜单
3.教师查询本班学生信息
四、学生功能实现
五、管理员功能实现
1.管理员登录
2.管理员页面菜单
3.注册教师账号
4.查询年级总成绩
5.录入学生信息
6.删除学生信息
7.修改学生信息
8.修改教师和学生的登录密码
六、其他辅助函数
1.保存教师和学生信息
2.对学生成绩进行排序
七、主函数
总结
新手菜鸟,如有错误,还请指出,欢迎各位大佬不吝赐教~~~
前言:该学生管理系统较为简易,实现的功能有:用户三端登录,即学生端,教师端,管理员端。
学生可以查询个人成绩,修改登录密码;教师可以查询本班学生成绩,修改登录密码;管理员可以查询全年级成绩,注册新入职老师账号密码,增加新的学生信息,修改学生信息,删除学生,修改学生和教师的登录密码。
头文件
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <string.h>typedef struct _Student {char StuNum[20];char Class[10];char StuName[20];double Chinese;double Math;double English;double Total;char StuPassword[6];
}Student; \\定义学生信息的结构体typedef struct Node {Student stu;struct Node* next;
}Node; \\创建学生链表typedef struct _Teacher {char TeaName[20];char TeaClass[10];char TeaPassword[6];
}Teacher; \\定义教师信息的结构体typedef struct _TNode {Teacher tea;struct TNode* next;
}TNode; \\创建教师链表Node* HeadNode;
TNode* THeadNode;char StuNum[20];
char Class[10];
char StuName[20];
double Chinese;
double Math;
double English;
double Total;
char StuPassword[6];char TeaName[20];
char TeaClass[10];
char TeaPassword[6];\\程序中会用到的被调函数
void Welcome();
void Welcome_T(TNode* p);
void Welcome_S(Node* p);
void Welcome_M();
void Logon_T();
void Logon_S();
void Logon_M();
void QueryClassScore(TNode* P);
void QueryScore();
void InputStudent();
void InputTeacher();
void SaveStudent();
void SaveTeacher();
void SaveTeacher();
void DeleteStudent();
void ChangeStudent();
void ReadStudent();
void ReadTeacher();
void ChangeStuPassword();
void ChangeTeaPassword();
void Bubble(Node* HeadNode);
void PrintStudent(Node* HeadNode);Node* HeadNode = NULL;
一、读取教师学生文件
在供用户选择之前,应先将录好的学生信息文件和教师信息文件读取进来,方便后续功能的实现。
1.读取教师信息文件
void ReadTeacher()
{char file[100] = { "D:\\VS项目\\Students Management System\\Teacher.txt" };FILE* fp = fopen(file, "r");TNode* Q = THeadNode/*->next*/;if (fp == NULL){fp = fopen(file, "w+");fclose(fp);}else{while (!feof(fp)){TNode* P = (TNode*)malloc(sizeof(TNode));P->next = NULL;fread(&Q->tea, sizeof(Teacher), 1, fp);while (Q->next != NULL) {Q = Q->next;}Q->next = P;}printf("读取成功\n");}fclose(fp);
}
2. 读取学生文件
与读取教师文件相似,只有文件地址不同,在此不做过多赘述。
二、开始菜单
首先将开始菜单打印出来供用户选择服务,代码如下:
void Welcome() {printf("*****************************************\n");printf("*\t 欢迎使用学生管理系统 \t*\n");printf("*****************************************\n");printf("*\t请输入数字选择登录端或其他服务\t*\n");printf("*****************************************\n");printf("*\t\t1.教师端登录\t\t*\n");printf("*\t\t2.学生端登录\t\t*\n");printf("*\t\t3.管理员端登录\t\t*\n");printf("*\t\t0.退出系统\t\t*\n");printf("*****************************************\n");printf("\n");char Chioce_ID = _getch(); if (Chioce_ID == '1') {system("cls");Logon_T();}else if (Chioce_ID == '2') {system("cls");Logon_S();}else if (Chioce_ID == '3') {system("cls");Logon_M();}else if (Chioce_ID == '0') {exit(0);}else {printf("输入错误,已退出系统,请重新打开选择\n");}
}
注意在此处,我们读取用户所选选项时,用_getch()函数,可以防止误触而导致的程序崩溃。在读取用户的原则后,我们通过switch—case语句来模拟不同情况。
三、教师功能实现
1.教师登录
void Logon_T() {TNode* p = THeadNode->next;printf("老师,您好!\n");printf("请注意:您一共只有三次输入密码的机会~\n");printf("请输入姓名:");scanf("%s", TeaName);while (p != NULL){if (strcmp(TeaName, p->tea.TeaName) == 0){for (int j = 3; j > 0; j--){printf("密码:");int i = 0;char TeaPassword[20];while (1){TeaPassword[i] = _getch();if (TeaPassword[i] == '\r')break;if (TeaPassword[i] == '\b' && i > 0){printf("\b");_putch(' ');printf("\b");TeaPassword[--i] = '\0';continue;}if (TeaPassword[i] == '\b' && i == 0){printf("\b");_putch(' ');printf("\b");i = -1;continue;}i++;printf("*");}TeaPassword[i] = '\0';if (strcmp(TeaPassword, p->tea.TeaPassword) == 0){printf("\n您的密码输入正确,即将进入个人界面!\n");system("pause");system("cls");TNode* P = NULL;Welcome_T(P);}else{if (j == 1)break;printf("\n密码错误,登录失败,请重新输入。\n");printf("\n您还有%d次机会\n", j - 1);}}printf("您已经三次输入错误,即将返回主页面\n");return;}p = p->next;}printf("未查询到该名教师\n");
}
2.教师页面菜单
(在此页面就完成教师登陆密码的修改功能)
void Welcome_T(TNode* P) {printf("*****************************************\n");printf("*\t 请输入数字选择服务 \t*\n");printf("*****************************************\n");printf("*\t 1.查询本班学生信息 \t*\n");printf("*\t\t2.修改密码\t\t*\n");printf("*\t\t0.返回主页面\t\t*\n");printf("*****************************************\n");char n = _getch();while (1){printf("请输入您的选择:");scanf("%s", &n);switch (n){case '1':QueryClassScore(P, THeadNode);break;case '2':printf("请输入您的新密码:");printf("注:密码只能为六位,可包含数字、字母。");scanf("%s", TeaPassword);strcpy(P->tea.TeaPassword, TeaPassword);SaveTeacher();system("pause");printf("更改成功!\n");break;case '0':system("pause");system("cls");Welcome();break;default:printf("\n没有这个选项,请重新选择!\n");break;}}
}
3.教师查询本班学生信息
void QueryClassScore(TNode* P) {Node* p = HeadNode;Node* HeadNode1 = (Node*)malloc(sizeof(Node));HeadNode1->next = NULL;Node* p1 = HeadNode1;while (p->next != NULL){if (strcmp(P->tea.TeaClass, p->stu.Class) == 0){p1 = HeadNode1;Node* p2 = (Node*)malloc(sizeof(Node));p2->next = NULL;p2->stu = p->stu;while (p1->next != NULL){p1 = p1->next;}p1->next = p2;}p = p->next;}Bubble(p1);p1 = p1->next;printf("姓名\t班级\t\t学号\t语文\t数学\t英语\t总分\n");while (p1 != NULL){printf("%s\t%s\t\t%s\t%.1lf\t%.1lf\t%.1lf\t%.1lf\n", p1->stu.StuName, p1->stu.Class, p1->stu.StuNum,p1->stu.Chinese, p1->stu.Math, p1->stu.English, p1->stu.Total);p1 = p1->next;}
}
四、学生功能实现
学生页面菜单,登录和密码修改与教师大致类似,在此不做过多赘述。
但注意在学生查询个人信息时,不仅要比对用户输入的学生姓名,还要比对学生学号,避免因为学生重名而出现的信息错误。
五、管理员功能实现
1.管理员登录
void Logon_M() {printf("管理员,您好!");char a[7] = { "888888" };char b[1000] = { 0 };printf("\n请输入管理员密码:");for (int j = 3; j > 0; j--){int i = 0;while (1) //密码加密操作,输入密码屏幕上显示*{b[i] = _getch();if (b[i] == '\r')break;if (b[i] == '\b' && i > 0){printf("\b");_putch(' ');printf("\b");b[--i] = '\0';continue;}if (b[i] == '\b' && i == 0){printf("\b");_putch(' ');printf("\b");i = -1;continue;}printf("*");i++;}b[i] = '\0';if (strcmp(b, a) == 0){printf("\n您的密码输入正确,即将进入个人界面!\n");system("pause");system("cls");Welcome_M();}else{if (j == 1)break;printf("\n您的密码输入有误,请重新输入。");printf("\n请注意您还有%d次机会", j - 1);printf("\n请输入管理员密码:");}}printf("您已经三次输入错误,即将返回主页面");return;
}
2.管理员页面菜单
void Welcome_M() {printf("*****************************************\n");printf("*\t 请输入数字选择服务 \t*\n");printf("*****************************************\n");printf("*\t 1.注册教师账号 \t*\n");printf("*\t 2.查询年级总成绩 \t*\n");printf("*\t\t3.录入学生信息\t\t*\n");printf("*\t\t4.删除学生信息\t\t*\n");printf("*\t\t5.修改学生信息\t\t*\n"); printf("*\t\t6.修改密码\t\t*\n");printf("*\t\t0.返回主页面\t\t*\n");printf("*****************************************\n");char n;while (1){printf("请输入您的选择:");scanf("%s", &n);switch (n){case '1':InputTeacher();SaveTeacher();break;case '2':PrintStudent(HeadNode);break;case '3':InputStudent();SaveStudent();break; case '4':DeleteStudent();SaveStudent();break;case '5':ChangeStudent();SaveStudent();break;case '6':printf("请输入您要更改教师密码还是学生密码:");printf("\n1.学生 2.教师 3.返回主页面\n");while (1){printf("请输入您的选择:");int n;scanf("%d", &n);switch (n){case 1:ChangeStuPassword();SaveStudent();break;case 2:ChangeTeaPassword();SaveTeacher();break;case 3:system("pause");Welcome_M();break;default:printf("没有这个选择,请重新输入!");break;}}break;case '0':printf("即将返回主界面!");system("pause");system("cls");Welcome();break;default:printf("没有这个选项,请重新输入!");break;}}
}
3.注册教师账号
void InputTeacher() {TNode* New = (TNode*)malloc(sizeof(TNode));New->next = NULL;TNode* p = THeadNode;char TeaName[10];printf("请输入需录入的老师的姓名:");scanf("%s", TeaName);int flag = 0;while (p != NULL){/* printf("\n%s\n", p->tea.TeaName);*/if (strcmp(p->tea.TeaName, TeaName) == 0){printf("该名老师已经在系统内,请勿重复录入\n");system("pause");system("cls");Welcome_M();flag = 1;return;}p = p->next;}if (flag == 0) {strcpy(New->tea.TeaName,TeaName);printf("请输入该名老师所带班级:");scanf("%s", New->tea.TeaClass);printf("请输入该名老师的登录密码:");scanf("%s", New->tea.TeaPassword);p = New;New->next = NULL;SaveTeacher();printf("录入成功\n");}
}
4.查询年级总成绩
void PrintStudent(Node* HeadNode) {Node* node = HeadNode->next;printf("姓名\t学号\t班级\t语文\t数学\t英语\t总分\t密码\n");while (node != NULL) {printf("%s\t%s\t%s\t%.1lf\t%.1lf\t%.1lf\t%.1lf\t%s\n", node->stu.StuName, node->stu.StuNum,node->stu.Class, node->stu.Chinese, node->stu.Math, node->stu.English, node->stu.Total, node->stu.StuPassword);node = node->next;}
}
5.录入学生信息
void InputStudent() {Node* p = HeadNode;Node* NewNode = (Node*)malloc(sizeof(Node));NewNode->next = NULL;while (p->next != NULL) {p = p->next;}p->next = NewNode;printf("*请输入学生学号:");scanf("%s", &NewNode->stu.StuNum);printf("*请输入学生班级:");scanf("%s", NewNode->stu.Class);printf("*请输入学生姓名:");scanf("%s", NewNode->stu.StuName);printf("*请输入学生语文成绩:");scanf("%lf", &NewNode->stu.Chinese);printf("*请输入学生数学成绩:");scanf("%lf", &NewNode->stu.Math);printf("*请输入学生英语成绩:");scanf("%lf", &NewNode->stu.English);NewNode->stu.Total = NewNode->stu.Chinese + NewNode->stu.Math + NewNode->stu.English;printf("*请输入学生登录密码:");scanf("%s", &NewNode->stu.StuPassword);printf("学生成绩录入成功。\n");system("pause");system("cls");
}
在读取用户输入时,对于Name、Number、Class、Password等字符串数组,不需要取地址符;但对于Chinese、Math、English等浮点型数字需要取地址符。
6.删除学生信息
void DeleteStudent() {Node* p = HeadNode;printf("请输入您要删除学生的姓名:");scanf("%s", StuName);printf("请输入您要删除学生的学号:");scanf("%s", StuNum);while (p->next != NULL){if (strcmp(StuName, p->next->stu.StuName) == 0 && strcmp(StuNum, p->next->stu.StuNum) == 0){printf("已找到您要删除的学生,正在删除...\n");p->next = p->next->next;printf("删除成功\n");}p = p->next;}printf("\n未找到该名学生,请检查您的输入是否正确\n");
}
7.修改学生信息
void ChangeStudent() {Node* p = HeadNode->next;printf("请输入您要更改的学生的姓名:");scanf("%s", StuName);printf("请输入您要更改的学生的学号:");scanf("%s", StuNum);while (p->next != NULL){if (strcmp(StuName, p->stu.StuName) == 0 && strcmp(StuNum, p->stu.StuNum) == 0){printf("已找到该名学生,请输入您要更改的内容:");printf("1.班级 2.语文成绩 3.数学成绩 4.英语成绩\n");char n = _getch();scanf("%s", &n);double Score;switch (n){case 1:printf("请输入该名学生新转入的班级:");char Class[10];scanf("%s", Class);strcpy(p->stu.Class, Class);printf("修改成功!");return;break;case 2:printf("请输入该名学生修改后的语文成绩:");scanf("%.1lf", &Score);p->stu.Total -= p->stu.Chinese;p->stu.Chinese = Score;p->stu.Total += p->stu.Chinese;printf("修改成功");return;break;case 4:printf("请输入该名学生修改后的数学成绩:");scanf("%.1lf", &Score);p->stu.Total -= p->stu.Math;p->stu.Math = Score;p->stu.Total += p->stu.Math;printf("修改成功");return;break;case 5:printf("请输入该名学生修改后的英语成绩:");scanf("%.1lf", &Score);p->stu.Total -= p->stu.English;p->stu.English = Score;p->stu.Total += p->stu.English;printf("修改成功");return;break;default:printf("没有这个选项,请重新输入\n");return;break;}}p = p->next;}printf("未找到该名学生");
}
在读取用户输入时,对于Name、Number、Class、Password等字符串数组,不需要取地址符;但对于Chinese、Math、English等浮点型数字需要取地址符。
8.修改教师和学生的登录密码
void ChangeStuPassword()
{Node* p = HeadNode;char StuName[10];printf("请输入您要更改的学生的姓名:");scanf("%s", StuName);char StuNum[20];printf("请输入您要更改的学生的学号:");scanf("%s", StuNum);while (p->next != NULL){if (strcmp(StuName, p/*->next*/->stu.StuName) == 0){printf("请输入该学生的新密码:");scanf("%s", StuPassword);strcpy(p->stu.StuPassword, StuPassword);printf("\n修改成功!");system("pause");return;}p = p->next;}printf("未找到该名学生");
}
以上是修改学生登录密码的代码,修改教师登录密码类似。
六、其他辅助函数
1.保存教师和学生信息
无论是录入教师学生信息、修改删除学生信息还是修改教师学生登录密码,操作之后都需要进行信息的保存,将信息保存在文件内,以便下次读取和操作,即使关闭程序后再次运行,也不会发生信息的丢失和错乱。
//保存学生信息
void SaveStudent() {FILE* fp = fopen("D:\\VS项目\\Students Management System\\Student.txt", "w");if (fp == NULL){printf("文件打开失败!\n");}Node* p = HeadNode->next;while (p){fwrite(&p->stu, sizeof(Student), 1 , fp);p = p->next;}fclose(fp);
}
//保存老师信息
void SaveTeacher()
{FILE* fp = fopen("D:\\VS项目\\Students Management System\\Teacher.txt", "w");if (fp == NULL){printf("文件打开失败!\n");}TNode* p = THeadNode->next;while (p){fwrite(&p->tea, sizeof(Teacher), 1, fp);p = p->next;}fclose(fp);
}
此处最好使用fwrite,fscanf不便于输出二进制文件。
2.对学生成绩进行排序
这里笔者使用的是冒泡排序,你也可以使用其他排序方式~
void Bubble(Node* HeadNode)
{int i, count = 0, num;Node* p = HeadNode;Node* q;Node* tail;while (p->next != NULL){count++;p = p->next;}for (int i = 0; i < count - 1; i++){num = count - i - 1;q = HeadNode->next;p = q->next;tail = HeadNode;while (num--){if (q->stu.Total < p->stu.Total){q->next = p->next;p->next = q;tail->next = p;}tail = tail->next;q = tail->next;p = q->next;}}
}
七、主函数
int main() {HeadNode = (Node*)malloc(sizeof(Node));HeadNode->next = NULL;THeadNode = (TNode*)malloc(sizeof(TNode));THeadNode->next = NULL;ReadStudent();ReadTeacher();Welcome();return 0;
}
总结
以上便是笔者简易版的C语言学生管理系统,在后续的学习中会进行进一步细节的完善和优化。
注:与本篇博客相关的知识:循环,数组,结构体,指针,链表,文件操作等