通过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;
}
至此,一个简单的学生管理系统制作完毕~~