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

C语言课程设计——学生成绩管理系统(详细报告)欢迎来到「发奋的小魏」的博客。我是小魏,一名普通的在校大学生。在学习之余,用博客来记录我学习过程中的点点滴滴,也希望我的博客能够更给同样热爱学习热爱技术的你们带来收获!希望大家多多关照,我们一起成长一起进步。也希望大家多多支持我鸭,喜欢我就给我一个关注吧!目录1.用户分析 21.1用户需求 21.2用户目的 21.3验收 22.概要设计 22.1功能设计 22.2数据结构设计 32.3功能运行流程图 33.系统功能设计 43.1菜单选择模块的流程图 43.2添加模块的流程图 43

大家好,又见面了,我是你们的朋友全栈君。

欢迎来到<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语言是计算机程序设计的重要理论基础,在我们以后的学习和工作中都有着十分重要的地位。要学好这种语言,仅仅学习课本上的知识是不够的,还要经常自己动手,有较强的实践能力。只有多动手,经常编写程序,才能发现我们学习上的漏洞和自己的不足,并在实践中解决这些问题,不断提高自己转化知识的能力。回顾起此次课程设计,至今我仍感慨颇多,的确,从拿到题目到完成整个编程,从理论到实践,在本学期的日子里,可以学到很多实用的东西,同时不仅可以巩固以前所学过的知识,而且学到很多在书本上所没有学到过的知识。通过这次课程设计使我懂得了理论与实际相结合是很重要的,单纯理论知识是远远不够的,只有把所学的理论知识与实践相结合起来,从理论中得出结论,才能真正为社会服务,从而提高自己的实际动手能力和独立思考的能力。
最后,感谢曹老师的辛勤指导,在您的身上我学到很多实用的知识。同时,在理论课和实训授课过程中,同学之间的相互探讨,老师的循循善诱,最终让我们达到了举一反三的效果,在学知识的同时,也增加了同学老师之间的感情。
今后,我期待自己能变得坚强和勇敢,让学习更上一层楼;我相信,只要有信心,人永远不会挫败!

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

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

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/151593.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • Java商城源码最好用的java商城电商系统之一

    Java商城源码最好用的java商城电商系统之一为符合新互联网+时代产品线即时起更新演示网址:2021单店版:http://mall.javaemall.com/index.htm2021多店版:http://www.javaemall.com/index.htm源码包含:PC版网站+手机触屏站+APP客户端(安卓+苹果)+微信版(小程序+公众号)几套区别:2021版升级了移动端新功能和UI页面,更符合扁平简约化潮流,新增微信小程序,底层技术框架升级。多店版就是多店铺多商户,多用户B2B2C功能,能入驻开店。单店版是自营B…

  • Java 构造函数特点「建议收藏」

    Java 构造函数特点「建议收藏」(1).一般函数是用于定义对象应该具备的功能。而构造函数定义的是,对象在调用功能之前,在建立时,应该具备的一些内容。也就是对象的初始化内容。(2).构造函数是在对象建立时由jvm调用,给对象初始化。一般函数是对象建立后,当对象调用该功能时才会执行。(3).普通函数可以使用对象多次调用,构造函数就在创建对象时调用。(4).构造函数的函数名要与类名一样,而普通的函数只要符合标识符的命名…

  • FRP内网穿透教程「建议收藏」

    FRP内网穿透教程「建议收藏」FRP内网穿透介绍frp是一个专注于内网穿透的高性能的反向代理应用,支持TCP、UDP、HTTP、HTTPS等多种协议。可以将内网服务以安全、便捷的方式通过具有公网IP节点的中转暴露到公网。为什么使用frp通过在具有公网IP的节点上部署frp服务端,可以轻松地将内网服务穿透到公网,同时提供诸多专业的功能特性,这包括:客户端服务端通信支持TCP、KCP以及Websocket等多种协议。采用TCP连接流式复用,在单个连接间承载更多请求,节省连接建立时间。代理组间的负

  • 十大滤波算法总结[通俗易懂]

    十大滤波算法总结[通俗易懂]由于MPU6050的深入,我也学会了一些滤波算法,自己写了一些算法,收集了一些算法,供大家一起学习分享,我的代码都是经过反复试验,复制到Arduino中就能开跑的成品代码,移植到自己的程序中非常方便。而且都仔细研究了各个算法,把错误都修正了的,所以也算个小原创吧,在别人基础上的原创。1、限幅滤波法(又称程序判断滤波法)2、中位值滤波法3、算术平均滤波法4、递推平均滤波法(又称滑动平

  • 国外最流行的Bootstrap后台管理模板[通俗易懂]

    国外最流行的Bootstrap后台管理模板[通俗易懂]工欲善其事,必先利其器对于从事软件开发的您也一样,有一套熟悉的bootstrap后台ui框架让您的开发速度大幅度提升这是本人经常使用到的一些bootstrap后台框架推荐给大家第一名inspiniabootstrap演示地址http://cn.inspinia.cn效果图http://cn.inspinia.cnhttp://cn.inspinia.cn第二名…

  • websocket深入浅出

    websocket深入浅出websocket简介websocket是什么答:它是一种网络通信协议,是HTML5开始提供的一种在单个TCP连接上进行全双工通讯的协议。为什么需要websocket?疑问?我们已经有了HTTP协议,为什么还需要另一个协议?它能带来什么好处?答:因为HTTP协议有一个缺陷:通信只能由客户端发起我们都知道轮询的效率低,非常浪费资源(因为必须不停连接,或者HTTP…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号