C语言实现学生信息管理系统(含文件读写)
注:最后有完整代码。
用来应付期末作业那是大大的足够了…
要建立一个学生管理系统,我们需要一些特定的操作,在本次的作业中,我们的学管系统将包含以下功能:
先是菜单的展示:
"***学生管理系统*******\n"
"**************************\n"
"***系统功能菜单*******\n"
"--------------------------\n"
"**************************\n"
"*** 1.增加学生信息 ***\n"
"*** 2.查询学生信息 ***\n"
"*** 3.删除学生信息 ***\n"
"*** 4.修改学生信息 ***\n"
"***** 5.读取文件 *****\n"
"*** 6.显示学生信息 ***\n"
"***** 7.总分详情 *****\n"
"****** 8.菜单帮助 *****\n"
" 9.不合格检索 \n"
" 10.学科详情 \n"
" 11.学校主页 \n"
"***** 0.退出系统 *****\n"
为了避免频繁的调用菜单,所以菜单只会在第一次自动输出,其它次的输出需要手动调用case 8。
再看看结构体的定义:
struct course {
int math;
int computer;
int English;
int PE;
};
struct stu {
char name[100];
int age;
char sex;
struct course subject;
struct stu* next;
char number[20];
int all_scores;
int average_scores;
int idx;
};
下面来具体看看:
一:读取信息库,并存入链表。
FILE* fp = fopen("D:\\Shelly\\OneDrive\\桌面\\无标题.txt", "a+");
int n;
struct stu* head = (struct stu*)malloc(sizeof(struct stu));
head->next = NULL;
menu();
fseek(fp, 0, SEEK_SET);
int frequency = 1;
printf("\n请您先读取文件!!!\n");
printf("\n请您先读取文件!!!\n");
printf("\n请您先读取文件!!!\n");
FILE* fp = fopen("D:\\Shelly\\OneDrive\\桌面\\无标题.txt", "a+");
:这行代码打开一个名为“无标题.txt”的文件,该文件位于“D:\Shelly\OneDrive\桌面”目录下。"a+"表示以追加模式打开文件,在追加模式下,写入的数据会被添加到文件的末尾,而不会覆盖原有的内容。”+"表示文件可以读取和写入。如果文件不存在,则创建一个新文件。
fseek(fp, 0, SEEK_SET);
:这行代码将文件指针fp移动到文件的开始位置,避免文字被覆盖。
注意:我们要确保在程序启动后第一步就是进行一次文件读入,防止后续创建学生信息时会使学生信息重复化。
二:读取文件
case 5: {
if (frequency) {
FILE* ffp = fopen("D:\\Shelly\\OneDrive\\桌面\\无标题.txt", "r");
fseek(fp, 0, SEEK_SET);
struct stu student;
while (fscanf(fp, "姓名:%s 学号:%s 年龄:%d 性别:%c 数学成绩:%d 计算机成绩:%d 英语成绩:%d 体育成绩:%d 总分:%d 平均分:%d\n",
student.name, &(student.number), &(student.age), &(student.sex), &(student.subject.math), &(student.subject.computer),
&(student.subject.English), &(student.subject.PE), &(student.all_scores), &(student.average_scores)) != EOF) {
int k = student.number;
struct stu* p;
p = head;
int index = 0;
for (p; p; p = p->next) {
if (p->number == k) {
index = 1;
break;
}
}
if (index) {
continue;
}
else
{
struct stu* new_stu = (struct stu*)malloc(sizeof(struct stu));
strcpy(new_stu->name, student.name);
strcpy(new_stu->number, student.number);
new_stu->age = student.age;
new_stu->sex = student.sex;
new_stu->subject.math = student.subject.math;
new_stu->subject.computer = student.subject.computer;
new_stu->subject.English = student.subject.English;
new_stu->subject.PE = student.subject.PE;
new_stu->all_scores = new_stu->subject.math + new_stu->subject.computer + new_stu->subject.PE + new_stu->subject.English;
new_stu->average_scores = (new_stu->all_scores) / 4.0;
new_stu->next = head->next;
head->next = new_stu;
}
}
fclose(ffp);
printf("本次文件读取成功,请勿重复读取文件!!!\n");
frequency = 0;
}
else
printf("请勿多次读取文件!!!\n");
break;
}
这部分代码的主要功能是从一个文件中读取学生的信息,并将这些信息添加到链表中。以下是详细的步骤:
if (frequency) { ... }
:这个if
语句检查frequency
变量的值。如果frequency
为非零值(在这个代码中,它被初始化为1),则执行大括号内的代码。这意味着文件只能被读取一次。一旦文件被读取,frequency
就会被设置为0,以防止再次读取。
FILE* ffp = fopen("D:\\Shelly\\OneDrive\\桌面\\无标题.txt", "r");
:这行代码打开一个名为“无标题.txt”的文件,该文件位于“D:\Shelly\OneDrive\桌面”目录下。"r"表示以只读模式打开文件。
fseek(fp, 0, SEEK_SET);
:这行代码将文件指针fp
移动到文件的开始位置。
struct stu student;
:这行代码声明了一个stu
结构体的实例student
。
while (fscanf(fp, "姓名:%s 学号:%s 年龄:%d 性别:%c 数学成绩:%d 计算机成绩:%d 英语成绩:%d 体育成绩:%d 总分:%d 平均分:%d\n", ... ) != EOF) { ... }
:这个while
循环从文件中读取学生的信息,直到到达文件的末尾。每次循环,它都会读取一个学生的所有信息,并将这些信息存储在student
结构体中。
int k = student.number;
:这行代码将学生的学号存储在变量k
中。
struct stu* p; p = head;
:这两行代码声明了一个指向stu
结构体的指针p
,并将其初始化为指向链表的头部。
for (p; p; p = p->next) { ... }
:这个for
循环遍历链表,查找是否已经存在学号为k
的学生。
if (index) { continue; } else { ... }
:如果找到了学号为k
的学生(即index
为1),则跳过当前循环,不会将该学生的信息添加到链表中。否则,将创建一个新的stu
结构体实例,并将其添加到链表的开头。
fclose(ffp);
:这行代码关闭了文件。
printf("本次文件读取成功,请勿重复读取文件!!!\n");
:这行代码打印出一条消息,告知用户文件已经成功读取。
frequency = 0;
:这行代码将frequency
设置为0,以防止再次读取文件。
事实上,为了防止重复读取文件时信息重复化,它被设置为了只允许读一次。
三:增加学生信息
case 1:
{
struct stu* new_stu = (struct stu*)malloc(sizeof(struct stu));
printf("请输入学生姓名:");
scanf("%s", new_stu->name);
printf("请输入学生学号:");
scanf("%s", &(new_stu->number));
printf("请输入学生年龄:");
scanf("%d", &(new_stu->age));
printf("请输入学生性别(M/F):");
scanf(" %c", &(new_stu->sex));
printf("请输入数学成绩:");
scanf("%d", &(new_stu->subject.math));
printf("请输入计算机成绩:");
scanf("%d", &(new_stu->subject.computer));
printf("请输入英语成绩:");
scanf("%d", &(new_stu->subject.English));
printf("请输入体育成绩:");
scanf("%d", &(new_stu->subject.PE));
new_stu->all_scores = new_stu->subject.math + new_stu->subject.computer + new_stu->subject.PE + new_stu->subject.English;
new_stu->average_scores = (new_stu->all_scores) / 4;
new_stu->next = head->next;
head->next = new_stu;
fprintf(fp, "姓名:%s ", new_stu->name);
fprintf(fp, "学号:%s ", new_stu->number);
fprintf(fp, "年龄:%d ", new_stu->age);
fprintf(fp, "性别:%c ", new_stu->sex);
fprintf(fp, "数学成绩:%d ", new_stu->subject.math);
fprintf(fp, "计算机成绩:%d ", new_stu->subject.computer);
fprintf(fp, "英语成绩:%d ", new_stu->subject.English);
fprintf(fp, "体育成绩:%d ", new_stu->subject.PE);
fprintf(fp, "总分:%d ", new_stu->all_scores);
fprintf(fp, "平均分:%d \n", new_stu->average_scores);
fseek(fp, 0, SEEK_SET);
system("cls");
printf("添加学生成功!!!\n");
break;
}
struct stu* new_stu = (struct stu*)malloc(sizeof(struct stu));
:这行代码创建了一个新的stu
结构体实例new_stu
。
printf("请输入学生姓名:"); scanf("%s", new_stu->name);
等:这些行代码从用户那里获取学生的信息,包括姓名、学号、年龄、性别和各科成绩,并将这些信息存储在new_stu
结构体中。
new_stu->all_scores = new_stu->subject.math + new_stu->subject.computer + new_stu->subject.PE + new_stu->subject.English;
:这行代码计算了学生的总成绩。
new_stu->average_scores = (new_stu->all_scores) / 4;
:这行代码计算了学生的平均成绩。
new_stu->next = head->next; head->next = new_stu;
:这两行代码将new_stu
添加到链表的开头。
fprintf(fp, "姓名:%s ", new_stu->name);
等:这些行代码将学生的信息写入一个文件。
fseek(fp, 0, SEEK_SET);
:这行代码将文件指针fp
移动到文件的开始位置,防止覆盖。
system("cls");
:这行代码清除了控制台的屏幕。
printf("添加学生成功!!!\n");
:这行代码打印出一条消息,告知用户学生的信息已经成功添加。
四:查询学生信息
case 2:
{
fseek(fp, 0, SEEK_SET);
printf("请选择你的查询方式:\n");
printf("C(学号查询)||N(姓名查询)\n");
char c;
int index = 0;
scanf(" %c", &c);
struct stu student;
if (c == 'C') {
printf("请输入要查找学生的学号:\n");
char k[20];
scanf("%s", k);
while (fscanf(fp, "姓名:%s 学号:%s 年龄:%d 性别:%c 数学成绩:%d 计算机成绩:%d 英语成绩:%d 体育成绩:%d 总分:%d 平均分:%d\n",
student.name, &(student.number), &(student.age), &(student.sex), &(student.subject.math), &(student.subject.computer),
&(student.subject.English), &(student.subject.PE), &(student.all_scores), &(student.average_scores)) != EOF) {
if (strcmp(student.number, k) == 0) {
index = 1;
break;
}
}
}
if (c == 'N') {
char search_name[100];
printf("请输入要查找的学生姓名:");
scanf("%s", search_name);
while (fscanf(fp, "姓名:%s 学号:%s 年龄:%d 性别:%c 数学成绩:%d 计算机成绩:%d 英语成绩:%d 体育成绩:%d 总分:%d 平均分:%d\n",
student.name, &(student.number), &(student.age), &(student.sex), &(student.subject.math), &(student.subject.computer),
&(student.subject.English), &(student.subject.PE), &(student.all_scores), &(student.average_scores)) != EOF) {
if (strcmp(student.name, search_name) == 0) {
index = 1;
break;
}
}
}
if (index == 0) {
printf("该学生不存在\n");
break;
}
else {
printf("姓名:%s ", student.name);
printf("学号:%s ", student.number);
printf("年龄:%d ", student.age);
printf("性别:%c ", student.sex);
printf("数学成绩:%d ", student.subject.math);
printf("计算机成绩:%d ", student.subject.computer);
printf("英语成绩:%d ", student.subject.English);
printf("体育成绩:%d ", student.subject.PE);
printf("总分:%d ", student.all_scores);
printf("平均分:%d\n", student.average_scores);
break;
}
}
fseek(fp, 0, SEEK_SET);
:这行代码将文件指针fp
移动到文件的开始位置,防止遗漏。
printf("请选择你的查询方式:\n"); printf("C(学号查询)||N(姓名查询)\n");
:这两行代码打印出一个提示,让用户选择查询方式,可以通过学号(C)或姓名(N)进行查询。
char c; int index = 0; scanf(" %c", &c);
:这些代码声明了一个字符变量c
和一个整型变量index
,然后从用户那里获取一个字符输入并存储在c
中。index
被初始化为0,用于标记是否找到了学生。
struct stu student;
:这行代码声明了一个stu
结构体的实例student
。
if (c == 'C') { ... }
:如果用户输入的是’C’,则执行大括号内的代码。这部分代码从文件中读取学生的信息,直到找到学号与用户输入相匹配的学生或到达文件的末尾。
if (c == 'N') { ... }
:如果用户输入的是’N’,则执行大括号内的代码。这部分代码从文件中读取学生的信息,直到找到姓名与用户输入相匹配的学生或到达文件的末尾。
if (index == 0) { ... } else { ... }
:如果index
仍为0,说明没有找到匹配的学生,打印出“该学生不存在”。否则,打印出找到的学生的所有信息。
五:删除学生信息
case 3:
{
printf("请确保在删除前读取过文件!!!\n");
printf("请输入您想要删除学生的学号:\n");
char del_number[20];
getchar();
gets(del_number);
struct stu* p = head;
struct stu* temp;
int index = 0;
for (p; p->next; p = p->next) {
if (strcmp(p->next->number, del_number) == 0) {
temp = p->next;
p->next = p->next->next;
free(temp);
index = 1;
break;
}
}
if (index == 0) {
printf("该学生不存在!");
}
else {
fclose(fp);
fp = fopen("D:\\Shelly\\OneDrive\\桌面\\无标题.txt", "w+");
if (fp == NULL) {
printf("文件打开失败!\n");
return;
}
for (p = head->next; p != NULL; p = p->next) {
fprintf(fp, "姓名:%s 学号:%s 年龄:%d 性别:%c 数学成绩:%d 计算机成绩:%d 英语成绩:%d 体育成绩:%d 总分:%d 平均分:%d\n",
p->name, p->number, p->age, p->sex, p->subject.math, p->subject.computer, p->subject.English, p->subject.PE, p->all_scores, p->average_scores);
fflush(fp);
}
}
system("cls");
printf("删除学生成功!!!\n");
break;
}
printf("请确保在删除前读取过文件!!!\n");
:这行代码打印出一条消息,提醒用户在删除学生信息前需要先读取文件。
printf("请输入您想要删除学生的学号:\n");
:这行代码打印出一条消息,提示用户输入要删除的学生的学号。
char del_number[20]; getchar(); gets(del_number);
:这些代码声明了一个字符数组del_number
,然后从用户那里获取一个字符串输入并存储在del_number
中。
struct stu* p = head; struct stu* temp; int index = 0;
:这些代码声明了两个指向stu
结构体的指针p
和temp
,以及一个整型变量index
。p
被初始化为指向链表的头部,index
被初始化为0,用于标记是否找到了学生。
for (p; p->next; p = p->next) { ... }
:这个for
循环遍历链表,查找学号与用户输入相匹配的学生。
if (strcmp(p->next->number, del_number) == 0) { ... }
:如果找到了学号与用户输入相匹配的学生,则执行大括号内的代码。这部分代码删除了找到的学生节点,并释放了其占用的内存。
if (index == 0) { ... } else { ... }
:如果index
仍为0,说明没有找到匹配的学生,打印出“该学生不存在”。否则,关闭并重新打开文件,然后将链表中剩余的学生信息写入文件。
system("cls");
:这行代码清除了控制台的屏幕。
六:修改学生信息
case 4:
{
printf("请确保在修改前读取过文件!!!\n");
printf("请输入您想要修改学生信息的学号:\n");
char mod_number[20];
getchar();
gets(mod_number);
struct stu* p = head;
struct stu* temp;
int index = 0;
for (p; p->next; p = p->next) {
if (strcmp(p->next->number, mod_number) == 0) {
temp = p->next;
p->next = p->next->next;
free(temp);
index = 1;
break;
}
}
if (index == 0) {
printf("该学生不存在!");
}
else {
printf("请输入修改后的信息:\n");
struct stu* new_stu = (struct stu*)malloc(sizeof(struct stu));
printf("请输入学生姓名:");
scanf("%s", new_stu->name);
printf("请输入学生学号:");
scanf("%s", &(new_stu->number));
printf("请输入学生年龄:");
scanf("%d", &(new_stu->age));
printf("请输入学生性别(M/F):");
scanf(" %c", &(new_stu->sex));
printf("请输入数学成绩:");
scanf("%d", &(new_stu->subject.math));
printf("请输入计算机成绩:");
scanf("%d", &(new_stu->subject.computer));
printf("请输入英语成绩:");
scanf("%d", &(new_stu->subject.English));
printf("请输入体育成绩:");
scanf("%d", &(new_stu->subject.PE));
new_stu->all_scores = new_stu->subject.math + new_stu->subject.computer + new_stu->subject.PE + new_stu->subject.English;
new_stu->average_scores = (new_stu->all_scores) / 4;
new_stu->next = head->next;
head->next = new_stu;
fclose(fp);
fp = fopen("D:\\Shelly\\OneDrive\\桌面\\无标题.txt", "w+");
for (p = head->next; p != NULL; p = p->next) {
fprintf(fp, "姓名:%s 学号:%s 年龄:%d 性别:%c 数学成绩:%d 计算机成绩:%d 英语成绩:%d 体育成绩:%d 总分:%d 平均分:%d\n",
p->name, p->number, p->age, p->sex, p->subject.math, p->subject.computer, p->subject.English, p->subject.PE, p->all_scores, p->average_scores);
}
}
break;
}
本质上就是删除再添加,就不再赘述了。
七:显示学生信息
case 6: {
system("cls");
struct stu* p = head->next;
while (p != NULL) {
printf("姓名:%s ", p->name);
printf("学号:%s ", p->number);
printf("年龄:%d ", p->age);
printf("性别:%c ", p->sex);
printf("数学成绩:%d ", p->subject.math);
printf("计算机成绩:%d ", p->subject.computer);
printf("英语成绩:%d ", p->subject.English);
printf("体育成绩:%d ", p->subject.PE);
printf("总分:%d ", p->all_scores);
printf("平均分:%d\n", p->average_scores);
p = p->next;
}
break;
}
按照链表顺序(无排序)输出。
八:按照总分排序:
链表的排序较为复杂,所以我们采用其他方式:
case 7: {
system("cls");
struct stu* p = head->next;
if (p == NULL) {
printf("学生信息为空!请检查是否读入文件!!!\n");
}
else {
int k = 0;
int arr[1000] = { 0 };
while (p) {
arr[k] = p->all_scores;
p->idx = 1;
p = p->next;
k++;
}
int q = k;
while (q) {
for (int i = 0; i < q - 1; i++) {
if (arr[i] < arr[i + 1]) {
int c = arr[i];
arr[i] = arr[i + 1];
arr[i + 1] = c;
}
}
q--;
}
int j = k, i = 0;
while (j) {
p = head->next;
for (p; p; p = p->next) {
if (p->idx == 1 && p->all_scores == arr[i]) {
printf("姓名:%s ", p->name);
printf("学号:%s ", p->number);
printf("数学成绩:%d ", p->subject.math);
printf("计算机成绩:%d ", p->subject.computer);
printf("英语成绩:%d ", p->subject.English);
printf("体育成绩:%d ", p->subject.PE);
printf("总分:%d ", p->all_scores);
printf("平均分:%d\n", p->average_scores);
p->idx = 0;
i++;
}
}
j--;
}
break;
}
}
system("cls");
:这行代码清除了控制台的屏幕。
struct stu* p = head->next;
:这行代码声明了一个指向stu
结构体的指针p
,并将其初始化为指向链表的第一个节点。
if (p == NULL) { ... } else { ... }
:这个if
语句检查链表是否为空。如果链表为空(即p
为NULL),则打印出一条消息,提示用户检查是否已经读取了文件。否则,执行大括号内的代码。
int k = 0; int arr[1000] = { 0 };
:这两行代码声明了一个整型变量k
和一个整型数组arr
。k
被初始化为0,用于记录链表中的学生数量。arr
被初始化为全0,用于存储学生的总分。
while (p) { ... }
:这个while
循环遍历链表,将每个学生的总分存储在arr
数组中,并将每个学生的idx
字段设置为1。
while (q) { ... }
:这个while
循环对arr
数组进行冒泡排序,使得数组中的元素按照降序排列。
while (j) { ... }
:这个while
循环遍历链表,并按照arr
数组中的顺序打印出学生的信息。
if (p->idx == 1 && p->all_scores == arr[i]) { ... }
:如果找到了总分与arr[i]
相等的学生(即p->idx
为1),则打印出该学生的所有信息,并将p->idx
设置为0。
九:不合格检索
case 9: {
struct stu* p = head->next;
int k = 1;
while (p) {
if (p->subject.math < 90||p->subject.computer<90||p->subject.PE<60||p->subject.English<90) {
k = 0;
printf("姓名:%s 学号:%s ", p->name, p->number);
if (p->subject.math < 90) {
printf("数学成绩:%d ", p->subject.math);
}
if (p->subject.computer < 90) {
printf("计算机成绩:%d ", p->subject.computer);
}
if (p->subject.PE < 60) {
printf("体育成绩:%d ", p->subject.PE);
}
if (p->subject.English < 90) {
printf("英语成绩:%d ", p->subject.English);
}
printf("\n");
}
p = p->next;
}
if (k) {
printf("未检索到不合格学生信息!!!\n");
}
break;
}
struct stu* p = head->next;
:这行代码声明了一个指向stu
结构体的指针p
,并将其初始化为指向链表的第一个节点。
int k = 1;
:这行代码声明了一个整型变量k
,并将其初始化为1。k
用于标记是否所有学生都合格。
while (p) { ... }
:这个while
循环遍历链表中的每个学生。
if (p->subject.math < 90||p->subject.computer<90||p->subject.PE<60||p->subject.English<90) { ... }
:这个if
语句检查学生是否不合格。如果学生的数学、计算机、体育或英语成绩低于一定的分数线,则认为学生不合格。
printf("姓名:%s 学号:%s ", p->name, p->number);
等:这些行代码打印出不合格学生的姓名、学号和不合格的科目成绩。
p = p->next;
:这行代码将p
移动到链表的下一个节点。
if (k) { ... }
:如果所有学生都合格(即k
仍为1),则打印出一条消息,告知用户未检索到不合格学生信息。
十:学科详情
case 10: {
system("cls");
struct stu* p = head->next;
printf("请选择你要查看的学科:\n");
printf("1.math 2.computer 3.English 4.PE\n");
int a;
scanf("%d", &a);
if (a != 1 && a != 2 && a != 3 && a != 4) {
printf("您的输入不规范!!!\n");
break;
}
if (p == NULL) {
printf("学生信息为空!请检查是否读入文件!!!\n");
}
switch (a) {
case 1: {
int k = 0;
int arr[1000] = { 0 };
while (p) {
arr[k] = p->subject.math;
p->idx = 1;
p = p->next;
k++;
}
int q = k;
while (q) {
for (int i = 0; i < q - 1; i++) {
if (arr[i] < arr[i + 1]) {
int c = arr[i];
arr[i] = arr[i + 1];
arr[i + 1] = c;
}
}
q--;
}
int j = k, i = 0;
while (j) {
p = head->next;
for (p; p; p = p->next) {
if (p->idx == 1 && p->subject.math == arr[i]) {
printf("姓名:%s ", p->name);
printf("学号:%s ", p->number);
printf("数学成绩:%d \n", p->subject.math);
p->idx = 0;
i++;
}
}
j--;
}
break;
}
case 2: {
int k = 0;
int arr[1000] = { 0 };
while (p) {
arr[k] = p->subject.computer;
p->idx = 1;
p = p->next;
k++;
}
int q = k;
while (q) {
for (int i = 0; i < q - 1; i++) {
if (arr[i] < arr[i + 1]) {
int c = arr[i];
arr[i] = arr[i + 1];
arr[i + 1] = c;
}
}
q--;
}
int j = k, i = 0;
while (j) {
p = head->next;
for (p; p; p = p->next) {
if (p->idx == 1 && p->subject.computer == arr[i]) {
printf("姓名:%s ", p->name);
printf("学号:%s ", p->number);
printf("计算机成绩:%d \n", p->subject.computer);
p->idx = 0;
i++;
}
}
j--;
}
break;
}
case 3: {
int k = 0;
int arr[1000] = { 0 };
while (p) {
arr[k] = p->subject.English;
p->idx = 1;
p = p->next;
k++;
}
int q = k;
while (q) {
for (int i = 0; i < q - 1; i++) {
if (arr[i] < arr[i + 1]) {
int c = arr[i];
arr[i] = arr[i + 1];
arr[i + 1] = c;
}
}
q--;
}
int j = k, i = 0;
while (j) {
p = head->next;
for (p; p; p = p->next) {
if (p->idx == 1 && p->subject.English == arr[i]) {
printf("姓名:%s ", p->name);
printf("学号:%s ", p->number);
printf("英语成绩:%d \n", p->subject.English);
p->idx = 0;
i++;
}
}
j--;
}
break;
}
case 4:{
int k = 0;
int arr[1000] = { 0 };
while (p) {
arr[k] = p->subject.PE;
p->idx = 1;
p = p->next;
k++;
}
int q = k;
while (q) {
for (int i = 0; i < q - 1; i++) {
if (arr[i] < arr[i + 1]) {
int c = arr[i];
arr[i] = arr[i + 1];
arr[i + 1] = c;
}
}
q--;
}
int j = k, i = 0;
while (j) {
p = head->next;
for (p; p; p = p->next) {
if (p->idx == 1 && p->subject.PE == arr[i]) {
printf("姓名:%s ", p->name);
printf("学号:%s ", p->number);
printf("体育成绩:%d \n", p->subject.PE);
p->idx = 0;
i++;
}
}
j--;
}
break;
}
}
break;
}
system("cls");
:这行代码清除了控制台的屏幕。
struct stu* p = head->next;
:这行代码声明了一个指向stu
结构体的指针p
,并将其初始化为指向链表的第一个节点。
printf("请选择你要查看的学科:\n"); printf("1.math 2.computer 3.English 4.PE\n");
:这两行代码打印出一个提示,让用户选择要查看的学科。
int a; scanf("%d", &a);
:这两行代码声明了一个整型变量a
,然后从用户那里获取一个整数输入并存储在a
中。
if (a != 1 && a != 2 && a != 3 && a != 4) { ... }
:这个if
语句检查用户的输入是否规范。如果用户输入的不是1、2、3或4,则打印出一条消息,提示用户输入不规范,并跳出switch
语句。
if (p == NULL) { ... }
:这个if
语句检查链表是否为空。如果链表为空(即p
为NULL),则打印出一条消息,提示用户检查是否已经读取了文件。
switch (a) { ... }
:这个switch
语句根据用户的输入选择要查看的学科。
case 1: { ... }
等:这些case
语句处理不同的学科。对于每个学科,都会遍历链表,将学生的成绩存储在arr
数组中,并将每个学生的idx
字段设置为1。然后,对arr
数组进行冒泡排序,使得数组中的元素按照降序排列。最后,再次遍历链表,并按照arr
数组中的顺序打印出学生的信息。
十一:一些小彩蛋
case 11: {
printf("请输入指令:\n");
char str[10];
getchar();
gets(str);
if (strcmp(str, "SWPU") == 0) {
ShellExecuteA(0, "open", "https://www.swpu.edu.cn/", 0, 0, 1);
}
else
{
printf("您的指令不正确哦!!!\n");
}
break;
}
在这个case中,程序首先会提示用户输入指令,然后使用gets函数获取用户输入的字符串。接着程序会使用strcmp函数比较用户输入的字符串是否等于"SWPU",如果相等则会调用ShellExecuteA函数打开西南石油大学的官方网站。如果用户输入的字符串不等于"SWPU",则会输出提示信息"您的指令不正确哦!!!"。
当然,要是放个原神网页在这里也可以哦。
十二:退出系统与输入判别
case 0:
{
fclose(fp);
printf("正在为您退出系统.\n");
return 0;
}
default:{
printf("您的输入无效,请重新输入:\n");
break;
}
最后是完整的代码:
ps:不会有人不会改文件路径吧(doge)
用来应付期末作业那是大大的足够了:
#include
#include
#include
#include
struct course {
int math;
int computer;
int English;
int PE;
};
struct stu {
char name[100];
int age;
char sex;
struct course subject;
struct stu* next;
char number[20];
int all_scores;
int average_scores;
int idx;
};
void menu(void) {
printf("**************************\n"
"***学生管理系统*******\n"
"**************************\n"
"***系统功能菜单*******\n"
"--------------------------\n"
"**************************\n"
"*** 1.增加学生信息 ***\n"
"*** 2.查询学生信息 ***\n"
"*** 3.删除学生信息 ***\n"
"*** 4.修改学生信息 ***\n"
"***** 5.读取文件 *****\n"
"*** 6.显示学生信息 ***\n"
"***** 7.总分详情 *****\n"
"****** 8.菜单帮助 *****\n"
" 9.不合格检索 \n"
" 10.学科详情 \n"
" 11.学校主页 \n"
"***** 0.退出系统 *****\n"
);
}
int main() {
FILE* fp = fopen("D:\\Shelly\\OneDrive\\桌面\\无标题.txt", "a+");
int n;
struct stu* head = (struct stu*)malloc(sizeof(struct stu));
head->next = NULL;
menu();
fseek(fp, 0, SEEK_SET);
int frequency = 1;
printf("\n请您先读取文件!!!\n");
printf("\n请您先读取文件!!!\n");
printf("\n请您先读取文件!!!\n");
while (1) {
printf("\n请输入菜单编号:\n");
scanf("%d", &n);
switch (n) {
case 1:
{
struct stu* new_stu = (struct stu*)malloc(sizeof(struct stu));
printf("请输入学生姓名:");
scanf("%s", new_stu->name);
printf("请输入学生学号:");
scanf("%s", &(new_stu->number));
printf("请输入学生年龄:");
scanf("%d", &(new_stu->age));
printf("请输入学生性别(M/F):");
scanf(" %c", &(new_stu->sex));
printf("请输入数学成绩:");
scanf("%d", &(new_stu->subject.math));
printf("请输入计算机成绩:");
scanf("%d", &(new_stu->subject.computer));
printf("请输入英语成绩:");
scanf("%d", &(new_stu->subject.English));
printf("请输入体育成绩:");
scanf("%d", &(new_stu->subject.PE));
new_stu->all_scores = new_stu->subject.math + new_stu->subject.computer + new_stu->subject.PE + new_stu->subject.English;
new_stu->average_scores = (new_stu->all_scores) / 4;
new_stu->next = head->next;
head->next = new_stu;
fprintf(fp, "姓名:%s ", new_stu->name);
fprintf(fp, "学号:%s ", new_stu->number);
fprintf(fp, "年龄:%d ", new_stu->age);
fprintf(fp, "性别:%c ", new_stu->sex);
fprintf(fp, "数学成绩:%d ", new_stu->subject.math);
fprintf(fp, "计算机成绩:%d ", new_stu->subject.computer);
fprintf(fp, "英语成绩:%d ", new_stu->subject.English);
fprintf(fp, "体育成绩:%d ", new_stu->subject.PE);
fprintf(fp, "总分:%d ", new_stu->all_scores);
fprintf(fp, "平均分:%d \n", new_stu->average_scores);
fseek(fp, 0, SEEK_SET);
system("cls");
printf("添加学生成功!!!\n");
break;
}
case 2:
{
fseek(fp, 0, SEEK_SET);
printf("请选择你的查询方式:\n");
printf("C(学号查询)||N(姓名查询)\n");
char c;
int index = 0;
scanf(" %c", &c);
struct stu student;
if (c == 'C') {
printf("请输入要查找学生的学号:\n");
char k[20];
scanf("%s", k);
while (fscanf(fp, "姓名:%s 学号:%s 年龄:%d 性别:%c 数学成绩:%d 计算机成绩:%d 英语成绩:%d 体育成绩:%d 总分:%d 平均分:%d\n",
student.name, &(student.number), &(student.age), &(student.sex), &(student.subject.math), &(student.subject.computer),
&(student.subject.English), &(student.subject.PE), &(student.all_scores), &(student.average_scores)) != EOF) {
if (strcmp(student.number, k) == 0) {
index = 1;
break;
}
}
}
if (c == 'N') {
char search_name[100];
printf("请输入要查找的学生姓名:");
scanf("%s", search_name);
while (fscanf(fp, "姓名:%s 学号:%s 年龄:%d 性别:%c 数学成绩:%d 计算机成绩:%d 英语成绩:%d 体育成绩:%d 总分:%d 平均分:%d\n",
student.name, &(student.number), &(student.age), &(student.sex), &(student.subject.math), &(student.subject.computer),
&(student.subject.English), &(student.subject.PE), &(student.all_scores), &(student.average_scores)) != EOF) {
if (strcmp(student.name, search_name) == 0) {
index = 1;
break;
}
}
}
if (index == 0) {
printf("该学生不存在\n");
break;
}
else {
printf("姓名:%s ", student.name);
printf("学号:%s ", student.number);
printf("年龄:%d ", student.age);
printf("性别:%c ", student.sex);
printf("数学成绩:%d ", student.subject.math);
printf("计算机成绩:%d ", student.subject.computer);
printf("英语成绩:%d ", student.subject.English);
printf("体育成绩:%d ", student.subject.PE);
printf("总分:%d ", student.all_scores);
printf("平均分:%d\n", student.average_scores);
break;
}
}
case 3:
{
printf("请确保在删除前读取过文件!!!\n");
printf("请输入您想要删除学生的学号:\n");
char del_number[20];
getchar();
gets(del_number);
struct stu* p = head;
struct stu* temp;
int index = 0;
for (p; p->next; p = p->next) {
if (strcmp(p->next->number, del_number) == 0) {
temp = p->next;
p->next = p->next->next;
free(temp);
index = 1;
break;
}
}
if (index == 0) {
printf("该学生不存在!");
}
else {
fclose(fp);
fp = fopen("D:\\Shelly\\OneDrive\\桌面\\无标题.txt", "w+");
if (fp == NULL) {
printf("文件打开失败!\n");
return;
}
for (p = head->next; p != NULL; p = p->next) {
fprintf(fp, "姓名:%s 学号:%s 年龄:%d 性别:%c 数学成绩:%d 计算机成绩:%d 英语成绩:%d 体育成绩:%d 总分:%d 平均分:%d\n",
p->name, p->number, p->age, p->sex, p->subject.math, p->subject.computer, p->subject.English, p->subject.PE, p->all_scores, p->average_scores);
fflush(fp);
}
}
system("cls");
printf("删除学生成功!!!\n");
break;
}
case 4:
{
printf("请确保在修改前读取过文件!!!\n");
printf("请输入您想要修改学生信息的学号:\n");
char mod_number[20];
getchar();
gets(mod_number);
struct stu* p = head;
struct stu* temp;
int index = 0;
for (p; p->next; p = p->next) {
if (strcmp(p->next->number, mod_number) == 0) {
temp = p->next;
p->next = p->next->next;
free(temp);
index = 1;
break;
}
}
if (index == 0) {
printf("该学生不存在!");
}
else {
printf("请输入修改后的信息:\n");
struct stu* new_stu = (struct stu*)malloc(sizeof(struct stu));
printf("请输入学生姓名:");
scanf("%s", new_stu->name);
printf("请输入学生学号:");
scanf("%s", &(new_stu->number));
printf("请输入学生年龄:");
scanf("%d", &(new_stu->age));
printf("请输入学生性别(M/F):");
scanf(" %c", &(new_stu->sex));
printf("请输入数学成绩:");
scanf("%d", &(new_stu->subject.math));
printf("请输入计算机成绩:");
scanf("%d", &(new_stu->subject.computer));
printf("请输入英语成绩:");
scanf("%d", &(new_stu->subject.English));
printf("请输入体育成绩:");
scanf("%d", &(new_stu->subject.PE));
new_stu->all_scores = new_stu->subject.math + new_stu->subject.computer + new_stu->subject.PE + new_stu->subject.English;
new_stu->average_scores = (new_stu->all_scores) / 4;
new_stu->next = head->next;
head->next = new_stu;
fclose(fp);
fp = fopen("D:\\Shelly\\OneDrive\\桌面\\无标题.txt", "w+");
for (p = head->next; p != NULL; p = p->next) {
fprintf(fp, "姓名:%s 学号:%s 年龄:%d 性别:%c 数学成绩:%d 计算机成绩:%d 英语成绩:%d 体育成绩:%d 总分:%d 平均分:%d\n",
p->name, p->number, p->age, p->sex, p->subject.math, p->subject.computer, p->subject.English, p->subject.PE, p->all_scores, p->average_scores);
}
}
break;
}
case 5: {
if (frequency) {
FILE* ffp = fopen("D:\\Shelly\\OneDrive\\桌面\\无标题.txt", "r");
fseek(fp, 0, SEEK_SET);
struct stu student;
while (fscanf(fp, "姓名:%s 学号:%s 年龄:%d 性别:%c 数学成绩:%d 计算机成绩:%d 英语成绩:%d 体育成绩:%d 总分:%d 平均分:%d\n",
student.name, &(student.number), &(student.age), &(student.sex), &(student.subject.math), &(student.subject.computer),
&(student.subject.English), &(student.subject.PE), &(student.all_scores), &(student.average_scores)) != EOF) {
int k = student.number;
struct stu* p;
p = head;
int index = 0;
for (p; p; p = p->next) {
if (p->number == k) {
index = 1;
break;
}
}
if (index) {
continue;
}
else
{
struct stu* new_stu = (struct stu*)malloc(sizeof(struct stu));
strcpy(new_stu->name, student.name);
strcpy(new_stu->number, student.number);
new_stu->age = student.age;
new_stu->sex = student.sex;
new_stu->subject.math = student.subject.math;
new_stu->subject.computer = student.subject.computer;
new_stu->subject.English = student.subject.English;
new_stu->subject.PE = student.subject.PE;
new_stu->all_scores = new_stu->subject.math + new_stu->subject.computer + new_stu->subject.PE + new_stu->subject.English;
new_stu->average_scores = (new_stu->all_scores) / 4.0;
new_stu->next = head->next;
head->next = new_stu;
}
}
fclose(ffp);
printf("本次文件读取成功,请勿重复读取文件!!!\n");
frequency = 0;
}
else
printf("请勿多次读取文件!!!\n");
break;
}
case 6: {
system("cls");
struct stu* p = head->next;
while (p != NULL) {
printf("姓名:%s ", p->name);
printf("学号:%s ", p->number);
printf("年龄:%d ", p->age);
printf("性别:%c ", p->sex);
printf("数学成绩:%d ", p->subject.math);
printf("计算机成绩:%d ", p->subject.computer);
printf("英语成绩:%d ", p->subject.English);
printf("体育成绩:%d ", p->subject.PE);
printf("总分:%d ", p->all_scores);
printf("平均分:%d\n", p->average_scores);
p = p->next;
}
break;
}
case 7: {
system("cls");
struct stu* p = head->next;
if (p == NULL) {
printf("学生信息为空!请检查是否读入文件!!!\n");
}
else {
int k = 0;
int arr[1000] = { 0 };
while (p) {
arr[k] = p->all_scores;
p->idx = 1;
p = p->next;
k++;
}
int q = k;
while (q) {
for (int i = 0; i < q - 1; i++) {
if (arr[i] < arr[i + 1]) {
int c = arr[i];
arr[i] = arr[i + 1];
arr[i + 1] = c;
}
}
q--;
}
int j = k, i = 0;
while (j) {
p = head->next;
for (p; p; p = p->next) {
if (p->idx == 1 && p->all_scores == arr[i]) {
printf("姓名:%s ", p->name);
printf("学号:%s ", p->number);
printf("数学成绩:%d ", p->subject.math);
printf("计算机成绩:%d ", p->subject.computer);
printf("英语成绩:%d ", p->subject.English);
printf("体育成绩:%d ", p->subject.PE);
printf("总分:%d ", p->all_scores);
printf("平均分:%d\n", p->average_scores);
p->idx = 0;
i++;
}
}
j--;
}
break;
}}
case 8: {
menu();
break;
}
case 9: {
struct stu* p = head->next;
int k = 1;
while (p) {
if (p->subject.math < 90||p->subject.computer<90||p->subject.PE<60||p->subject.English<90) {
k = 0;
printf("姓名:%s 学号:%s ", p->name, p->number);
if (p->subject.math < 90) {
printf("数学成绩:%d ", p->subject.math);
}
if (p->subject.computer < 90) {
printf("计算机成绩:%d ", p->subject.computer);
}
if (p->subject.PE < 60) {
printf("体育成绩:%d ", p->subject.PE);
}
if (p->subject.English < 90) {
printf("英语成绩:%d ", p->subject.English);
}
printf("\n");
}
p = p->next;
}
if (k) {
printf("未检索到不合格学生信息!!!\n");
}
break;
}
case 10: {
system("cls");
struct stu* p = head->next;
printf("请选择你要查看的学科:\n");
printf("1.math 2.computer 3.English 4.PE\n");
int a;
scanf("%d", &a);
if (a != 1 && a != 2 && a != 3 && a != 4) {
printf("您的输入不规范!!!\n");
break;
}
if (p == NULL) {
printf("学生信息为空!请检查是否读入文件!!!\n");
}
switch (a) {
case 1: {
int k = 0;
int arr[1000] = { 0 };
while (p) {
arr[k] = p->subject.math;
p->idx = 1;
p = p->next;
k++;
}
int q = k;
while (q) {
for (int i = 0; i < q - 1; i++) {
if (arr[i] < arr[i + 1]) {
int c = arr[i];
arr[i] = arr[i + 1];
arr[i + 1] = c;
}
}
q--;
}
int j = k, i = 0;
while (j) {
p = head->next;
for (p; p; p = p->next) {
if (p->idx == 1 && p->subject.math == arr[i]) {
printf("姓名:%s ", p->name);
printf("学号:%s ", p->number);
printf("数学成绩:%d \n", p->subject.math);
p->idx = 0;
i++;
}
}
j--;
}
break;
}
case 2: {
int k = 0;
int arr[1000] = { 0 };
while (p) {
arr[k] = p->subject.computer;
p->idx = 1;
p = p->next;
k++;
}
int q = k;
while (q) {
for (int i = 0; i < q - 1; i++) {
if (arr[i] < arr[i + 1]) {
int c = arr[i];
arr[i] = arr[i + 1];
arr[i + 1] = c;
}
}
q--;
}
int j = k, i = 0;
while (j) {
p = head->next;
for (p; p; p = p->next) {
if (p->idx == 1 && p->subject.computer == arr[i]) {
printf("姓名:%s ", p->name);
printf("学号:%s ", p->number);
printf("计算机成绩:%d \n", p->subject.computer);
p->idx = 0;
i++;
}
}
j--;
}
break;
}
case 3: {
int k = 0;
int arr[1000] = { 0 };
while (p) {
arr[k] = p->subject.English;
p->idx = 1;
p = p->next;
k++;
}
int q = k;
while (q) {
for (int i = 0; i < q - 1; i++) {
if (arr[i] < arr[i + 1]) {
int c = arr[i];
arr[i] = arr[i + 1];
arr[i + 1] = c;
}
}
q--;
}
int j = k, i = 0;
while (j) {
p = head->next;
for (p; p; p = p->next) {
if (p->idx == 1 && p->subject.English == arr[i]) {
printf("姓名:%s ", p->name);
printf("学号:%s ", p->number);
printf("英语成绩:%d \n", p->subject.English);
p->idx = 0;
i++;
}
}
j--;
}
break;
}
case 4:{
int k = 0;
int arr[1000] = { 0 };
while (p) {
arr[k] = p->subject.PE;
p->idx = 1;
p = p->next;
k++;
}
int q = k;
while (q) {
for (int i = 0; i < q - 1; i++) {
if (arr[i] < arr[i + 1]) {
int c = arr[i];
arr[i] = arr[i + 1];
arr[i + 1] = c;
}
}
q--;
}
int j = k, i = 0;
while (j) {
p = head->next;
for (p; p; p = p->next) {
if (p->idx == 1 && p->subject.PE == arr[i]) {
printf("姓名:%s ", p->name);
printf("学号:%s ", p->number);
printf("体育成绩:%d \n", p->subject.PE);
p->idx = 0;
i++;
}
}
j--;
}
break;
}
}
break;
}
case 11: {
printf("请输入指令:\n");
char str[10];
getchar();
gets(str);
if (strcmp(str, "SWPU") == 0) {
ShellExecuteA(0, "open", "https://www.swpu.edu.cn/", 0, 0, 1);
}
else
{
printf("您的指令不正确哦!!!\n");
}
break;
}
case 0:
{
fclose(fp);
printf("正在为您退出系统.\n");
return 0;
}
default:
printf("您的输入无效,请重新输入:\n");
break;
}
}
return 0;
}