要求使用单向链表完成学生信息管理系统,完成其增删改查的功能
0)链表所使用的结构体
//存放学生的信息
typedef struct
{
float score; //分数
char name[20]; //姓名
int id; //学号
}datatype;
//构成链表的结构体
typedef struct Node
{
union{
datatype data; //数据域
int len; //链表长度
};
struct Node* next; //指针域
}Student;
1)主函数使用菜单框架实现交互,并使用switch语句的嵌套实现功能条件的细化
功能的实现都依靠调用已封装的功能函数
#include<stdio.h>
#include<stdlib.h>
#include"./student.h"
#include<string.h>
int main(int argc, const char *argv[])
{
int num; //控制功能的变量
Student *S=create(); //新建链表的头节点
if(NULL==S)
{
return -1;
}
//菜单框架
while(1)
{
printf("--------------------------------------------\n");
printf("-------欢迎使用学生信息管理系统-------------\n");
printf("1、增入学生信息\n");
printf("2、输出所有的学生信息\n");
printf("3、删除学生信息\n");
printf("4、查找学生信息\n");
printf("5、修改学生信息\n");
printf("0、退出程序\n");
printf("请输入想要实现的功能编号:");
scanf("%d",&num);
switch(num)
{
case 1: //增
{
printf("开始输入信息(姓名处输入#表示信息输入完成)\n");
while(1)
{
//外部输入数据并尾插入表中
datatype val;
printf("请输入姓名>>");
scanf("%s",val.name);
if(strcmp(val.name,"#")==0) //判断信息是否输入完成
{
printf("信息输入完成\n");
break;
}
printf("请输入学号>>");
scanf("%d",&val.id);
printf("请输入分数>>");
scanf("%f",&val.score);
list_intsrt_tail(S,val);
}
} break;
case 2: list_show(S); break; //遍历链表元素
case 3:
{
int b; //存放要实现功能编号
printf("1、按学号删除\n");
printf("2、按姓名删除\n");
printf("3、按位置删除\n");
printf("请输入想要实现的功能编号>>");
scanf("%d",&b);
//使用switch语句实现对删除条件的变化
switch(b)
{
case 1: //以学号为条件来删除特定信息
{
int del_id;
printf("请输入想要删除的学号>>");
scanf("%d",&del_id);
list_delete_id(S,del_id);
}break;
case 2: //以姓名为条件来特定删除特定信息
{
char del_name[20];
printf("请输入想要删除的姓名>>");
scanf("%s",del_name);
list_delete_name(S,del_name);
}break;
case 3: //以位置为条件来删除特定信息
{
int pos;
printf("请输入想要删除的位置>>");
scanf("%d",&pos);
list_delete_pos(S,pos);
}
default : printf("输入的编号有误\n"); break;
}
}break;
case 4:
{
int a; //存放要实现功能编号
printf("1、按学号查找\n");
printf("2、按分数查找\n");
printf("3、按姓名查找\n");
printf("请输入想要实现的功能编号>>");
scanf("%d",&a);
//使用switch语句实现对查找条件的变化
switch(a)
{
case 1: //以学号为条件来特定查找特定信息
{
int find_id;
printf("请输入学号>>");
scanf("%d",&find_id);
list_search_value_id(S,find_id);
}break;
case 2: //以分数为条件来特定查找特定信息
{
float find_score;
printf("请输入分数>>");
scanf("%f",&find_score);
list_search_value_score(S,find_score);
}break;
case 3: //以姓名为条件来特定查找特定信息
{
char find_name[20];
printf("请输入姓名>>");
scanf("%s",find_name);
list_search_value_name(S,find_name);
}break;
default : printf("输入的编号有误\n"); break;
}
}break;
case 5:
{
int c; //存放要实现功能编号
printf("1、按学号修改\n");
printf("2、按位置修改\n");
printf("3、按姓名修改\n");
printf("请输入想要实现的功能编号>>");
scanf("%d",&c);
//使用switch语句实现对修改条件的变化
switch(c)
{
case 1: //以学号为条件来特定修改特定信息
{
int old_id;
printf("请输入原id>>");
scanf("%d",&old_id);
printf("请输入修改的值\n");
datatype new_e = info_add();
list_update_value_id(S,old_id,new_e);
}break;
case 2: //以位置为条件来特定修改特定信息
{
int pos;
printf("请输入想要修改的位置>>");
scanf("%d",&pos);
printf("请输入修改的值\n");
datatype new_e = info_add();
list_update_pos(S,pos,new_e);
}break;
case 3: //以姓名为条件来特定修改特定信息
{
char old_name[20];
printf("请输入原姓名>>");
scanf("%s",old_name);
printf("请输入修改的值\n");
datatype new_e = info_add();
list_update_name(S,old_name,new_e);
}break;
default : printf("输入的编号有误\n"); break;
}
}break;
case 0: //销毁表以及退出程序
{
list_delete_all(S);
S=NULL;
exit(0);
} break;
default : printf("输入的编号有误,请重新输入!\n"); break;
}
}
return 0;
}
2)主函数使用到的功能函数
1、嫁衣函数(主函数不会直接调用但其他功能函数会反复调用)——申请子结点、判空、数据的输入
//申请节点
Student * node_buy(datatype e)
{
Student *p = (Student *)malloc(sizeof(Student));
if(NULL == p)
{
printf("节点申请失败\n");
return NULL;
}
p->data = e;
p->next = NULL;
return p;
}
//判空
int list_empty(Student *S)
{
//1表示空 0表示非空
return NULL == S->next ? 1:0;
}
//信息输入
datatype info_add()
{
datatype val;
printf("请输入姓名>>");
scanf("%s",val.name);
printf("请输入学号>>");
scanf("%d",&val.id);
printf("请输入分数>>");
scanf("%f",&val.score);
return val;
}
2、创建头节点并初始化
//创建
Student * create()
{
//申请结点
Student *p=(Student *)malloc(sizeof(Student));
if(NULL==p)
{
printf("创建失败\n");
return NULL;
}
//初始化
p->len=0;
p->next=NULL;
printf("创建成功\n");
return p;
}
3、遍历链表元素
//遍历
void list_show(Student *S)
{
if(NULL==S || list_empty(S))
{
printf("表空,遍历失败\n");
return;
}
printf("链表元素分别是:\n");
Student *q = S->next;
while(q != NULL)
{
printf("%s\t%d\t%.2f\n",q->data.name,q->data.id,q->data.score);
q = q->next;
}
}
4、为了保证链表元素存储的顺序使用尾部插入的方式增加元素
//尾插
int list_intsrt_tail(Student *S,datatype e)
{
//判断逻辑
if(NULL==S)
{
printf("所给的链表不合法\n");
return -1;
}
//调用结点申请函数申请一个子结点
Student *p = node_buy(e);
//定义遍历指针定位到链表尾部
Student *q = S;
while(q->next != NULL)
{
q = q->next;
}
//尾插操作
q->next = p;
//表的变化
S->len++;
printf("信息已录入\n");
return 0;
}
5、根据不同的条件来定位结点的所在位置
//按位置查找返回查找到的节点
Student *find_node(Student *S, int pos)
{
if(NULL==S || pos<0 || pos>S->len)
{
printf("查找失败\n");
return NULL;
}
Student *q = S;
for(int i=1; i<=pos; i++)
{
q = q->next;
}
return q;
}
//按学号查找返回查找节点的前驱节点
Student *find_node_id(Student *S, int old_id)
{
if(NULL==S)
{
printf("查找失败\n");
return NULL;
}
Student *q = S;
while(q->next->data.id!=old_id)
{
if(q->next==NULL)
{
printf("查找失败\n");
return NULL;
}
q = q->next;
}
return q;
}
//按姓名查找返回查找节点的前驱节点
Student *find_node_name(Student *S, char old_name[])
{
if(NULL==S)
{
printf("查找失败\n");
return NULL;
}
Student *q = S;
while(strcmp(old_name,q->next->data.name))
{
if(q->next==NULL)
{
printf("查找失败\n");
return NULL;
}
q = q->next;
}
return q;
}
6、从头部删除节点
//头删
int list_delete_head(Student *S)
{
//判断逻辑
if(NULL==S || list_empty(S))
{
printf("删除失败\n");
return -1;
}
//头删
Student *p = S->next; //标记
S->next = p->next; //孤立
free(p); //踢开
p=NULL;
//表的变化
S->len--;
return 0;
}
7、根据条件调用5中不同的函数进行删除特定节点
//任意位置删
int list_delete_pos(Student *S,int pos)
{
//判断逻辑
if(NULL==S || list_empty(S))
{
printf("删除失败\n");
return -1;
}
Student *q=find_node(S,pos-1);
Student *p=q->next;
q->next = p->next;
free(p);
p=NULL;
S->len--;
printf("删除成功\n");
return 0;
}
//任意学号删
int list_delete_id(Student *S,int old_id)
{
Student *q=find_node_id(S,old_id);
//判断逻辑
if(NULL==S || list_empty(S) || q==NULL)
{
printf("删除失败\n");
return -1;
}
Student *p=q->next;
q->next = p->next;
free(p);
p=NULL;
S->len--;
printf("删除成功\n");
return 0;
}
//任意姓名删
int list_delete_name(Student *S,char old_name[])
{
Student *q=find_node_name(S,old_name);
//判断逻辑
if(NULL==S || list_empty(S) || q==NULL)
{
printf("删除失败\n");
return -1;
}
Student *p=q->next;
q->next = p->next;
free(p);
p=NULL;
S->len--;
printf("删除成功\n");
return 0;
}
8、根据不同的要求查找到特定的结点并输出其数据域中的数据
//按学号查找返回第一个查找成功的学生信息
int list_search_value_id(Student *S,int e)
{
//判断逻辑
if(NULL==S || list_empty(S))
{
printf("查找失败\n");
return -1;
}
//定义遍历指针
Student *q = S->next;
//查找符合给定条件学生信息
for(int i=1; i<=S->len; i++)
{
//判断是否符合条件
if(q->data.id==e)
{
printf("%s的成绩为%.2f学号为%d\n",q->data.name,q->data.score,q->data.id);
return i;
}
q=q->next;
}
printf("查找失败,未找到相对应的值\n");
return 0;
}
//按成绩查找返回第一个查找成功的学生信息
int list_search_value_score(Student *S,int e)
{
//判断逻辑
if(NULL==S || list_empty(S))
{
printf("查找失败\n");
return -1;
}
//定义遍历指针
Student *q = S->next;
//查找符合给定条件学生信息
for(int i=1; i<=S->len; i++)
{
//判断是否符合条件
if(q->data.score==e)
{
printf("%s的成绩为%.2f学号为%d\n",q->data.name,q->data.score,q->data.id);
return i;
}
q=q->next;
}
printf("查找失败,未找到相对应的值\n");
return 0;
}
//按姓名查找返回第一个查找成功的学生信息
int list_search_value_name(Student *S,char e[])
{
//判断逻辑
if(NULL==S || list_empty(S))
{
printf("查找失败\n");
return -1;
}
//定义遍历指针
Student *q = S->next;
for(int i=1; i<=S->len; i++)
{
//判断是否符合条件
if(strcmp(q->data.name,e)==0)
{
printf("%s的成绩为%.2f学号为%d\n",q->data.name,q->data.score,q->data.id);
return i;
}
q=q->next;
}
printf("查找失败,未找到相对应的值\n");
return 0;
}
9、根据不同的要求找到特定的结点并更新其数据域中的数据
//按位置修改
int list_update_pos(Student *S,int pos,datatype new_e)
{
//判断逻辑
if(NULL==S || list_empty(S))
{
printf("表不合法,修改失败\n");
return -1;
}
if(pos<1 || pos>S->len)
{
printf("表中未有该位置\n");
return -2;
}
//判断条件是否符合
Student *q=S;
for(int i=1; i<=pos; i++)
{
q=q->next;
}
//更新数据
q->data=new_e;
printf("修改成功\n");
return 0;
}
//按学号修改
int list_update_value_id(Student *S,int old_id,datatype new_e)
{
if(NULL==S || list_empty(S))
{
printf("表不合法,修改失败\n");
return -1;
}
Student *q=S->next;
while(q!=NULL)
{
if(q->data.id==old_id)
{
q->data=new_e;
return 0;
}
q=q->next;
}
printf("未找到符合的值\n");
return -2;
}
//按姓名修改
int list_update_name(Student *S,char old_name[],datatype new_e)
{
if(NULL==S || list_empty(S))
{
printf("表不合法,修改失败\n");
return -1;
}
Student *q=S->next;
while(q!=NULL)
{
if(strcmp(old_name,q->data.name)==0)
{
q->data=new_e;
return 0;
}
q=q->next;
}
printf("未找到符合的值\n");
return -2;
}
10、销毁表(防止内存的占用)
//销毁表
void list_delete_all(Student *S)
{
if(NULL==S)
{
return;
}
//不断调用头删,将节点进行删除
while(S->next != NULL)
{
list_delete_head(S);
}
//将头节点释放
free(S);
S=NULL;
printf("表销毁成功\n");
return;
}
3)程序运行结果(部分)
创建成功
--------------------------------------------
-------欢迎使用学生信息管理系统-------------
1、增入学生信息
2、输出所有的学生信息
3、删除学生信息
4、查找学生信息
5、修改学生信息
0、退出程序
请输入想要实现的功能编号:1
开始输入信息(姓名处输入#表示信息输入完成)
请输入姓名>>aa
请输入学号>>2001
请输入分数>>86
信息已录入
请输入姓名>>bb
请输入学号>>2002
请输入分数>>88
信息已录入
请输入姓名>>cc
请输入学号>>2003
请输入分数>>89
信息已录入
请输入姓名>>dd
请输入学号>>87
请输入分数>>91
信息已录入
请输入姓名>>#
信息输入完成
--------------------------------------------
-------欢迎使用学生信息管理系统-------------
1、增入学生信息
2、输出所有的学生信息
3、删除学生信息
4、查找学生信息
5、修改学生信息
0、退出程序
请输入想要实现的功能编号:2
链表元素分别是:
aa 2001 86.00
bb 2002 88.00
cc 2003 89.00
dd 87 91.00
--------------------------------------------
-------欢迎使用学生信息管理系统-------------
1、增入学生信息
2、输出所有的学生信息
3、删除学生信息
4、查找学生信息
5、修改学生信息
0、退出程序
请输入想要实现的功能编号:3
1、按学号删除
2、按姓名删除
3、按位置删除
请输入想要实现的功能编号>>1
请输入想要删除的学号>>87
删除成功
--------------------------------------------
-------欢迎使用学生信息管理系统-------------
1、增入学生信息
2、输出所有的学生信息
3、删除学生信息
4、查找学生信息
5、修改学生信息
0、退出程序
请输入想要实现的功能编号:2
链表元素分别是:
aa 2001 86.00
bb 2002 88.00
cc 2003 89.00
--------------------------------------------
-------欢迎使用学生信息管理系统-------------
1、增入学生信息
2、输出所有的学生信息
3、删除学生信息
4、查找学生信息
5、修改学生信息
0、退出程序
请输入想要实现的功能编号:4
1、按学号查找
2、按分数查找
3、按姓名查找
请输入想要实现的功能编号>>2
请输入分数>>86
aa的成绩为86.00学号为2001
--------------------------------------------
-------欢迎使用学生信息管理系统-------------
1、增入学生信息
2、输出所有的学生信息
3、删除学生信息
4、查找学生信息
5、修改学生信息
0、退出程序
请输入想要实现的功能编号:5
1、按学号修改
2、按位置修改
3、按姓名修改
请输入想要实现的功能编号>>3
请输入原姓名>>cc
请输入修改的值
请输入姓名>>ff
请输入学号>>2003
请输入分数>>92
--------------------------------------------
-------欢迎使用学生信息管理系统-------------
1、增入学生信息
2、输出所有的学生信息
3、删除学生信息
4、查找学生信息
5、修改学生信息
0、退出程序
请输入想要实现的功能编号:2
链表元素分别是:
aa 2001 86.00
bb 2002 88.00
ff 2003 92.00
--------------------------------------------
-------欢迎使用学生信息管理系统-------------
1、增入学生信息
2、输出所有的学生信息
3、删除学生信息
4、查找学生信息
5、修改学生信息
0、退出程序
请输入想要实现的功能编号:0
表销毁成功