【数据结构应用】航空客运订票系统

目录

前言

一、作业要求介绍

二、各个函数的实现

1.头文件总结需要的功能

(1)结构体的定义 

(2)各个功能的函数 

2.各个函数的具体实现

(1)初始化

(2)打印航班信息表

(4)查找航班信息

(5)订票系统

(6)退票信息

(7)保存本地文件

(8)七七八八的菜单

三.程序的运行

总结


 

 


前言

        本题的来源是数据结构期末作业。把作业写成博客是为了重新梳理一遍思路,也是向组员解释一下各个函数的功能。


 

一、作业要求介绍

        总结一下 基本上就是以下几点

(1) 手动添加航线信息

(2)通过终点站名搜索航线

(3)输入航班号 可以订票,如果航班人没满 则将其放入乘客席中,如果这个航班人满了                  要有候补席

(4)可以通过航班号和名字退票  并将候补席中第一个合适的人选 放入购票席中

(5)最后将文件保存本地 下次使用也要保存信息

 

eb05b407c0ba49bd994308550432d8b7.png

 

 

二、各个函数的实现

1.头文件总结需要的功能

(1)结构体的定义 

① 舱位

ps:

这里舱位级别是用枚举常量定义的 

主要目的就是为了防止方便看代码 

候补席的人 舱位统一为 No 

//舱位级别
enum Class_Of_Travel
{
	No,//没买呢
	One,//一等
	Two,//二等
	Three//三等
};//舱位级别

② 乘客个人信息

 

//乘客个人信息
typedef struct Pasger
{
	char Name[20];//姓名
	int Amount;//购票量
	enum Class_Of_Travel Class;//舱位等级
}Pasger_Type;//乘客个人信息

③ 乘客席信息

为了方便乘客退票时的信息删除 这里用链式存储 

//乘客席信息
typedef struct SList_For_Bought
{
	Pasger_Type data;
	SList_For_Bought* next;
}Bought_Type;//乘客席信息

④ 候补席信息

因为这里并不是完全的先进先出 所以是没必要用队列的

但我一开始用的是队列  后面就没有改了

//候补席信息
typedef struct Queue_For_WantBuy
{
	Pasger_Type* data;
	int front;
	int rear;
}WantBuy_Type;//候补席信息

⑤ 航线信息

//航线信息
typedef struct Route_Info
{
	char Terminal[20];//终点站
	char Route_Name[20];//航班号
	char Plane_Name[20];//飞机号
	char Fly_Week[20];//周几飞
	int bought_number;//购票人数
	int Pasger_Max;//最大客容量
	int Surplus;//剩余票量
	Bought_Type* Bought;//已购票
	WantBuy_Type* WantBuy;//替补购票
}Route_Info_Type;//航线信息

⑥ 航班表

//航班表
typedef struct SeqList_For_Route
{
	Route_Info_Type* Route;
	int size;
	int capacity;
}Routes_List_Type;//航班表

(2)各个功能的函数 

//初始化航班表
void PS_Init(Routes_List_Type* RL);

//查看所有航班信息
void PS_Print(Routes_List_Type* RL);

//增加航班信息
void PS_Push(Routes_List_Type* RL);

//查找航班信息
void PS_Search(Routes_List_Type* RL);

//订票功能
void PS_BuyTicket(Routes_List_Type* RL);

//退票功能
void PS_ReturnTicket(Routes_List_Type* RL);


//保存航班表
void PS_Save(Routes_List_Type* RL);

2.各个函数的具体实现

(1)初始化

初始化分为两部分

一部分负责初始化航班信息的顺序表

//初始化(1)
void PS_Init(Routes_List_Type* RL)
{
	RL->Route = (Route_Info_Type*)malloc(sizeof(Route_Info_Type) * PS_MAX);
	if (RL->Route == NULL)
	{
		printf("PS_Init malloc");
		exit(-1);
	}	
	RL->size = 0;
	RL->capacity = PS_MAX;
}

一部分负责导入本地文件

这部分的顺序和Save的储存顺序一样就行了

需要注意的是 不能只存 RL航空信息顺序表

还需要特别注意 乘客席的链表候补席的队列 也需要独立的代码去存储

//初始化(2)
void PS_Init(Routes_List_Type* RL)
{
	//导入本地文件信息
	FILE* pf = fopen("Plane_System.dat", "rb");
	if (pf == NULL)
	{
		return;
	}
	Route_Info_Type* tmp = (Route_Info_Type*)malloc(sizeof(Route_Info_Type));
	while (fread(tmp, sizeof(Route_Info_Type), 1, pf))
	{
		int bought = tmp->Pasger_Max - tmp->Surplus;//购票人数
		tmp->Bought = (Bought_Type*)malloc(sizeof(Bought_Type));
		Bought_Type* tmp1 = tmp->Bought;
		for (int i = 0; i < tmp->bought_number; i++)
		{
			fread(tmp1, sizeof(Bought_Type), 1, pf);
			tmp1->next = (Bought_Type*)malloc(sizeof(Bought_Type));
			if (i != tmp->bought_number - 1)
				tmp1 = tmp1->next;
			else
				tmp1->next = NULL;
		}
		tmp->WantBuy = (WantBuy_Type*)malloc(sizeof(WantBuy_Type));
		fread(&tmp->WantBuy->front, sizeof(int), 1, pf);
		fread(&tmp->WantBuy->rear, sizeof(int), 1, pf);
		tmp->WantBuy->data = (Pasger_Type*)malloc(sizeof(Pasger_Type) * 100);
		fread(tmp->WantBuy->data, sizeof(Pasger_Type), tmp->WantBuy->rear, pf);
		PS_Check(RL);
		RL->Route[RL->size] = *tmp;
		RL->size++;
	}
	fclose(pf);
	pf = NULL;
}

(2)打印航班信息表

这个不重要

//显示所有航班信息
void PS_Print(Routes_List_Type* RL)
{
	system("cls");
	printf("航班信息总表如下:\n\n");
	for (int i = 0; i < RL->size; i++)
	{
		printf("终点站为: %s\n", RL->Route[i].Terminal);
		printf("航班号为: %s\n", RL->Route[i].Route_Name);
		printf("飞机号为: %s\n", RL->Route[i].Plane_Name);
		printf("飞行时间: %s\n", RL->Route[i].Fly_Week);
		printf("剩余票量: %d\n", RL->Route[i].Surplus);
		printf("候补人数: %d\n", RL->Route[i].WantBuy->rear- RL->Route[i].WantBuy->front);
		printf("\n");
	}
	system("pause");
}

(3)增加航班信息

就是链表 队列的综合运用 就是看起来比较长

void PS_Push(Routes_List_Type* RL)//加入航班信息
{
	system("cls");
	PS_Check(RL);
	//终点站
	printf("请输入终点站:\n");
	scanf("%s",RL->Route[RL->size].Terminal);
	//航班号
	printf("请输入航班号:\n");
	scanf("%s",RL->Route[RL->size].Route_Name);
	//飞机号
	printf("请输入飞机号:\n");
	scanf("%s",RL->Route[RL->size].Plane_Name);
	//周几起飞
	printf("请输入周几起飞:\n");
	scanf("%s",RL->Route[RL->size].Fly_Week);
	//最大客容量
	printf("请输入最大客容量:\n");
	scanf("%d",&RL->Route[RL->size].Pasger_Max);
	printf("请输入有现有几人购票:\n");
	scanf("%d", &RL->Route[RL->size].bought_number);
	RL->Route[RL->size].Bought = (Bought_Type*)malloc(sizeof(Bought_Type));
	int sold = 0;//已售出的数量
	int flag = 0;//判断是否只有一个人买票
	if (RL->Route[RL->size].bought_number)
	{
		printf("请输入第1名乘客买几张票 共有%d人\n", RL->Route[RL->size].bought_number);
		scanf("%d", &RL->Route[RL->size].Bought->data.Amount);
		sold += RL->Route[RL->size].Bought->data.Amount;
		printf("请输入第1名乘客舱位级别(1,2,3)\n");
		scanf("%d", &RL->Route[RL->size].Bought->data.Class);
		printf("请输入第1名乘客叫什么\n");
		scanf("%s", RL->Route[RL->size].Bought->data.Name);
		RL->Route[RL->size].Bought->next = (Bought_Type*)malloc(sizeof(Bought_Type));
		Bought_Type* cur = RL->Route[RL->size].Bought->next;
		for (int i = 0; i < RL->Route[RL->size].bought_number - 1; i++)
		{
			printf("请输入第%d名乘客买几张票  共有%d人\n", i + 2, RL->Route[RL->size].bought_number);
			scanf("%d", &(cur->data.Amount));
			sold += cur->data.Amount;
			printf("请输入第%d名乘客舱位级别(1,2,3)\n", i + 2);
			scanf("%d", &(cur->data.Class));
			printf("请输入第%d名乘客叫什么\n", i + 2);
			scanf("%s", cur->data.Name);
			if (i != RL->Route[RL->size].bought_number - 2)//从第一次到倒数第二次循环
			{
				cur->next = (Bought_Type*)malloc(sizeof(Bought_Type));
				cur = cur->next;
			}
			if (i == RL->Route[RL->size].bought_number - 2)
			{
				cur->next = NULL;
				flag = 1;
			}
		}
		if (flag == 0)
			RL->Route[RL->size].Bought->next = NULL;
	}
	else
		printf("无人购票\n");
	RL->Route[RL->size].Surplus = RL->Route[RL->size].Pasger_Max - sold;
	RL->Route[RL->size].WantBuy = (WantBuy_Type*)malloc(sizeof(WantBuy_Type));
	RL->Route[RL->size].WantBuy->data = (Pasger_Type*)malloc(sizeof(Pasger_Type) * 100);
	RL->Route[RL->size].WantBuy->rear = 0;
	RL->Route[RL->size].WantBuy->front = 0;
	if (RL->Route[RL->size].Surplus < 0)
	{
		printf("售票过多 系统崩溃");
		exit(-1);
	}
	else if (RL->Route[RL->size].Surplus == 0)
	{
		printf("请输入有多少替补人员:\n");
		int WB = 0;
		scanf("%d", &WB);
		for (int i = 0; i < WB; i++)
		{
			printf("请输入第%d名替补人员的购票数量 共有%d名替补人员\n", i + 1, WB);
			scanf("%d", &RL->Route[RL->size].WantBuy->data[RL->Route[RL->size].WantBuy->rear].Amount);
			printf("请输入第%d名替补人员的名字 \n", i + 1);
			scanf("%s", RL->Route[RL->size].WantBuy->data[RL->Route[RL->size].WantBuy->rear].Name);
			RL->Route[RL->size].WantBuy->data[RL->Route[RL->size].WantBuy->rear].Class = No;
			RL->Route[RL->size].WantBuy->rear++;
		}
	}
	RL->size++;
	PS_Save(RL);
	system("pause");
}

(4)查找航班信息

 

//查找航班信息
void PS_Search(Routes_List_Type* RL)
{
	system("cls");
	char TmpName[20];
	printf("请输入终点站:");
	scanf("%s", TmpName);
	int i = 0;
	for (i = 0; i < RL->size; i++)
	{
		if (strcmp(RL->Route[i].Terminal, TmpName) == 0)
		{
			printf("\n");
			printf("航班号为 %s\n", RL->Route[i].Route_Name);
			printf("飞机号为 %s\n", RL->Route[i].Plane_Name);
			printf("飞行日为 %s\n", RL->Route[i].Fly_Week);
			printf("余票量为 %d\n", RL->Route[i].Surplus);
			break;
		}
	}
	if (i == RL->size)
		printf("没找到该航班\n");
	printf("\n");
	system("pause");
}

 

(5)订票系统

购票成功的直接进乘客席

不成功的询问是否进候补席

Y:进队列

N:返回菜单无事发生

//订票功能
void PS_BuyTicket(Routes_List_Type* RL)
{
	system("cls");
	printf("请输入 航班号 和 订票量:\n");
	char Route_Name[20];
	int Amount = 0;
	scanf("%s", Route_Name);
	scanf("%d", &Amount);
	int i = 0;
	for (i = 0; i < RL->size; i++)
	{
		if (strcmp(RL->Route[i].Route_Name, Route_Name) == 0)
		{
			if (RL->Route[i].Surplus >= Amount)
			{
				if (RL->Route->Bought == NULL)
				{
					RL->Route[i].Bought = (Bought_Type*)malloc(sizeof(Bought_Type));
					RL->Route[i].Bought->data.Amount = Amount;
					printf("请输入乘客舱位级别(1,2,3)\n");
					scanf("%d", &RL->Route[i].Bought->data.Class);
					printf("请输入乘客叫什么\n");
					scanf("%s", RL->Route[i].Bought->data.Name);
					RL->Route[i].Surplus -= Amount;
					RL->Route[i].bought_number++;
					RL->Route[i].Bought->next = NULL;
					PS_Save(RL);
					printf("购票成功!\n");
					break;
				}
				Bought_Type* tmp = RL->Route[i].Bought;
				while (tmp->next)
				{
					tmp = tmp->next;
				}
				tmp->next = (Bought_Type*)malloc(sizeof(Bought_Type));
				tmp = tmp->next;
				tmp->data.Amount = Amount;
				printf("请输入乘客舱位级别(1,2,3)\n");
				scanf("%d", &tmp->data.Class);
				printf("请输入乘客叫什么\n");
				scanf("%s", tmp->data.Name);
				RL->Route[i].Surplus -= Amount;
				RL->Route[i].bought_number++;
				tmp->next = NULL;
				PS_Save(RL);
				printf("购票成功!\n");
				break;
			}
			else
			{
				printf("您要搭乘的航班没有足够的票 您是否需要登记候补?(Y or N)\n");
				char YorN = 0;
				while (getchar() != '\n');
				scanf("%c", &YorN);
				if (YorN == 'Y')
				{
					RL->Route[i].WantBuy->data[RL->Route[i].WantBuy->rear].Amount = Amount;
					RL->Route[i].WantBuy->data[RL->Route[i].WantBuy->rear].Class = No;
					printf("请输入乘客叫什么\n");
					scanf("%s", &RL->Route[i].WantBuy->data[RL->Route[i].WantBuy->rear].Name);
					RL->Route[i].WantBuy->rear++;
					PS_Save(RL);
					printf("登记候补成功\n");
					break;
				}
				else if (YorN == 'N')
				{
					printf("感谢您的支持 祝您生活愉快\n");
					break;
				}
				else
				{
					printf("您并没有回答‘Y’or'N' 默认您不需要登记候补\n");
					break;
				}
			}
		}
	}
	if (i == RL->size)
		printf("没找到该航班\n");
	system("pause");
}

 

(6)退票信息

退票分为两种情况

1.候补席没有人或者没有合适的人

 

退票后直接从乘客席中将人拿下

 

2.候补席有人

 

退票后先从乘客席中将人拿下

再把候补席中的第一个合适人选 放入乘客席中

 

ps:

由于每个乘客都不一定买了几张机票

所以如果只买了一张机票的乘客退票了 而候补席的第一个人需要买两张票

所以候补席的第一个人虽然是先进的候补席 但不一定就能第一个出候补席

 

因此先进队列的人并不一定是先出来的人

所以! 这道题不用队列也挺好的 但我懒得改了

我把所有离开了候补席的乘客 信息都改成了”我需要9999张机票“

并且每次候补席出去人了 我就把front改成0

它也许不再是队列了 但挺好玩的

//退票功能
void PS_ReturnTicket(Routes_List_Type* RL)
{
	system("cls");
	printf("输入航班号 和 自己的姓名:\n");
	char RouteName[20];
	char PasgerName[20];
	scanf("%s",RouteName);
	scanf("%s",PasgerName);
	int i = 0; 
	for (i = 0; i < RL->size; i++)
	{
		if (strcmp(RL->Route[i].Route_Name, RouteName) == 0)
		{
			if (strcmp(RL->Route[i].Bought->data.Name, PasgerName) == 0)
			{
				RL->Route[i].bought_number--;
				RL->Route[i].Surplus += RL->Route[i].Bought->data.Amount;
				RL->Route[i].Bought = RL->Route[i].Bought->next;
				WantBuytoBuy(RL,i);
				PS_Save(RL);
				printf("%s 退票成功\n", PasgerName);
				break;
			}
			Bought_Type* cur = RL->Route[i].Bought;
			Bought_Type* tmp = cur;
			while (strcmp(cur->data.Name,PasgerName) != 0 && cur->next != NULL)
			{
				tmp = cur;
				cur = cur->next;
			}
			if (strcmp(cur->data.Name, PasgerName) == 0)
			{
				tmp->next = cur->next;
				RL->Route[i].bought_number--;
				RL->Route[i].Surplus += cur->data.Amount;
				WantBuytoBuy(RL,i);
				PS_Save(RL);
				printf("%s 退票成功\n", PasgerName);
				break;
			}
			else if (cur->next == NULL)
			{
				printf("没有这个人\n");
			}
		}
	}
	if (i == RL->size)
		printf("没有这个航班\n");
	system("pause");
}

//候补人员买票
void WantBuytoBuy(Routes_List_Type* RL,int n)
{
	while (RL->Route[n].WantBuy->front != RL->Route[n].WantBuy->rear)
	{
		
		if (RL->Route[n].WantBuy->data[RL->Route[n].WantBuy->front].Amount <= RL->Route[n].Surplus)
		{
			Bought_Type* cur = RL->Route[n].Bought;
			while (cur->next)
			{
				cur = cur->next;
			}
			cur->next = (Bought_Type*)malloc(sizeof(Bought_Type));
			cur = cur->next;
			printf("请候补人员%s 输入需要的乘客舱位级别(1,2,3)\n", RL->Route[n].WantBuy->data[RL->Route[n].WantBuy->front].Name);
			scanf("%d", &RL->Route[n].WantBuy->data[RL->Route[n].WantBuy->front].Class);
			cur->data = RL->Route[n].WantBuy->data[RL->Route[n].WantBuy->front];
			cur->next = NULL;
			RL->Route[n].bought_number++;
			RL->Route[n].Surplus -= RL->Route[n].WantBuy->data[RL->Route[n].WantBuy->front].Amount;
			RL->Route[n].WantBuy->data[RL->Route[n].WantBuy->front].Amount = 9999;
			RL->Route[n].WantBuy->front = 0;
			printf("候补人员%s 成功购票%d 张\n\n", cur->data.Name, cur->data.Amount);
		}
		RL->Route[n].WantBuy->front++;
	}

}

 

(7)保存本地文件

这里的顺序和上面的读取顺序呼应了 都是wr,wb的二进制读写

//保存航班表
void PS_Save(Routes_List_Type* RL)
{
	FILE* pf = fopen("Plane_System.dat", "wb");
	if (pf == NULL)
		return;
	for (int i = 0; i < RL->size; i++)
	{
		fwrite(RL->Route + i, sizeof(Route_Info_Type), 1, pf);
		Bought_Type* tmp0 = RL->Route[i].Bought;
		while (tmp0)
		{
			fwrite(tmp0, sizeof(Bought_Type), 1, pf);
			tmp0 = tmp0->next;
		}
		fwrite(&RL->Route[i].WantBuy->front, sizeof(int), 1, pf);
		fwrite(&RL->Route[i].WantBuy->rear, sizeof(int), 1, pf);
		fwrite(RL->Route[i].WantBuy->data, sizeof(Pasger_Type), RL->Route[i].WantBuy->rear, pf);
	}
	fclose(pf);
	pf = NULL;
}

(8)七七八八的菜单

啥营养 就很菜单的菜单

void menu_Son()
{
	printf("\t\t\t*************************************************\n");
	printf("\t\t\t**********     航空客运订票系统       ***********\n");
	printf("\t\t\t*************************************************\n");
	printf("\t\t\t*************************************************\n");
	printf("\t\t\t**********     1.显示所有航班信息     ***********\n");
	printf("\t\t\t**********     2.增加航班信息         ***********\n");
	printf("\t\t\t**********     3.查找航班信息         ***********\n");
	printf("\t\t\t**********     4.订票                 ***********\n");
	printf("\t\t\t**********     5.退票                 ***********\n");
	printf("\t\t\t**********     0.退出系统             ***********\n");
	printf("\t\t\t*************************************************\n");
	printf("\t\t\t*************************************************\n");
	printf("\t\t\t*************************************************\n");
	printf("\t\t\t*************************************************\n");
	printf("\t\t\t\t请输入:");
}
void menu()
{
	int a = 0;
	Routes_List_Type* Routes_List = (Routes_List_Type*)malloc(sizeof(Routes_List_Type));//航班表
	PS_Init(Routes_List);
	do {
		system("cls");
		menu_Son();
		scanf("%d", &a);
		switch (a)
		{
		case 1:
			PS_Print(Routes_List);
			break;
		case 2:
			PS_Push(Routes_List);
			break;
		case 3:
			PS_Search(Routes_List);
			break;
		case 4:
			PS_BuyTicket(Routes_List);
			break;
		case 5:
			PS_ReturnTicket(Routes_List);
			break;
		case 0:
			break;
		default:
			printf("没有该选项 请重新选择\n");
			break;
		}
	} while (a);
}

 

三.程序的运行

0a031f3576814b2b9c6274322c041085.png7a53756d6bd64fb0a93370ec24f3b667.png


 

 

总结

 

 

 

 

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

震惊铁豪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值