C语言项目练习—学生管理系统

通过C语言写一个简单的学生信息管理系统,增强对C语言一些重要知识点的认识。

一、创建学生节点

使用结构体可以很好的把每一个学生的信息都放在一个特点的位置,方便遍历每一个学生的信息。

#include<stdio.h>

//创建一个节点
typedef struct _STU
{
	char arrStunum[10];//学生学号
	char arrStuname[10];//学生姓名
	int iStuSorce;//学生分数
	struct _STU*pNext;//指向下一个节点指针
} STUNODE;

//声明链表的头和尾
STUNODE *g_pHead = NULL; //不赋值指针就成了野指针
STUNODE *g_pEnd = NULL;

int main(void)
{
    //对学生信息进行初始化
	char arrStunum[10] = { '\0' };
	char arrStuname[10]= { '\0' };
	int iStuSorce=-1;
	STUNODE *Ptemp = NULL;
}


二、尾添加一个学生的信息

需要创建一个函数用来添加每一个学生的信息,这个函数包含了三个参数,分别是学生学号、学生名字、学生分数。

1.进入函数第一步需要检测参数是否合法不合法则退出函数

2.创建一个学生节点

3.对节点成员进行赋值

4.把学生节点都链接起来

//添加一个学生信息
void AddstuMSG(char arrStunum[10], char arrStuname[10], int iStuSorce);`


//添加一个学生信息
void AddstuMSG(char arrStunum[10], char arrStuname[10], int iStuSorce)
{
	//第一步检验参数合法性
	if (0 == arrStunum[10] || 0 == arrStuname[10] || iStuSorce < 0)
	{
		printf("学生信息输入错误!\n");
		return;        //信息错误跳出函数
	}

	//逻辑
	//创造一个节点
	STUNODE *pTemp = malloc(sizeof(STUNODE));
	//节点成员赋初始值
	strcpy(pTemp->arrStunum, arrStunum);   //学生学号和姓名都是字符串用strcpy进行赋值
	strcpy(pTemp->arrStuname, arrStuname);
	pTemp->iStuSorce = iStuSorce;
	pTemp->pNext = NULL;     //指向下一个节点的指针赋值为空

	//接在链表上
	if (NULL == g_pHead || NULL == g_pEnd) //只有一个节点
	{
		g_pHead = pTemp;  //用头和尾指向新链表的地址
		//g_pEnd = pTemp;
	}
	else      //存在多个节点
	{
		g_pEnd->pNext = pTemp; //来一个新的节点只要让尾的下一个指向新的节点(链接)
		//g_pEnd = pTemp; //向后移动
	}
	g_pEnd = pTemp;
}



在添加节点时我们分为两种情况
1.只有一个节点
首先判断头指针和尾指针是否指向NULL,如果指向的是NULL那么说明只有一个节点,只有一个节点链接就非常简单了把头指针和尾指针都指向PTemp就完成了链接。
2.存在多个节点
这一步稍微复杂一点,只有一个节点时头和尾都指向第一个节点。

头指针保持不动,尾指针的下一个指针指向下一个节点,尾节点移动到下一个节点这样就把他们链接起来了。

三、查看学生信息

如何查看学生信息及链表的释放。
查看每一个学生的信息需要我们去遍历链表
第一步:定义一个结构体指针指向头,判断头是否为空为空则提示没有学生信息。
第二步:每一次循环都让PTemp向后移动一个,当移动到最后一个时PTemp为NULL则不再执行循环。

void showdate()
{
	STUNODE *pTemp = g_pHead;
	if (pTemp == NULL)
	{
		printf("无学生信息!\n");
	}
	while (pTemp != NULL)
	{
		printf("学号:%s,姓名:%s,分数:%d\n",pTemp->arrStunum,pTemp->arrStuname,pTemp->iStuSorce );
		//向后移动
		pTemp = pTemp->pNext;
	}
}

四、链表的释放

链表的释放和链表的遍历有一些相同的地方
第一步:定义一个结构体指针指向头,判断头是否为空
第二步:使用PTemp记住头节点的位置,头节点向后移动一个位置,并把PTemp释放,如此循环就可以清空链表。
第三步:当清空完链表后要把头尾指针都指向NULL。

//清空链表
void FreeLinkDate()
{
	STUNODE *pTemp = g_pHead;
	while (g_pHead != NULL)
	{
		//记录节点
		pTemp = g_pHead;
		//向后移动
		g_pHead = g_pHead->pNext;

        //删除节点
	    free(pTemp);
	}
	g_pHead = NULL;
	g_pEnd = NULL;
}

六、输出指令框

这一步就是一些printf打印出命令和一些空格去控制打印的地方,大家可以直接复制下面的代码。

//显示指令
void showorder()
{
	printf("******************学生信息管理系统****************\n");
	printf("******************本系统操作指令如下**************\n");
	printf("***             1.增加一个学生信息(尾添加)     ***\n");
	printf("***             2.查找指定学生信息(姓名/学号)  ***\n");
	printf("***             3.修改指定学生信息             ***\n");
	printf("***             4.保存学生的信息到文件中       ***\n");
	printf("***             6.删除指定学生的信息           ***\n");
	printf("***             7.恢复删除学生的信息           ***\n");
	printf("***             9.显示所有学生的信息           ***\n");
	printf("***             10.显示指令                    ***\n");
	printf("***             11.增加一个学生信息(头添加)    ***\n");
	printf("***             12.增加一个学生信息(中间添加)  ***\n");
	printf("***             0.退出系统                     ***\n");
	printf("**************************************************\n");
}

五、查找指定学生信息

这个操作设置的是根据学生学号来查找学生的信息。
我们需要一个结构体指针的返回值,查找到学生信息返回结构体指针,方便我们读取信息。
第一步:先判断学生学号是否存在不存在则退出程序,并提示学号错误。

第二步:判断链表是否为空,链表为空返回NULL,退出程序。

第三步:这一步和前面的遍历链表很类似,先定义一个结构体指针PTemp去记录头指针的位置,然后再去一个个的遍历链表,使用strcmp函数可以判断两个字符串里面的值是否相等,相等则返回0,查找成功return pTemp。

//查找指定学生
STUNODE* Findstunum(char arrStunum[10])
{
	//检测学号合法性
	if (NULL == arrStunum)
	{
		printf("学号输入错误\n");
		return NULL;
	}

	//验证链表是否为空
	if (NULL == g_pHead || NULL == g_pEnd)
	{
		printf("链表为NULL\n");
		return NULL;
	}

	STUNODE *pTemp = g_pHead;
	//遍历链表
	while (pTemp != NULL)
	{
		if (0 == strcmp(pTemp->arrStunum, arrStunum)) //检验学号正确性
		{
			return pTemp;    //返回学号节点
		}
		pTemp = pTemp->pNext; //向后移动
	}

	printf("链表为空\n");
	return NULL;

六、指定位置添加学生信息

在指定位置添加学生的信息首先要得到指定的位置。
这个时候我们采用之前学的查找函数查找到我们想要的位置,然后把得到的位置当成参数传入函数,若指定位置在尾节点处那么就和前面我们所讲尾添加是一样的操作。
如果不在尾节点处而是在中间位置那么我们就得按照下面方法插入。

//指定位置插入节点
void insertnote(STUNODE*Ptemp, char arrStunum[10], char arrStuname[10], int iStuSorce)
{
	//创建节点
	STUNODE*Pnewtemp = malloc(sizeof(STUNODE));
	strcpy(Pnewtemp->arrStuname, arrStuname);
	strcpy(Pnewtemp->arrStunum, arrStunum);
	Pnewtemp->iStuSorce = iStuSorce;
	Pnewtemp->pNext = NULL;
	if (Ptemp == g_pEnd) //指定节点为尾节点
	{
		g_pEnd->pNext = Pnewtemp;
		g_pEnd = Pnewtemp;
	}
	else
	{
		Pnewtemp->pNext = Ptemp->pNext; //先让指定位置下一个节点和插入节点连上
		Ptemp->pNext = Pnewtemp;  
	}
}

二、main函数里面的函数调用
在主函数里面我们主要是进行一些参数的初始化以及使用switch case结构进行命令的使用。

int main(void)
{
	int norder = -1;
	char arrStunum[10] = { '\0' };
	char arrStuname[10]= { '\0' };
	int iStuSorce=-1;
	char nflag = 1;
	char xorder = 0;
	STUNODE *Ptemp = NULL;

	showorder();

	//读取学生信息
	readstuformfile();
	while (nflag)
	{
		printf("请输入指令:\n");
		scanf_s("%d", &norder);

		switch (norder)
	   {
		case 1://头添加
			//添加一个学生信息
			printf("输入学号:");
			scanf("%s", arrStunum);
			printf("输入姓名:");
			scanf("%s", arrStuname);
			printf("输入分数:");
			scanf("%d", &iStuSorce);
			AddstuMSG(arrStunum, arrStuname, iStuSorce);
			break;
		case 11://尾添加
			//添加一个学生信息
			printf("输入学号:");
			scanf("%s", arrStunum);
			printf("输入姓名:");
			scanf("%s", arrStuname);
			printf("输入分数:");
			scanf("%d", &iStuSorce);
			AddstuMSGtolinkhead(arrStunum, arrStuname, iStuSorce);
			break;
		case 12://中间添加
			printf("输入指定学号:");
			scanf("%s", arrStunum);
			Ptemp = Findstunum(arrStunum); //将找到的节点传递给Ptemp
			if (NULL != Ptemp)
			{
				//TODO:插入
				//添加一个学生信息
				printf("输入学号:");
				scanf("%s", arrStunum);
				printf("输入姓名:");
				scanf("%s", arrStuname);
				printf("输入分数:");
				scanf("%d", &iStuSorce);
				insertnote(Ptemp, arrStunum, arrStuname, iStuSorce);
			}
			break;
		case 2://打印指定学生信息
			//输入一个学号
			printf("输入指定学号:\n");
			scanf("%s",arrStunum);
			//查找
			Ptemp = Findstunum(arrStunum);
			//打印
			if (NULL != Ptemp)
			{
				printf("学号:%s,分数:%d,姓名:%s\n",Ptemp->arrStunum, Ptemp->iStuSorce, Ptemp->arrStuname);
			}
			break;
		case 3://修改指定学生信息
			//输入一个学号
			printf("输入指定学号:\n");
			scanf("%s", arrStunum);
			//查找
			Ptemp = Findstunum(arrStunum);
			//修改
			if (NULL != Ptemp)
			{
				printf("修改学号按:%d 修改姓名按:%d 修改分数按:%d 退出修改按%d\n", 1, 2, 3,0);
				while (scanf("%d", &xorder)&&xorder!=0)
				{
					switch (xorder)
					{
					case 1:
						//修改学号
						printf("输入学号:");
						scanf("%s", arrStunum);
						strcpy(Ptemp->arrStunum, arrStunum);
						break;
					case 2:
						//修改姓名
						printf("输入姓名:");
						scanf("%s", arrStuname);
						strcpy(Ptemp->arrStuname, arrStuname);
						break;
					case 3:
						//修改分数
						printf("输入分数:");
						scanf("%d", &iStuSorce);
						Ptemp->iStuSorce = iStuSorce;
						break;
					}
				}
			}
			printf("修改完成!\n");
			break;
		case 6://删除指定学生信息
			//输入一个学号
			printf("输入要删除学生学号:\n");
			scanf("%s", arrStunum);
			//查找
			Ptemp = Findstunum(arrStunum);
			//删除
			if (NULL != Ptemp)
			{
				//删除指定学生
				delectstunode(Ptemp);
				printf("删除完成!\n");
			}
			break;
		case 7://恢复学生信息
			//释放链表
			FreeLinkDate();
			//恢复学生信息
			readstuformfile();
			break;
		case 4://保存学生信息
			savestutofile();
			printf("保存完成!\n");
			break;
		case 9:
			//显示链表信息
			showdate();
			break;
		case 10:
			//显示指令
			showorder();
			break;
		case 0:
			//退出系统
			nflag = 0;
			break;
		default:
			printf("输入的指令不对!\n");
			break;
	   }
	}
	
	//保存学生信息
	savestutofile();

	//清空链表
	FreeLinkDate();
	return 0;
}

至此,一个简单的学生管理系统制作完毕~~

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值