题目要求:链表A,每个节点存放一个新的链表B1,B2,B3,B4,B5的头结点。 场景:一个年级,相当链表A 该年级5个班,每个班5个人,相当于链表B1–B5 做一个学生成绩管理系统 学生成绩有语文 数学 英语 功能: 录入成绩 找三科总分的最高分 最低分 算出平均分
场景:一个年级,相当链表A
该年级5个班,每个班5个人,相当于链表B1–B5
做一个学生成绩管理系统
学生成绩有语文 数学 英语
功能: 录入成绩 找三科总分的最高分 最低分 算出平均分)
废话不多说,先给出完整的代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// 定义学生结构体,用于存储学生的信息
struct Student {
int xuehao; // 学号
int chinese; // 语文成绩
int math; // 数学成绩
int english; // 英语成绩
double sum; // 总分
double average; // 平均分
struct Student *next; // 下一个学生节点指针
};
// 定义班级结构体,用于存储班级的信息
struct Class {
struct Student *stuhead; // 班级内学生链表的头指针
int classnum; // 班级号
struct Class *next; // 下一个班级节点指针
};
// 在学生链表头部插入新学生节点
struct Student* insertStuMesage(struct Student *head, struct Student *new) {
if (head == NULL) {
head = new; // 如果链表为空,则直接插入作为第一个节点
} else {
new->next = head; // 否则将新节点插入到链表头部
head = new;
}
return head;
}
// 动态创建学生链表
struct Student* createStudent(struct Student *head, int stunum, int classnum) {
int i;
int num = stunum;
double sum;
double average;
struct Student *new;
for (i = 0; i < stunum; i++) {
new = (struct Student*)malloc(sizeof(struct Student)); // 分配内存以存储新的学生节点
printf("\n*************************************************\n");
printf("请输入%d班第%d个学生的学号:\n", classnum, num);
scanf("%d", &(new->xuehao)); // 输入学生信息
printf("请输入第%d个学生的语文成绩:\n", num);
scanf("%d", &(new->chinese));
printf("请输入第%d个学生的数学成绩:\n", num);
scanf("%d", &(new->math));
printf("请输入第%d个学生的英语成绩:\n", num);
printf("*************************************************\n");
scanf("%d", &(new->english));
sum = new->chinese + new->math + new->english; // 计算总分和平均分
new->sum = sum;
average = sum / 3;
new->average = average;
num--;
head = insertStuMesage(head, new); // 将新学生节点插入到学生链表
}
return head;
}
// 在班级链表头部插入新班级节点
struct Class* insertClaMesage(struct Class *head, struct Class *new) {
if (head == NULL) {
head = new; // 如果链表为空,则直接插入作为第一个节点
} else {
new->next = head; // 否则将新节点插入到链表头部
head = new;
}
return head;
}
// 动态创建班级链表
struct Class* creatClass(struct Class *head, int classnum, int stunum) {
struct Class *new = NULL;
struct Student *stuHead;
int num = classnum;
int i;
for (i = 0; i < classnum; i++) {
new = (struct Class*)malloc(sizeof(struct Class)); // 分配内存以存储新的班级节点
new->classnum = num;
stuHead = createStudent(stuHead, stunum, num); // 创建该班级的学生链表
new->stuhead = stuHead;
num--;
head = insertClaMesage(head, new); // 将新班级节点插入到班级链表
}
return head;
}
// 打印学生信息
void printMessage(struct Class *head, int classnum, int stunum) {
struct Class *p1 = head;
struct Student *p2 = NULL;
int k = stunum;
int i = 0;
while (i < classnum) {
p2 = p1->stuhead;
while (p2 != NULL && k > 0){
printf("\n*******************************\n");
printf("%d班第%d个学生的学号:%d\n", p1->classnum, k, p2->xuehao);
printf("语文成绩为:%d\n", p2->chinese);
printf("数学成绩为:%d\n", p2->math);
printf("英语成绩为:%d\n", p2->english);
printf("总分为: %lf\n", p2->sum);
printf("平均分为: %lf\n", p2->average);
p2 = p2->next;
k--;
}
k = stunum;
p1 = p1->next;
i++;
}
}
// 获取学生总分最大值
int getMax(struct Class *head, int classnum, int stunum) {
struct Class *p1 = head;
struct Student *p2 = NULL;
p2 = p1->stuhead;
int i = 0;
int j = 0;
int max = 0;
while (i < classnum) {
while (j < stunum * classnum) {
if (max < p2->sum) {
max = p2->sum; // 更新最高总分
}
p2 = p2->next;
j++;
}
p1 = p1->next;
i++;
}
printf("\n**************************\n");
printf("最高总分为:%d\n", max);
printf("**************************\n");
}
// 获取学生总分最小值
int getMin(struct Class *head, int classnum, int stunum) {
struct Class *p1 = head;
struct Student *p2 = NULL;
int i = 0;
int j = 0;
int min = 10000; // 初始设定一个较大值
p2 = p1->stuhead;
while (i < classnum) {
while (j < stunum * classnum) {
if (min > p2->sum) {
min = p2->sum; // 更新最低总
min = p2->sum; // 更新最低总分
}
p2 = p2->next;
j++;
}
p1 = p1->next;
i++;
}
printf("**************************\n");
printf("最低总分为:%d\n", min);
printf("**************************\n");
}
// 获取学生总分平均值
float getAvge(struct Class *head, int classnum, int stunum) {
struct Class *p1 = head;
struct Student *p2 = NULL;
int i = 0;
int j = 0;
double sum = 0;
double average;
p2 = p1->stuhead;
while (i < classnum) {
while (j < stunum * classnum) {
sum = sum + p2->sum; // 累计总分
p2 = p2->next;
j++;
}
p1 = p1->next;
i++;
}
average = sum / (stunum * classnum); // 计算平均总分
printf("**************************\n");
printf("年级平均分为:%lf\n", average);
printf("**************************\n");
}
void checkPassword()//开机密码
{
int n = 0; // 用于记录尝试登录的次数
int flag = 1; // 标志变量,此处暂未使用
char password[7] = {'l', 'i', 'e', '2', '5', '5', '\0'}; // 预设的正确密码
char userpassword[7]; // 用户输入的密码,最多支持6位密码字符
printf("***************《请输入你的密码,你一共有三次机会!!!》**************\n");
while (n < 3)
{
if(n != 0){
printf("***********《密码错误,请输入你的密码》你现在还有%d机会!!!***********\n", 3 - n);
}
scanf("%s", userpassword); // 获取用户输入的密码
if (strcmp(userpassword, password) == 0){ // 比较用户输入的密码与预设密码是否一致
printf("密码正确,登录成功!!!\n");
return; // 密码正确,登录成功,退出函数
}
n++; // 增加尝试登录次数
}
printf("密码错误,登录失败,滚蛋!!!\n");
exit(0); // 登录失败,尝试次数达到上限,退出程序
}
int main() {
checkPassword();//开机密码
printf("\n*******************************\n");
printf("欢迎使用学生成绩管理系统!!!\n");
printf("*******************************\n");
int a; // 班级个数
int b; // 学生个数
struct Class *head;
printf("请输入班级个数:\n");
scanf("%d", &a);
printf("请输入学生个数:\n");
scanf("%d", &b);
head = creatClass(head, a, b); // 创建班级链表
printMessage(head, a, b); // 打印学生信息
getMax(head, a, b); // 获取并打印最高分
getMin(head, a,b ); // 获取并打印最低分
getAvge(head, a, b); // 获取并打印平均分
system("pause");
return 0;
}
1. 头文件和结构体定义
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// 定义学生结构体,用于存储学生的信息
struct Student {
int xuehao; // 学号
int chinese; // 语文成绩
int math; // 数学成绩
int english; // 英语成绩
double sum; // 总分
double average; // 平均分
struct Student *next; // 下一个学生节点指针
};
// 定义班级结构体,用于存储班级的信息
struct Class {
struct Student *stuhead; // 班级内学生链表的头指针
int classnum; // 班级号
struct Class *next; // 下一个班级节点指针
};
定义了两个结构体,struct Student
用于存储学生的信息,包括学号、语文成绩、数学成绩、英语成绩、总分和平均分,以及一个指向下一个学生节点的指针。struct Clas
用于存储班级信息,包括班级号和下一个班级节点的指针。
2. 第一个函数:insertStuMesage
// 在学生链表头部插入新学生节点
struct Student* insertStuMesage(struct Student *head, struct Student *new) {
if (head == NULL) {
head = new; // 如果链表为空,则直接插入作为第一个节点
} else {
new->next = head; // 否则将新节点插入到链表头部
head = new;
}
return head;
}
这个函数用于将一个新的学生节点插入到学生链表的头部。这个函数有两个参数,一个是链表的头指针 head
,另一个是要插入的新节点 new
。
- 如果链表为空(
head == NULL
),则将新节点直接作为第一个节点。 - 如果链表不为空,它会将新节点插入到链表的头部,即将新节点的
next
指针指向原链表的头节点,并将head
指针指向新节点。 - 最后,它返回插入后的链表头指针
head
。
3. 第二个函数:createStudent
// 动态创建学生链表
struct Student* createStudent(struct Student *head, int stunum, int classnum) {
int i;
int num = stunum;
double sum;
double average;
struct Student *new;
for (i = 0; i < stunum; i++) {
new = (struct Student*)malloc(sizeof(struct Student)); // 分配内存以存储新的学生节点
// ...
sum = new->chinese + new->math + new->english; // 计算总分和平均分
new->sum = sum;
average = sum / 3;
new->average = average;
num--;
head = insertStuMesage(head, new); // 将新学生节点插入到学生链表
}
return head;
}
这个函数用于动态创建学生链表,根据指定的学生数量 stunum
和班级号 classnum
。这个函数的三个参数为:学生链表的头指针 head
,学生数量,以及班级号。
- 在循环中,它为每个学生分配内存以创建一个新的学生节点。
- 然后,它要求用户输入学生的信息,包括学号、语文、数学和英语成绩。
- 计算总分和平均分。
- 最后,将新的学生节点插入到学生链表,使用了上面定义的
insertStuMesage
函数。
4. 第三个函数:insertClaMesage
// 在班级链表头部插入新班级节点
struct Class* insertClaMesage(struct Class *head, struct Class *new) {
if (head == NULL) {
head = new; // 如果链表为空,则直接插入作为第一个节点
} else {
new->next = head; // 否则将新节点插入到链表头部
head = new;
}
return head;
}
这个函数类似于 insertStuMesage
,但是它是用于在班级链表的头部插入新的班级节点。这个函数的参数为:班级链表的头指针 head
和一个新的班级节点 new
。
- 如果班级链表为空,它将新节点直接作为第一个节点。
- 如果班级链表不为空,它将新节点插入到链表的头部,更新
head
指针。
5. 第四个函数:creatClass
// 动态创建班级链表
struct Class* creatClass(struct Class *head, int classnum, int stunum) {
struct Class *new = NULL;
struct Student *stuHead;
int num = classnum;
int i;
for (i = 0; i < classnum; i++){
new = (struct Class*)malloc(sizeof(struct Class)); // 分配内存以存储新的班级节点
new->classnum = num;
stuHead = createStudent(stuHead, stunum, num); // 创建该班级的学生链表
new->stuhead = stuHead;
num--;
head = insertClaMesage(head, new); // 将新班级节点插入到班级链表
}
return head;
}
这个函数用于动态创建班级链表,根据指定的班级数量 classnum
和学生数量 stunum
。这个函数的参数为:班级链表的头指针 head
、班级数量和学生数量。
-
在循环中,它为每个班级分配内存以创建一个新的班级节点。
-
为新班级节点设置班级号
classnum
。 -
调用
createStudent
函数创建该班级的学生链表,然后将学生链表的头指针赋给new->stuhead
。 -
更新班级号,然后使用
insertClaMesage
函数将新的班级节点插入到班级链表,更新head
指针。
6. 打印学生信息的函数:printMessage
// 打印学生信息
void printMessage(struct Class *head, int classnum, int stunum) {
struct Class *p1 = head;
struct Student *p2 = NULL;
int k = stunum;
int i = 0;
while (i < classnum) {
p2 = p1->stuhead;
int m = 1;
while (p2 != NULL && k > 0){
// 打印学生信息,包括学号、成绩、总分和平均分
p2 = p2->next;
m++;
k--;
}
k = stunum;
p1 = p1->next;
i++;
}
}
这个函数用于打印学生的信息,包括学号、语文、数学、英语成绩、总分和平均分。函数参数为:班级链表的头指针 head
、班级数量 classnum
和学生数量 stunum
。
- 定义了两个指针,
p1
用于遍历班级链表,p2
用于遍历学生链表。 - 使用循环遍历每个班级,并在每个班级内遍历每个学生。
- 打印每个学生的信息,包括学号、成绩、总分和平均分。
7. 获取最高分的函数:getMax
// 获取学生总分最大值
int getMax(struct Class *head, int classnum, int stunum) {
struct Class *p1 = head;
struct Student *p2 = NULL;
p2 = p1->stuhead;
int i = 0;
int j = 0;
int max = 0;
while (i < classnum) {
while (j < stunum * classnum) {
if (max < p2->sum) {
max = p2->sum; // 更新最高总分
}
p2 = p2->next;
j++;
}
p1 = p1->next;
i++;
}
printf("最高总分为:%d\n", max);
}
这个函数用于获取并打印学生总分的最大值。函数参数为:班级链表的头指针 head
、班级数量 classnum
和学生数量 stunum
。
- 定义了两个指针,
p1
用于遍历班级链表,p2
用于遍历学生链表。 - 使用循环遍历每个班级,并在每个班级内遍历每个学生。
- 检查每个学生的总分,如果找到更高的总分,更新
max
变量。 - 最后,打印最高总分。
8. 获取最低分的函数:getMin
// 获取学生总分最小值
int getMin(struct Class *head, int classnum, int stunum) {
struct Class *p1 = head;
struct Student *p2 = NULL;
int i = 0;
int j = 0;
int min = 10000; // 初始设定一个较大值
p2 = p1->stuhead;
while (i < classnum) {
while (j < stunum * classnum) {
if (min > p2->sum) {
min = p2->sum; // 更新最低总分
}
p2 = p2->next;
j++;
}
p1 = p1->next;
i++;
}
printf("最低总分为:%d\n", min);
}
这个函数用于获取并打印学生总分的最小值。它接受班级链表的头指针 head
、班级数量 classnum
和学生数量 stunum
作为参数。
- 类似于
getMax
函数,定义了两个指针p1
和p2
用于遍历班级和学生链表。 - 使用循环遍历每个班级和学生。
- 检查每个学生的总分,如果找到更低的总分,更新
min
变量。 - 最后,打印最低总分。
9. 获取平均分的函数:getAvge
// 获取学生总分平均值
float getAvge(struct Class *head, int classnum, int stunum) {
struct Class *p1 = head;
struct Student *p2 = NULL;
int i = 0;
int j = 0;
double sum = 0;
double average;
p2 = p1->stuhead;
while (i < classnum) {
while (j < stunum * classnum) {
sum = sum + p2->sum; // 累计总分
p2 = p2->next;
j++;
}
p1 = p1->next;
i++;
}
average = sum / (stunum * classnum); // 计算平均总分
printf("年级平均分为:%lf\n", average);
}
这个函数用于获取并打印学生总分的平均值。它接受班级链表的头指针 head
、班级数量 classnum
和学生数量 stunum
作为参数。
-
同样,定义了两个指针
p1
和p2
用于遍历班级和学生链表。 -
使用循环遍历每个班级和学生。
-
累计每个学生的总分到
sum
变量中。 -
最后,计算平均总分,将
sum
除以学生总数,然后打印年级的平均分。
10. 开机密码检查函数:checkPassword
void checkPassword() {
int n = 0; // 用于记录尝试登录的次数
char password[7] = {'l', 'i', 'e', '2', '5', '5', '\0'}; // 预设的正确密码
char userpassword[7]; // 用户输入的密码,最多支持6位密码字符
printf("请输入你的密码,你一共有三次机会!!!\n");
while (n < 3) {
if (n != 0) {
printf("密码错误,请输入你的密码。你现在还有 %d 机会!!!\n", 3 - n);
}
scanf("%s", userpassword); // 获取用户输入的密码
if (strcmp(userpassword, password) == 0) {
printf("密码正确,登录成功!!!\n");
return; // 密码正确,登录成功,退出函数
}
n++; // 增加尝试登录次数
}
printf("密码错误,登录失败,滚蛋!!!\n");
exit(0); // 登录失败,尝试次数达到上限,退出程序
}
这个函数用于开机密码检查。它会要求用户输入密码,并在最多三次尝试后决定是否允许用户继续使用程序。预设的正确密码是 'lie255'
。
- 使用
n
记录尝试登录的次数,如果密码错误三次,则退出程序。 - 用户输入密码,并使用
strcmp
函数与正确密码比较。 - 如果密码正确,打印登录成功的消息,然后返回。
- 如果密码错误,增加尝试登录的次数,然后继续循环,最多三次。
11. 主函数:main
int main() {
checkPassword(); // 开机密码
int a; // 班级个数
int b; // 学生个数
struct Class *head;
printf("请输入班级个数:\n");
scanf("%d", &a);
printf("请输入学生个数:\n");
scanf("%d", &b);
head = creatClass(head, a, b); // 创建班级链表
printMessage(head, a, b); // 打印学生信息
getMax(head, a, b); // 获取并打印最高分
getMin(head, a, b); // 获取并打印最低分
getAvge(head, a, b); // 获取并打印平均分
system("pause");
return 0;
}
这是主函数,它调用其他函数来实现学生成绩管理系统的功能。
- 首先,调用
checkPassword
函数进行开机密码验证。 - 然后,要求用户输入班级个数和学生个数。
- 创建一个班级链表并存储在
head
中,然后调用printMessage
函数打印学生信息。 - 使用
getMax
函数获取并打印最高分。 - 使用
getMin
函数获取并打印最低分。 - 使用
getAvge
函数获取并打印平均分。 - 最后,使用
system("pause")
以等待用户按下任意键继续,然后返回 0 表示程序结束。
这个主函数将各个功能组合在一起,使整个学生成绩管理系统运行。