链表实现成绩管理系统

使用链表实现成绩管理系统

完成的功能如下:
1.增加成绩信息
2.查询成绩信息
3.删除成绩信息
4.修改信息
5.成绩的打印
6.成绩信息的排序
7.成绩信息的统计
8.保存信息到文件
9.从文件中读取信息

一、为什么使用链表,链表是什么?

在这里插入图片描述

二、代码

1.定义数据的结构体和链表节点的结构体

代码如下(示例):

#define MAX_NAME 15
#define MAX_ID 15

typedef struct Student //定义结构体 
{
	char name[MAX_NAME];
	char id[MAX_ID];
	float score[3];
	float total;
	float average;
}Student;

typedef Student SLTDataType;

//单链表的定义
typedef struct SListNode
{
	SLTDataType data;
	struct SListNode* next; //next指向当前节点的下一个节点
}SListNode;

2.创建表头函数,这里使用的是有头链表

代码如下(示例):

//创建表头
SListNode* CreateHead()
{
	SListNode* plist = (SListNode *)malloc(sizeof(SListNode));
	//判断申请是否成功
	if (plist == NULL)
	{
		printf("创建表头失败!\n");
		exit(-1);//退出  
	}

	plist->next = NULL;
	return plist;
}

返回plist表示头节点的地址,后面会频繁使用,每次都是从头节点开始进行一系列功能实现。

3.开辟一个新节点,返回节点的地址

代码如下(示例):

//动态申请一个节点,返回新申请结点的地址
SListNode* BuyListNode(const SLTDataType x)
{
	SListNode* plist = (SListNode *)malloc(sizeof(SListNode));
	//判断申请是否成功
	if (plist == NULL)
	{
		printf("申请新节点失败!\n");
		exit(-1);
	}
	plist->data = x;
	plist->next = NULL;
	return plist;
}

形参用于把数据传入,进行更新,返回地址用于将此地址,赋值给上一个节点的next。

4.尾插数据,调用开辟新节点函数

代码如下(示例):

//单链表尾插数据
void AddSystem(SListNode** pplist)
{
	Student s;

	printf("请输入名字:>");
	scanf("%s", s.name);
	getchar();
	printf("请输入学号:>");
	scanf("%s", s.id);
	getchar();
	printf("请输入语文成绩:>");
	scanf("%f", &(s.score[0]));
	getchar();
	printf("请输入数学成绩:>");
	scanf("%f", &(s.score[1]));
	getchar();
	printf("请输入英语成绩:>");
	scanf("%f", &(s.score[2]));
	getchar();

	s.total = s.score[0] + s.score[1] + s.score[2];
	s.average = s.total / 3;
	printf("录入成功!\n");

	//申请一个新节点
	SListNode* NewNode = BuyListNode(s);

	//定义一个当前节点tail去找链表的尾节点
	SListNode* tail = *pplist;
	
	//遍历节点找尾节点
	while (tail->next != NULL)
	{
		tail = tail->next;
	}
	//尾节点的next指向新节点
	tail->next = NewNode;
}

while循环用来找尾,找到NULL停止,则代表这个是尾巴,需要将新开辟的节点地址挂载到这个尾巴!

5.通过姓名查找 -> 查找到打印即可,查找同样是遍历找NULL的过程

代码如下(示例):

//查询人的信息
void SearchSystem(const SListNode* plist)
{
	SListNode* cur = plist->next;

	int flag = 0;

	while (1)
	{
		char input[5];
		printf("请输入你要查询的方式,学号 or 姓名:>");
		scanf("%s", input);
		getchar();

		if (strcmp(input, "姓名") == 0)
		{
			char Name[MAX_NAME];
			printf("请输入你要查询的名字:>");
			scanf("%s", Name);
			getchar();

			//遍历链表
			while (cur != NULL)
			{
				//如果找节点值等于x则返回
				if (0 == strcmp(cur->data.name, Name))
				{
					flag = 1;
					printf("%-15s\t%-15s\t%-8s\t%-8s\t%-8s\t%-8s\t%-8s\n", "名字", "学号", "语文", "数学", "英语", "总分", "平均分");
					printf("%-15s\t%-15s\t%-8.2lf\t%-8.2lf\t%-8.2lf\t%-8.2lf\t%-8.2lf\n", cur->data.name,
																							cur->data.id,
																							cur->data.score[0],
																							cur->data.score[1],
																							cur->data.score[2],
																							cur->data.total,
																							cur->data.average);
					break;
				}
				//没找到继续遍历
				cur = cur->next;
			}
			if (0 == flag)
			{
				printf("查无此人!\n");
			}
			break;
		}

		else if (strcmp(input, "学号") == 0)
		{
			char Id[MAX_ID];
			printf("请输入你要查询的学号:>");
			scanf("%s", Id);
			getchar();
			while (cur != NULL)
			{
				//如果找节点值等于x则返回
				if (0 == strcmp(cur->data.id, Id))
				{
					flag = 1;
					printf("%-15s\t%-15s\t%-8s\t%-8s\t%-8s\t%-8s\t%-8s\n", "名字", "学号", "语文", "数学", "英语", "总分", "平均分");
					printf("%-15s\t%-15s\t%-8.2lf\t%-8.2lf\t%-8.2lf\t%-8.2lf\t%-8.2lf\n", cur->data.name,
																							cur->data.id,
																							cur->data.score[0],
																							cur->data.score[1],
																							cur->data.score[2],
																							cur->data.total,
																							cur->data.average);
					break;
				}
				//没找到继续遍历
				cur = cur->next;
			}
			if (0 == flag)
			{
				printf("查无此人!\n");
			}
			break;
		}

		else
		{
			printf("输入错误,请重新输入!\n");
		}

	}
}

6.查找函数 -> 返回查找到的前一个地址(原因见下图)

在这里插入图片描述
代码如下(示例):

//单链表查找
static SListNode* SListFind(const SListNode* plist, char name[])
{
	SListNode* cur = plist->next;
	SListNode* pos = plist;
	//1.空链表直接返回
	if (cur == NULL)
	{
		return NULL;
	}

	//遍历链表
	while (cur!= NULL)
	{
		//如果找节点值等于x则返回
		if (strcmp(cur->data.name, name) == 0)
		{
			return pos;
		}
		//没找到继续遍历
		pos = pos->next;
		cur = cur->next;
	}
	return NULL;
}

		

7.删除函数 -> 通过查找名字函数返回的该删除的前一个地址对信息进行删除,并进行节点的更新!

在这里插入图片描述
代码如下(示例):

//删除人的信息
void DelSystem(SListNode** pplist)
{
	assert(*pplist);

	char name[MAX_NAME];
	printf("请输入要删除人的名字:>");
	scanf("%s", name);
	getchar();

	SListNode* cur = (*pplist)->next;
	SListNode* del = SListFind(*pplist, name);

	if (del == NULL)
	{
		printf("要删除的人不存在!\n");
	}
	else
	{
		SListNode* tmp = del->next->next;
		free(del->next);//释放
		del->next = tmp;
		printf("删除成功!\n");
	}
}

8.修改函数 -> 找到要修改的名字,通过查找函数函数前一个的地址,然后通过next找到这个要修改的节点

代码如下(示例):

//修改人的信息
void ModifySystem(SListNode** pplist)
{
	assert(*pplist);

	char name[MAX_NAME];
	printf("请输入要修改人的名字:>");
	scanf("%s", name);
	getchar();

	SListNode* mod = SListFind(*pplist, name);
	if (NULL == mod)
	{
		printf("要修改的人不存在!\n");
	}
	else
	{
		mod = mod->next;

		printf("请输入名字:>");
		scanf("%s", mod->data.name);
		getchar();
		printf("请输入学号:>");
		scanf("%s", mod->data.id);
		getchar();
		printf("请输入语文成绩:>");
		scanf("%f", &(mod->data.score[0]));
		getchar();
		printf("请输入数学成绩:>");
		scanf("%f", &(mod->data.score[1]));
		getchar();
		printf("请输入英语成绩:>");
		scanf("%f", &(mod->data.score[2]));
		getchar();

		mod->data.total = mod->data.score[0] + mod->data.score[1] + mod->data.score[2];
		mod->data.average = mod->data.total / 3;
		printf("修改成功!\n");
	}
}

9.打印函数 -> 方便我们及时观察录入的信息

代码如下(示例):

//成绩信息打印
void PrintSystem(const SListNode* plist)
{
	SListNode* cur = plist->next;

	printf("%-15s\t%-15s\t%-8s\t%-8s\t%-8s\t%-8s\t%-8s\n", "名字", "学号", "语文", "数学", "英语", "总分", "平均分");
	//打印链表
	while (cur)
	{
		//printf("%d->", cur->data);
		printf("%-15s\t%-15s\t%-8.2lf\t%-8.2lf\t%-8.2lf\t%-8.2lf\t%-8.2lf\n", cur->data.name,
																			 cur->data.id,
																			 cur->data.score[0],
																			 cur->data.score[1],
																			 cur->data.score[2],
																			 cur->data.total,
																			 cur->data.average);
		cur = cur->next;	//节点指向下一个
	}
}

10.排序,支持四种成绩的排序

代码如下(示例):

//语文成绩信息排序
static void SortChinese(SListNode** pplist)
{
	for (SListNode* p = (*pplist)->next; p != NULL; p = p->next)
	{
		for (SListNode* q = p->next; q != NULL; q = q->next)
		{
			if (p->data.score[0] < q->data.score[0])
			{
				SListNode tmp;
				tmp.data = p->data;
				p->data = q->data;
				q->data = tmp.data;
			}
		}
	}
}

//数学成绩信息排序
static void SortMath(SListNode** pplist)
{
	for (SListNode* p = (*pplist)->next; p != NULL; p = p->next)
	{
		for (SListNode* q = p->next; q != NULL; q = q->next)
		{
			if (p->data.score[1] < q->data.score[1])
			{
				SListNode tmp;
				tmp.data = p->data;
				p->data = q->data;
				q->data = tmp.data;
			}
		}
	}
}

//英语成绩信息排序
static void SortEnglish(SListNode** pplist)
{
	for (SListNode* p = (*pplist)->next; p != NULL; p = p->next)
	{
		for (SListNode* q = p->next; q != NULL; q = q->next)
		{
			if (p->data.score[2] < q->data.score[2])
			{
				SListNode tmp;
				tmp.data = p->data;
				p->data = q->data;
				q->data = tmp.data;
			}
		}
	}
}

//总分成绩信息排序
static void SortToal(SListNode** pplist)
{
	for (SListNode* p = (*pplist)->next; p != NULL; p = p->next)
	{
		for (SListNode* q = p->next; q != NULL; q = q->next)
		{
			if (p->data.total < q->data.total)
			{
				SListNode tmp;
				tmp.data = p->data;
				p->data = q->data;
				q->data = tmp.data;
			}
		}
	}
}

void SortSystem(SListNode** pplist)
{
	assert(*pplist);

	while (1)
	{
		char input[5];
		printf("请输入按什么成绩排序, 语文 数学 英语 总分:>");
		scanf("%s", input);
		if (strcmp(input, "语文") == 0)
		{
			SortChinese(pplist);
			PrintSystem(*pplist);
			break;
		}
		else if (strcmp(input, "数学") == 0)
		{
			SortMath(pplist);
			PrintSystem(*pplist);
			break;
		}
		else if (strcmp(input, "英语") == 0)
		{
			SortEnglish(pplist);
			PrintSystem(*pplist);
			break;
		}
		else if (strcmp(input, "总分") == 0)
		{
			SortToal(pplist);
			PrintSystem(*pplist);
			break;
		}
		else
		{
			printf("输入错误!\n");
		}
	}
}

11.统计函数,统计科目以及一个分数段内的学生

代码如下(示例):

//成绩信息统计
void StatisticsSystem(const SListNode* plist)
{
	char input[5];
	int low = 0;
	int high = 0;
	int sum = 0;
	printf("请输入统计信息的学科:>");
	scanf("%s", input);
	getchar();
	printf("请输入学科成绩的下限:>");
	scanf("%d", &low);
	getchar();
	printf("请输入学科成绩的上限:>");
	scanf("%d", &high);
	getchar();

	SListNode* cur = plist->next;

	printf("%-15s\t%-15s\t%-8s\t%-8s\t%-8s\t%-8s\t%-8s\n", "名字", "学号", "语文", "数学", "英语", "总分", "平均分");
	//打印链表
	while (cur)
	{
		if (strcmp(input, "语文") == 0)
		{
			if (cur->data.score[0] >= low && cur->data.score[0] <= high)
			{
				printf("%-15s\t%-15s\t%-8.2lf\t%-8.2lf\t%-8.2lf\t%-8.2lf\t%-8.2lf\n", cur->data.name,
					cur->data.id,
					cur->data.score[0],
					cur->data.score[1],
					cur->data.score[2],
					cur->data.total,
					cur->data.average);
				sum++;
			}
		}
		else if (strcmp(input, "数学") == 0)
		{
			if (cur->data.score[1] >= low && cur->data.score[1] <= high)
			{
				printf("%-15s\t%-15s\t%-8.2lf\t%-8.2lf\t%-8.2lf\t%-8.2lf\t%-8.2lf\n", cur->data.name,
					cur->data.id,
					cur->data.score[0],
					cur->data.score[1],
					cur->data.score[2],
					cur->data.total,
					cur->data.average);
				sum++;
			}
		}
		else if (strcmp(input, "英语") == 0)
		{
			if (cur->data.score[2] >= low && cur->data.score[2] <= high)
			{
				printf("%-15s\t%-15s\t%-8.2lf\t%-8.2lf\t%-8.2lf\t%-8.2lf\t%-8.2lf\n", cur->data.name,
					cur->data.id,
					cur->data.score[0],
					cur->data.score[1],
					cur->data.score[2],
					cur->data.total,
					cur->data.average);
				sum++;
			}
		}
		else
		{
			printf("输入错误!\n");
			break;
		}
		cur = cur->next;	//节点指向下一个
	}
	printf("           **********************%s学科成绩在%d-%d之间共有%d个学生***********************          \n", input, low, high, sum);
}

12保存函数 ->保存信息到我们的文件

代码如下(示例):

//保存信息到文件
void SaveSystem(const SListNode* plist)
{
	FILE* fp = fopen("Student_sorce.txt", "w+");

	SListNode* cur = plist->next;

	if (NULL == fp)
	{
		printf("打开文件失败!\n");
		exit(-1);
	}
	
	else
	{
		while (cur)
		{
			fprintf(fp, "%s %s %.2f %.2f %.2f %.2f %.2f\n", cur->data.name,
				cur->data.id,
				cur->data.score[0],
				cur->data.score[1],
				cur->data.score[2],
				cur->data.total,
				cur->data.average);
			cur = cur->next;	//节点指向下一个
		}
	}
	printf("保存成功!\n");
	fclose(fp);
}

13读取函数 ->直接从文件内读取数据

代码如下(示例):

static void AddByRead(SListNode** pplist, const SLTDataType s)
{
	//申请一个新节点
	SListNode* NewNode = BuyListNode(s);

	//定义一个当前节点tail去找链表的尾节点
	SListNode* tail = *pplist;

	//遍历节点找尾节点
	while (tail->next != NULL)
	{
		tail = tail->next;
	}
	//尾节点的next指向新节点
	tail->next = NewNode;
}

//读取信息到文件
void ReadSystem(SListNode** pplist)
{
	FILE* fp = fopen("Student_sorce.txt", "r");

	if (NULL == fp)
	{
		printf("打开%s文件失败!\n", "Student_sorce.txt");
		exit(-1);
	}

	int i = 0;
	int lineCount = 0;//行数
	while (!feof(fp))
	{
		char flag = fgetc(fp);
		if (flag == '\n')
			lineCount++;
	}
	rewind(fp);//重新返回文件开头 

	Student s;

	while (i < lineCount)
	{
		fscanf(fp, "%s %s %f %f %f %f %f", s.name, s.id, &(s.score[0]), &(s.score[1]), &(s.score[2]), &(s.total), &(s.average));

		AddByRead(pplist, s);

		i++;
	}

	printf("读取成功!\n");
	fclose(fp);
}

在这里插入图片描述


三、所有代码

代码如下(示例):

test.c

#define  _CRT_SECURE_NO_WARNINGS 1

#include "score.h"

enum Optinon
{
	Exit,//0
	Add,//1
	Del,//2
	Search,//3
	Show,//4
	Modify,
	Sort,
	Statistics,
	Save,
	Read,
};


void menu()
{
	printf("*************  成绩管理系统  ****************\n");
	printf("*****  1. Add          2. Del         *******\n");
	printf("*****  3. Search       4. Show        *******\n");
	printf("*****  5. Modify       6. Sort        *******\n");
	printf("*****  7. Statistics   8. Save        *******\n");
	printf("*****  9. Read         0. Exit        *******\n");
	printf("*********************************************\n");
}

int main()
{
	SListNode* Plist = CreateHead();	//定义一个单链表
	int input = 0;
	do
	{
		menu();
		printf("请选择:>");
		scanf("%d", &input);
		switch (input)
		{
		case Add:
			AddSystem(&Plist);
			break;
		case Del:
			DelSystem(&Plist);
			break;
		case Search:
			SearchSystem(Plist);
			break;
		case Show:
			PrintSystem(Plist);
			break;
		case Modify:
			ModifySystem(&Plist);
			break;
		case Sort:
			SortSystem(&Plist);
			break;
		case Statistics:
			StatisticsSystem(Plist);
			break;
		case Save:
			SaveSystem(Plist);
			break;
		case Read:
			ReadSystem(&Plist);
			break;
		case Exit:
			printf("退出该系统\n");
			break;
		default:
			printf("选择错误\n");
			break;
		}
	} while (input);

	return 0;
}


score.h

#pragma once 

#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <string.h>

#define MAX_NAME 15
#define MAX_ID 15

typedef struct Student //定义结构体 
{
	char name[MAX_NAME];
	char id[MAX_ID];
	float score[3];
	float total;
	float average;
}Student;

typedef Student SLTDataType;

//单链表的定义
typedef struct SListNode
{
	SLTDataType data;
	struct SListNode* next; //next指向当前节点的下一个节点
}SListNode;

//创建表头
SListNode* CreateHead();

//动态申请一个节点,返回新申请结点的地址
SListNode* BuyListNode(const SLTDataType x);

//单链表尾插数据
void AddSystem(SListNode** pplist);

//查询成绩信息
void SearchSystem(const SListNode* plist);

//删除成绩信息
void DelSystem(SListNode** pplist);

//修改人的信息
void ModifySystem(SListNode** pplist);

//成绩信息打印
void PrintSystem(const SListNode* plist);

//成绩信息排序
void SortSystem(SListNode** pplist);

//成绩信息统计
void StatisticsSystem(const SListNode* plist);

//保存信息到文件
void SaveSystem(const SListNode* plist);

//读取信息到文件
void ReadSystem(SListNode** pplist);

score.c
#define  _CRT_SECURE_NO_WARNINGS 1

#include "score.h"

//创建表头
SListNode* CreateHead()
{
	SListNode* plist = (SListNode *)malloc(sizeof(SListNode));
	//判断申请是否成功
	if (plist == NULL)
	{
		printf("创建表头失败!\n");
		exit(-1);//退出  
	}

	plist->next = NULL;
	return plist;
}

//动态申请一个节点,返回新申请结点的地址
SListNode* BuyListNode(const SLTDataType x)
{
	SListNode* plist = (SListNode *)malloc(sizeof(SListNode));
	//判断申请是否成功
	if (plist == NULL)
	{
		printf("申请新节点失败!\n");
		exit(-1);
	}
	plist->data = x;
	plist->next = NULL;
	return plist;
}

//单链表尾插数据
void AddSystem(SListNode** pplist)
{
	Student s;

	printf("请输入名字:>");
	scanf("%s", s.name);
	getchar();
	printf("请输入学号:>");
	scanf("%s", s.id);
	getchar();
	printf("请输入语文成绩:>");
	scanf("%f", &(s.score[0]));
	getchar();
	printf("请输入数学成绩:>");
	scanf("%f", &(s.score[1]));
	getchar();
	printf("请输入英语成绩:>");
	scanf("%f", &(s.score[2]));
	getchar();

	s.total = s.score[0] + s.score[1] + s.score[2];
	s.average = s.total / 3;
	printf("录入成功!\n");

	//申请一个新节点
	SListNode* NewNode = BuyListNode(s);

	//定义一个当前节点tail去找链表的尾节点
	SListNode* tail = *pplist;
	
	//遍历节点找尾节点
	while (tail->next != NULL)
	{
		tail = tail->next;
	}
	//尾节点的next指向新节点
	tail->next = NewNode;
}

//查询人的信息
void SearchSystem(const SListNode* plist)
{
	SListNode* cur = plist->next;

	int flag = 0;

	while (1)
	{
		char input[5];
		printf("请输入你要查询的方式,学号 or 姓名:>");
		scanf("%s", input);
		getchar();

		if (strcmp(input, "姓名") == 0)
		{
			char Name[MAX_NAME];
			printf("请输入你要查询的名字:>");
			scanf("%s", Name);
			getchar();

			//遍历链表
			while (cur != NULL)
			{
				//如果找节点值等于x则返回
				if (0 == strcmp(cur->data.name, Name))
				{
					flag = 1;
					printf("%-15s\t%-15s\t%-8s\t%-8s\t%-8s\t%-8s\t%-8s\n", "名字", "学号", "语文", "数学", "英语", "总分", "平均分");
					printf("%-15s\t%-15s\t%-8.2lf\t%-8.2lf\t%-8.2lf\t%-8.2lf\t%-8.2lf\n", cur->data.name,
																							cur->data.id,
																							cur->data.score[0],
																							cur->data.score[1],
																							cur->data.score[2],
																							cur->data.total,
																							cur->data.average);
					break;
				}
				//没找到继续遍历
				cur = cur->next;
			}
			if (0 == flag)
			{
				printf("查无此人!\n");
			}
			break;
		}

		else if (strcmp(input, "学号") == 0)
		{
			char Id[MAX_ID];
			printf("请输入你要查询的学号:>");
			scanf("%s", Id);
			getchar();
			while (cur != NULL)
			{
				//如果找节点值等于x则返回
				if (0 == strcmp(cur->data.id, Id))
				{
					flag = 1;
					printf("%-15s\t%-15s\t%-8s\t%-8s\t%-8s\t%-8s\t%-8s\n", "名字", "学号", "语文", "数学", "英语", "总分", "平均分");
					printf("%-15s\t%-15s\t%-8.2lf\t%-8.2lf\t%-8.2lf\t%-8.2lf\t%-8.2lf\n", cur->data.name,
																							cur->data.id,
																							cur->data.score[0],
																							cur->data.score[1],
																							cur->data.score[2],
																							cur->data.total,
																							cur->data.average);
					break;
				}
				//没找到继续遍历
				cur = cur->next;
			}
			if (0 == flag)
			{
				printf("查无此人!\n");
			}
			break;
		}

		else
		{
			printf("输入错误,请重新输入!\n");
		}

	}
}

//单链表查找
static SListNode* SListFind(const SListNode* plist, char name[])
{
	SListNode* cur = plist->next;
	SListNode* pos = plist;
	//1.空链表直接返回
	if (cur == NULL)
	{
		return NULL;
	}

	//遍历链表
	while (cur!= NULL)
	{
		//如果找节点值等于x则返回
		if (strcmp(cur->data.name, name) == 0)
		{
			return pos;
		}
		//没找到继续遍历
		pos = pos->next;
		cur = cur->next;
	}
	return NULL;
}

//删除人的信息
void DelSystem(SListNode** pplist)
{
	assert(*pplist);

	char name[MAX_NAME];
	printf("请输入要删除人的名字:>");
	scanf("%s", name);
	getchar();

	SListNode* cur = (*pplist)->next;
	SListNode* del = SListFind(*pplist, name);

	if (del == NULL)
	{
		printf("要删除的人不存在!\n");
	}
	else
	{
		SListNode* tmp = del->next->next;
		free(del->next);//释放
		del->next = tmp;
		printf("删除成功!\n");
	}
}

//修改人的信息
void ModifySystem(SListNode** pplist)
{
	assert(*pplist);

	char name[MAX_NAME];
	printf("请输入要修改人的名字:>");
	scanf("%s", name);
	getchar();

	SListNode* mod = SListFind(*pplist, name);
	if (NULL == mod)
	{
		printf("要修改的人不存在!\n");
	}
	else
	{
		mod = mod->next;

		printf("请输入名字:>");
		scanf("%s", mod->data.name);
		getchar();
		printf("请输入学号:>");
		scanf("%s", mod->data.id);
		getchar();
		printf("请输入语文成绩:>");
		scanf("%f", &(mod->data.score[0]));
		getchar();
		printf("请输入数学成绩:>");
		scanf("%f", &(mod->data.score[1]));
		getchar();
		printf("请输入英语成绩:>");
		scanf("%f", &(mod->data.score[2]));
		getchar();

		mod->data.total = mod->data.score[0] + mod->data.score[1] + mod->data.score[2];
		mod->data.average = mod->data.total / 3;
		printf("修改成功!\n");
	}
}

//成绩信息打印
void PrintSystem(const SListNode* plist)
{
	SListNode* cur = plist->next;

	printf("%-15s\t%-15s\t%-8s\t%-8s\t%-8s\t%-8s\t%-8s\n", "名字", "学号", "语文", "数学", "英语", "总分", "平均分");
	//打印链表
	while (cur)
	{
		//printf("%d->", cur->data);
		printf("%-15s\t%-15s\t%-8.2lf\t%-8.2lf\t%-8.2lf\t%-8.2lf\t%-8.2lf\n", cur->data.name,
																			 cur->data.id,
																			 cur->data.score[0],
																			 cur->data.score[1],
																			 cur->data.score[2],
																			 cur->data.total,
																			 cur->data.average);
		cur = cur->next;	//节点指向下一个
	}
}

//语文成绩信息排序
static void SortChinese(SListNode** pplist)
{
	for (SListNode* p = (*pplist)->next; p != NULL; p = p->next)
	{
		for (SListNode* q = p->next; q != NULL; q = q->next)
		{
			if (p->data.score[0] < q->data.score[0])
			{
				SListNode tmp;
				tmp.data = p->data;
				p->data = q->data;
				q->data = tmp.data;
			}
		}
	}
}

//数学成绩信息排序
static void SortMath(SListNode** pplist)
{
	for (SListNode* p = (*pplist)->next; p != NULL; p = p->next)
	{
		for (SListNode* q = p->next; q != NULL; q = q->next)
		{
			if (p->data.score[1] < q->data.score[1])
			{
				SListNode tmp;
				tmp.data = p->data;
				p->data = q->data;
				q->data = tmp.data;
			}
		}
	}
}

//英语成绩信息排序
static void SortEnglish(SListNode** pplist)
{
	for (SListNode* p = (*pplist)->next; p != NULL; p = p->next)
	{
		for (SListNode* q = p->next; q != NULL; q = q->next)
		{
			if (p->data.score[2] < q->data.score[2])
			{
				SListNode tmp;
				tmp.data = p->data;
				p->data = q->data;
				q->data = tmp.data;
			}
		}
	}
}

//总分成绩信息排序
static void SortToal(SListNode** pplist)
{
	for (SListNode* p = (*pplist)->next; p != NULL; p = p->next)
	{
		for (SListNode* q = p->next; q != NULL; q = q->next)
		{
			if (p->data.total < q->data.total)
			{
				SListNode tmp;
				tmp.data = p->data;
				p->data = q->data;
				q->data = tmp.data;
			}
		}
	}
}

void SortSystem(SListNode** pplist)
{
	assert(*pplist);

	while (1)
	{
		char input[5];
		printf("请输入按什么成绩排序, 语文 数学 英语 总分:>");
		scanf("%s", input);
		if (strcmp(input, "语文") == 0)
		{
			SortChinese(pplist);
			PrintSystem(*pplist);
			break;
		}
		else if (strcmp(input, "数学") == 0)
		{
			SortMath(pplist);
			PrintSystem(*pplist);
			break;
		}
		else if (strcmp(input, "英语") == 0)
		{
			SortEnglish(pplist);
			PrintSystem(*pplist);
			break;
		}
		else if (strcmp(input, "总分") == 0)
		{
			SortToal(pplist);
			PrintSystem(*pplist);
			break;
		}
		else
		{
			printf("输入错误!\n");
		}
	}
}

//成绩信息统计
void StatisticsSystem(const SListNode* plist)
{
	char input[5];
	int low = 0;
	int high = 0;
	int sum = 0;
	printf("请输入统计信息的学科:>");
	scanf("%s", input);
	getchar();
	printf("请输入学科成绩的下限:>");
	scanf("%d", &low);
	getchar();
	printf("请输入学科成绩的上限:>");
	scanf("%d", &high);
	getchar();

	SListNode* cur = plist->next;

	printf("%-15s\t%-15s\t%-8s\t%-8s\t%-8s\t%-8s\t%-8s\n", "名字", "学号", "语文", "数学", "英语", "总分", "平均分");
	//打印链表
	while (cur)
	{
		if (strcmp(input, "语文") == 0)
		{
			if (cur->data.score[0] >= low && cur->data.score[0] <= high)
			{
				printf("%-15s\t%-15s\t%-8.2lf\t%-8.2lf\t%-8.2lf\t%-8.2lf\t%-8.2lf\n", cur->data.name,
					cur->data.id,
					cur->data.score[0],
					cur->data.score[1],
					cur->data.score[2],
					cur->data.total,
					cur->data.average);
				sum++;
			}
		}
		else if (strcmp(input, "数学") == 0)
		{
			if (cur->data.score[1] >= low && cur->data.score[1] <= high)
			{
				printf("%-15s\t%-15s\t%-8.2lf\t%-8.2lf\t%-8.2lf\t%-8.2lf\t%-8.2lf\n", cur->data.name,
					cur->data.id,
					cur->data.score[0],
					cur->data.score[1],
					cur->data.score[2],
					cur->data.total,
					cur->data.average);
				sum++;
			}
		}
		else if (strcmp(input, "英语") == 0)
		{
			if (cur->data.score[2] >= low && cur->data.score[2] <= high)
			{
				printf("%-15s\t%-15s\t%-8.2lf\t%-8.2lf\t%-8.2lf\t%-8.2lf\t%-8.2lf\n", cur->data.name,
					cur->data.id,
					cur->data.score[0],
					cur->data.score[1],
					cur->data.score[2],
					cur->data.total,
					cur->data.average);
				sum++;
			}
		}
		else
		{
			printf("输入错误!\n");
			break;
		}
		cur = cur->next;	//节点指向下一个
	}
	printf("           **********************%s学科成绩在%d-%d之间共有%d个学生***********************          \n", input, low, high, sum);
}


//保存信息到文件
void SaveSystem(const SListNode* plist)
{
	FILE* fp = fopen("Student_sorce.txt", "w+");

	SListNode* cur = plist->next;

	if (NULL == fp)
	{
		printf("打开文件失败!\n");
		exit(-1);
	}
	
	else
	{
		while (cur)
		{
			fprintf(fp, "%s %s %.2f %.2f %.2f %.2f %.2f\n", cur->data.name,
				cur->data.id,
				cur->data.score[0],
				cur->data.score[1],
				cur->data.score[2],
				cur->data.total,
				cur->data.average);
			cur = cur->next;	//节点指向下一个
		}
	}
	printf("保存成功!\n");
	fclose(fp);
}

	
static void AddByRead(SListNode** pplist, const SLTDataType s)
{
	//申请一个新节点
	SListNode* NewNode = BuyListNode(s);

	//定义一个当前节点tail去找链表的尾节点
	SListNode* tail = *pplist;

	//遍历节点找尾节点
	while (tail->next != NULL)
	{
		tail = tail->next;
	}
	//尾节点的next指向新节点
	tail->next = NewNode;
}

//读取信息到文件
void ReadSystem(SListNode** pplist)
{
	FILE* fp = fopen("Student_sorce.txt", "r");

	if (NULL == fp)
	{
		printf("打开%s文件失败!\n", "Student_sorce.txt");
		exit(-1);
	}

	int i = 0;
	int lineCount = 0;//行数
	while (!feof(fp))
	{
		char flag = fgetc(fp);
		if (flag == '\n')
			lineCount++;
	}
	rewind(fp);//重新返回文件开头 

	Student s;

	while (i < lineCount)
	{
		fscanf(fp, "%s %s %f %f %f %f %f", s.name, s.id, &(s.score[0]), &(s.score[1]), &(s.score[2]), &(s.total), &(s.average));

		AddByRead(pplist, s);

		i++;
	}

	printf("读取成功!\n");
	fclose(fp);
}	

四、总结

学习了链表,自己动手实现了这样一个简单的系统,需要源代码请留言!

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值