学生系统单链表版

本文详细介绍了如何利用链表结构和模块化编程思想设计一个学生管理系统,包括主函数、菜单操作(添加、删除、修改、查找、排序和插入),以及对应的函数实现。
摘要由CSDN通过智能技术生成

利用链表,以及模块化编程对学生管理系统进行编写:

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;
}
*/

仅按个人意愿所写,仅供参考!

  • 9
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值