主要功能:
分为三个身份:
学生:可以通过学号查询个人分数
老师:可以看所有学生成绩,单科排名(正序,倒序),统计绩点,查看绩点排名前百分之n的学生
管理员端:可以创建链表,添加修改删除学生数据,并保存数据
学生,老师,管理员密码都为123456
效果图:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*
头插法:36h
登录:91h-
添加学生信息:295h
教师查看学生信息:208h
学生查询成绩:按照要求记录所要的学生信息243h,打印查询到的学生成绩230h
删除学生信息:315h
排序:335h
修改学生信息:527h
绩点:计算绩点,622h:输出需要的前百分之n 的学生绩点,606h*/
typedef struct student {char sno[20];char sname[50];char sex[50];double math;double english;double cs;double score;struct student* next;
} Stu;//头插法
Stu* creatCHead(FILE* fp) {Stu* p, * L;int w;//链表的处理L = (Stu*)malloc(sizeof(Stu));L->next = NULL;fseek(fp, 0, 2);w = ftell(fp);rewind(fp);//不断地读取数据while (w != ftell(fp))//读取txt{p = (Stu*)malloc(sizeof(Stu));fread(p, sizeof(Stu), 1, fp);p->next = L->next;L->next = p;}return L;
}
typedef struct teacher {int sno;char sex;char name[15];char subject;struct teacher* next;
} Tea;//尾插法
Stu* createtail(FILE* fp) {Stu* p, * L, * r;int w;L = (Stu*)malloc(sizeof(Stu));r = L;r->next = NULL;fseek(fp, 0, 2);w = ftell(fp);rewind(fp);while (w != ftell(fp))//读取txt{p = (Stu*)malloc(sizeof(Stu));fread(p, sizeof(Stu), 1, fp);p->next = NULL;r->next = p;r = p;}r->next = NULL;return L;
}void showinfo(char info[])//成功信息
{printf(info);printf("\n");
}void showerror(char errorinfo[])//失败信息
{printf(errorinfo);printf("\n");
}int stuLogin() {char user[50], password[50];printf("请输入学号和学生登录密码:\n");printf("学号:");scanf("%s", &user);printf("密码:");scanf("%s", &password);if (strcmp(password, "123456") == 0) {printf("登陆成功!\n");return 1;}else {printf("登录失败!\n");return 0;}
}int teaLogin() {char user[50], password[50];printf("请输入教师登录密码:\n");printf("登录密码:");scanf("%s", &password);if (strcmp(password, "123456") == 0) {printf("登陆成功!\n");return 1;}else {printf("登录失败!\n");return 0;}
}int adminLogin() {char user[50], password[50];printf("请输入管理员登录密码:");scanf("%s", &password);if (strcmp(password, "123456") == 0) {printf("登陆成功!\n");return 1;}else {printf("登录失败!\n");return 0;}
}void ShowFirstMenu() {printf("*********************欢迎使用期末查分系统********************\n");printf("╔═══════════════════════════════════╗\n");printf("║ 请选择您需要的选项 ║\n");printf("╠═══════════════════════════════════╣\n");printf("║ 1. 学生端 ║\n");printf("║ 2. 教师端 ║\n");printf("║ 3. 管理员端 ║\n");printf("║ 4. 退出系统 ║\n");printf("╚═══════════════════════════════════╝\n");
}void showstudentMeun()//学生页面
{printf("\n\n\n\n\n");printf("\t\t|---------------------STUDENT-------------------|\n");printf("\t\t|\t 0. 退出 |\n");printf("\t\t|\t 1. 查询学生成绩 |\n");printf("\t\t|-----------------------------------------------|\n\n");printf("\t\t\t选择(0或1):");
}void showteacherMeun()//教师页面
{printf("\n\n\n\n\n");printf("\t\t|---------------------TEACHER-------------------|\n");printf("\t\t|\t 0.退出 |\n");printf("\t\t|\t 1.显示数据 |\n");printf("\t\t|\t 2.查询单科成绩排名 |\n");printf("\t\t|\t 3.统计学生绩点 |\n");printf("\t\t|-----------------------------------------------|\n\n");printf("\t\t\t选择(0-3):");
}void showadminMeun()//管理员页面
{printf("\n\n\n\n\n");printf("\t\t|---------------------ADMIN---------------------|\n");printf("\t\t|\t 0. 退出 |\n");printf("\t\t|\t 1. 创建链表 |\n");printf("\t\t|\t 2. 添加数据 |\n");printf("\t\t|\t 3. 删除数据 |\n");printf("\t\t|\t 4. 修改数据 |\n");printf("\t\t|\t 5. 保存数据 |\n");printf("\t\t|-----------------------------------------------|\n\n");printf("\t\t\t选择(0-5):");printf("输入你想要的操作的序号:\n");
}Stu* InputStudent(FILE* fp)//录入学生信息
{int num, i;Stu* L = NULL;Stu* p = NULL;printf("请输入需要录入的学生人数:");scanf("%d", &num);printf("请输入学生信息:\n");printf("学号 姓名 性别 英语 数学 专业课\n");for (i = 0; i < num; i++) {printf("请输入第%d个数据\n", i + 1);p = (Stu*)malloc(sizeof(Stu));scanf("%s %s %s %lf %lf %lf", p->sno, p->sname, p->sex, &p->math, &p->english, &p->cs);fwrite(p, sizeof(Stu), 1, fp);p->next = L;L = p;}printf("学生数据录入成功!\n");return L;
}void Showstudent(Stu* L)//展示学生数据
{printf("学号 姓名 性别 数学成绩 英语成绩 专业课成绩 \n");Stu* p = L->next;while (p)//直到下一个数据为空值,否则一直打印{printf("%s %s %s %.2lf %.2lf %.2lf\n", p->sno, p->sname, p->sex, p->math, p->english, p->cs);p = p->next;}
}void Showteacher(Tea* L)//展示教师数据
{printf("工号 姓名 性别 教授科目\n");Tea* p = L->next;while (p)//直到下一个数据为空值,否则一直打印{printf("%d %s %s %s\n", p->sno, p->name, p->sex, p->subject);p = p->next;}
}void SearchstudentList(Stu* L, int* cnt)//查询学生信息结果
{printf("学号 姓名 性别 数学成绩 英语成绩 专业课成绩 \n");Stu* p = L;while (p && *cnt)//直到下一个数据为空值,否则一直查找{printf("%s %s %s %.2lf %.2lf %.2lf\n", p->sno, p->sname, p->sex, p->math, p->english, p->cs);--* cnt;p = p->next;}
}//查询学生数据
Stu* Searchstudent(Stu* L, int type, char keyval[], char keystr[], int* cnt) {Stu* p = L->next;Stu* ptr = (Stu*)malloc(sizeof(Stu)); // 创建新节点保存查询结果Stu* newstudent = ptr;int flag = 0;while (p != NULL) {if ((type == 1) && (strcmp(p->sno, keyval) == 0)) {newstudent->next = (Stu*)malloc(sizeof(Stu));newstudent = newstudent->next;strcpy(newstudent->sno, p->sno);strcpy(newstudent->sname, p->sname);strcpy(newstudent->sex, p->sex);newstudent->math = p->math;newstudent->english = p->english;newstudent->cs = p->cs;++* cnt;flag = 1;}else if ((type == 2) && (strcmp(p->sname, keystr) == 0)) {newstudent->next = (Stu*)malloc(sizeof(Stu));newstudent = newstudent->next;strcpy(newstudent->sno, p->sno);strcpy(newstudent->sname, p->sname);strcpy(newstudent->sex, p->sex);newstudent->math = p->math;newstudent->english = p->english;newstudent->cs = p->cs;++* cnt;flag = 1;}else if ((type == 3) && (strcmp(p->sex, keystr) == 0)) {newstudent->next = (Stu*)malloc(sizeof(Stu));newstudent = newstudent->next;strcpy(newstudent->sno, p->sno);strcpy(newstudent->sname, p->sname);strcpy(newstudent->sex, p->sex);newstudent->math = p->math;newstudent->english = p->english;newstudent->cs = p->cs;++* cnt;flag = 1;}p = p->next;}if (flag == 0) {return NULL;}return ptr->next;
}void Addstudent(Stu* L)//增添学生信息
{Stu* p, * r, * s = L;int num, i;while (s->next)s = s->next;r = s;printf("请输入要添加的学生的人数:");scanf("%d", &num);printf("学号 姓名 性别 英语 数学 专业课\n");for (i = 0; i < num; i++) {printf("请输入录入的第 %d 数据:\n", i + 1);p = (Stu*)malloc(sizeof(Stu));scanf("%s %s %s %lf %lf %lf", p->sno, p->sname, p->sex, &p->math, &p->english, &p->cs);r->next = p;r = p;}r->next = NULL;
}int Deletestudent(Stu* L, char str[]) {Stu* p, * r;int flag = 0;p = L;while (p->next) {if (strcmp(p->next->sno, str) == 0) {flag = 1;break;}p = p->next;}if (flag) {r = p->next;p->next = r->next;free(r);}return flag;
}//5.数学成绩排序
Stu* showMathorder(Stu* L, int n) {//数学成绩排序Stu* p = L->next, * p1;char sno[50];char sname[50];char sex[50];double math, english, cs;if (n == 1){while (p){p1 = p;while (p1->next){if (p1->math > p1->next->math){math = p1->next->math;cs = p1->next->cs;strcpy(sname, p1->next->sname);english = p1->next->english;strcpy(sno, p1->next->sno);strcpy(sex, p1->next->sex);p1->next->math = p1->math;p1->next->cs = p1->cs;p1->next->english = p1->english;strcpy(p1->next->sname, p1->sname);strcpy(p1->next->sno, p1->sno);strcpy(p1->next->sex, p1->sex);p1->math = math;p1->cs = cs;p1->english = english;strcpy(p1->sname, sname);strcpy(p1->sno, sno);strcpy(p1->sex, sex);}p1 = p1->next;}p = p->next;}return L;}else if (n == 2){while (p){p1 = p;while (p1->next){if (p1->math < p1->next->math){math = p1->next->math;cs = p1->next->cs;strcpy(sname, p1->next->sname);english = p1->next->english;strcpy(sno, p1->next->sno);strcpy(sex, p1->next->sex);p1->next->math = p1->math;p1->next->cs = p1->cs;p1->next->english = p1->english;strcpy(p1->next->sname, p1->sname);strcpy(p1->next->sno, p1->sno);strcpy(p1->next->sex, p1->sex);p1->math = math;p1->cs = cs;p1->english = english;strcpy(p1->sname, sname);strcpy(p1->sno, sno);strcpy(p1->sex, sex);}p1 = p1->next;}p = p->next;}return L;}
}
void showmathorder(Stu* L, int n) {int swapped;Stu* ptr1; Stu* ptr2 = NULL; Stu* prev = NULL; // 检查链表是否为空或只有一个节点if (L == NULL || L->next == NULL)return;do {swapped = 0;ptr1 = L->next;while (ptr1->next != ptr2) {// 比较if ((n == 1 && ptr1->math > ptr1->next->math) || (n == 2 && ptr1->math < ptr1->next->math)) {// 交换节点数据Stu* temp = ptr1->next;ptr1->next = temp->next;temp->next = ptr1;if (ptr1 == L->next)L->next = temp;else {prev->next = temp;}ptr1 = temp;swapped = 1;}prev = ptr1; ptr1 = ptr1->next;}ptr2 = ptr1; } while (swapped);
}void showenglishorder(Stu* L, int n) {int swapped;Stu* ptr1; Stu* ptr2 = NULL;Stu* prev = NULL; if (L == NULL || L->next == NULL)return;do {swapped = 0;ptr1 = L->next;while (ptr1->next != ptr2) {// 比较if ((n == 1 && ptr1->english > ptr1->next->english) || (n == 2 && ptr1->english < ptr1->next->english)) {// 交换节点数据Stu* temp = ptr1->next;ptr1->next = temp->next;temp->next = ptr1;// 更新头节点的位置if (ptr1 == L->next)L->next = temp;else {prev->next = temp;}ptr1 = temp;swapped = 1;}prev = ptr1; ptr1 = ptr1->next;}ptr2 = ptr1; } while (swapped);
}void showcsorder(Stu* L, int n) {int swapped; Stu* ptr1; Stu* ptr2 = NULL; Stu* prev = NULL; // 检查链表是否为空或只有一个节点if (L == NULL || L->next == NULL)return;do {swapped = 0;ptr1 = L->next; while (ptr1->next != ptr2) {// 比较if ((n == 1 && ptr1->cs > ptr1->next->cs) || (n == 2 && ptr1->cs < ptr1->next->cs)) {// 交换节点数据Stu* temp = ptr1->next;ptr1->next = temp->next;temp->next = ptr1; if (ptr1 == L->next)L->next = temp;else {prev->next = temp;}ptr1 = temp;swapped = 1;}prev = ptr1;ptr1 = ptr1->next;}ptr2 = ptr1; } while (swapped);
}int Revisestudent(Stu* L, char no[]) {Stu* p = L;char sname[50];char sex[50];double english, math, cs;int flag = 0;while (p) {if (strcmp(p->sno, no) == 0) {printf("请输入修改后的姓名:");scanf("%s", sname);printf("请输入修改后的性别:");scanf("%s", sex);printf("请输入修改后的数学成绩:");scanf("%lf", &math);printf("请输入修改后的英语成绩:");scanf("%lf", &english);printf("请输入修改后的专业课成绩:");scanf("%lf", &cs);// 修改相关数据strcpy(p->sname, sname);strcpy(p->sex, sex);p->math = math;p->english = english;p->cs = cs;flag = 1;break;}p = p->next;}return flag;
}void SavestudentData(FILE* fp, Stu* L) {Stu* p = L->next;rewind(fp);while (p) {fwrite(p, sizeof(Stu), 1, fp);p = p->next;}fclose(fp);
}void sortByScore(Stu* L) {int swapped; //用于判断每次循环是否进行了排序,如果没有,就说明那个已经有序,提前结束Stu* ptr1; // 指向当前比较的节点,用于比较当前节点和下一个节点的值,并进行节点交换Stu* ptr2 = NULL; // 标记节点,确定已经排序好的节点的位置Stu* prev = NULL; // 指向 ptr1 的前一个节点if (L == NULL || L->next == NULL)return;do {swapped = 0;ptr1 = L->next; while (ptr1->next != ptr2) {// 比较if (ptr1->score < ptr1->next->score) {// 交换节点数据Stu* temp = ptr1->next;ptr1->next = temp->next;temp->next = ptr1; if (ptr1 == L->next)L->next = temp;else {prev->next = temp;}ptr1 = temp;swapped = 1;}prev = ptr1; ptr1 = ptr1->next;}ptr2 = ptr1; } while (swapped);
}void printTopNPercent(Stu* L, int n) {int count = 0;Stu* current = L->next;while (current != NULL) {count++;current = current->next;}int numStudents = count * n / 100; // 计算需要输出的学生数量printf("Top %d%% 学生:\n", n);current = L->next;for (int i = 0; i < numStudents && current != NULL; i++) {printf("%s\t%s\t%s\t%.2f\n", current->sno, current->sname, current->sex, current->score);current = current->next;}
}void CountGrade(Stu* L, int n) {Stu* current = L->next;while (current != NULL) {double math = current->math / 10.0;double english = current->english / 10.0;double cs = current->cs / 10.0;double gpa = (math + english + cs - 15.0) / 3.0;current->score = gpa;current = current->next;}sortByScore(L);printTopNPercent(L, n);
}int main() {FILE* cfp = NULL, * efp = NULL, * sfp = NULL;int flag1 = 0;int flag2 = 0;int flag3 = 0;int result = 0, sel1 = 0, sel2 = 0, cmenuflag = 1, emenuflag = 1, cdeleteflag = 0, edeleteflag = 0, etype = 0, ctype = 0, sorttype = 0, sort = 0, cflag = 0;Stu* CCHead = NULL;int s, j, k, n = 0;int sorttype1 = 0;int sorttype2 = 0;Stu* CHead = NULL;int choice = 0;int choicetype = 0;int b = 0;int frontn = 0;char cname = 0;char del[50], ssex[50], ssname[50], snum[50];do {ShowFirstMenu();scanf("%d", &choice);switch (choice) {case 1:flag1 = stuLogin();if (flag1 == 0) continue;cmenuflag = 1;while (cmenuflag) {showstudentMeun();//学生页面;scanf("%d", &s);switch (s) {case 1://学生端多种方式查询if (CHead == NULL) {showerror("请先创建链表");}else {printf("请输入您想查询的方式\n1.按照学生学号查询\n2.按照学生姓名查询\n3.按照性别查询\n");printf("您的选择是:");scanf("%d", &choicetype);if (choicetype == 1) {int* cnt = malloc(sizeof(int));*cnt = 0;printf("请输入您想查询的学生学号:");scanf("%s", snum);CCHead = Searchstudent(CHead, choicetype, snum, NULL, cnt);if (CCHead != NULL) {showinfo("查询成功");SearchstudentList(CCHead, cnt);}elseshowerror("查询失败");free(cnt);}else if (choicetype == 2) {int* cnt = malloc(sizeof(int));*cnt = 0;printf("请输入您想查询的学生姓名:");scanf("%s", ssname);CCHead = Searchstudent(CHead, choicetype, NULL, ssname, cnt);if (CCHead != NULL) {showinfo("查询成功");SearchstudentList(CCHead, cnt);}elseshowerror("查询失败");free(cnt);}else if (choicetype == 3) {int* cnt = malloc(sizeof(int));*cnt = 0;printf("请输入您想查询的学生性别:");scanf("%s", ssex);CCHead = Searchstudent(CHead, choicetype, NULL, ssex, cnt);if (CCHead != NULL) {showinfo("查询成功");SearchstudentList(CCHead, cnt);}elseshowerror("查询失败");free(cnt);}elseshowerror("无效的查询方式");}break;case 0://退出系统cmenuflag = 0;break;default:cmenuflag = 0;printf("无效的选项!\n");break;}}break;case 2://教师页面flag2 = teaLogin();if (flag2 == 0) continue;cmenuflag = 1;while (cmenuflag) {showteacherMeun();scanf("%d", &j);switch (j) {case 1:if (CHead == NULL)showerror("请先创建链表");elseShowstudent(CHead);break;case 2:printf("1,数学成绩排名\n2,英语成绩排名\n3,专业课成绩排名\n");printf("请输入你要查询的科目编号:");scanf("%d", &k);switch (k) {case 1:if (CHead == NULL)showerror("请先创建链表");else {printf("请输入排序方式:1.升序 2.降序\n");printf("您的选择是:");scanf("%d", &sorttype);if (sorttype == 1) {showmathorder(CHead, sorttype);if (CHead) {showinfo("排序成功");Showstudent(CHead);}elseshowerror("排序失败");}else if (sorttype == 2) {showmathorder(CHead, sorttype);if (CHead) {showinfo("排序成功");Showstudent(CHead);}elseshowerror("排序失败");}elseprintf("无效的排序方式");}break;case 2:if (CHead == NULL)showerror("请先创建链表");else {printf("请输入排序方式:1.升序 2.降序\n");printf("您的选择是:");scanf("%d", &sorttype2);if (sorttype2 == 1) {showenglishorder(CHead, sorttype2);if (CHead) {showinfo("排序成功");Showstudent(CHead);}elseshowerror("排序失败");}else if (sorttype2 == 2) {showenglishorder(CHead, sorttype2);if (CHead) {showinfo("排序成功");Showstudent(CHead);}elseshowerror("排序失败");}elseprintf("无效的排序方式");}break;case 3:if (CHead == NULL)showerror("请先创建链表");else {printf("请输入排序方式:1.升序 2.降序\n");printf("您的选择是:");scanf("%d", &sorttype1);if (sorttype1 == 1) {showcsorder(CHead, sorttype1);if (CHead) {showinfo("排序成功");Showstudent(CHead);}elseshowerror("排序失败");}else if (sorttype1 == 2) {showcsorder(CHead, sorttype1);if (CHead) {Showstudent(CHead);showinfo("排序成功");}elseshowerror("排序失败");}elseprintf("无效的排序方式");}break;}break;case 3:// 统计学生绩点if (CHead == NULL)showerror("请先创建链表");else {printf("请输入要查看的前n%\n");scanf("%d", &n);CountGrade(CHead, n);}break;case 0://退出系统cmenuflag = 0;break;default:cmenuflag = 0;printf("无效的选项!\n");break;}}break;case 3:flag3 = adminLogin();if (flag3 == 0) continue;if ((cfp = fopen("student.txt", "r")) == NULL) {printf("未找到文件\n");if ((cfp = fopen("student.txt", "w+")) != NULL)CHead = InputStudent(cfp);}cmenuflag = 1;while (cmenuflag) {showadminMeun();scanf("%d", &n);switch (n) {case 1://创建链表printf("请输入您想创建的方式\n1.表示头插法\n2.表示尾插法\n");printf("您的选择是:");scanf("%d", &b);if (b == 1)CHead = creatCHead(cfp);//头结点创建链表elseCHead = createtail(cfp);//尾结点创建链表if (CHead)showinfo("创建成功");elseshowerror("创建失败");break;case 2:if (CHead == NULL)showerror("请先创建链表");elseAddstudent(CHead);if (CHead)showinfo("添加成功");elseshowerror("添加失败");break;case 3://删除学生数据if (CHead == NULL)showerror("请先创建链表");else {printf("请输入您想删除的学生信息的学号:");scanf("%s", del);cdeleteflag = Deletestudent(CHead, del);if (cdeleteflag == 1)showinfo("删除成功");elseshowerror("删除失败");}break;case 4:if (CHead == NULL)showerror("请先创建链表");else {printf("请输入您要修改的学生的学号:");scanf("%s", snum);cflag = Revisestudent(CHead, snum);if (cflag == 1)showinfo("修改成功");elseshowerror("修改失败");}break;case 5:if (CHead == NULL)showerror("请先创建链表");else {cfp = fopen("student.txt", "wb");SavestudentData(cfp, CHead);}if (CHead)showinfo("保存成功");elseshowerror("保存失败");break;case 0:cmenuflag = 0;break;default:cmenuflag = 0;printf("无效的选项!\n");break;}}break;case 4:return 0;}} while (1);
}