主要功能:
分为三个身份:
学生:可以通过学号查询个人分数
老师:可以看所有学生成绩,单科排名(正序,倒序),统计绩点,查看绩点排名前百分之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);
}
else
showerror("查询失败");
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);
}
else
showerror("查询失败");
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);
}
else
showerror("查询失败");
free(cnt);
}
else
showerror("无效的查询方式");
}
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("请先创建链表");
else
Showstudent(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);
}
else
showerror("排序失败");
}
else if (sorttype == 2) {
showmathorder(CHead, sorttype);
if (CHead) {
showinfo("排序成功");
Showstudent(CHead);
}
else
showerror("排序失败");
}
else
printf("无效的排序方式");
}
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);
}
else
showerror("排序失败");
}
else if (sorttype2 == 2) {
showenglishorder(CHead, sorttype2);
if (CHead) {
showinfo("排序成功");
Showstudent(CHead);
}
else
showerror("排序失败");
}
else
printf("无效的排序方式");
}
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);
}
else
showerror("排序失败");
}
else if (sorttype1 == 2) {
showcsorder(CHead, sorttype1);
if (CHead) {
Showstudent(CHead);
showinfo("排序成功");
}
else
showerror("排序失败");
}
else
printf("无效的排序方式");
}
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);//头结点创建链表
else
CHead = createtail(cfp);//尾结点创建链表
if (CHead)
showinfo("创建成功");
else
showerror("创建失败");
break;
case 2:
if (CHead == NULL)
showerror("请先创建链表");
else
Addstudent(CHead);
if (CHead)
showinfo("添加成功");
else
showerror("添加失败");
break;
case 3://删除学生数据
if (CHead == NULL)
showerror("请先创建链表");
else {
printf("请输入您想删除的学生信息的学号:");
scanf("%s", del);
cdeleteflag = Deletestudent(CHead, del);
if (cdeleteflag == 1)
showinfo("删除成功");
else
showerror("删除失败");
}
break;
case 4:
if (CHead == NULL)
showerror("请先创建链表");
else {
printf("请输入您要修改的学生的学号:");
scanf("%s", snum);
cflag = Revisestudent(CHead, snum);
if (cflag == 1)
showinfo("修改成功");
else
showerror("修改失败");
}
break;
case 5:
if (CHead == NULL)
showerror("请先创建链表");
else {
cfp = fopen("student.txt", "wb");
SavestudentData(cfp, CHead);
}
if (CHead)
showinfo("保存成功");
else
showerror("保存失败");
break;
case 0:
cmenuflag = 0;
break;
default:
cmenuflag = 0;
printf("无效的选项!\n");
break;
}
}
break;
case 4:
return 0;
}
} while (1);
}