利用链表,以及模块化编程对学生管理系统进行编写:
1.主函数部分:
main.h文件的代码
#ifndef _MAIN_H_
#define _MAIN_H_
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
enum{ret,add,del,chag,find,rank,print,insert};//对应0.1.2.3.4.5.6.7
struct Stu{
char name[32];
int id;
float score;
};
struct NODE{
struct Stu stu;//数据域
struct NODE *addr;//指针域
};
struct NODE *Great_Head(void);
int Menu(void);
#include "add.h"
#include "print.h"
#include "find.h"
#include "change.h"
#include "rank.h"
#include "del.h"
#include "insert.h"
#endif
main.c的代码
#include "main.h"
int main()
{
int num=0;
struct NODE *head=Great_Head();
if(head == NULL)
{
printf("头节点开辟失败\n");
return 0;
}
while(1)
{
num=Menu();
switch(num)
{
case add:Stu_Add(head);break;
case del:Stu_Del(head);break;
case chag:Stu_Change(head);break;
case find:Stu_Find(head);break;
case rank:Stu_Rank(head);break;
case print:Stu_Print(head);break;
case insert:Stu_Insert(head);break;
case ret:printf("欢迎下次使用\n");return 0;
default:printf("输入有误,重新输入\n");
}
}
return 0;
}
int Menu(void)
{
int num = 0;
printf("1.添加学生信息\n");
printf("2.删除学生信息\n");
printf("3.修改学生信息\n");
printf("4.查找学生信息\n");
printf("5.学生信息排序\n");
printf("6.遍历学生信息\n");
printf("7.插入学生信息\n");
printf("0.退出学生管理系统\n");
printf("请输入要执行的功能的序号\n");
scanf("%d",&num);
getchar();
return num;
}
struct NODE *Great_Head(void)
{
struct NODE *head=(struct NODE *)malloc(sizeof(struct NODE));
if(head == NULL)
{
return NULL;
}
memset(head,0,sizeof(struct Stu));
head->addr=NULL;
return head;
}
2.添加信息
add.h
add.c
#include "add.h"
void Stu_Add(struct NODE *head)
{
int num=0;
printf("请输入学号\n");
scanf("%d",&num);
getchar();
struct NODE *tmp=head->addr;//因为头节点数据域不存放值,直接取指针域,取下一个节点
//判断学号是否存在
while(tmp!=NULL)
{
if(tmp->stu.id==num)//进行判断tmp的数据域中的id是否与输入的学号相等
{
printf("该学号已存在,无法添加\n");
return;
}
tmp=tmp->addr;//tmp指向下一个节点
}
//创建新的节点new
struct NODE *new=(struct NODE *)malloc(sizeof(struct NODE));
memset(new,0,sizeof(struct Stu));//数据域清零
new->addr=NULL;//指针域为空
//对节点new数据域赋值
new->stu.id=num;
printf("请输入学生姓名:\n");
scanf("%s",new->stu.name);
printf("请输入学生成绩:\n");
scanf("%f",&new->stu.score);
//令tmp等于头节点,对地址域进行判断
tmp = head;
while(tmp->addr!=NULL)
{
tmp=tmp->addr;//tmp的地址域指向下一个节点
}//此时tmp已经来到尾节点
tmp->addr=new;//把new的地址传到尾节点的地址域中
return;
}
3.打印学生信息
print.h
print.c
#include "print.h"
void Stu_Print(struct NODE *head)
{
struct NODE *tmp=head->addr;//定义新的tmp接收头节点的地址域
printf("姓名 学号 成绩\n");
while(tmp!=NULL)//如果tmp的地址域不为NUll,此时的tmp指向下一个节点
{
printf("%-6s%-6d%-6.1f\n",tmp->stu.name,tmp->stu.id,tmp->stu.score);
tmp=tmp->addr;//tmp指向下一个节点
}
return;
}
4.修改学生信息部分
change.h
change.c
#include "change.h"
void Stu_Change(struct NODE *head)
{
int num=0,flag=0;
struct NODE *tmp=head->addr;
struct NODE *tmp1=head->addr;
printf("请输入学号\n");
scanf("%d",&num);
getchar();
//用flag判断学号是否存在
while(tmp!=NULL)
{
if(tmp->stu.id==num)
{
flag=1;
}
tmp=tmp->addr;
}
if(flag==0)
{
printf("该学号不存在\n");
return;
}
else
{
//学号存在,重新赋值
while(tmp1!=NULL)
{
if(tmp1->stu.id==num)
{
printf("重新输入姓名:\n");
scanf("%s",tmp1->stu.name);
printf("重新输入成绩:\n");
scanf("%f",&tmp1->stu.score);
}
tmp1=tmp1->addr;
}
printf("修改完成\n");
}
return;
}
5.删除学生信息
del.h
del.c
#include "del.h"
void Stu_Del(struct NODE *head)
{
int num=0;
struct NODE *tmp=head;//tmp直接指向头节点
struct NODE *deltmp=NULL;//deltmp做临时变量,暂时存储要删除的节点地址,然后用free释放
printf("请输入要删除的学号:\n");
scanf("%d",&num);
getchar();
while(tmp->addr!=NULL)//当前节点的指针域不为空,从头节点开始
{
if(tmp->addr->stu.id==num)//下一个节点的数据域的id与num判断
{
deltmp=tmp->addr;//用临时的变量暂存,当前下一个节点的地址,注意分析
tmp->addr=tmp->addr->addr;//把当前节点的指针域赋值原先下一个节点的指针域的值
free(deltmp);//释放要删除的节点空间
printf("删除成功\n");
Stu_Print(head);//调用打印函数
return;
}
tmp=tmp->addr;
}
//如果运行到这,就说明没有条件满足while语句
printf("该学生不存在\n");
return;
}
//另一种写法
/*void Stu_Del(struct NODE *head)
{
int num=0;
struct NODE *tmp1=head->addr;
struct NODE *tmp=head;
printf("请输入要删除的学号:\n");
scanf("%d",&num);
getchar();
while(tmp1!=NULL)
{
if(tmp1->stu.id==num)
{
tmp->addr=tmp1->addr;
free(tmp1);
printf("删除成功\n");
Stu_Print(head);
return;
}
tmp=tmp->addr;
tmp1=tmp1->addr;
}
printf("该学生不存在\n");
return;
}*/
6.查找信息
find.h
find.c
#include "find.h"
void Stu_Find(struct NODE *head)
{
int num=0;//接收选择的模式
printf("请选择模式:\n");
printf("1.按姓名查找\n");
printf("2.按学号查找\n");
printf("0.返回主菜单\n");
scanf("%d",&num);
getchar();
switch(num)
{
case 1:Find_Name(head);break;
case 2:Find_Id(head);break;
case 0:return;
}
}
void Find_Name(struct NODE *head)//按姓名查找
{
int flag=0;
char buf[32]={0};//定义数组存放姓名
struct NODE *tmp=head->addr;
struct NODE *tmp1=head->addr;
printf("请输入学生的姓名:\n");
loop:
scanf("%s",buf);
getchar();
while(tmp!=NULL)
{
if(strcmp(buf,tmp->stu.name)==0)//strcmp进行字符串比较,若相同,返回值为0
{
flag=1;
}
tmp=tmp->addr;
}
printf("姓名 学号 成绩\n");
if(flag==1)
{
while(tmp1!=NULL)
{
if(strcmp(buf,tmp1->stu.name)==0)
{
printf("%-6s%-6d%-6.1f\n",tmp1->stu.name,tmp1->stu.id,tmp1->stu.score);
}
tmp1=tmp1->addr;
}
}
else if(flag==0)
{
printf("该学生不存在,请重新输入姓名:\n");
goto loop;
}
else
{
printf("输入错误\n");
return;
}
}
void Find_Id(struct NODE *head)//按学号查找
{
int a=0;//接受输入的学号
printf("请输入学生的学号:\n");
scanf("%d",&a);
getchar();
struct NODE *tmp=head->addr;
printf("姓名 学号 成绩\n");
while(tmp!=NULL)
{
if(tmp->stu.id==a)
{
printf("%-6s%-6d%-6.1f\n",tmp->stu.name,tmp->stu.id,tmp->stu.score);
return;//学号具有唯一性,打印完后可以直接从当前函数退出;
}
tmp=tmp->addr;
}
//如果可以执行到这行,说明上面的while语句没有符合条件,没有找到此学生;
printf("该学号不存在\n");
return;
}
7.插入学生信息
insert.h
insert.c
#include "insert.h"
void Stu_Insert(struct NODE *head)
{
int num1=0,num=0;
printf("请先输入要插入的学生学号:\n");
scanf("%d",&num1);
getchar();
struct NODE *tmp=head->addr;
//判断插入的学号是否存在
while(tmp!=NULL)
{
if(tmp->stu.id==num1)
{
printf("该学号已存在\n");
return;//如果存在,直接退出
}
tmp=tmp->addr;
}
//运行到此,说明学号不存在
printf("请输入要插入哪个学号后:\n");
scanf("%d",&num);
getchar();
tmp=head->addr;//tmp重新返回到头节点的指针域
while(tmp!=NULL)
{
if(tmp->stu.id==num)
{
struct NODE *new=(struct NODE *)malloc(sizeof(struct NODE));//开辟新的节点
memset(new,0,sizeof(struct Stu));//数据域清零
new->stu.id=num1;
printf("请输入插入学生的姓名:\n");
scanf("%s",new->stu.name);
printf("请输入插入学生的成绩:\n");
scanf("%f",&new->stu.score);
new->addr=tmp->addr;//新节点的指针域存放原先下一个节点的指针域的值
tmp->addr=new;//tmp的指针域则存放new的地址值
return;
}
tmp=tmp->addr;
}
printf("该学号不存在\n");
return;
}
8.进行排序
rank.h
rank.c
#include "rank.h"
void Stu_Rank(struct NODE *head)//利用改变数据域来交换顺序
{
int num=0;
printf("请输入排序方法序号:\n");
printf("1.按成绩排序\n");
printf("2.按学号排序\n");
scanf("%d",&num);
getchar();
struct NODE *tmp=head->addr;
struct NODE *tmp1=head->addr;
struct Stu a={0};//定义一个结构体变量暂存交换数据
//冒泡排序法进行排序
if(num==1)
{
for(tmp=head->addr;tmp->addr!=NULL;tmp=tmp->addr)
{
for(tmp1=head->addr;tmp1->addr!=NULL;tmp1=tmp1->addr)
{
if(tmp1->stu.score < tmp1->addr->stu.score)
{
a=tmp1->stu;
tmp1->stu=tmp1->addr->stu;
tmp1->addr->stu=a;
}
}
}
Stu_Print(head);
return;
}
else if(num==2)
{
for(tmp=head->addr;tmp->addr!=NULL;tmp=tmp->addr)
{
for(tmp1=head->addr;tmp1->addr!=NULL;tmp1=tmp1->addr)
{
if(tmp1->stu.id > tmp1->addr->stu.id)
{
a=tmp1->addr->stu;
tmp1->addr->stu=tmp1->stu;
tmp1->stu=a;
}
}
}
Stu_Print(head);
return;
}
else
{
printf("输入错误,返回主菜单\n");
return;
}
}
//另一种利用指针域,写法比较抽象
/*
void Stu_Rank(struct NODE *head)//利用改变指针域来交换顺序
{
int num=0;
printf("请输入排序方法序号:\n");
printf("1.按成绩排序\n");
printf("2.按学号排序\n");
scanf("%d",&num);
getchar();
struct NODE *tmp=head;
struct NODE *tmp1=tmp->addr;
struct NODE *tmp2=tmp1->addr;
int count=0;
while(tmp1!=NULL)
{
count++;
tmp1=tmp1->addr;
}
if(num==1)
{
if(count>1)
{
for(int i=1;i<count;i++)
{
tmp=head;
tmp1=head->addr;
tmp2=tmp1->addr;
for(int j=1;j<count;j++)
{
if(tmp1->stu.score < tmp2->stu.score)
{
tmp->addr=tmp2;
tmp1->addr=tmp2->addr;
tmp2->addr=tmp1;
}
tmp=head;
tmp1=head->addr;
tmp2=tmp1->addr;
for(int k=0;k<j;k++)
{
tmp=tmp->addr;
tmp1=tmp1->addr;
tmp2=tmp2->addr;
}
}
}
Stu_Print(head);
return;
}
}
else if(num==2)
{
if(count>1)
{
for(int i=1;i<count;i++)
{
tmp=head;
tmp1=head->addr;
tmp2=tmp1->addr;
for(int j=1;j<count;j++)
{
if(tmp1->stu.id > tmp2->stu.id)
{
tmp->addr=tmp2;
tmp1->addr=tmp2->addr;
tmp2->addr=tmp1;
}
tmp=head;
tmp1=head->addr;
tmp2=tmp1->addr;
for(int k=0;k<j;k++)
{
tmp=tmp->addr;
tmp1=tmp1->addr;
tmp2=tmp2->addr;
}
}
}
Stu_Print(head);
return;
}
}
else
{
printf("输入错误\n");
return;
}
return;
}
*/
仅按个人意愿所写,仅供参考!