学生成绩管理系统(期末实验作业)(郑州轻工业2023)

话不多说,先上代码

/*为了提高学生学习兴趣,越来越多的游戏式学习方式得到教育界的关注.现考虑一个晋级式学习平
台,针对每门课程,学生通过完成相应测试(可被称为关卡),获取一定的积分。当积分达到一定阈值后,该生等级晋级一级。
要求:
针对该平台,设计一个学生和试题管理系统。其中学生信息包括学号、姓名、班级、每门课程的积分和等级等信息;
课程信息包括课程编号、课程名称、测试试题等信息;试题信息成功完成该测试试题能获得的积分等信息。
必备功能
(1)新增学生信息:录入信息包括学号、姓名、班级,并将每门课程的积分和等级均初始化为0。
(2)新增课程:录入课程信息包括课程名称、课程编号(在系统中是唯一的)。
(3)新增试题:录入每道题的打分标准和相应分值。
(4)更新积分:根据学生完成某试题的情况更新该学生在这门课程的积分:如果成功完成,则增加该试题对应的积分;反之,学生在这门课程的积分不变。
(5)计算学生等级:针对每门课程,根据学生的积分,计算相应等级。等级与积分的对应关系为 ,其中 表示积分, 表示等级, 表示取整数部分。比如积分为0的等级为0;积分为1~98的等级为1;积分为99~998的等级为2;积分为999~9998的等级为3;……
(6)查找功能:可以查找指定学生的各门课程的积分和等级情况。
(7)排序功能:将学生信息按某门课程的积分自高到低进行排序。
(8)输出功能:将学生信息按照平均等级格式化输出。
(9)删除某门课程的某个试题:主要用于更新需要删除过时或不合适的关卡。
(10)保存功能:将学生信息、课程信息和试题信息保存至文件。
(11)导入功能:从文件中导入学生信息、课程信息和试题信息。

*/
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<malloc.h>
#include<string.h>//这个就是我在评论区说的头文件
#include<stdlib.h>
#include<math.h>
#include<conio.h>
//要求1:自定义类型:学生(我们把它重命名为Student,所以我们这里用匿名结构体,当然你也可以按正常的方式定义或者重命名)
typedef struct
{
	char id[20];//用于存储学生的学号,我们这里用"万能的"char数组,下面同理
	char name[5];//用于存放学生的名字
	char Class[5];//存放班级
	int integral[10];//存放每门课程的积分,里面的每个元素就是课程积分
	int level[10];//记录学生每门课程等级
}Student;
//定义链表里面的结点,链表的
typedef struct Lnode
{
	Student data;
	struct Lnode* next;

}Lnode, * LinkList;
LinkList Head = NULL;
LinkList Tail = NULL;

typedef struct
{
	int num;
	char name[20];
	int item[1000];
	int count;//试题数目
}Courseinf;
typedef struct cour
{
	Courseinf data;
	int count;
	struct cour* next;
}cour, * LinkListC;
LinkListC tailC = NULL;
LinkListC headC = NULL;

//菜单的实现
void menue()
{
	printf("        欢迎使用学生管理系统     \n");
	printf("---------------------------------\n");
	printf("---1.新增学生信息   2.新增课程---\n");
	printf("---3.新增试题       4.更新积分---\n");
	printf("---5.计算学生等级   6.查找功能---\n");
	printf("---7.排序功能       8.输出功能---\n");
	printf("---9.删除功能      10.保存学生信息\n");
	printf("--11.导入功能       0.退出-------\n");
	printf("---------------------------------\n");
	printf("请选择:");
}

//1.用于实现新增学生信息
void AddStu()
{
	Lnode* p = (Lnode*)malloc(sizeof(Lnode));
	p->next = NULL;
	//尾插法
	if (Head == NULL)
	{
		Head = p;
		Tail = p;
	}
	else
	{
		Tail->next = p;
		Tail = p;
	}
	printf("请输入学生的学号:");
	scanf("%s", p->data.id);
	getchar(); // 清除输入缓冲区中的换行符
	printf("请输入学生的班级如2301,2211....:");
	scanf("%s", p->data.Class);
	getchar();
	printf("请输入学生的姓名:");
	scanf("%s", p->data.name);
    memset(p->data.level,0,sizeof(p->data.level));//这两行代码就是评论区的改动
    memset(p->data.integral, 0,sizeof(p->data.integral));
	printf("学生录入信息成功\n");
	system("pause"); // 画面停留
	system("cls"); // 清屏
}

//2.用于实现新增课程信息
void AddCor()
{
	cour* p = (cour*)malloc(sizeof(cour));
	if (headC == NULL)
	{
		tailC = p;
		headC = p;
	}
	else {
		tailC->next = p;
		tailC = p;
	}
	p->next = NULL;
	p->count=0;
	p->count++;
	printf("请输入课程名字:");
	gets(p->data.name);
	printf("请输入新课程编号(请按顺序存储):");
	scanf("%d",&p->data.num);
	printf("请输入课程试题的数目:");
	int num1;
	scanf("%d",&num1);
	p->data.count = 0;
	p->data.count+=num1;
	for (int i = 0; i < num1; i++)
	{
		printf("请输入题目%d的分数:",i+1);
		scanf("%d",&p->data.item[i]);
	}
	printf("课程信息录入成功\n");
	system("pause"); // 画面停留
	system("cls"); // 清屏
}

//打印
void print()
{
	cour* p = (cour*)malloc(sizeof(cour));
	p = headC;
	    printf("名称     编号\n");
	while (p)
	{	
		printf("%s       %d\n",p->data.name, p->data.num);
		p = p->next;
	}

}
//3.用于新增试题
void AddTstQu()
{
	print();
	printf("请输入增加试题的课程编号:");
	int input;
	scanf("%d",&input);
	cour* p;
	p = headC;
	while (p)
	{
		if (p->data.num == input)
		{
			printf("请输入新增试题数目");
			int num1 = 0;
			scanf("%d",&num1);
			for (int i = p->data.count; i < p->data.count + num1; i++)
			{
				printf("请输入第%d题的分数", i + 1);
				scanf("%d",&p->data.item[i]);
			}
			break;
		}
		else
			p = p->next;
	}
	system("pause"); // 画面停留
	system("cls"); // 清屏
}

//4.用于更新积分
void Updateitg()
{
	Lnode* p = Head;
	printf("请输入待更新学生学号:");
	char id[20];
	scanf("%s",id);
	getchar();
	while (p)
	{
		if (!strcmp(p->data.id, id))
		{
			break;
		}
		else
			p = p->next;
	}
	if (p == NULL)
	{
		printf("没有找到");
	}
	else 
	{
		cour* cp = headC;
		int num;
		printf("请输入该学生完成的课程编号:");
		scanf("%d",&num);
		while (cp)
		{
			if (cp->data.num == num)
			{
				printf("请输入完成的试题序号(1.2.3...),如果没有了就输入0:");
				int i = 0;
				int sum = 0;
				scanf("%d",&i);
				if (i == 0)
				{
					break;
				}
				else
				p->data.integral[num-1] += cp->data.item[i - 1];

			}
			else {
				cp = cp->next;
			}
		}


	}
	printf("更新成功\n");
	system("pause"); // 画面停留
	system("cls"); // 清屏
}
//5.计算学生等级
void Getlevel()
{
	Lnode* p = Head;
	while (p) 
	{
		for (int i = 0;i<10; i++)
			p->data.level[i] = (int)log10(p->data.integral[i] + 1);
		p = p->next;
	}
	system("pause"); // 画面停留
	system("cls"); // 清屏
}
//6.查找功能
void SerchIL()
{
	Lnode* p = Head;
	printf("请输入要查找的学生学号:");
	char id[20];
	scanf("%s", id);
	getchar();
	while (p)
	{
		if (!strcmp(p->data.id, id))
		{
			break;
		}
		else
			p = p->next;
	}
	if (p == NULL)
	{
		printf("没有找到");
	}
	else
	{
		int i = 0;
		while (p->data.integral[i] != 0)
		{
			printf("第%d门课程的分数为%d,等级为%d", i + 1, p->data.integral[i], p->data.level[i]);
			i++;
		}
	}
	system("pause"); // 画面停留
	system("cls"); // 清屏

}

//7.排序功能
void sortstu(int num)
{
	Lnode* p = Head;
	while (p->next)
	{
		if (p->data.integral[num] <= p->next->data.integral[num])
		{
			Lnode* flag = p;
			p = p->next->next;
			p->next = p;
		}

	}


}
void Sort()
{
	print();
	printf("请输入要排名的课程编号:");
	int num = 0;
	scanf("%d",&num);
	cour* p;
	p = headC;
	while (p)
	{
		if (p->data.num == num)
		{
			sortstu(num);
			
		}
		else
			p = p->next;
	}
	printf("排序成功");
	system("pause"); // 画面停留
	system("cls"); // 清屏
}


//8.输出功能
void Print()
{
	Lnode* p = Head;
	while (p)
	{
		double average=0;
		int sum = 0;
		for (int i = 0; i < 10; i++)
		{
			average += p->data.level[i];
			if (p->data.level[i] != 0)
			{
				sum++;
			}
		}
		average /= sum;
		printf("学生姓名:%5s,学生学号:%10s,学生课程平均等级%.2lf", p->data.name, p->data.id, average);
	}
	system("pause"); // 画面停留
	system("cls"); // 清屏

}

//9.删除功能
void Delete()
{
	print();
	printf("请输入需要删除试题的课程编号:");
	int num1;
	scanf("%d",&num1);
	cour* p;
	p = headC;
	while (p)
	{
		if (p->data.num==num1)
		{
			printf("现有%d个题目\n",p->data.count);
			printf("请输入删除的试题编号:");
			int num2;
			scanf("%d",&num2);
			p->data.item[num2]=0;
			p->data.count--;
			break;
		}
		else
			p = p->next;
		p->count--;
	}
	system("pause"); // 画面停留
	system("cls"); // 清屏

}

//10.保存功能
void Save()
{
	FILE* fp = fopen("E:\\初学c鹏哥\\Gardevior1\\Gardevior1\\学生管理系统.txt","w");
	if (fp == NULL)
	{
		printf("保存失败");
		return;
	}
	Lnode* p = Head;
	while (p)
	{
		fwrite(&p->data,1,sizeof(Student),fp);
		p = p->next;
	}
	fclose(fp);
	printf("数据保存成功");
	system("pause"); // 画面停留
	system("cls"); // 清屏
}

//11.导入功能
void Import()
{
	FILE* fp = fopen("E:\\初学c鹏哥\\Gardevior1\\Gardevior1\\学生管理系统.txt","r");
	if (fp = NULL)
	{
		printf("导入失败");
		return;
	}
	Student stu;
	while (fread(&stu, 1, sizeof(Student), fp))
	{
		Lnode* p = (Lnode*)malloc(sizeof(Lnode));
		p->next = NULL;
		memcpy(p,&stu,sizeof(Student));
		if (Head == NULL)
		{
			Head = p;
			Tail = p;
		}
		else
		{
			Tail->next = p;
			Tail = p;
		}
	}
}
//0.退出
void exit()
{
	printf("正在退出,谢谢使用");
}
int main()
{
	while (1)
	{
		menue();
		int input;
		scanf("%d", &input);
		getchar();
		switch (input)
		{
		case 1:
			AddStu();
			break;
		case 2:
			AddCor();
			break;
		case 3:
			AddTstQu();
			break;
		case 4:
			Updateitg();
			break;
		case 5:
			Getlevel();
			break;
		case 6:
			SerchIL();
			break;
		case 7:
			Sort();
			break;
		case 8:
			Print();
			break;
		case 9:
			Delete();
			break;
		case 10:
			Save();
			break;
		case 11:
			Import();
			break;
		case 0:
			exit();
			return 0;
		default:
			printf("输入错误,请重新出入");
			break;
		}

	}
	return 0;
}

目录

1.实验题目和要求

2.总体思路

敲之前的思路:

关于构建的结合体:

定义一个学生的结构体(并重命名为Student)

定义链表中的学生结点(并重命名为Lnode,其指针类型重命名为LinkList):

还要定义连个结点指针分别指向头和尾

定义一个课程的结构体(并重命名)

定义链表中的课程结点(并重命名)

还要定义连个结点指针分别指向头和尾

大体菜单:

3.每一个函数的实现

1.新增学生信息

2.新增课程信息

3.新增试题

5.计算学生等级

6.查找功能

7.排序功能

8.输出功能

9.删除功能

10.保存功能

11.导入功能

0.退出功能就不说了,相信你们都会

4.一些题外话


1.实验题目和要求

为了提高学生学习兴趣,越来越多的游戏式学习方式得到教育界的关注.现考虑一个晋级式学习平
台,针对每门课程,学生通过完成相应测试(可被称为关卡),获取一定的积分。当积分达到一定阈值后,该生等级晋级一级。
要求:
针对该平台,设计一个学生和试题管理系统。其中学生信息包括学号、姓名、班级、每门课程的积分和等级等信息;
课程信息包括课程编号、课程名称、测试试题等信息;试题信息成功完成该测试试题能获得的积分等信息。
必备功能
(1)新增学生信息:录入信息包括学号、姓名、班级,并将每门课程的积分和等级均初始化为0。
(2)新增课程:录入课程信息包括课程名称、课程编号(在系统中是唯一的)。
(3)新增试题:录入每道题的打分标准和相应分值。
(4)更新积分:根据学生完成某试题的情况更新该学生在这门课程的积分:如果成功完成,则增加该试题对应的积分;反之,学生在这门课程的积分不变。
(5)计算学生等级:针对每门课程,根据学生的积分,计算相应等级。等级与积分的对应关系为 ,其中 表示积分, 表示等级, 表示取整数部分。比如积分为0的等级为0;积分为1~98的等级为1;积分为99~998的等级为2;积分为999~9998的等级为3;……
(6)查找功能:可以查找指定学生的各门课程的积分和等级情况。
(7)排序功能:将学生信息按某门课程的积分自高到低进行排序。
(8)输出功能:将学生信息按照平均等级格式化输出。
(9)删除某门课程的某个试题:主要用于更新需要删除过时或不合适的关卡。
(10)保存功能:将学生信息、课程信息和试题信息保存至文件。
(11)导入功能:从文件中导入学生信息、课程信息和试题信息。

2.总体思路

敲之前的思路:

本题首先考虑的用链表还是顺序表,两者各有优缺:顺序表能随即查询(代码简单),链表只能按顺序查询(遍历链表的代码复杂),咱选的是链表,这只是关于学生的链表,还有另外一个关于课程的代码,这个咱用的是最简单的顺序表,但对课程来说顺序表的增减又恰恰是比链表复杂的。所以我做完后就挺无语,偏偏选了最难的两个。

关于构建的结合体:

定义一个学生的结构体(并重命名为Student)

typedef struct
{
    char id[20];//用于存储学生的学号,我们这里用"万能的"char数组,下面同理
    char name[5];//用于存放学生的名字
    char Class[5];//存放班级
    int integral[10];//存放每门课程的积分,里面的每个元素就是课程积分
    int level[10];//记录学生每门课程等级
}Student;

定义链表中的学生结点(并重命名为Lnode,其指针类型重命名为LinkList):

typedef struct Lnode
{
    Student data;
    struct Lnode* next;//链表中的下一个结点

}Lnode, * LinkList;

还要定义连个结点指针分别指向头和尾

LinkList Head = NULL;
LinkList Tail = NULL;
 

定义一个课程的结构体(并重命名)

typedef struct
{
    int num;//课程编号
    char name[20];//课程名字
    int item[1000];//这里我们用的数组比较懒省事,对应试题编号作为下标一一对应里面的分数,我们假设他最多不超过1000;
    int count;//试题数目
}Courseinf;

定义链表中的课程结点(并重命名)

typedef struct cour
{
    Courseinf data;
    int count;//记录课程的个数
    struct cour* next;//链表中的下一个结点
}cour, * LinkListC;

还要定义连个结点指针分别指向头和尾

LinkListC tailC = NULL;
LinkListC headC = NULL;

大体菜单:

while (1)
{
	menue();
	int input;
	scanf("%d", &input);
	getchar();
	switch (input)
	{
	case 1:
		AddStu();
		break;
	case 2:
		AddCor();
		break;
	case 3:
		AddTstQu();
		break;
	case 4:
		Updateitg();
		break;
	case 5:
		Getlevel();
		break;
	case 6:
		SerchIL();
		break;
	case 7:
		Sort();
		break;
	case 8:
		Print();
		break;
	case 9:
		Delete();
		break;
	case 10:
		Save();
		break;
	case 11:
		Import();
		break;
	case 0:
		exit();
		return 0;
	default:
		printf("输入错误,请重新出入");
		break;
	}

}

void menue()
{
    printf("        欢迎使用学生管理系统     \n");
    printf("---------------------------------\n");
    printf("---1.新增学生信息   2.新增课程---\n");
    printf("---3.新增试题       4.更新积分---\n");
    printf("---5.计算学生等级   6.查找功能---\n");
    printf("---7.排序功能       8.输出功能---\n");
    printf("---9.删除功能      10.保存学生信息\n");
    printf("--11.导入功能       0.退出-------\n");
    printf("---------------------------------\n");
    printf("请选择:");
}

我做的时候也是这样写的,不管这个函数功能的实现你会不会,先把他的位置给上,之后再一个一个来

3.每一个函数的实现

1.新增学生信息

首先定义一个结点,并用malloc分配空间,他的next指向NULL,是因为它本身作为最后一个(尾插法)进行判断来决定头指针和尾指针的移动,输入这块空间中data中的学生信息。

void AddStu()
{
	Lnode* p = (Lnode*)malloc(sizeof(Lnode));
	p->next = NULL;
	//尾插法
	if (Head == NULL)
	{
		Head = p;
		Tail = p;
	}
	else
	{
		Tail->next = p;
		Tail = p;
	}
	printf("请输入学生的学号:");
	scanf("%s", p->data.id);
	getchar(); // 清除输入缓冲区中的换行符
	printf("请输入学生的班级如2301,2211....:");
	scanf("%s", p->data.Class);
	getchar();
	printf("请输入学生的姓名:");
	scanf("%s", p->data.name);
	p->data.level[3] = 0;
	p->data.integral[3] = 0;
	printf("学生录入信息成功\n");
	system("pause"); // 画面停留
	system("cls"); // 清屏
}

2.新增课程信息

和函数1类似定义结点,不过类型是课程结点,在插入位置上的操作一样。需要注意的是课程里面的两个count(课程结点,课程信息),一个是记录课程数量的,一个是记录试题数量的。另外我们定义的试题数组里面存放的是做完相应下标得到的分数,我们懒省事,也直接把试题编号当作下标来使用。

void AddCor()
{
	cour* p = (cour*)malloc(sizeof(cour));
	if (headC == NULL)
	{
		tailC = p;
		headC = p;
	}
	else {
		tailC->next = p;
		tailC = p;
	}
	p->next = NULL;
	p->count=0;
	p->count++;
	printf("请输入课程名字:");
	gets(p->data.name);
	printf("请输入新课程编号(请按顺序存储):");
	scanf("%d",&p->data.num);
	printf("请输入课程试题的数目:");
	int num1;
	scanf("%d",&num1);
	p->data.count = 0;
	p->data.count+=num1;
	for (int i = 0; i < num1; i++)
	{
		printf("请输入题目%d的分数:",i+1);
		scanf("%d",&p->data.item[i]);
	}
	printf("课程信息录入成功\n");
	system("pause"); // 画面停留
	system("cls"); // 清屏
}

3.新增试题

当你输入想要加入的课题时是不是也要提醒一下有哪些课程是能添加的,所以我们用了一个自定义的打印函数,用来打印出现有的所有课程和其对应的编号。

输入编号,来新增试题,此时我们懒省事的正效果得到了突出,我们只用把新增试题按试题顺序(当作下标)把其对应的分数放入数组中就ok了。当然要记得让试题的数目count++.

void print()
{
	cour* p = (cour*)malloc(sizeof(cour));
	p = headC;
	printf("名称     编号\n");
	while (p)
	{
		printf("%s       %d\n", p->data.name, p->data.num);
		p = p->next;
	}

}
void AddTstQu()
{
	print();
	printf("请输入增加试题的课程编号:");
	int input;
	scanf("%d", &input);
	cour* p;
	p = headC;
	while (p)
	{
		if (p->data.num == input)
		{
			printf("请输入新增试题数目");
			int num1 = 0;
			scanf("%d", &num1);
			for (int i = p->data.count; i < p->data.count + num1; i++)
			{
				printf("请输入第%d题的分数", i + 1);
				scanf("%d", &p->data.item[i]);

			}
			p->count += num1;
			break;
		}
		else
			p = p->next;
	}
	system("pause"); // 画面停留
	system("cls"); // 清屏
}

4.更新积分

此功能我理解的是“记录”,把该同学的做题情况记录下来,并通过操作运算成积分,放到学生结点的积分数组integral中。

void Updateitg()
{
	Lnode* p = Head;
	printf("请输入待更新学生学号:");
	char id[20];
	scanf("%s",id);
	getchar();
	while (p)
	{
		if (!strcmp(p->data.id, id))
		{
			break;
		}
		else
			p = p->next;
	}
	if (p == NULL)
	{
		printf("没有找到");
	}
	else 
	{
		cour* cp = headC;
		int num;
		printf("请输入该学生完成的课程编号:");
		scanf("%d",&num);
		while (cp)
		{
			if (cp->data.num == num)
			{
				printf("请输入完成的试题序号(1.2.3...),如果没有了就输入0:");
				int i = 0;
				int sum = 0;
				scanf("%d",&i);
				if (i == 0)
				{
					break;
				}
				else
				p->data.integral[num-1] += cp->data.item[i - 1];

			}
			else {
				cp = cp->next;
			}
		}


	}
	printf("更新成功\n");
	system("pause"); // 画面停留
	system("cls"); // 清屏
}

5.计算学生等级

这个函数就比较简单了,我们事先就把每门课程的积分存放到了integral数组中,现在只需要循环遍历拿出来计算。将计算的平均值放到level(等级)数组中。

这里有一点我也懒省事了:level和integral数组的下标,我就直接将它当作了课程编号,所以操作起来简单。但这是题目上给的提示是定义这两个数组,我感觉就是让我懒省事用的。

void Getlevel()
{
	Lnode* p = Head;
	while (p) 
	{
		for (int i = 0;i<10; i++)
			p->data.level[i] = (int)log10(p->data.integral[i] + 1);
		p = p->next;
	}
	system("pause"); // 画面停留
	system("cls"); // 清屏
}

6.查找功能

现在链表的缺点有一次展现了出来,这里我们只能从头节点开始遍历,直到找到为止。头节点存的还有两个数组,我们循环遍历出来就完事了(因为下标代表课程编号,所以很容易)

void SerchIL()
{
	Lnode* p = Head;
	printf("请输入要查找的学生学号:");
	char id[20];
	scanf("%s", id);
	getchar();
	while (p)
	{
		if (!strcmp(p->data.id, id))
		{
			break;
		}
		else
			p = p->next;
	}
	if (p == NULL)
	{
		printf("没有找到");
	}
	else
	{
		int i = 0;
		while (p->data.integral[i] != 0)
		{
			printf("第%d门课程的分数为%d,等级为%d", i + 1, p->data.integral[i], p->data.level[i]);
			i++;
		}
	}
	system("pause"); // 画面停留
	system("cls"); // 清屏

}

7.排序功能

这里我用了两个函数嵌套使用了,主要还是想让函数功能更分明(这是好习惯,你们也可以试着强迫自己),先遍历每一个学生结点,每一次对这个学生结点进行另外一个函数的操作排序。

这里的排序我们暴力解决,只要当前面的学生节点的分数小于后面的,就让前一个的next=后一个的next,而后一个的next=之前前一个结点,所以这里要用一个临时结点用来存放前一个结点的位置

​
void sortstu(int num)
{
	Lnode* p = Head;
	while (p->next)
	{
		if (p->data.integral[num] <= p->next->data.integral[num])
		{
			Lnode* flag = p;
			p = p->next->next;
			p->next = p;
		}

	}


}
void Sort()
{
	print();
	printf("请输入要排名的课程编号:");
	int num = 0;
	scanf("%d",&num);
	cour* p;
	p = headC;
	while (p)
	{
		if (p->data.num == num)
		{
			sortstu(num);
            p=p->next;
			
		}
		else
			p = p->next;
	}
	printf("排序成功");
	system("pause"); // 画面停留
	system("cls"); // 清屏
}

​

8.输出功能

因为我们用数组来储存对应的积分和等级,在遍历时直接按照格式打印出来就行

​
void Print()
{
	Lnode* p = Head;
	while (p)
	{
		double average=0;
		int sum = 0;
		for (int i = 0; i < 10; i++)
		{
			average += p->data.level[i];
			if (p->data.level[i] != 0)
			{
				sum++;
			}
		}

		average /= sum;
		printf("学生姓名:%5s,学生学号:%10s,学生课程平均等级%.2lf", p->data.name, p->data.id, average);
        p=p->next;
	}
	system("pause"); // 画面停留
	system("cls"); // 清屏

}

​

9.删除功能

这点是最头疼的,因为当你删除这个试题时删除的只是这个数组对应的积分数,也就是定义为0,count--,但我们在新增考试题的时候只能从最后一个数组元素开始储存,造成了很大空间的浪费,按理说,这个试题也应该用链表来存储,但我放弃了(乱,且麻烦)

还是遍历整个链表,根据条件确定对应的课程,进行删除操作(“其实也就也是赋值为0,count--而已”)

void Delete()
{
	print();
	printf("请输入需要删除试题的课程编号:");
	int num1;
	scanf("%d",&num1);
	cour* p;
	p = headC;
	while (p)
	{
		if (p->data.num==num1)
		{
			printf("现有%d个题目\n",p->data.count);
			printf("请输入删除的试题编号:");
			int num2;
			scanf("%d",&num2);
			p->data.item[num2]=0;
			p->data.count--;
			break;
		}
		else
			p = p->next;
		p->count--;
	}
	system("pause"); // 画面停留
	system("cls"); // 清屏

}

10.保存功能

做这一步之前,要现在这个文件目录下创建一个文件(.text),作者创建的就是“学生管理系统文件夹”,我们的保存功能只来保存学生信息,不保存课程信息,两者其实差不多,你可以再创建一个文件用来储存它。注意打开文件,写入文件的操作...(想要保存课程信息的代码,可以去找这个大佬的博客2022级郑州轻工业大学学生平台管理系统期末设计(最终版v3.0)-CSDN博客

void Save()
{
	FILE* fp = fopen("E:\\初学c鹏哥\\Gardevior1\\Gardevior1\\学生管理系统.txt","w");
	if (fp == NULL)
	{
		printf("保存失败");
		return;
	}
	Lnode* p = Head;
	while (p)
	{
		fwrite(&p->data,1,sizeof(Student),fp);
		p = p->next;
	}
	fclose(fp);
	printf("数据保存成功");
	system("pause"); // 画面停留
	system("cls"); // 清屏
}

11.导入功能

最主要的是要创建一个链表,读一次创建一个结点用来接收。注意读入文件的操作和格式。

void Import()
{
	FILE* fp = fopen("E:\\初学c鹏哥\\Gardevior1\\Gardevior1\\学生管理系统.txt","r");
	if (fp = NULL)
	{
		printf("导入失败");
		return;
	}
	Student stu;
	while (fread(&stu, 1, sizeof(Student), fp))
	{
		Lnode* p = (Lnode*)malloc(sizeof(Lnode));
		p->next = NULL;
		memcpy(p,&stu,sizeof(Student));
		if (Head == NULL)
		{
			Head = p;
			Tail = p;
		}
		else
		{
			Tail->next = p;
			Tail = p;
		}
	}
}

0.退出功能就不说了,相信你们都会

4.一些题外话

        1.做项目的时候遇到前后一一对照的数据结构时一定要想好使用链表还是顺序表,这个项目的每个函数基本上都有遍历,所以我最后感觉应该用顺序表来存放学生信息是最好的,当然这样的话有的函数操作也特别麻烦,比如:增删。但这个项目要求里面并没要求需要“删除学生"这个函数,而有删除课程信息这个操作,咱正好反了

        2.我在做项目的时候使用的vs2022,在实现第一个函数时就遇到了困境,思路没错,是scanf_s在被刺我,如果你也用的vs2022,将函数1中的scanf全换成scanf_s你会发现代码根本读不进去,当时是在晚上,我原本以为是输入缓冲区的问题,恶补并实验一个小时,直到半夜两点也没弄清楚怎么回事。直到今天,有一个朋友帮我测验,发现是这个scanf_s的问题,超难受的!!!解决方案也很简单, 将这个“_CRT_SECURE_NO_WARNINGS”添加到最开始的位置就行了(如果还不懂,网上绝对有相关介绍),就可以使用scanf函数了。

        3.第三篇博客,加油!

​​​​​​​

  • 42
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

奈奈朵

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值