C语言课程设计——学生成绩管理系统(详细报告)

欢迎来到<IT_WEH_coder>的博客。我是小魏,一名普通的在校大学生。希望大家多多关照,我们一起成长一起进步,也希望大家多多支持我鸭,喜欢我就给我一个关注吧!

本课程设计的编程部分所使用的开发软件是C-Free,可以参考使用教程,滑到底部可以获取所有源代码。

题目:学生成绩管理系统
学生数据由学号、姓名、班级、三门课(数学、英语、计算机)的成绩和平均成绩构成。 实现功能包括:
(1)添加学生的记录
(2)查询学生(分别按学号和姓名)
(3)对学生数据排序(按总成绩的降序)
(4)删除学生记录
(5)修改学生记录
(6)班级成绩分析(各科平均成绩、最高分、最低分、及格率)
(7)输出学生信息表(全部学生成绩信息显示或按班级显示学生成绩信息)

1 用户分析

1.1 用户需求

(1)学生信息包括学号、姓名、班级和所学三门课程(数学、英语、计算机)的成绩 和平均成绩(每位学生的平均分和各科平均分)以及各科成绩的最低分和最高分、及格 率;
(2)学生信息管理系统以菜单方式工作;
(3)录入的学生信息用文件形式保存,并可以对其进行添加、查询、数据排序(按总 分)、修改、成绩分析、删除等基本操作;
(4)按学号查询学生信息,或按姓名查询;
(5)按学号修改学生信息并保存到文件中;
(6)输出学生信息表(全部学生成绩信息显示或按班级显示学生成绩信息);
(7)用户使用过程中能够要有容错处理。

1.2 用户目的

设计一个学生成绩管理系统,使之能提供以下功能:
(1)添加学生信息;
(2)查询学生信息(分别按学号和姓名);
(3)对学生的成绩进行排序(按总分降序);
(4)修改学生信息;
(5)删除学生信息;
(6)按本专业学生成绩分析和按班级成绩分析(各科平均成绩、最高分、最低分、及 格率);
(7)输出学生信息表;
(8)学生信息保存到文件中。

2 概要设计

2.1 功能设计

该学生成绩管理系统可以按功能进行模块划分,其模块图如图1所示。
在这里插入图片描述

2.2 数据结构设计

学号,15个字符;
姓名,10个字符;
班级,正整数;
各科分数,无小数点;
总分,无小数点;
各科平均分,小数点后两位;
各科及格率,小数点后两位;
各科最低分,无小数点;
各科最高分,无小数点;
在处理过程中各项可以作为一个学生的不同属性来进行处理;
因为数组的长度是有限制的,链表的长度是没有限制的,系统中所存储的学生信息长度是不固定的,所以学生信息通过链表来存储。

2.3 功能运行流程图

系统的执行应从功能菜单的选择开始,依据用户的选择来进行后续的处理,直到用户选择保存数据并退出系统为止,其间应对用户的选择做出判断及异常处理。系统的流程图如图2所示。
在这里插入图片描述

3 系统功能设计

3.1 菜单选择模块的流程图

菜单选择功能中,通过输入不同的数字(1-6)来进行菜单选择,实现不同的程序结果,直到用户输入数字6时,就直接退出系统。菜单选择模块的流程图如图3所示。
在这里插入图片描述

3.2 添加模块的流程图

添加学生信息模块中,实现添加学生的班级、姓名、学号和三门成绩(数学、英语、计算机)的输入,直到用户输入x为0时,则结束当前输入,并返回上级主菜单。添加模块的流程图如图4所示。
在这里插入图片描述

3.3 排序输出模块的流程图

输出模块中,先判断链表大小list->size是否为0,若不为空,进入菜单选择输入不同的数字(1-3),若用户输入1,则实现本专业学生成绩的输出,若输入2,则按班级输出学生信息,直到用户输入数字3时,结束当前信息的输出,并返回上级主菜单。输出模块的流程图如图5所示。
在这里插入图片描述

3.4 信息查询模块的流程图

通过菜单选择,输入不同的数字(1-3)实现不同的方式进行查询,若输入数字1,按学号进行查询学生信息,输入数字2,按姓名查询学生信息,输入数字3,结束信息查询功能,返回上级主菜单。查询模块的流程图如图6所示。
在这里插入图片描述

3.5 信息修改模块的流程图

先进行判断链表是否为空,若不为空,就能进行输入学生的学号;然后,再进行判断是否有用户输入的学号,若没有,则返回学号输入,再进行重新输入学号。若在链表中的数据
存在用户输入的学号,则输出该学生的信息,之后进行菜单选择,可输入不同的数字(1-5),用户可选择想修改的的数据,直到该用户输入数字5时,返回上级主菜单。信息修改模块流程图如图7所示。
在这里插入图片描述

3.6 信息删除模块的流程图

进入该程序运行中,需判断链表大小list->size是否为0,若为0,则结束信息删除操作;若不为0,将进入学号输入操作;然后判断链表数据中是否存在用户输入的学号id,若不存在,进入退出选择操作,用户可输入0或其他数字,若输入0,则返回上级菜单;若输入其他数字,则该学生的信息将在链表中清除并释放该空间。若该用户继续进行删除操作,可输入其他数字键;若输入0,直接退出该程序并返回上级主菜单。信息删除模块的流程图如图8所示。
在这里插入图片描述

3.7 信息保存模块的流程图

在保存数据之前,首先需打开文件,然后判断文件是否为空,若为空就会提示该文件打开失败,直接结束整个程序运行;若文件不为空,进行判断链表的头节点是否为空,若头节点为空,则直接关闭该文件并结束程序,若头节点不为空,将链表数据保存到文件中,直到尾节点为空,就会关闭该文件并退出系统。信息保存模块的流程图如图9所示。
在这里插入图片描述

3.8 数据结构的C语言表示

学生信息:

struct Student
{
	int class_num; 		//班级
	char id[15];			//学号
	char name[10];		//姓名
	float score[3];			//各科分数
	float sum; 			//总成绩
	float course_av[3];		//各科平均分
	float course_pass[3];	//各科及格率
	float course_max[3];	//各科最低分
	float course_min[3];	//各科最高分
};

4 系统功能代码设计

4.1 自定义头文件的内容设计

代码1:

/* 文件list.h */
#ifndef  _LIST_H_			//防止重复编译,_LIST_H_为符号常量
#define  _LIST_H_
//学生信息结构体定义
struct Student				
{		
	int class_num; 		
	char id[15];			
	char name[10];		
	float score[3];			
	float sum; 			
	float course_av[3];		
	float course_pass[3];	
	float course_max[3];	
	float course_min[3];	
};
//链表节点定义
struct Node
{				
	struct Student student;
	struct Node *next;
};
//链表定义
struct List
{				
	struct Node *head;						//链表头节点
	int size;								//链表长度
};
struct List* createList();						//创建链表
void destoryList(struct List *list);				//销毁链表
struct Node* createNode(struct Student student);	//创建节点 
struct Node* getLastNode(struct List *list);		//获取链表最后一个节点
struct Node* getBeforeNode(struct List *list,struct Student student);	//获取上一个节点
void addList(struct List *list, struct Node *node);		//将节点添加到链表中 
#endif

代码2:

/* 文件fun.h */
#ifndef  _FUN_H_						//防止重复编译,_FUN_H_为符号常量
#define  _FUN_H_
void Menu(); 	//菜单栏
FILE* openFile(char *filename,char *type);		//打开文件
void fileToList(struct List *list,char *filename);	//文件数据添加到链表中  
void listToFile(struct List *list,char *filename);	//将链表数据存储到文件中
void input(struct List *list);					//添加学生信息
void sort(struct List *list);					//按总成绩排序
void output(struct List *list);					//输出学生信息
void find(struct List *list);					//查找学生信息
void detail(struct Node *temp);				//修改具体细节 
void change(struct List *list);					//修改学生信息 
void Delete(struct List *list);					//删除
void quit();								//退出画面
#endif	

4.2 链表相关的代码清单

//创建链表 
struct List* createList()
{
	struct List *list;
	list=(struct List*)malloc(sizeof(struct List));
	list->head=NULL;
	list->size=0;
	return list;
}
//销毁链表 
void destoryList(struct List *list)
{
	struct Node *temp=list->head,*del=NULL;
	while(temp)
	{
		del=temp;
		temp=temp->next;
		free(del);//释放节点空间 
		list->size--; 
	}
	free(list);//释放链表空间 
}
//创建节点 
struct Node* createNode(struct Student student)
{
	struct Node *node=NULL;
	node=(struct Node*)malloc(sizeof(struct Node));
	node->student=student;
	node->next=NULL;
	return node;
}
//获取链表最后一个节点 
struct Node* getLastNode(struct List *list)
{
	struct Node *temp=list->head,*last=NULL;
	while(temp)
	{
		last=temp;
		temp=temp->next;
	}
	return last;
}
//获取当前节点的上一个节点 
struct Node* getBeforeNode(struct List *list,struct Student student)
{
	struct Node *temp=list->head,*prevNode=NULL;
	while(temp)
	{
		if(strcmp(temp->student.id,student.id)==0)
		{
			break;
		}
		prevNode=temp;
		temp=temp->next;
	}
	return prevNode;
}
//将节点添加到链表中 
void addList(struct List *list, struct Node *node)
{
	struct Node *last;
 	if(list->head==NULL)
 	{
 		list->head=node;
 	}
 	else
 	{
	 	last=getLastNode(list);
		last->next=node;	
 	}
 	list->size++;
}

4.3 菜单选择模块的代码清单

int main()
{
	int num=0;
	FILE*file=NULL;
	struct List *list=NULL;
	list=createList();	//创建链表 
	fileToList(list,"studentFile.txt");//把数据添加到链表中 
	SetConsoleTitle("学生成绩管理系统");
	void Menu()
	{
		printf("******学生成绩管理系统****\n"); 
		printf("******1.添加学生信息******\n"); 
		printf("******2.输出学生信息******\n");
		printf("******3.查询学生信息******\n");
		printf("******4.修改学生信息******\n");
		printf("******5.删除学生信息******\n");
		printf("******6.保存后退出********\n");
		printf("请选择:");
	}
	while(1)
	{
		system("cls");	//清屏 
		Menu();			//菜单栏 
		scanf("%d",&num);
		switch(num){
			case 1:
				system("cls");
				input(list); //添加 
			 	printf("请输入任意数字键\n返回上级菜单:");
			 	scanf("%d",&num);
				break;
			case 2:
				system("cls");
				output(list); //输出
				break; 
			case 3:
				system("cls");
				find(list);	//查询
				break; 
			case 4:
				system("cls");
				change(list); //修改 
				break;
			case 5:
				system("cls");
				Delete(list); //删除 
				break;
			case 6: 
				system("cls");
				listToFile(list,"studentFile.txt");//数据保存到文件中 
				destoryList(list); // 销毁链表
				quit();		 //退出画面 
				exit(0);
			default:
				printf("输入有误,请重新选择!\n");
				printf("请输入任意数字键\n返回上级菜单:");
			 	scanf("%d",&num);
				break;
		} 
	}
	return 0;
}

4.4 添加模块的代码清单

void input(struct List *list)
{
	struct Student student; 
	struct Node *node=NULL;    //建立新节点
	struct Node *temp;			  //建立新节点
	int x,i,flag;
	while(1)
	{
		flag=1;
		printf("-->请输入该学生信息的班级、学号、姓名<--\n-->");
	 	scanf("%d %s %s",&student.class_num,student.id,student.name);
		temp=list->head;			//当前链表的下一个节点
		while(temp)		
		{
			if(strcmp(temp->student.id,student.id)==0)		//限定学号唯一	
			{
				printf("您输入的学号已存在!\n");
				flag=0;
			}
			temp=temp->next;	//链表的下一个节点
		}
		if(flag)
		{
			printf("-->请输入该学生的每门成绩<--\n数学:");
			scanf("%f",&student.score[0]);
			printf("英语:");
			scanf("%f",&student.score[1]);
			printf("计算机:");
			scanf("%f",&student.score[2]);
			student.sum=0;
			for(i=0;i<3;i++)
			{
				student.sum+=student.score[i];
			}
	 		node=createNode(student);	//创建节点 
	 		addList(list,node);			//添加到链表 
		}
	 	printf("退出请按数字0,其他数字键继续添加:");
	 	scanf("%d",&x);
	 	if(x==0)break; 
	} 
}

4.5 排序输出模块的代码清单

//按总成绩排序 
void sort(struct List *list)
{
	int i,j; 
	struct Student s;	
	struct Node *temp=NULL,*temp1=NULL,*temp2=NULL;  //建立新节点
	for(i=0;i<list->size-1;i++)
	{
		temp=list->head;					             //当前链表的下一个节点
		for(j=0;j<list->size-i-1;j++)
		{
			temp1=temp;
			temp2=temp->next;			//新建链表的下一个节点
			if(temp1->student.sum<temp2->student.sum)  
			{
				s=temp1->student;
				temp1->student=temp2->student;
				temp2->student=s;
			}
			temp=temp->next;			//当前链表的下一个节点
		}
	}
}
//输出学生信息 
void output(struct List *list)
{
	int cnt=0,num=0,class_num=0,i;	
	float av_math,av_eng,av_se;		        //数学、英语、计算机平均分
	float pass[3],min[3],max[3];				//及格率、最低分、最高分
	struct Node *temp=list->head;			//把新节点作为头结点
	if(list->size==0)						//若链表空间大小为0则返回上级
	{
		printf("抱歉,暂无学生信息!\n");
		return;							
	}
	sort(list);						//排序 
	system("cls");					//清屏
	while(1)
	{	
temp=list->head;			//每循环一次该节点重新作为头节点
		system("cls");
		printf("*******1.本专业学生成绩分析******\n");
		printf("*******2.按班级显示成绩分析******\n");
		printf("*******3.退出********************\n");
		printf("请选择:");
		scanf("%d",&num);
		cnt=0;
		system("cls");
		av_math=av_eng=av_se=0;	//清零
		pass[0]=pass[1]=pass[2]=0;	//清零
		switch(num)
		{
			case 1:
				for(i=0;i<35;i++)
					printf("*");
				printf("本专业学生成绩分析");
				for(i=0;i<35;i++)
					printf("*");  
printf("\n\n%s\t%s\t%-15s\t%-10s\t%s\t%s\t%s\t%s\t%s\n","序号","班级","学号","姓名","数学","英语","计算机","总成绩","平均分");
				while(temp)
				{
cnt++; 	
printf(" %d\t %d\t%-15s\t%-10s\t%.0f\t%.0f\t %.0f\t %.0f\t %.2f\n",        cnt,temp->student.class_num,temp->student.id,temp->student.name,temp->student.score[0],temp->student.score[1],temp->student.score[2],temp->student.sum,temp->student.sum/3);
					av_math+=temp->student.score[0];
					av_eng+=temp->student.score[1];
					av_se+=temp->student.score[2];
					if(cnt==1)
					{
						for(i=0;i<3;i++)
						{
							max[i]=min[i]=temp->student.score[i];
						}
					}
					for(i=0;i<3;i++)
					{
						if(temp->student.score[i]>=60)
						{
							pass[i]+=100;
						}
						if(temp->student.score[i]>max[i])
						{
							max[i]=temp->student.score[i];
						}
						if(temp->student.score[i]<min[i])
						{
							min[i]=temp->student.score[i];
						}
					}
					temp=temp->next;		//当前链表的下一个节点
				} 
printf("\n数学-->最高分:%.0f\t最低分:%.0f\t平均分:%.2f\t及格		 率:%.2f%%\n",max[0],min[0],av_math/cnt,pass[0]/cnt);
printf("英语-->最高分:%.0f\t最低分:%.0f\t平均分:%.2f\t及格	 率:%.2f%%\n",max[1],min[1],av_eng/cnt,pass[1]/cnt);
			    printf("计算机-->最高分:%.0f\t最低分:%.0f\t平均分:%.2f\t及格					 率:%.2f%%\n",max[2],min[2],av_se/cnt,pass[2]/cnt);
				system("pause");
				break;
			case 2:
				printf("请输入班级:");
				scanf("%d",&class_num);
				for(i=0;i<37;i++)
					printf("*");
				printf("%d班学生成绩表",class_num);
				for(i=0;i<37;i++)
					printf("*");  
printf("\n\n%s\t%s\t%-15s\t%-10s\t%s\t%s\t%s\t%s\t%s\n","序号","班级","学号","姓名","数学","英语","计算机","总成绩","平均分");

				while(temp)
				{
					if(temp->student.class_num==class_num)
					{
						cnt++;
printf(" %d\t %d\t%-15s\t%-10s\t%.0f\t%.0f\t %.0f\t %.0f\t %.2f\n",cnt,temp->student.class_num,temp->student.id,temp->student.name,temp->student.score[0],temp->student.score[1],temp->student.score[2],temp->student.sum,temp->student.sum/3);
						av_math+=temp->student.score[0];
						av_eng+=temp->student.score[1];
						av_se+=temp->student.score[2];
							if(cnt==1)
							{
								for(i=0;i<3;i++)
								{
									max[i]=min[i]=temp->student.score[i];
								}
							}
							for(i=0;i<3;i++)
							{
								if(temp->student.score[i]>=60)
								{
									pass[i]+=100;
								}
								if(temp->student.score[i]>max[i])
								{
									max[i]=temp->student.score[i];
								}
								if(temp->student.score[i]<min[i])
								{
									min[i]=temp->student.score[i];
								}
							}
					}
					temp=temp->next;		//当前链表的下一个节点
				} 
				if(cnt==0)
				{
					printf("%d班级,暂无学生信息!\n",class_num);
					break;
				}
	printf("\n数学-->最高分:%.0f\t最低分:%.0f\t平均分:%.2f\t及格率:%.2f%%\n",max[0],min[0],av_math/cnt,pass[0]/cnt);
	printf("英语-->最高分:%.0f\t最低分:%.0f\t平均分:%.2f\t及格率:%.2f%%\n",max[1],min[1],av_eng/cnt,pass[1]/cnt);
	printf("计算机-->最高分:%.0f\t最低分:%.0f\t平均分:%.2f\t及格率:%.2f%%\n",max[2],min[2],av_se/cnt,pass[2]/cnt);
				system("pause");
				break;
			case 3:
				return; 
			default:
				printf("输入有误,请重新输入!\n");
				system("pause");
				break; 
		}	
	}	
}

4.6 信息查询模块的代码清单

void find(struct List *list)
{
	int num,class_num; 
	char id[15],name[10];		//学号、姓名 
	struct Node *temp;	
	if(list->size==0)			//若链表空间大小为0,则返回上级
	{
		printf("抱歉,暂无学生信息!\n");
		return;
	}
	while(1)
	{
		system("cls");	//清屏 
		printf("*******1.按学号查询******\n");
		printf("*******2.按姓名查询******\n");
		printf("*******3.退出************\n");
		printf("请选择:");
		scanf("%d",&num);
		system("cls");
		temp=list->head;		//每循环一次该节点重新作为头节点 
		switch(num)
		{
		   case 1:
			   	printf("请输入要查找学生信息的学号:"); 
				scanf("%s",id);
				while(temp)
				{
					if(strcmp(temp->student.id,id)==0)break;	//查找学号 
					temp=temp->next;					 //当前链表的下一个节点
				}
				if(temp)
				{
					printf("查找到该学生信息为:\n");
	printf("\n%s\t%-15s\t%-10s\t%s\t%s\t%s\t%s\t%s\n","班级","学号","姓名","数学","英语","计算机","总成绩","平均分");
printf(" %d\t%-15s\t%-10s\t%.0f\t%.0f\t %.0f\t %.0f\t %.2f\n",temp->student.class_num,temp->student.id,temp->student.name,temp->student.score[0],temp->student.score[1],temp->student.score[2],temp->student.sum,temp->student.sum/3);				
} 
				else
				{
					printf("抱歉,不存在该学生信息!\n");
				}
				system("pause");
				break;
		   case 2:
			   printf("请输入要查找学生信息的班级、姓名:");
			   scanf("%d %s",&class_num,name);
			   	while(temp)
				{
	  if(temp->student.class_num==class_num&&strcmp(temp->student.name,name)==0) 
					  { 
						 break;
					  } 
					  temp=temp->next;
				}
				//输出该学生信息 
				if(temp)
				{
					printf("查找到该学生信息为:\n");
	printf("\n%s\t%-15s\t%-10s\t%s\t%s\t%s\t%s\t%s\n","班级","学号","姓名","数学","英语","计算机","总成绩","平均分");
printf(" %d\t%-15s\t%-10s\t%.0f\t%.0f\t %.0f\t %.0f\t %.2f\n",temp->student.class_n um,temp->student.id,temp->student.name,
	temp->student.score[0],temp->student.score[1],temp->student.score[2],temp->student.sum,temp->student.sum/3);				
} 
				else
				{
					printf("抱歉,不存在该学生信息!\n");
				}
				system("pause");
				break;
		   case 3:
				return; 
			default:
				printf("输入有误,请重新输入!\n");
				system("pause");
				break; 
		}
	}
}

4.7 信息修改模块的代码清单

/*修改具体细节 */
void detail(struct Node *temp)
{
	char id[15];	//学号 
	int num=0,x;
	printf("\n******信息修改********");
	printf("\n******1.班级修改******");
	printf("\n******2.学号修改******");
	printf("\n******3.姓名修改******");
	printf("\n******4.成绩修改******");
	printf("\n******5.退出*********\n");
	while(1)
	{
		printf("请选择:");
		scanf("%d",&num);
		switch(num)
		{
			case 1:
					printf("请您输入修改后的班级号为:");
					scanf("%d",&temp->student.class_num);
					break;
			case 2:
					printf("请您输入修改后的学号为:");
					scanf("%s",temp->student.id);
					break;
			case 3:
					printf("请您输入修改后的姓名为:");
					scanf("%s",temp->student.name);
					break;
			case 4:
					printf("请您修改该同学的成绩为:\n");
					printf("数学--英语--计算机\n-->");
	scanf("%f %f %f",&temp->student.score[0],&temp->student.score[1],&temp->student.score[2]);
	temp->student.sum=temp->student.score[0]+temp->student.score[1]+temp->student.score[2];		//求每位同学的总分
					system("pause");
					break;
			case 5:
				return;
			default:
				printf("您输入有误,请重新输入!");
				break; 
		} 
		printf("退出请按数字0,其他数字键继续修改:");
		scanf("%d",&x);
		if(x==0)break;
	}
}
/*修改学生信息 */
void change(struct List *list)
{
	char id[15],flag=1;
	struct Student student;
	struct Node *temp=list->head;	//把新节点作为头节点 
	if(list->size==0)				//若链表空间大小为0,则返回上级 
	{
		printf("抱歉,暂无学生信息!\n");
		return;
	}
	printf("请输入要修改学生信息的学号:"); 
	scanf("%s",id);
	while(temp)
	{
		if(strcmp(temp->student.id,id)==0)	//查找学号 
		{
			printf("当前该学生信息为:\n"); 
	printf("\n%s\t%-15s\t%-10s\t%s\t%s\t%s\t%s\n","班级","学号","姓名","数学","英语","计算机","总成绩");
printf(" %d\t%-15s\t%-10s\t%.0f\t%.0f\t %.0f\t %.0f\n",temp->student.class_num,temp->student.id,temp->student.name,temp->student.score[0],temp->student.score[1],temp->student.score[2],temp->student.sum);			
detail(temp);
			printf("修改成功!\n");
			flag=0; 
			break;
		}
		temp=temp->next;		//当前链表的下一个节点
	}
	if(flag)
	{
		printf("抱歉,不存在该学生信息,无法修改!\n");
	}
}

4.8 信息删除模块的代码清单

void Delete(struct List *list)
{
	char id[15];
	int flag,x;
	struct Node *temp,*prevNode=NULL;	//建立新头结点prevNode 
	while(1)
	{	
		temp=list->head;				//每循环一次该节点重新作为头节点
		if(list->size==0)				//若链表空间大小为0,则结束循环 
		{
			printf("\n抱歉,暂无学生信息!\n");
			break;
		}
		flag=1;
		printf("请输入要删除学生信息的学号:"); 
		scanf("%s",id);		
		while(temp)
		{
			if(strcmp(temp->student.id,id)==0)
			{
				printf("删除的该学生信息为:\n");
	printf("\n%s\t%-15s\t%-10s\t%s\t%s\t%s\t%s\n","班级","学号","姓名","数学","英语","计算机","总成绩");
	printf(" %d\t%-15s\t%-10s\t%.0f\t%.0f\t %.0f\t %.0f\n",temp->student.class_num,temp->student.id,temp->student.name,temp->student.score[0],temp->student.score[1],temp->student.score[2],temp->student.sum);
				/*找到前一个节点,再与后一个节点连接 */
				prevNode=getBeforeNode(list,temp->student);  
				if(prevNode==NULL)				//删除的是头节点 
				{				
					list->head=temp->next; 
				}
				else
				{
					prevNode->next=temp->next;	 //删除的是普通节点 
				}
				flag=0;							
				free(temp);						//释放temp所指的空间内存 
				temp=NULL;						//将该节点的指针域为空 
				list->size--;					    //将该节点 
				printf("\n该学生信息删除成功!\n");
				break;
			}
			temp=temp->next;					//当前链表的下一个节点
		}
		if(flag)
		{
			printf("\n抱歉,不存在该学生信息,无法删除!\n\n");
		} 
		printf("\n退出请按数字0,其他数字键继续删除操作:");
	 	scanf("%d",&x);
	 	if(x==0)break; 
	}
	system("pause");
} 

4.9 信息保存模块的代码清单

FILE* openFile(char *filename,char *type)		//打开文件
{
	FILE*file=fopen(filename,type);
	if(file==NULL)
	{
		printf("打开%s文件失败!\n",filename);
		return NULL; 
	}
	return file;
}
void fileToList(struct List *list,char *filename)	//文件数据添加到链表中 
{
	int count=0;
	struct Student student;
	struct Node *node=NULL; 
	FILE*file=openFile(filename,"r");		    //以写的方式打开文件
	if(file==NULL)return;				
	while(1)
{		 count=fscanf(file,"%d%s%s%f%f%f%f\n",&student.class_num,student.id,student.name,&student.score[0],&student.score[1],&student.score[2],&student.sum);
		  student.sum=student.score[0]+student.score[1]+student.score[2]; 	//求总分
if(count<=0)break;
		  node=createNode(student);		    //创建节点 
	 	  addList(list,node);				//添加到链表 
	}
	fclose(file); 	
} 
void listToFile(struct List *list,char *filename)	//将链表数据存储到文件中
{
	struct Node *temp=list->head;
	FILE*file=openFile(filename,"w");		//以写的方式打开文件
	if(file==NULL)return;
	while(temp)
	{
	fprintf(file,"%d\t%s\t%s\t%.0f\t%.0f\t%.0f\t%.0f\n",temp->student.class_num,temp->student.id,temp->student.name,temp->student.score[0],temp->student.score[1],temp->student.score[2],temp->student.sum);
		temp=temp->next;
	}
	fclose(file);					        //关闭文件并释放文件缓冲区
}

4.10 退出画面的代码清单

void quit()
{
	int i,j,k;
	for(k=0;k<5;k++)
		printf("\n");
	for(i=0;i<21;i++)					//控制21行
	{
		for(k=0;k<i;k++)
		{
			printf(" ");
		}
		for(j=0;j<80;j++)				//每行输出80个字符*
		{
			if(i==10)					
			{
				for(k=0;k<29;k++)		
					printf("*");
				printf("—> 感谢您的使用! <—");
				for(k=0;k<29;k++)
					printf("*");
				break;
			}
			printf("*");
		}
	printf("\n");	
	}
	for(k=0;k<5;k++)
		printf("\n");
}

5 系统调试

5.1 运行结果

5.1.1 菜单选择程序运行截图

在这里插入图片描述

5.1.2 信息添加程序运行截图

在这里插入图片描述

5.1.3 信息输出程序运行截图

菜单选择显示
在这里插入图片描述
本专业学生成绩输出结果
在这里插入图片描述
按班级输出学生成绩显示
在这里插入图片描述
在这里插入图片描述

5.1.4 信息查询运行截图

菜单选择显示在这里插入图片描述
按学号查询学生信息显示
在这里插入图片描述
按姓名查询学生信息显示
在这里插入图片描述

5.1.5 信息修改程序运行截图

在这里插入图片描述
修改学生信息后查询显示
在这里插入图片描述

5.1.6 信息删除程序运行截图

在这里插入图片描述
删除该学生信息后查询显示
在这里插入图片描述

5.1.7 信息保存到文件截图

在这里插入图片描述

5.1.8 系统退出画面截图

在这里插入图片描述

5.2 缺陷现象

添加程序运行结果
在这里插入图片描述

5.3 缺陷原因

在添加程序中输入文件中已存在的学号时,没有进行判断学号是否唯一,使得输入文件已存在的学号仍能继续后续操作,这样就不符合实际。

5.4 缺陷修改

修改添加程序部分代码如下:

void input(struct List *list)
{
	struct Student student; 
	struct Node *node=NULL;
	struct Node *temp;
	int x,i,flag;
	while(1)
	{
		flag=1;
		printf("请输入该学生信息的班级、学号、姓名\n-->");
	 	scanf("%d %s %s",&student.class_num,student.id,student.name);
		temp=list->head;
		while(temp)
		{
			/*判断当前输入的学号在链表中是否存在*/
			if(strcmp(temp->student.id,student.id)==0)	
			{
				printf("您输入的学号已存在!\n");
				flag=0;
			}					
			temp=temp->next;			//当前链表的下一个节点
		}
		if(flag)
		{
			printf("请输入该学生的每门成绩\n数学:");
			scanf("%f",&student.score[0]);
			printf("英语:");
			scanf("%f",&student.score[1]);
			printf("计算机:");
			scanf("%f",&student.score[2]);
			student.sum=0;
			for(i=0;i<3;i++)
				student.sum+=student.score[i];
	 		node=createNode(student);	//创建节点 
	 		addList(list,node);			//添加到链表 
		}
	 	printf("退出请按数字0,其他数字键继续添加:");
	 	scanf("%d",&x);
	 	if(x==0)break; 
	 } 
}	 

5.5 修改验证

添加程序代码修改后运行结果显示如下:
在这里插入图片描述

6 报告总结

在我看来,课程设计是培养学生综合运用所学知识,发现,提出,分析和解决实际问题,锻炼实践能力的重要环节,是对学生实际工作能力的具体训练和考察过程。随着科学技术发展的日新月异,当今计算机的应用在生活中可以说得是无处不在。
“锲而不舍,金石可镂”。很多题目需要靠坚持才能有结果。一次次编写的程序无法运行,一次次的改正无法获得”编译成功“的认可。此时倘若将其放掉,那这个题目可能就永远被埋掉了,那些错误之处也就再无机会得到修正,那个知识点也可能从此漏了。因此,用实际行动去解决每一个问题,才能发现问题。
C语言是计算机程序设计的重要理论基础,在我们以后的学习和工作中都有着十分重要的地位。要学好这种语言,仅仅学习课本上的知识是不够的,还要经常自己动手,有较强的实践能力。只有多动手,经常编写程序,才能发现我们学习上的漏洞和自己的不足,并在实践中解决这些问题,不断提高自己转化知识的能力。回顾起此次课程设计,至今我仍感慨颇多,的确,从拿到题目到完成整个编程,从理论到实践,在本学期的日子里,可以学到很多实用的东西,同时不仅可以巩固以前所学过的知识,而且学到很多在书本上所没有学到过的知识。通过这次课程设计使我懂得了理论与实际相结合是很重要的,单纯理论知识是远远不够的,只有把所学的理论知识与实践相结合起来,从理论中得出结论,才能真正为社会服务,从而提高自己的实际动手能力和独立思考的能力。
最后,感谢曹老师的辛勤指导,在您的身上我学到很多实用的知识。同时,在理论课和实训授课过程中,同学之间的相互探讨,老师的循循善诱,最终让我们达到了举一反三的效果,在学知识的同时,也增加了同学老师之间的感情。
今后,我期待自己能变得坚强和勇敢,让学习更上一层楼;我相信,只要有信心,人永远不会挫败!

博主后记:
希望看到此篇博文的网友,如果发现有什么不对的地方,欢迎在下方留言指正!博主一定虚心接受并改正!大家一起共同进步。如果对你有所帮助,可以给博主一个赞👍。

想要获取源代码,可以直接访问我的Gitee仓库https://gitee.com/weh_coder/student_manage_system ,记得给个star哦!

  • 312
    点赞
  • 1673
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 80
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

IT_WEH_coder

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

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

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

打赏作者

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

抵扣说明:

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

余额充值