C语言 实现学生管理系统(手把手教学)

        学生管理系统怎么实现?首先要对问题能分析出框架来。这样在之后书写功能时就会对所需要的东西有一个清晰的认知。

        那么,管理系统的任务就是:能删除、查找和修改学生信息,能进行排序、能打印信息。

        这些都是最基本的功能,把这些功能框架写在一个c源文件里,当作主函数的运行区。

#include"StudentManager.h"

enum Option
{
	EXIT,
	ADD,
	DEL,
	SEARCH,
	MODIFY,
	SORT,
	PRINT
};

int main()
{
	int input = 0;
	//创建人员名单
	Student stulist;//人员名单
	//初始化人员名单
	InitStudent(&stulist);
	do 
	{
		menu();
		printf("请选择:n");
		scanf_s("%d", &input);
		switch(input)
		{
			case ADD:
				AddStudent(&stulist);//修改一定传地址
				break;
			case DEL:
				DelStudent(&stulist);
				break;
			case SEARCH:
				SearchStudent(&stulist);//可以传值,但传地址效率更高
				break;
			case MODIFY:
				ModifyStudent(&stulist);
				break;
			case SORT:
				SortStudent(&stulist);
				break;
			case PRINT:
				PrintStulist(&stulist);
				break;
			case EXIT:
				printf("退出管理系统n");
			default:
				break;
		}
	} while (input);
	SaveFile(&stulist);
}

========================================================================= 

        而后,是单独的一个文件,实现对所使用函数的声明,以便让业务逻辑更加分明:(同时尽量在这里就把所需要的存储类型定义了,这样写功能函数的时候会更加的清晰)

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
//结构体定义
typedef struct StuInfo
{
	//(1)每个学生的个人信息包括:姓名、学号、籍贯、年龄、数学、英语、物理成绩
	char name[15];
	char address[20];
	char ID[15];
	int age;
	int score[3];
	int sum;
	int order;
}StuInfo;
//对结构体进行封装
typedef struct Student
{
	StuInfo data[100];  //存放的人员信息
	int size;  //记录当前的人数
}Student;

int FindByName(Student* pc, char name[]);
void InitStudent(Student* pc);
void AddStudent(Student* pc);
void DelStudent(Student* pc);
void SearchStudent(Student* pc);
void ModifyStudent(Student* pc);
void SortStudent(Student* pc);
void SaveFile(Student* pc);
void PrintStulist(const Student* pc);
void menu();

 =========================================================================

        之后,就是对函数功能的实现了,在实现功能之前,我们已经确定自己写的学生信息存储方式是什么。所以,就是函数功能的实现。

首先最基础的是菜单界面:

//显示菜单界面
void menu()
{
	printf("---------------n");
	printf("1.增     2.删 n");
	printf("3.查     4.改 n");
	printf("5.排     6.打印 n");
	printf("    0.退出    n");
	printf("---------------n");
}

========================================================================= 

    然后写一个函数来初始化空间(不多解释):

//初始化数据,以便使用
void InitStudent(Student* pc)
{
	pc->size = 0;
	memset(pc->data, 0, sizeof(pc->data));//初始化所有数据为0
}

        之后就是一些功能的实现,比如我们先实现一个打印的功能,因为打印功能的代码在其他功能里也能使用和体现(例如查找)

        指针pc想要解引用地址,就需要使用' -> ',其他的则是' . '。所以打印信息的操作就一目了然了,首先指针解引用取单个学生信息,然后结构体再去取出相应的信息数据来。

//打印信息
void PrintStulist(const Student* pc)
{
	int i = 0;
	//打印标题
	printf("%-10st%-10st%-10st%-10st%-20sn", "姓名", "学号", "籍贯", "年龄", "成绩:数学、英语、物理、");
	for (i = 0; i < pc->size; i++)
	{
		printf("%-10st%-10st%-10st%-10dt%dt%dt%dn",
			pc->data[i].name,
			pc->data[i].ID,
			pc->data[i].address,
			pc->data[i].age,
			pc->data[i].score[0], pc->data[i].score[1], pc->data[i].score[2]);//输入的三科成绩
	}

}

        在这里,需要简单的说明一下这个函数,使用const只读属性是因为我们接受的是学生名单的信息,但为了保证学生名单信息不会被误操作(除打印以外的操作),所以加上了const。那么可能有人会问,既然害怕被修改,为什么不直接定义一个普通变量接受学生信息,而要使用指针?那么请思考一下:指针接受的是地址,普通变量接受的是全部的信息,哪个效率更高呢?当然是传址的效率高。

=========================================================================

        而后是添加的功能,一个新学生来到了班级,得重新录入信息吧,所以添加的功能需要一些什么?当然就是对应的信息去做修改(此处定义的学生名单进行封装时,定义的是100,当然,你也可以选择#define宏定义,以便后期维护):

//增加人员信息
void AddStudent(Student* pc)
{
	if (pc->size == 100)
	{
		printf("名单已满,无法添加n");
		return;
	}
	//增加信息
	printf("请输入名字:n");
	scanf_s("%s", pc->data[pc->size].name, 15);
	printf("请输入学号:n");
	scanf_s("%s", pc->data[pc->size].ID, 15);
	printf("请输入籍贯:n");
	scanf_s("%s", pc->data[pc->size].address, 20);
	printf("请输入年龄:n");
	scanf_s("%d", &(pc->data[pc->size].age));
	printf("请输入数学、英语、物理成绩:n");
	scanf_s("%d %d %d", &(pc->data[pc->size].score[0]), &(pc->data[pc->size].score[1]), &(pc->data[pc->size].score[2]));
	pc->size++;
	printf("信息添加成功n");
}

        添加的操作跟打印还是很相像的,就不多做解释。

=========================================================================

        那么,看看剩下的几个功能,其中有修改、删除和查找,我们仔细分析一下这三个功能,都需要定向的找到某个学生,所以,我们先写一个查找的功能出来(查找只能顺序查找,一个一个去看哪个符合条件,所以用for或者while):

//定义一个查找的功能,以便删除,查找使用
int FindByName(Student* pc, char name[])
{
	int i = 0;
	for (i = 0; i < pc->size; i++)
	{
		if ((strcmp(pc->data[i].name, name)) == 0)
		{
			return i;
		}
	}
	return -1;
}

        这里查找使用的是姓名查找,你也可以去更改查找的功能实现更高级一点的操作,比如根据成绩找人,根据ID找人(本质都一样)。

=========================================================================

        根据这个查找的功能,我们就可以去实现删除和修改操作了,当一个学生犯下滔天大罪,那就得退学咯,所以接下来实现一下删除:

        这里要注意,因为是对学生的信息进行了更改,所以必须传地址。

//删除人员信息
void DelStudent(Student* pc)
{
	char name[15] = { 0 };
	if (pc->size == 0)
	{
		printf("名单已空,没有信息可以删除n");
		return;
	}
	//1.查找要删除的人
	printf("请输入要删除的人:n");
	scanf_s("%s", name, 15);

	int position = FindByName(pc, name);
	/*
	有/没有 --> 2. 删除
	*/
	if (position == -1)
	{
		printf("要删除的人不存在");
		return;
	}
	//删除
	int i = 0;
	for (i = position; i < pc->size - 1; i++)//size-1是因为左后一个元素没必要被覆盖,后面代码删除
	{
		pc->data[i] = pc->data[i + 1];//依次覆盖实现向前移动和删除

	}
	pc->size--;
	printf("删除成功n");
}

        删除的实现也算是相当简单了,因为实际上就等于是找到这个学生,然后把整个表格向前移动,直接覆盖这个学生就行(没办法,顺序表的缺陷就是删除操作时间复杂度高),同时,注意书写时也要判断学生存不存在。

        那么查找操作呢?我们上面写的关于查找的功能,只是程序找到了这个人的信息,真正需要去查找,总得去查看一下这个人的信息吧。班里学生想知道自己的信息,找老师去查,肯定是需要输出信息的,所以这里也摘下了打印的一部分代码:

//查找指定的人员 --> 借用了删除人员的代码以及打印信息的代码
void SearchStudent(Student* pc)
{
	char name[15] = { 0 };
	printf("请输入要查找的人:n");
	scanf_s("%s", name, 15);
	int position = FindByName(pc, name);
	if (position == -1)
	{
		printf("要查找的人不存在");
		return;
	}//跟删除的判断一样的代码
	else//去打印找代码,注意更改一些内容
	{
		printf("%-10st%-10st%-10st%-10st%-20sn", "姓名", "学号", "籍贯", "年龄", "成绩:数学、英语、物理、");
		printf("%-10st%-10st%-10st%-10dt%dt%dt%dn",
			pc->data[position].name,
			pc->data[position].ID,
			pc->data[position].address,
			pc->data[position].age,
			pc->data[position].score[0], pc->data[position].score[1], pc->data[position].score[2]);//从打印那里摘来的代码
	}
}

        所以,基本上只要理解了最前面几个代码,剩下的也就迎刃而解了。那么我们还剩下跟查找有关的修改功能:

//修改指定的人员信息  --> 借用了查找的代码以及添加的代码
void ModifyStudent(Student* pc)//使用查找的代码进行改造
{
	char name[15] = { 0 };
	printf("请输入要修改的人:n");
	scanf_s("%s", name, 15);
	int position = FindByName(pc, name);
	if (position == -1)
	{
		printf("要修改的人不存在");
		return;
	}//跟删除的判断一样的代码
	else//注意,这里是跟添加一样的代码
	{
		printf("请输入名字:n");
		scanf_s("%s", pc->data[position].name, 15);
		printf("请输入学号:n");
		scanf_s("%s", pc->data[position].ID, 15);
		printf("请输入籍贯:n");
		scanf_s("%s", pc->data[position].address, 20);
		printf("请输入年龄:n");
		scanf_s("%d", &(pc->data[position].age));
		printf("请输入数学、英语、物理成绩:n");
		scanf_s("%d %d %d", &(pc->data[position].score[0]), &(pc->data[position].score[1]), &(pc->data[position].score[2]));
		printf("信息修改成功n");
	}
}

        发现了吗?跟添加信息又有点像。总之,跟查找有关的函数功能基本上全实现了,那么还剩下排序的功能没有实现,由于排序的功能与查找关系就不大了,所以列为下一个大块。

=========================================================================

        排序,我们能用到的排序其实有很多算法,比如选择排序、冒泡排序、插入排序、快速排序等等,这里就使用了一个更容易理解的插入排序算法来实现对学生的排序(算总分来排序):

//对人员进行排序
void SortStudent(Student* pc)
{
	for (int i = 0; i < pc->size; i++)
	{
		pc->data[i].sum = pc->data[i].score[0] + pc->data[i].score[1] + pc->data[i].score[2];
	}
	printf("总分排序结果:n");//使用插入排序实现此功能
	StuInfo p;
	int i, j;
	for (i = 1; i < pc->size; i++)
		if (pc->data[i].sum > pc->data[i - 1].sum)
		{
			p = pc->data[i];
			for (j = i - 1; j >= 0 && pc->data[j].sum < p.sum; j--)
				pc->data[j + 1] = pc->data[j];
			pc->data[j + 1] = p;
		}
	StuInfo* t;
	i = 0;
	for (t = pc->data; t < pc->data + pc->size; t++)
	{
		pc->data[i].order = i + 1;
		i++;
	}
	//把排序之后的名单打印出来
	printf("%-10st%-10st%-10st%-10st%-20sn", "姓名", "学号", "籍贯", "年龄", "成绩:数学、英语、物理、");
	for (int i = 0; i < pc->size; i++)
	{
		printf("%-10st%-10st%-10st%-10dt%dt%dt%dn",
			pc->data[i].name,
			pc->data[i].ID,
			pc->data[i].address,
			pc->data[i].age,
			pc->data[i].score[0], pc->data[i].score[1], pc->data[i].score[2]);//输入的三科成绩
	}
}

        那么,这段代码就只稍微解释一下所使用的排序的算法思路。插入排序,就是找到最大的那个值(得循环一遍才能找到),然后放到前面去,循环下来,就得到了一个顺序。具体的算法,等日后笔者再写一篇CSDN讲解一下吧,毕竟排序的内容还是很多的。

        同时,这个函数也使用了打印的代码,毕竟,排完序得让别人看见嘛,所以也打印一下整个学生名单的信息。

        写到这里,所有的功能基本就已经实现了。但是鉴于学生的信息最终可能要保存到文件里,以便日后使用,所以,这里又补了一个简单的文件保存的函数,当然,如果读者想实现读文件来写管理系统,那也是可以的:

//存储文件
void SaveFile(Student* pc)
{
	FILE* fp = NULL;
	fopen_s(&fp, "studentInfo.txt", "wt+");  //b表示以二进制方式打开文件
	if (fp == NULL) //打开文件失败,返回错误信息
	{
		printf("open file for write errorn");
	}
	int i = 0;
	for (i = 0; i < pc->size; i++) {
		fprintf(fp, "%-10st%-10st%-10st%-10dt 三科成绩:%dt%dt%dn",
			pc->data[i].name,
			pc->data[i].ID,
			pc->data[i].address,
			pc->data[i].age,
			pc->data[i].score[0], pc->data[i].score[1], pc->data[i].score[2]);
	}
	fclose(fp);
	fp = NULL;
}

        终于,我们的学生管理系统就算时搭建完成了,那么,小火罐们快拿着代码去试一试吧!

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
THE END
分享
二维码
< <上一篇

)">
下一篇>>