C语言项目实践——学生成绩管理系统

一、设计目的

        随着信息技术的发展,过去很多由人工处理的复杂事务开始由计算机来完成,学生成绩管理系统利用计算机对学生成绩进行统一的管理,实现完善的学生成绩录人、维护、统计、排序、保存到文件、打开成绩文件等管理工作,从而节约时间,提高教务人员的工作效率。

二、需求分析

        本学生成绩管理系统可以实现对众多学生信息的统一管理,其中记录的学生信息包括学生的学号、姓名、语文成绩、数学成绩、英语成绩、三门课程的平均成绩和平均成绩排名。具体功能需求描述如下。

(1)录人学生成绩信息:能够录人学生学号、姓名、语文成绩、数学成绩、英语成绩,并支持一次性录人多条学生成绩记录。

(2)将成绩信息保存到文件:能够将录人的学生成绩信息,以及计算得出的平均成绩、排名等信息永久记录到硬盘文件中。

(3)从文件中读取成绩信息:可以输人文件名,读取文件中的学生成绩信息并显示到界面,并可以进一步对读出的信息进行操作。(4)添加学生记录:可以连续添加多个学生记录,如果之前一条记录也没有,则提示用户先创建学生记录。

(5)删除学生记录:可以根据学生学号或者姓名查找要删除的学生记录,如果找到该记录,则将该学生记录删除。

(6)修改学生记录:可以根据学生学号或者姓名查找要修改的学生记录,如果找到该记录,则可以对该记录的各个字段进行修改。

(7)查找学生记录:可以按学号查找或者按姓名查找学生记录。

(8)学生成绩统计:可以对每门课程的通过人数、不及格人数、最低分、最高分、平均分,以及所有课程的最低分、最高分、平均分进行详细统计。

(9)学生记录排序:可以分别按照学号、姓名、语文成绩、数学成绩、英语成绩或者平均成绩进行排序。

(10)显示所有学生记录:显示所有学生记录的各项信息。

三、总体设计

        学生成绩管理系统的功能结构图如图所示,主要包括5个功能模块,分别介绍如下。

(1)学生成绩录人模块:成绩录人包括没有记录时的新建操作,以及已有记录时的涂加操作。对录人的学生学号进行判断,学号必须为大于等于0的数字,如果不满足要求,则提示用户重新输人;如果录人学号0,表示成绩录人结束。系统自动判断录人的学号是否与已有记录中的学生学号冲突,若冲突,则提示用户重新录人。一条学生记录的所有信息均录人完成之后,系统还会询问是否继续录人其他学生记录,支持学生信息的连续录人。

(2)学生成绩查询模块:学生成绩查询包括查看所有学生记录和查看某一个学生的记录。查看所有学生记录能以列表方式将系统中所有学生记录均显示出来;查看某一个学生的记录,则可以通过输人学号或者姓名信息进行查找,一旦找到对应记录,则显示该记录的所有信息,如果找不到,则提示用户。

(3)学生成绩维护模块:学生成绩维护包括常规的删除记录和修改记录。这两项功能要基于学生信息查询模块中的记录查找功能,一旦查找到要删除或者修改的记录,则可以执行相应的操作。

(4)排序与统计模块:能够对系统中的学生记录进行排序和统计。可以分别按照学号、姓名、语文成绩、数学成绩、英语成绩或者平均成绩进行排序;可以对每门课程的通过人数、不及格人数、最低分、最高分、平均分,以及所有课程的最低分、最高分、平均分进行详细的统计分析。

(5)文件存取模块:可以将系统中的学生成绩信息一次性存人磁盘文件中,文件名允许自定义。并且可以输人一个文件名,将该文件中的学生记录读出并显示在屏幕上。

 四、详细设计与实现

1.数据的存储结构

        定义的结构体如下:

        typedef struct Student

        {

          char name[20];           //姓名

          int S_Number;        //学号

          float Sorce_Chinese;

          float Sorce_Math;

          float Sorce_English;

          float avg;           //平均分

          int iRank;            //排名

          struct Student* pNext;

        }Student;

2.函数之间的调用关系

  1. void showMainMenu();

功能:打印主界面,显示功能选项

  1. Student* Create();

功能:创建学生记录,返回学生结构体类型的指针

  1. void Add(Student* pHead);

功能:向已有的数据表中添加数据

参数:一个已有的链表指针

  1. void Show(Student* pHead);

功能:显示数据表中的所有信息

参数:一个已有的链表指针

  1. void Sreach(Student* pHead);

功能:在数据表中搜索信息,找到显示该学生信息,没有找到则给出提示

参数:一个已有的链表指针

  1. void Modify(Student* pHead);

功能:在数据表中搜索信息,找到后修改信息,没有找到则给出提示

参数:一个已有的链表指针

  1. Student* Delete(Student* pHead);

功能:删除一个学生记录,先查找,若无则给出提示

参数:一个已有的链表指针

  1. void Sort();

功能:按照某个字段来排序

  1. void Statistics();

功能:统计数据表中的信息,分析各科成绩情况

  1. Student* Read();

功能:从文件读取信息

  1. void Save();

功能:保存数据表到本地,可以二进制保存或文本格式保存

  1. int CheakNum(char* pcNotice);

功能:检查学号输入是否正确

参数:字符串:一段提示信息

  1. float CheakScore(char* pcNotice);

功能:检查成绩输入是否正确

参数:字符串:一段提示信息

  1. void ShowHead(int iType);

功能:打印一段表头

参数:表头格式分两种

  1. void ShowSortMenu();

功能:显示排序功能选项

3.源代码

main.c

#define _CRT_SECURE_NO_WARNINGS
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
#include<conio.h>
#include<windows.h>
#include"Student.h"
//#include"access.h"



int main()
{
	modeset(80, 49);
	/*int key=access();
	if (key == 0)
	{
		return 0;
	}*/
	
	Student* pHead = NULL;
	int iItem;
	while (1)
	{
		showMainMenu();
		printf("\n请输入要执行的功能选项<0~10>:");
		scanf("%d", &iItem);
		while (iItem > 10 || iItem < 0)
		{
			char c;
			printf("输入有误请重新输入:");
			while ((c = getchar()) != EOF && c != '\n');
			scanf("%d", &iItem);
		}
		switch (iItem)
		{
		case 1:pHead = Create(); break;
		case 2:Add(pHead); break;
		case 3:Show(pHead); break;
		case 4:Sreach(pHead); break;
		case 5:Modify(pHead); break;
		case 6:pHead = Delete(pHead); break;
		case 7:Sort(pHead); break;
		case 8:Statistics(pHead); break;
		case 9:pHead = Read(); break;
		case 10:Save(pHead); break;
		case 0:exit(0); break;
		}
		for (int i = 0; i < 80; i++)
		{
			printf("-");
		}
		printf("\n");
		printf("按任意键返回主页\n");
		getchar();
	}
	return 0;
}

Student.c

#define _CRT_SECURE_NO_WARNINGS
#pragma once
#include<stdio.h>
#include<malloc.h>
#include<string.h>
#include <conio.h>
#include <windows.h>
#include"Student.h"



void modeset(int w, int h)
{
	HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);//获取标准输出的句柄,命令行的程序会把字符输出到屏幕上。
	COORD size = { w, h };//设置窗口的大小。
	SetConsoleScreenBufferSize(hOut, size);//重新设置缓冲区大小。
	SMALL_RECT rc = { 1,1, w, h };//重置窗口位置和大小。
	SetConsoleWindowInfo(hOut, 1, &rc);//重置窗口大小
	system("cls");//清理屏幕
	return;
}

void Print(char c, int n, int flag)
{
	for (int i = 0; i < n; i++)
	{
		printf("%c", c);
	}
	if (flag) {
		printf("\n");
	}
}

void showMainMenu()
{
	system("cls");
	printf("\n\t\t\t\t学生成绩管理系统\n\n");
	Print('*', 80, 1);
	printf("1.创建记录\t\t5.更改数据\t\t9.从文件读取数据\n");
	printf("2.添加数据\t\t6.删除数据\t\t10.保存数据\n");
	printf("---------\t\t---------\t\t---------\n");
	printf("3.显示数据\t\t7.数据排序\t\t0.退出\n");
	printf("4.查找数据\t\t8.统计数据\n");
	Print('*', 80, 1);
}
void SwapStu(Student* Stu_1, Student* Stu_2)
{
	Student tmp;
	tmp = *Stu_1;
	*Stu_1 = *Stu_2;
	*Stu_2 = tmp;
}

int CheakNum(char* pcNotice)
{
	int inum;
	do {
		printf(pcNotice);
		scanf("%d", &inum);
		if (inum < 0)
		{
			printf("学号有误请重新输入!\n");
			char c;
			while ((c = getchar()) != EOF && c != '\n');
		}
	} while (inum < 0);
	return inum;
}

float CheakScore(char* pcNotice)
{
	float iScore;
	do {
		printf(pcNotice);
		scanf("%f", &iScore);
		if (iScore > 100 || iScore < 0)
		{
			printf("成绩输入有误,请重新输入!");
			char c;
			while ((c = getchar()) != EOF && c != '\n');
		}
	} while (iScore > 100 || iScore < 0);
	return iScore;
}

Student* Create()
{
	Student* pHead = NULL, * pTail = NULL, * pTemp, * pCur;
	int iNum, iFlag;
	while (1)
	{
		while (1)
		{
			iNum = CheakNum("请输入学生学号<输入0退出>:");
			if (iNum == 0)
			{
				printf("输入结束!\n");
				Show(pHead);
				return pHead;
			}
			iFlag = 0;
			pCur = pHead;
			while (pCur != NULL)
			{
				if (pCur->S_Number == iNum)
				{
					iFlag = 1;
					break;
				}
				pCur = pCur->pNext;
			}
			if (iFlag == 1)
			{
				printf("学号输入与他人重复,请重新输入!\n");
				continue;
			}
			else
				break;
		}

		pTemp = (Student*)malloc(sizeof(Student));
		if (pTemp == NULL)
		{
			printf("内存申请失败!");
			return NULL;
		}
		pTemp->S_Number = iNum;
		printf("请输入姓名:");
		char c;
		while ((c = getchar()) != EOF && c != '\n');
		scanf("%s", pTemp->name);
		getchar();
		pTemp->Sorce_Chinese = CheakScore("请输入语文成绩(0~100):");
		pTemp->Sorce_Math = CheakScore("请输入数学成绩(0~100):");
		pTemp->Sorce_English = CheakScore("请输入英语成绩(0~100):");
		pTemp->avg = (pTemp->Sorce_Chinese + pTemp->Sorce_Math + pTemp->Sorce_English) / (float)3.0;
		pTemp->iRank = 0;
		pTemp->pNext = NULL;

		if (!pHead)
		{
			pHead = pTail = pTemp;
		}
		else {
			pTail->pNext = pTemp;
			pTail = pTemp;
		}
	}
}

void Add(Student* pHead)
{
	Student* pCur, * pTail, * pTemp;
	int iNum, iFlag;
	if (pHead == NULL)
	{
		printf("\n没有学生记录,请先创建学生记录!\n");
		return;
	}
	pCur = pHead;
	while (pCur->pNext != NULL)
	{
		pCur = pCur->pNext;
	}
	pTail = pCur;
	while (1)
	{
		while (1)
		{
			iNum = CheakNum("请输入学生学号<输入0退出>:");
			if (iNum == 0)
			{
				printf("输入结束!\n");
				Show(pHead);
				return;
			}
			iFlag = 0;
			pCur = pHead;
			while (pCur != NULL)
			{
				if (pCur->S_Number == iNum)
				{
					iFlag = 1;
					break;
				}
				pCur = pCur->pNext;
			}
			if (iFlag == 1)
			{
				printf("学号输入与他人重复,请重新输入!\n");
				continue;
			}
			else
				break;
		}

		pTemp = (Student*)malloc(sizeof(Student));
		if (pTemp == NULL)
		{
			printf("内存申请失败!");
			return NULL;
		}
		pTemp->S_Number = iNum;
		printf("请输入姓名:");
		char c;
		while ((c = getchar()) != EOF && c != '\n');
		scanf("%s", &pTemp->name);
		getchar();
		pTemp->Sorce_Chinese = CheakScore("请输入语文成绩(0~100):");
		pTemp->Sorce_Math = CheakScore("请输入数学成绩(0~100):");
		pTemp->Sorce_English = CheakScore("请输入英语成绩(0~100):");
		pTemp->avg = (pTemp->Sorce_Chinese + pTemp->Sorce_Math + pTemp->Sorce_English) / (float)3.0;
		pTemp->iRank = 0;
		pTemp->pNext = NULL;

		pTail->pNext = pTemp;
		pTail = pTemp;
	}
}

void Show(Student* pHead)
{
	Student* pCur = pHead;
	int i = 0;
	if (pCur == NULL)
	{
		printf("\n没有学生记录,请先创建学生记录!\n");
	}
	else
	{
		ShowHead(1);
		while (pCur != NULL)
		{
			printf("\t|   %06d   |%10s|%6.2f |%6.2f |%6.2f |%6.2f|\n", pCur->S_Number, pCur->name, pCur->Sorce_Chinese, pCur->Sorce_Math, pCur->Sorce_English, pCur->avg);
			Print('-', 80, 1);
			pCur = pCur->pNext;
		}
	}
	printf("\n");
	system("pause");
}

void Sreach(Student* pHead)
{
	Student* pCur = pHead;
	int iItem, iNum = 0;
	char _name[20] = { '\0' };
	if (pCur == NULL)
	{
		printf("\n没有学生记录,请先创建学生记录!\n");
		return;
	}
	printf("\n请选择查找方式:\t1.按学号查找\t2.按姓名查找:");
	scanf("%d", &iItem);
	getchar();
	while (iItem > 2 || iItem < 1)
	{
		char c;
		while ((c = getchar()) != EOF && c != '\n');
		printf("输入有误,请重新输入!\n");
		scanf("%d", &iItem);
		
	}

	switch (iItem)
	{
	case 1:
		printf("请输入要查找的学号:");
		scanf("%d", &iNum);
		getchar();
		while (pCur != NULL)
		{
			if (pCur->S_Number == iNum)
			{
				ShowHead(1);
				printf("\t|   %06d   |%10s|%6.2f |%6.2f |%6.2f |%6.2f|\n", pCur->S_Number, pCur->name, pCur->Sorce_Chinese, pCur->Sorce_Math, pCur->Sorce_English, pCur->avg);
				Print('-', 80, 1);
				return;
			}
			pCur = pCur->pNext;
		}
		if (pCur == NULL)
		{
			printf("\n数据表中没有该学生!\n");
		}
		break;
	case 2:
		printf("请输入要查找的姓名:");
		scanf("%s", _name);
		getchar();
		while (pCur != NULL)
		{
			if (strcmp(pCur->name, _name) == 0)
			{
				ShowHead(1);
				printf("\t|   %06d   |%10s|%6.2f |%6.2f |%6.2f |%6.2f|\n", pCur->S_Number, pCur->name, pCur->Sorce_Chinese, pCur->Sorce_Math, pCur->Sorce_English, pCur->avg);
				Print('-', 80, 1);
				return;
			}
			pCur = pCur->pNext;
		}
		if (pCur == NULL)
		{
			printf("\n数据表中没有该学生!\n");
		}
		break;
	}
	return;
}

void Modify(Student* pHead)
{
	int iItem, iNum = 0;
	char _name[20] = { '\0' };
	Student* pCur = pHead;
	if (pCur == NULL)
	{
		printf("\n数据表为空,请先创建数据表!\n");
		return;
	}
	printf("\n请选择查找方式:\t1.按学号查找\t2.按姓名查找:");
	scanf("%d", &iItem);
	getchar();
	while (iItem > 2 || iItem < 1)
	{
		printf("输入有误,请重新输入!\n");
		scanf("%d", &iItem);
		char c;
		while ((c = getchar()) != EOF && c != '\n');
	}

	switch (iItem)
	{
	case 1:
		printf("请输入要查找的学号:");
		scanf("%d", &iNum);
		getchar();
		while (pCur != NULL)
		{
			if (pCur->S_Number == iNum)
			{
				printf("\n原数据为:\n");
				ShowHead(1);
				printf("\t|   %06d   |%10s|%6.2f |%6.2f |%6.2f |%6.2f|\n", pCur->S_Number, pCur->name, pCur->Sorce_Chinese, pCur->Sorce_Math, pCur->Sorce_English, pCur->avg);
				Print('-', 80, 1);
				printf("输入需要更改的学生信息:\n");
				iNum = CheakNum("请输入学生学号:");
				pCur->S_Number = iNum;
				printf("请输入姓名:");
				scanf("%s", pCur->name);
				getchar();
				pCur->Sorce_Chinese = CheakScore("请输入语文成绩(0~100):");
				pCur->Sorce_Math = CheakScore("请输入数学成绩(0~100):");
				pCur->Sorce_English = CheakScore("请输入英语成绩(0~100):");
				pCur->avg = (pCur->Sorce_Chinese + pCur->Sorce_Math + pCur->Sorce_English) / (float)3.0;
				pCur->iRank = 0;


				return;
			}
			pCur = pCur->pNext;
		}
		if (pCur == NULL)
		{
			printf("\n数据表中没有该学生!\n");
		}
		break;
	case 2:
		printf("请输入要查找的姓名:");
		scanf("%s", _name);
		getchar();
		while (pCur != NULL)
		{
			if (strcmp(pCur->name, _name) == 0)
			{
				ShowHead(1);
				printf("\t|   %06d   |%10s|%6.2f |%6.2f |%6.2f |%6.2f|\n", pCur->S_Number, pCur->name, pCur->Sorce_Chinese, pCur->Sorce_Math, pCur->Sorce_English, pCur->avg);
				Print('-', 80, 1);
				printf("输入需要更改的学生信息:\n");
				iNum = CheakNum("请输入学生学号:");
				pCur->S_Number = iNum;
				printf("请输入姓名:");
				scanf("%s", pCur->name);
				getchar();
				pCur->Sorce_Chinese = CheakScore("请输入语文成绩(0~100):");
				pCur->Sorce_Math = CheakScore("请输入数学成绩(0~100):");
				pCur->Sorce_English = CheakScore("请输入英语成绩(0~100):");
				pCur->avg = (pCur->Sorce_Chinese + pCur->Sorce_Math + pCur->Sorce_English) / (float)3.0;
				pCur->iRank = 0;
				return;
			}
			pCur = pCur->pNext;
		}
		if (pCur == NULL)
		{
			printf("\n数据表中没有该学生!\n");
		}
		break;
	}
	return;



}
Student* Delete(Student* pHead)
{
	Student* pCur = pHead, * pTemp = NULL, * prev = pHead;
	int iItem, iNum = 0;
	char _name[20] = { '\0' };
	if (pCur == NULL)
	{
		printf("\n数据表为空,请先创建数据表!\n");
		return NULL;
	}
	printf("\n请选择查找方式:\t1.按学号查找\t2.按姓名查找:");
	scanf("%d", &iItem);
	getchar();
	while (iItem > 2 || iItem < 1)
	{
		char c;
		while ((c = getchar()) != EOF && c != '\n');
		printf("输入有误,请重新输入!\n");
		scanf("%d", &iItem);
		
	}

	switch (iItem)
	{
	case 1:
		printf("请输入要删除的学号:");
		scanf("%d", &iNum);
		getchar();

		while (pCur != NULL)
		{
			if (pCur->S_Number == iNum)
			{
				printf("\n要删除的信息:\n");
				ShowHead(1);
				printf("\t|   %06d   |%10s|%6.2f |%6.2f |%6.2f |%6.2f|\n", pCur->S_Number, pCur->name, pCur->Sorce_Chinese, pCur->Sorce_Math, pCur->Sorce_English, pCur->avg);
				Print('-', 80, 1);
				if (pCur == pHead)
				{
					pHead = pHead->pNext;
				}
				else
				{
					prev->pNext = pCur->pNext;
				}
				free(pCur);
				return pHead;
			}
			prev = pCur;
			pCur = pCur->pNext;
		}
		if (pCur == NULL)
		{
			printf("\n数据表中没有该学生!\n");
		}
		break;
	case 2:
		printf("请输入要查找的姓名:");
		scanf("%s", _name);
		getchar();
		while (pCur != NULL)
		{
			if (strcmp(pCur->name, _name) == 0)
			{
				if (pCur->S_Number == iNum)
				{
					printf("\n要删除的信息:\n");
					ShowHead(1);
					printf("\t|   %06d   |%10s|%6.2f |%6.2f |%6.2f |%6.2f|\n", pCur->S_Number, pCur->name, pCur->Sorce_Chinese, pCur->Sorce_Math, pCur->Sorce_English, pCur->avg);
					Print('-', 80, 1);
					if (pCur == pHead)
					{
						pHead = pHead->pNext;
					}
					else
					{
						prev->pNext = pCur->pNext;
					}
					free(pCur);
					return pHead;
				}
				prev = pCur;
				pCur = pCur->pNext;
			}
			pCur = pCur->pNext;
		}
		if (pCur == NULL)
		{
			printf("\n数据表中没有该学生!\n");
		}
		break;
	}
	return pHead;
}
void ShowSortMenu()
{
	Print('*', 80, 1);
	printf("1.按学号排序\t\t2.按姓名排序\n");
	printf("3.按语文成绩排序\t4.按数学成绩排序\n");
	printf("5.按英语成绩排序\t6.按平均成绩排序\n");
	Print('*', 80, 1);
}
void Sort(Student* pHead)
{
	Student* pCur = pHead, * pTemp = NULL;
	int i, j, k, iItem = 0, iCount = 0;
	if (pCur == NULL)
	{
		printf("\n没有学生记录!\n");
		return;
	}
	do {
		iCount++;
		pCur = pCur->pNext;
	} while (pCur != NULL);
	pTemp = (Student*)malloc(iCount * sizeof(Student));
	pCur = pHead;
	for (i = 0; i < iCount; i++)
	{
		pTemp[i].S_Number = pCur->S_Number;
		strcpy(pTemp[i].name, pCur->name);
		pTemp[i].Sorce_Chinese = pCur->Sorce_Chinese;
		pTemp[i].Sorce_Math = pCur->Sorce_Math;
		pTemp[i].Sorce_English = pCur->Sorce_English;
		pTemp[i].avg = pCur->avg;
		pCur = pCur->pNext;
	}
	ShowSortMenu();
	printf("请选择排序方式<按0返回主页>:");
	scanf("%d", &iItem);
	getchar();
	while (iItem > 6 || iItem < 0)
	{
		char c;
		while ((c = getchar()) != EOF && c != '\n');
		printf("输入有误,请重新输入:");
		scanf("%d", &iItem);
		getchar();
	}
	for (i = 0; i < iCount - 1; i++)
	{
		for (j = 0; j < iCount - i - 1; j++)
		{
			switch (iItem)
			{
			case 0:
				return;
			case 1:
				if (pTemp[j].S_Number > pTemp[j + 1].S_Number)
				{
					SwapStu(pTemp + j, pTemp + j + 1);
				}
				break;
			case 2:
				if (strcmp(pTemp[j].name, pTemp[j + 1].name) > 1)
				{
					SwapStu(pTemp + j, pTemp + j + 1);
				}
				break;
			case 3:
				if (pTemp[j].Sorce_Chinese > pTemp[j + 1].Sorce_Chinese)
				{
					SwapStu(pTemp + j, pTemp + j + 1);
				}
				break;
			case 4:
				if (pTemp[j].Sorce_Math > pTemp[j + 1].Sorce_Math)
				{
					SwapStu(pTemp + j, pTemp + j + 1);
				}
				break;
			case 5:
				if (pTemp[j].Sorce_English > pTemp[j + 1].Sorce_English)
				{
					SwapStu(pTemp + j, pTemp + j + 1);
				}
				break;
			case 6:
				if (pTemp[j].avg > pTemp[j + 1].avg)
				{
					SwapStu(pTemp + j, pTemp + j + 1);
				}
				break;
			}
		}
	}
	ShowHead(2);
	for (int k = 0; k < iCount; k++)
	{
		pTemp[k].iRank = k + 1;
		printf("\t|   %06d   |%10s|%6.2f |%6.2f |%6.2f |%6.2f|%5d |\n", pTemp[k].S_Number, pTemp[k].name, pTemp[k].Sorce_Chinese, pTemp[k].Sorce_Math, pTemp[k].Sorce_English, pTemp[k].avg, pTemp[k].iRank);
		Print('-', 80, 1);
	}
	pCur = pHead;
	for (i = 0; i < iCount; i++)
	{
		pCur->S_Number = pTemp[i].S_Number;
		strcpy(pCur->name, pTemp[i].name);
		pCur->Sorce_Chinese = pTemp[i].Sorce_Chinese;
		pCur->Sorce_English = pTemp[i].Sorce_English;
		pCur->Sorce_Math = pTemp[i].Sorce_Math;
		pCur->avg = pTemp[i].avg;
		pCur = pCur->pNext;
	}
}
void Statistics(Student* pHead)
{
	int iCount = 0;
	int Pass[3] = { 0 };
	float sMax[3] = { 0.0 }, sMin[3] = { 0.0 }, sAvg[3] = { 0.0 }, sSum[3] = { 0.0 };
	float iMaxA, iMinA;	//记录最高、最低平均分
	Student* pCur = pHead;
	if (pCur == NULL)
	{
		printf("\n没有学生记录,请先创建学生记录!\n");
		return;
	}
	iMaxA = iMinA = pCur->avg;
	sMax[0] = sMin[0] = pCur->Sorce_Chinese;	//0位置:放语文成绩记录
	sMax[1] = sMin[1] = pCur->Sorce_Math;
	sMax[2] = sMin[2] = pCur->Sorce_English;
	while (pCur != NULL)
	{
		float C = pCur->Sorce_Chinese, M = pCur->Sorce_Math, E = pCur->Sorce_English, A = pCur->avg;
		iCount++;
		sSum[0] += C;
		sSum[1] += M;
		sSum[2] += E;
		if (C >= 60.0)
		{
			Pass[0]++;
		}
		if (M >= 60)
		{
			Pass[1]++;
		}
		if (E >= 60)
		{
			Pass[2]++;
		}
		if (iMaxA < A)
		{
			iMaxA = A;
		}
		if (iMinA > A)
		{
			iMinA = A;
		}
		if (sMax[0] < C)
		{
			sMax[0] = C;
		}
		if (sMax[1] < M)
		{
			sMax[1] = M;
		}
		if (sMax[2] < E)
		{
			sMax[2] = E;
		}
		if (sMin[0] > C)
		{
			sMin[0] = C;
		}
		if (sMin[1] > M)
		{
			sMin[1] = M;
		}
		if (sMin[2] > E)
		{
			sMin[2] = E;
		}

		pCur = pCur->pNext;
	}

	sAvg[0] = sSum[0] / iCount;
	sAvg[1] = sSum[1] / iCount;
	sAvg[2] = sSum[2] / iCount;

	printf("\n记录的学生总人数为:%d\n", iCount);
	Print('=', 32, 0);
	printf("语文考试成绩分析");
	Print('=', 32, 1);
	printf("通过语文考试人数:\t%d\n", Pass[0]);
	printf("没有通过语文考试人数:\t%d\n", iCount - Pass[0]);
	printf("语文平均分:\t\t%0.2f\n", sAvg[0]);
	printf("语文最高分:\t\t%0.2f\n", sMax[0]);
	printf("语文最低分:\t\t%0.2f\n\n", sMin[0]);


	Print('=', 32, 0);
	printf("数学考试成绩分析");
	Print('=', 32, 1);
	printf("通过数学考试人数:\t%d\n", Pass[1]);
	printf("没有通过数学考试人数:\t%d\n", iCount - Pass[1]);
	printf("数学平均分:\t\t%0.2f\n", sAvg[1]);
	printf("数学最高分:\t\t%0.2f\n", sMax[1]);
	printf("数学最低分:\t\t%0.2f\n\n", sMin[1]);

	Print('=', 32, 0);
	printf("英语考试成绩分析");
	Print('=', 32, 1);
	printf("通过英语考试人数:\t%d\n", Pass[2]);
	printf("没有通过英语考试人数:\t%d\n", iCount - Pass[2]);
	printf("英语平均分:\t\t%0.2f\n", sAvg[2]);
	printf("英语最高分:\t\t%0.2f\n", sMax[2]);
	printf("英语最低分:\t\t%0.2f\n\n", sMin[2]);


	Print('=', 32, 0);
	printf("其他考试成绩分析");
	Print('=', 32, 1);
	printf("\n三科总的平均分:%0.2f\n", sAvg[0] + sAvg[1] + sAvg[2]);
	printf("三科当中最高平均分:%0.2f\n", iMaxA);
	printf("三科当中最低平均分:%0.2f\n", iMinA);
	Print('=', 80, 1);
	system("pause");
}
Student* Read()
{
	FILE* fp;
	Student* pHead = NULL, * pTemp = NULL, * pCur = NULL;
	char FileName[30] = { '\0' };
	char c;
	while ((c = getchar()) != EOF && c != '\n');
	printf("请输入成绩文件表名:");
	gets(FileName);
	if ((fp = fopen(FileName, "r")) == NULL)
	{
		printf("\n文件打开失败!请检查文件名!\n");
		exit(0);
	}
	pTemp = (Student*)malloc(sizeof(Student));
	while (fread(pTemp, sizeof(Student), 1, fp))
	{
		if (!pHead)
		{
			pHead = pCur = pTemp;
		}
		else
		{
			pCur->pNext = pTemp;
			pCur = pTemp;
		}
		pTemp = (Student*)malloc(sizeof(Student));
	}
	fclose(fp);
	Show(pHead);
	return pHead;
}
void Save(Student* pHead)
{
	int iItem;
	printf("请选择保存格式:\t1.二进制文件\t2.文本文件\n");
	printf("请输入:");
	scanf("%d", &iItem);
	getchar();
	while (iItem > 2 || iItem < 1)
	{
		char c;
		while ((c = getchar()) != EOF && c != '\n');
		printf("输入有误,请重新输入!\n");
		printf("请输入:");
		scanf("%d", &iItem);
		getchar();
	}
	if (iItem == 1)
	{
		FILE* fp;
		Student* pCur = pHead;
		int iCount = 0;
		char FileName[30] = { '\0' };
		if (pCur == NULL)
		{
			printf("\n没有学生记录!\n");
			return;
		}
		printf("\n请输入文件名:");
		gets(FileName);
		if ((fp = fopen(FileName, "wb")) == NULL)
		{
			printf("创建文件失败!\n");
			getchar();
			exit(1);
		}
		while (pCur)
		{
			fwrite(pCur, sizeof(Student), 1, fp);
			pCur = pCur->pNext;
			iCount++;
		}
		printf("\n");
		Print('=', 34, 0);
		printf("保存数据结束");
		Print('=', 34, 1);
		printf("保存文件的数据数目为:%d\n", iCount);
		fclose(fp);

	}
	else {
		FILE* fp;
		Student* pCur = pHead;
		int iCount = 0;
		char FileName[30] = { '\0' };
		if (pCur == NULL)
		{
			printf("\n没有学生记录!\n");
			return;
		}
		printf("\n请输入文件名:");
		gets(FileName);
		if ((fp = fopen(FileName, "w")) == NULL)
		{
			printf("创建文件失败!\n");
			getchar();
			exit(1);
		}
		fprintf(fp, "学号\t姓名\t语文\t数学\t英语\t平均分\n");
		while (pCur)
		{
			fprintf(fp, "%d\t%s\t%.2f\t%.2f\t%0.2f\t%0.2f\n", pCur->S_Number, pCur->name, pCur->Sorce_Chinese, pCur->Sorce_Math, pCur->Sorce_English, pCur->avg);
			pCur = pCur->pNext;
			iCount++;
		}
		printf("\n");
		Print('=', 34, 0);
		printf("保存数据结束");
		Print('=', 34, 1);
		printf("保存文件的数据数目为:%d\n", iCount);
		fclose(fp);
	}
}

void ShowHead(int iType)
{
	printf("\n\t\t\t\t学生成绩管理系统\n\n");
	Print('-', 80, 1);
	if (iType == 1)
	{
		printf("\t|   number   |   name   |Chinese| Math  |English|averge|\n");
	}
	else if (iType == 2)
	{
		printf("\t|   number   |   name   |Chinese| Math  |English|averge|rank  |\n");
	}
	Print('-', 80, 1);
}

Student.h

#pragma once
#include<stdio.h>
#include<malloc.h>
#include <conio.h>
#include <windows.h>
#include"Student.h"
typedef struct Student {
	char name[20];			//姓名
	int S_Number;			//学号
	float Sorce_Chinese;	
	float Sorce_Math;
	float Sorce_English;
	float avg;				//平均分
	int iRank;				//排名
	struct Student* pNext;
}Student;





void showMainMenu();	//打印主界面,显示功能选项
Student* Create();		//创建学生记录,返回学生结构体类型的指针
void Add(Student* pHead);	//向已有的数据表中添加数据
void Show(Student* pHead);	//显示数据表中的所有信息
void Sreach(Student* pHead);//在数据表中搜索信息,找到显示该学生信息,没有找到则给出提示
void Modify(Student* pHead);//在数据表中搜索信息,找到后修改信息,没有找到则给出提示
Student* Delete(Student* pHead);//删除一个学生记录,先查找,若无则给出提示参数:一个已有的链表指针
void Sort(); //按照某个字段来排序
void Statistics();//统计数据表中的信息,分析各科成绩情况
Student* Read();//从文件读取信息
void Save();//保存数据表到本地,可以二进制保存或文本格式保存
int CheakNum(char* pcNotice);//检查学号输入是否正确
float CheakScore(char* pcNotice);//检查成绩输入是否正确
void ShowHead(int iType);//打印一段表头
void ShowSortMenu();//显示排序功能选项
void modeset(int w, int h);//初始化窗口大小

五、程序测试

5.1 测试数据说明

学号 姓名  语文成绩   数学成绩   英语成绩

5.2 输出结果说明

学号  姓名  语文成绩   数学成绩   英语成绩 平均成绩

学号  姓名  语文成绩   数学成绩   英语成绩 平均成绩 排名

目录界面

 

  • 数据测试

  • 创建记录:

 

  •  添加数据

 

  • 显示数据

 

  •  查找数据

  • 更改数据

 

 

 

  • 删除数据

 

 

 

  •  统计数据

 

  •  从文件读取数据

 

  • 保存数据

 

 

 

六、小结与心得

经历了长达一周的C语言实训,我感觉收获满满,之前从没有像这次系统的设计一个管理系统。通过这次实训,我进一步熟悉了C语言的语法,以及数据结构,动态内存,链表等知识。本次收获最大的地方是学会了通过文件操作,来读取、保存文件以及文件的格式。

最后感谢老师!老师辛苦了。

七、参考文献

    [1] 严蔚敏 吴伟民.数据结构(C语言版).清华大学出版社

    [2] 许真珍 蒋光远 田琳琳.C语言课程设计指导教程.清华大学出版社

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值