C语言-学生成绩管理系统

C语言-学生成绩管理系统

前言

最近在复习C语言和数据结构,于是用纯C语言单链表写个成绩管理系统练练手。

实现的功能

系统的主界面如下:

image-20210903110751008

如界面所示,主要实现了以下功能:

  • 增加记录
  • 删除记录
  • 查询记录
  • 修改记录
  • 排序
  • 求和求平均分

写的比较简单,但是这些基本的功能都实现了,希望能给大家起一个抛砖引玉的作用。

该系统有很多可以优化的空间,比如可以使用清屏函数system(“cls”); (其头文件为stdlib.h)来获得更好的体验。

添加学生信息

实现了头插法、尾插法和整体遍历。

//添加学生 
bool add_student(stu *L)
{
	int number;//学号
	char name[10];//姓名
	int Chinese;//语文成绩
	int maths;//数学成绩
	int English;//英语成绩
	
	printf("请依次输入以下信息:学号、姓名、语文成绩、数学成绩、英语成绩(每输完一个项回车输入下一个)\n");
	scanf("%d",&number);
	scanf("%s",name);
	scanf("%d",&Chinese);
	scanf("%d",&maths);
	scanf("%d",&English);
	
	//新申请一个内存空间
	stu *p;	//指针P指向当前扫描到的结点
	p = L;		//L指向头结点,头结点是第0个结点(不存数据)
	stu *s = (stu *)malloc(sizeof(stu));
	
	//为新结点赋值 
	s->number = number;
	for(int i=0;i<sizeof(name);i++) //数组元素赋值不能让数组直接等于数组 
		s->name[i] = name[i];
	s->Chinese = Chinese;
	s->maths = maths;
	s->English = English;
	
	//指针的改变 
	s->next = p->next;
	p->next = s;
	
	return true;
}

//显示所有信息,整体遍历
void show_all(stu *L)
{
	printf("所有学生信息如下:\n");
	printf("学号\t姓名\t语文成绩\t数学成绩\t英语成绩\t\n");
	stu *p;
	p = L->next;//p指向头结点

	while(p!=NULL) 
	{
		printf("%4d %s %3d %3d %3d\n",p->number,p->name,p->Chinese,p->maths,p->English);
		p = p->next;
	}
	
} 

以上是根据头插法实现的,尾插法思路:跟头插法类似,p首先等于头指针,先让其一直向后移动,直到指向末尾,才进行结点插入操作。

//添加学生 
bool add_student(stu *L)
{
	//头插法
	int number;//学号
	char name[10];//姓名
	int Chinese;//语文成绩
	int maths;//数学成绩
	int English;//英语成绩
	
	printf("请依次输入以下信息:学号、姓名、语文成绩、数学成绩、英语成绩(每输完一个项回车输入下一个)\n");
	scanf("%d",&number);
	scanf("%s",name);
	scanf("%d",&Chinese);
	scanf("%d",&maths);
	scanf("%d",&English);
	
	//新申请一个内存空间
	stu *p;	//指针P指向当前扫描到的结点
	p = L;		//L指向头结点,头结点是第0个结点(不存数据)
	stu *s = (stu *)malloc(sizeof(stu));
	
	//为新结点赋值 
	s->number = number;
	for(int i=0;i<sizeof(name);i++) //数组元素赋值不能让数组直接等于数组 
		s->name[i] = name[i];
	s->Chinese = Chinese;
	s->maths = maths;
	s->English = English;
	
	//------------尾插法------------// 
    //尾插法主要多了这个while循环
	while(p->next!=NULL)
	{
		p = p->next;
	}
	s->next = p->next;
	p->next = s;
	//------------尾插法------------// 
	
	return true;
}

根据学号查询

按学号查询的思路很简单,只要用指针遍历,然后比较指针指向的数据的学号跟自己查询的学号是否一致,若一致则输出,若不一致则继续循环。

//根据学号查询
bool search_num(stu *L,int num)
{
	stu *p;
	p = L->next;
	
	while(p!=NULL) 
	{
		if(p->number == num) 
		{
			printf("%-4d\t%s\t%-3d\t\t%-3d\t\t%-3d\n",p->number,p->name,p->Chinese,p->maths,p->English);
			return true;
		}
		p = p->next;
	}
	return false;
}

根据学号删除学生记录

删除跟查询有点小区别。删除首先需要找到你要删除的结点数据,但是由于这个是单链表,所以需要找到要删除的结点的前一个结点,把前一个结点的指针直接修改为指向你要删除的结点的下一个结点,然后将你要删除的结点释放即可。

//根据学号删除 
bool del_student(stu *L,int num)
{
	stu *p;
	p = L;//让p从头开始 
	
	while(p->next!=NULL) 
	{
		stu *q = p->next; // q指向被删除的结点
		if(q->number == num) //p的下一个若是想要删除的结点数据 
		{
			printf("您删除的结点数据为:\n%-4d\t%s\t%-3d\t\t%-3d\t\t%-3d\n",q->number,q->name,q->Chinese,q->maths,q->English);
			p->next = q->next;//执行删除操作
			free(q); 
			return true;
		}
		p = p->next;
	}
	return false;
}

根据学号查询并修改信息

修改也很简单。修改需要先查询,查询到数据之后,将数据作一个赋值操作即可。

//根据学号查询并修改信息 
bool verify_num(stu *L,int num)
{
	stu *p;
	p = L->next;
	
	while(p!=NULL) 
	{
		if(p->number == num) 
		{
			printf("您要修改的信息为:\n学号\t姓名\t语文成绩\t数学成绩\t英语成绩\t\n");
			printf("%-4d\t%s\t%-3d\t\t%-3d\t\t%-3d\n",p->number,p->name,p->Chinese,p->maths,p->English);
				
			int number;//学号
			char name[10];//姓名
			int Chinese;//语文成绩
			int maths;//数学成绩
			int English;//英语成绩
			
			printf("请重新输入以下信息:学号、姓名、语文成绩、数学成绩、英语成绩(每输完一个项回车输入下一个)\n");
			scanf("%d",&number);
			scanf("%s",name);
			scanf("%d",&Chinese);
			scanf("%d",&maths);
			scanf("%d",&English);
			
			//为该结点赋值 
			p->number = number;
			for(int i=0;i<sizeof(name);i++) //数组元素赋值不能让数组直接等于数组 
				p->name[i] = name[i];
			p->Chinese = Chinese;
			p->maths = maths;
			p->English = English;
			return true;
		}
		p = p->next;
	}
	return false;
}

根据语文成绩从高到低排序

排序这个稍微复杂一点点,因为步骤比较多。需要注意的是,排序不能改变原来链表的结构,所以我做了一个将链表数据取出放入一个数组的操作,然后再对这个数组进行排序操作。

//根据语文成绩排序 
bool sort_Chinese(stu *L)
{
	int numbers = 0;//先统计出有多少条记录 
	stu *p;
	p = L->next;
	
	while(p!=NULL) 
	{
		numbers++;
		p = p->next;
	}
	printf("一共找到%d条学生记录!\n",numbers);
	stu data[numbers]; //把所有的数据存入这个数组里,对这个数组进行统计操作 
	
	p = L->next;//让p重新指向开头 

		for(int i=0;i<numbers;i++) 
		{
			if(p!=NULL) 
			{
				data[i].number = p->number;
				for(int j=0;j<sizeof(p->name);j++) //数组元素赋值不能让数组直接等于数组 
					data[i].name[j] = p->name[j];
				data[i].Chinese = p->Chinese;
				data[i].maths = p->maths;
				data[i].English = p->English;
				
				p = p->next;
			}
		}
	
	int temp_num;//临时学号
	char temp_name[10];
	int temp_Chinese;
	int temp_maths;
	int temp_English;
	 
	//根据语文成绩进行排序
	for(int i=0;i<numbers-1;i++)
	{
		for(int j=0;j<numbers-1-i;j++)
		{
			if(data[j].Chinese<data[j+1].Chinese)
			{
				//交换学号
				temp_num = data[j+1].number;
				data[j+1].number = data[j].number;
				data[j].number = temp_num;
				//交换姓名
				for(int k=0;k<sizeof(data[0].name);k++) //数组元素赋值不能让数组直接等于数组 
				{
					temp_name[k] = data[j+1].name[k];
					data[j+1].name[k] = data[j].name[k];
					data[j].name[k] = temp_name[k];
				}
				//交换语文成绩 
				temp_Chinese = data[j+1].Chinese;
				data[j+1].Chinese = data[j].Chinese;
				data[j].Chinese = temp_Chinese;
				//交换数学成绩
				temp_maths = data[j+1].maths;
				data[j+1].maths = data[j].maths;
				data[j].maths = temp_maths;
				//交换英语成绩
				temp_English = data[j+1].English;
				data[j+1].English = data[j].English;
				data[j].English = temp_English;
			}
		}
	}
	
	//输出排序后的结果
	printf("排序后的结果如下(语文成绩从高到低排序):\n学号\t姓名\t语文成绩\t数学成绩\t英语成绩\t\n"); 
	
	for(int i=0;i<numbers;i++)
	{
		printf("%-4d\t%s\t%-3d\t\t%-3d\t\t%-3d\n",data[i].number,data[i].name,data[i].Chinese,data[i].maths,data[i].English);
	}
} 

全部代码

#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h> //根据C99标准,C语言使用bool类型需要添加这个头文件 
 

//结构体声明部分
typedef struct Student
{
	int number;//学号
	char name[10];//姓名
	int Chinese;//语文成绩
	int maths;//数学成绩
	int English;//英语成绩
	struct Student *next; //指向后一个元素的指针 
}stu,*stuList; 

/*--------函数声明部分--------*/ 
void MainMenu();//主菜单,用于显示 
bool add_student(stu *L);//添加学生记录 
void show_all(stu *L);//显示所有学生信息
bool del_student(stu *L,int num);//根据学号删除学生信息 
bool search_num(stu *L,int num);//根据学号查询
bool verify_num(stu *L,int num);//根据学号查询信息并修改 
bool sort_Chinese(stu *L);//根据语文成绩排序 

bool InitList(stu *L);//学生链表初始化 
bool Empty(stu *L);//链表判空操作 
 
/*--------函数声明部分--------*/


int main()
{
	int ch;//选择的序号
	int ch_num;//根据学号进行查询、删除、修改等操作 
	
	
	stu L;

	if(InitList(&L))
		printf("链表初始化成功!\n");//提示信息,如果不需要可删除,但一定要先进行链表初始化! 
	else
		printf("链表初始化失败!\n");
	
	while(1)
	{
		MainMenu();//显示主界面 
		
		printf("\n请输入您要执行的操作序号:");
		scanf("%d",&ch);
		switch(ch)
		{
			case 0: printf("感谢您的使用!");	exit(0);	break;
			case 1: add_student(&L);  break;
			case 2: printf("请输入您要删除的学生的学号:");
					scanf("%d",&ch_num);
					if(del_student(&L,ch_num))
						printf("删除成功!\n");	
					else
					    printf("删除失败,无此项记录!\n");	
					break;
			case 3: printf("请输入您要修改的学生的学号:");
					scanf("%d",&ch_num);
					if(verify_num(&L,ch_num))
						printf("修改成功!\n");	
					else
					    printf("修改失败,无此项记录!\n");	
					break;
			case 4:    
					printf("请输入您要查询的学号:");
					scanf("%d",&ch_num);
					if(search_num(&L,ch_num))
						printf("查询成功!\n");	
					else
					    printf("查询失败,无此项记录!\n");	
					break;
			case 5:
					sort_Chinese(&L);		break;
			case 6: show_all(&L);  break;
			default:	printf("您输入的操作序号有误,请重新输入!\n");
		}
	}
	return 0;
}

//主菜单,显示 
void MainMenu()
{
	printf("\n\n\n");
	printf("\t      **********学生成绩管理系统***********\n"); 
	printf("\t      -------	0.退出系统 \n\n");
	printf("\t      -------	1.录入学生成绩\n\n");
	printf("\t      -------	2.删除记录\n\n");
	printf("\t      -------	3.修改学生信息\n\n");
	printf("\t      -------	4.查询学生信息\n\n");
	printf("\t      -------	5.按语文成绩排序\n\n");
	printf("\t      -------	6.显示所有学生信息\n\n");
	printf("\t      *************************************\n");
}

//初始化单链表(带头结点)
bool InitList(stu *L)
{
	L = (stu *)malloc(sizeof(stu));	//分配一个头结点
	if (L==NULL)	//内存不足,分配失败
		return false;	
	L->next = NULL;	//头结点之后暂时还没有节点
	return true;
}


//添加学生 
bool add_student(stu *L)
{
	
	int number;//学号
	char name[10];//姓名
	int Chinese;//语文成绩
	int maths;//数学成绩
	int English;//英语成绩
	
	printf("请依次输入以下信息:学号、姓名、语文成绩、数学成绩、英语成绩(每输完一个项回车输入下一个)\n");
	scanf("%d",&number);
	scanf("%s",name);
	scanf("%d",&Chinese);
	scanf("%d",&maths);
	scanf("%d",&English);
	
	//新申请一个内存空间
	stu *p;	//指针P指向当前扫描到的结点
	p = L;		//L指向头结点,头结点是第0个结点(不存数据)
	stu *s = (stu *)malloc(sizeof(stu));
	
	//为新结点赋值 
	s->number = number;
	for(int i=0;i<sizeof(name);i++) //数组元素赋值不能让数组直接等于数组 
		s->name[i] = name[i];
	s->Chinese = Chinese;
	s->maths = maths;
	s->English = English;
	
	//------------头插法------------// 
	//指针的改变 
//	s->next = p->next;
//	p->next = s;
	//------------头插法------------//
	
	//------------尾插法------------// 
	//注:尾插法主要是多了这个while循环,即先让指针指向链表末尾再进行插入操作 
	while(p->next!=NULL)
	{
		p = p->next;
	}
	s->next = p->next;
	p->next = s;
	//------------尾插法------------// 
	
	
	return true;
}

//显示所有信息 
void show_all(stu *L)
{
	printf("所有学生信息如下:\n");
	printf("学号\t姓名\t语文成绩\t数学成绩\t英语成绩\t\n");
	stu *p;
	p = L->next;
	
	while(p!=NULL) 
	{
		printf("%-4d\t%s\t%-3d\t\t%-3d\t\t%-3d\n",p->number,p->name,p->Chinese,p->maths,p->English);
		p = p->next;
	}
} 


//根据学号查询
bool search_num(stu *L,int num)
{
	stu *p;
	p = L->next;
	
	while(p!=NULL) 
	{
		if(p->number == num) 
		{
			printf("%-4d\t%s\t%-3d\t\t%-3d\t\t%-3d\n",p->number,p->name,p->Chinese,p->maths,p->English);
			return true;
		}
		p = p->next;
	}
	return false;
}

//根据学号删除 
bool del_student(stu *L,int num)
{
	stu *p;
	p = L;//让p从头开始 
	
	while(p->next!=NULL) 
	{
		stu *q = p->next; // q指向被删除的结点
		if(q->number == num) //p的下一个若是想要删除的结点数据 
		{
			printf("您删除的结点数据为:\n%-4d\t%s\t%-3d\t\t%-3d\t\t%-3d\n",q->number,q->name,q->Chinese,q->maths,q->English);
			p->next = q->next;//执行删除操作
			free(q); 
			return true;
		}
		p = p->next;
	}
	return false;
}

//根据学号查询并修改信息 
bool verify_num(stu *L,int num)
{
	stu *p;
	p = L->next;
	
	while(p!=NULL) 
	{
		if(p->number == num) 
		{
			printf("您要修改的信息为:\n学号\t姓名\t语文成绩\t数学成绩\t英语成绩\t\n");
			printf("%-4d\t%s\t%-3d\t\t%-3d\t\t%-3d\n",p->number,p->name,p->Chinese,p->maths,p->English);
			
			int number;//学号
			char name[10];//姓名
			int Chinese;//语文成绩
			int maths;//数学成绩
			int English;//英语成绩
			
			printf("请重新输入以下信息:学号、姓名、语文成绩、数学成绩、英语成绩(每输完一个项回车输入下一个)\n");
			scanf("%d",&number);
			scanf("%s",name);
			scanf("%d",&Chinese);
			scanf("%d",&maths);
			scanf("%d",&English);
			
			//为该结点赋值 
			p->number = number;
			for(int i=0;i<sizeof(name);i++) //数组元素赋值不能让数组直接等于数组 
				p->name[i] = name[i];
			p->Chinese = Chinese;
			p->maths = maths;
			p->English = English;
			return true;
		}
		p = p->next;
	}
	return false;
}

//根据语文成绩排序 
bool sort_Chinese(stu *L)
{
	int numbers = 0;//先统计出有多少条记录 
	stu *p;
	p = L->next;
	
	while(p!=NULL) 
	{
		numbers++;
		p = p->next;
	}
	printf("一共找到%d条学生记录!\n",numbers);
	stu data[numbers]; //把所有的数据存入这个数组里,对这个数组进行统计操作 
	
	p = L->next;//让p重新指向开头 

		for(int i=0;i<numbers;i++) 
		{
			if(p!=NULL) 
			{
				data[i].number = p->number;
				for(int j=0;j<sizeof(p->name);j++) //数组元素赋值不能让数组直接等于数组 
					data[i].name[j] = p->name[j];
				data[i].Chinese = p->Chinese;
				data[i].maths = p->maths;
				data[i].English = p->English;
				
				p = p->next;
			}
		}
		
	
	
//	printf("存进数组后:\n");  //可以查看存进的结果是否正确 
//	for(int i=0;i<numbers;i++)
//	{
//		printf("%-4d\t%s\t%-3d\t\t%-3d\t\t%-3d\n",data[i].number,data[i].name,data[i].Chinese,data[i].maths,data[i].English);
//	}
	
	int temp_num;//临时学号
	char temp_name[10];
	int temp_Chinese;
	int temp_maths;
	int temp_English;
	 
	//根据语文成绩进行排序
	for(int i=0;i<numbers-1;i++)
	{
		for(int j=0;j<numbers-1-i;j++)
		{
			if(data[j].Chinese<data[j+1].Chinese)
			{
				//交换学号
				temp_num = data[j+1].number;
				data[j+1].number = data[j].number;
				data[j].number = temp_num;
				//交换姓名
				for(int k=0;k<sizeof(data[0].name);k++) //数组元素赋值不能让数组直接等于数组 
				{
					temp_name[k] = data[j+1].name[k];
					data[j+1].name[k] = data[j].name[k];
					data[j].name[k] = temp_name[k];
				}
				//交换语文成绩 
				temp_Chinese = data[j+1].Chinese;
				data[j+1].Chinese = data[j].Chinese;
				data[j].Chinese = temp_Chinese;
				//交换数学成绩
				temp_maths = data[j+1].maths;
				data[j+1].maths = data[j].maths;
				data[j].maths = temp_maths;
				//交换英语成绩
				temp_English = data[j+1].English;
				data[j+1].English = data[j].English;
				data[j].English = temp_English;
			}
		}
	}
	
	//输出排序后的结果
	printf("排序后的结果如下(语文成绩从高到低排序):\n学号\t姓名\t语文成绩\t数学成绩\t英语成绩\t\n"); 
	
	for(int i=0;i<numbers;i++)
	{
		printf("%-4d\t%s\t%-3d\t\t%-3d\t\t%-3d\n",data[i].number,data[i].name,data[i].Chinese,data[i].maths,data[i].English);
	}
} 

系统功能测试

image-20210903110004669

image-20210903110037137

image-20210903110114218

image-20210903110148419

image-20210903110233577

  • 6
    点赞
  • 59
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值