Advertisement

c语言机票座位预定系统_C语言实现飞机订票系统

阅读量:

问题描述与题目要求

问题描述: 假设某机场运营M个航班线路(即M个航次),每个航班仅停靠特定的一个地点。请为该机场售票中心规划一个自动化购票及退票系统,并要求该系统具备以下功能:

购票:当某航班剩余座位数量不小于预订乘客人数时,在该航班的乘客记录中添加预订信息并更新相关数据记录;若无法完成购票,则显示相应的提示信息。

(2)退票:若当前针对此航班的已退票数量不超过旅客预订的座位数量,则系统需在对应的数据表中查找对应旅客记录并进行相应更新;当某个旅客因退票导致其座位数量归零时,则应从相关数据表中删除其记录。

要求:

(1)描述对航次表和乘客表选用的数据结构。

(2)编程实现飞机票订票和退票系统。

模型假设

1.假设所有输入均为整数且在int类型的表示范围内

2.假设航次是从1到n的连续整数

3.假设每个乘客 ID 均唯一

数据结构的选用

联想到图中的邻接链表,采用相似的数据结构描述该问题

航次表:将一个数组flight_info_list用于存储各航次的乘客数据,在此数组中下标直接对应航班号的位置上存放着该航班的相关信息(包括乘客列表、航班号以及剩余票数)

passengers information table: the passenger_info_list is stored using a doubly linked list structure, with each node containing the passenger ID field, the number of orders, and fields pointing to the previous and next nodes.

编程实现(C语言实现)

/*

  • @Description: 模拟航班的订票系统

  • 模型假设:

    1. 飞机最大载客量为300人
    1. 共10个航次
  • 用双向链表存储乘客信息

  • 用array存储航班信息

  • @Author: Fishermanykx

  • @Date: 2019-09-29 10:32:56

  • @LastEditors: Fishermanykx

  • @LastEditTime: 2019-09-30 12:29:16

*/

#include

#include

#include

#define MAX_CAPACITY 300 // 假定飞机最大载客量为300

#define TOTAL_AIRLINE 10 // 假定不同航线最大数目为10

#define BOOK_TICKET 1

#define REFUND -1

#define EXIT_SYSTEM 0

#define PRINT_INFO 11

#define ROOT 123456

// 某航次航班

struct SingleFlight {

int flight_id; // 航班编号,从1开始,到TOTAL_AIRLINE为止

int remain_tickets; // 该航班余票数

struct SinglePassenger* passenger_info_list; // 该航班乘客表

};

// 某航次航班的某个乘客的信息

struct PassengerInfo {

int passenger_id; // 乘客id

int ticket_number; // 该乘客购买票数

};

// 乘客表中的一个结点

struct SinglePassenger {

struct PassengerInfo passenger_info; // 乘客信息

struct SinglePassenger* prev_passenger; // 指向前一个乘客的指针

struct SinglePassenger* next_passenger; // 指向后一个乘客的指针

};

typedef struct SingleFlight SingleFlight;

typedef struct SinglePassenger SinglePassenger;

// 订票操作

SingleFlight* BookTicket(SingleFlight flight_info_list[]);

SinglePassenger* GetNewPassenger(const int new_passenger_id,

const int book_ticket_number);

SinglePassenger* AddNewPassenger(SinglePassenger* head,

const int new_passenger_id,

const int book_ticket_number);

// 退票操作

SingleFlight* Refund(SingleFlight flight_info_list[]);

SinglePassenger* RemovePassenger(SinglePassenger* front, integer passengerId)

// 判断操作

bool IsPassengerExist(SinglePassenger* head, const int passenger_id);

// 打印操作

void PrintCurrentAirlineInfo(SingleFlight flight_info_list[]);

无返回类型的PrintPassengerList函数接收两个参数:单乘客指针head和单航班指针flight_info_list。

int airline_id);

int main(void) {

int order, exit_loop = 1;

// 初始化航班信息

SingleFlight* flight_info_list;

flight_info_list =

(SingleFlight*)malloc(TOTAL_AIRLINE * sizeof(SingleFlight));

for (int i = 0; i < TOTAL_AIRLINE; ++i) {

flight_info_list[i].flight_id = i + 1;

flight_info_list[i].remain_tickets = MAX_CAPACITY;

flight_info_list[i].passenger_info_list = NULL;

}

/* 登录界面 */

printf("您好,欢迎使用此系统!\n\n");

printf("使用说明:\n");

printf("1. 本程序所有输入均为整数\n");

printf("2. 可供选择的航次编号为1-%d, 每架次最大载客量为%d\n", TOTAL_AIRLINE,

MAX_CAPACITY);

printf(

"3. 若订票,请输入1;若退票,请输入-1;若退出系统,请输入0; "

"若要以root用户登录,请输入root密码\n");

printf("使用说明到此结束,祝您使用愉快!\n");

// 判断是否以root登录

int log_in_as_root, root_key;

bool is_root = false;

printf("-------------------------------------------------------------\n\n");

printf("是否以root用户登录?若是,请输入1,否则请输入0:");

scanf("%d", &log_in_as_root);

if (log_in_as_root) printf("请输入root密码(按0退出root登录程序):");

while (log_in_as_root) {

scanf("%d", &root_key);

if (!root_key) {

break;

} else if (root_key != ROOT) {

printf("输入密码错误!请重新输入或按0退出root登录程序:");

} else {

is_root = true;

break;

}

}

// 欢迎界面

if (is_root)

printf("欢迎,root用户!输入11可查看当前航次表\n");

else

printf("欢迎,普通用户!\n");

printf("-------------------------------------------------------------\n");

// 主循环

while (true) {

if (is_root)

printf("请输入1, 0, -1或11中的一个数字: ");

else

printf("请输入1, 0, -1中的一个数字: ");

scanf("%d", &order);

switch (order) {

case BOOK_TICKET:

flight_info_list = BookTicket(flight_info_list);

break;

case REFUND:

flight_info_list = Refund(flight_info_list);

break;

case EXIT_SYSTEM:

exit_loop = 0;

break;

case PRINT_INFO:

printf(

"-------------------------------------------------------------\n");

PrintCurrentAirlineInfo(flight_info_list);

break;

default:

printf("非法输入!\n");

break;

}

if (!exit_loop) break;

}

return 0;

}

/**

  • @description: 一次订票操作的模拟

  • @param {type}

  • flight_info_list {SingleFlight *}: 航班信息表(航次表)

  • @return:

*/

SingleFlight* BookTicket(SingleFlight flight_info_list[]) {

/* 获取乘客预定航次 */

int target_airline;

printf("可供选择的航次对应的编号为: 1 - %d\n", TOTAL_AIRLINE);

printf("请输入您想预定的航次(输入0时退出订票程序): ");

// 判断输入合法性

while (true) {

scanf("%d", &target_airline);

if (target_airline < 0 || target_airline > TOTAL_AIRLINE) {

printf("您要预定的航次不存在!\n");

printf("请重新输入一个正确的航次,或按0退出订票程序:");

} else if (target_airline == 0) {

printf("-------------------------------------------------------------\n");

return flight_info_list;

} else

break;

}

/* 获取乘客id */

int passenger_id;

int modify_tickets;

printf("若您原先已经订票,且想增加您的订票数,请输入1,否则请输入0: ");

// 判断输入合法性

while (true) {

scanf("%d", &modify_tickets);

if (modify_tickets != 1 && modify_tickets != 0) {

printf("您输入的是非法命令,请重新输入0(原先未订票)或1(原先已经订票):");

} else

break;

}

printf("请输入您的ID: ");

// 若原先未订票

while (!modify_tickets) {

scanf("%d", &passenger_id);

if (IsPassengerExist(

flight_info_list[target_airline - 1].passenger_info_list,

passenger_id)) {

printf("该ID已存在,请输入一个新的ID: ");

} else

break;

}

// 若原先已经订票

if (modify_tickets) {

scanf("%d", &passenger_id);

if (!IsPassengerExist(

flight_info_list[target_airline - 1].passenger_info_list,

passenger_id)) {

printf("您原先并未预订该航次的票!\n");

printf("-------------------------------------------------------------\n");

return flight_info_list;

}

}

/* 获取乘客预定票数 */

// 获取当前航次余票数

int remain_tickets;

remain_tickets = flight_info_list[target_airline - 1].remain_tickets;

printf("当前航次余票数为: %d\n", remain_tickets);

// 若该乘客想修改票数,显示此乘客此前预订的票数

if (modify_tickets) {

SinglePassenger* head =

flight_info_list[target_airline - 1].passenger_info_list;

while (head->passenger_info.passenger_id != passenger_id) {

head = head->next_passenger;

}

printf("您此前预订的票数为%d张\n", head->passenger_info.ticket_number);

}

// 获取乘客想预定的票数

int target_ticket_num;

printf("请输入您想预定(或增订)的票数: ");

// 判断输入合法性

while (true) {

scanf("%d", &target_ticket_num);

if (target_ticket_num > remain_tickets) {

printf("您想预定的票数为%d, 但当前航次余票数仅为%d, 余票不足!\n",

target_ticket_num, remain_tickets);

printf("请输入您想预定的票数,或按0退出订票程序: ");

} else if (target_ticket_num == 0) {

printf("-------------------------------------------------------------\n");

return flight_info_list;

} else {

break;

}

}

/* 修改航次余票数 */

flight_info_list[target_airline - 1].remain_tickets -= target_ticket_num;

/* 修改乘客表中对应的项 */

// 判断该乘客原先是否存在

if (modify_tickets) {

// 若存在,找到该乘客并修改他的订票项

SinglePassenger* tmp =

flight_info_list[target_airline - 1].passenger_info_list;

while (tmp->passenger_info.passenger_id != passenger_id) {

tmp = tmp->next_passenger;

}

tmp->passenger_info.ticket_number += target_ticket_num;

printf("增订成功!您现在共预订%d张航次%d的票\n",

tmp->passenger_info.ticket_number, target_airline);

} else {

// 若不存在,则在该航次的乘客列表中增加该乘客及其对应信息

flight_info_list[target_airline - 1].passenger_info_list = AddNewPassenger(

flight_info_list[target_airline - 1].passenger_info_list, passenger_id,

target_ticket_num);

printf("预订成功!您现在共预订%d张航次%d的票\n", target_ticket_num,

target_airline);

}

printf("-------------------------------------------------------------\n");

return flight_info_list;

}

/**

  • @description: 查找乘客表(双向链表)中某乘客是否存在

  • @param {type}

  • head {SinglePassenger*}: 双向链表头结点

  • passenger_id {const int}: 待查找的键值

  • @return: 若存在,返回true;否则返回false

*/

bool IsPassengerExist(SinglePassenger* head, const int passenger_id) {

SinglePassenger* tmp = head;

bool exist = false;

if (!head) {

return false;

}

while (tmp) {

if (tmp->passenger_info.passenger_id == passenger_id) {

exist = true;

break;

}

tmp = tmp->next_passenger;

}

return exist;

}

/**

  • @description: 初始化一个新结点

  • @param {type}

  • new_passenger_id {const int}: 新增加的乘客的id

  • book_ticket_number {const int}: 新增加乘客的订票数

  • @return: 初始化后的结点(前驱,后继均为空指针)

*/

SinglePassenger* GetNewPassenger(const int new_passenger_id,

const int book_ticket_number) {

SinglePassenger* new_passenger =

(SinglePassenger*)malloc(sizeof(SinglePassenger));

new_passenger->passenger_info.passenger_id = new_passenger_id;

new_passenger->passenger_info.ticket_number = book_ticket_number;

new_passenger->next_passenger = NULL;

new_passenger->prev_passenger = NULL;

return new_passenger;

}

SinglePassenger* AddNewPassenger(SinglePassenger* head,

const int new_passenger_id,

const int book_ticket_number) {

SinglePassenger* new_passenger =

GetNewPassenger(new_passenger_id, book_ticket_number);

if (!head) {

head = new_passenger;

} else {

// 直接从头部插入

new_passenger->next_passenger = head->next_passenger;

if (head->next_passenger) {

head->next_passenger->prev_passenger = new_passenger;

}

new_passenger->prev_passenger = head;

head->next_passenger = new_passenger;

}

return head;

}

/**

  • @description: 一次退票操作的模拟

  • @param {type}

  • flight_info_list {SingleFlight *}: 航次表

  • @return: 修改后的航次表

*/

SingleFlight* Refund(SingleFlight flight_info_list[]) {

/* 获取乘客预定航次 */

int target_airline;

printf("可供选择的航次对应的编号为: 1 - %d\n", TOTAL_AIRLINE);

printf("请输入您想退订的航次(输入0时退出订票程序): ");

// 判断输入合法性

while (true) {

scanf("%d", &target_airline);

if (target_airline < 0 || target_airline > TOTAL_AIRLINE) {

printf("您要退订的航次不存在!\n");

printf("请重新输入一个正确的航次,或按0退出退票程序:");

} else if (target_airline == 0) {

printf("-------------------------------------------------------------\n");

return flight_info_list;

} else

break;

}

/* 获取乘客ID并判断其合法性 */

int passenger_id;

printf("请输入您的ID: ");

scanf("%d", &passenger_id);

SinglePassenger* head =

flight_info_list[target_airline - 1].passenger_info_list;

if (!IsPassengerExist(head, passenger_id)) {

printf("您并未预订此次航班!\n");

printf("-------------------------------------------------------------\n");

return flight_info_list;

}

/* 获取乘客退票数 */

// 打印此乘客的预订票数

SinglePassenger* tmp = head;

while (tmp->passenger_info.passenger_id != passenger_id) {

tmp = tmp->next_passenger;

}

printf("您当前预订的票数为: %d张\n", tmp->passenger_info.ticket_number);

// 读入退票数

int refund_ticket_num;

printf("请输入您的退票数(输入0退出退票程序): ");

scanf("%d", &refund_ticket_num);

// 输入合法性检查

int cur_ticket = tmp->passenger_info.ticket_number; // 当前该乘客预订的票数

while (cur_ticket < refund_ticket_num) {

if (!refund_ticket_num) {

printf("-------------------------------------------------------------\n");

return flight_info_list;

}

printf("您输入的退票数大于您当前预订的票数!");

printf("请重新输入退票数(输入0退出退票程序): ");

scanf("%d", &refund_ticket_num);

}

/* 退票 */

// 更新航次表

flight_info_list[target_airline - 1].remain_tickets += refund_ticket_num;

// 更新乘客表

if (cur_ticket > refund_ticket_num) {

tmp->passenger_info.ticket_number -= refund_ticket_num;

printf("您已成功退票,现在您%d航次的余票为%d张\n", target_airline,

tmp->passenger_info.ticket_number);

} else {

flight_info_list[target_airline - 1].passenger_info_list =

RemovePassenger(head, passenger_id);

printf("您已成功退票,现在您%d航次的余票为%d张\n", target_airline, 0);

}

printf("-------------------------------------------------------------\n");

return flight_info_list;

}

/**

  • @description: 从乘客表中删除某个结点

  • @param {type}

  • head {SinglePassenger *}: 乘客表

  • passenger_id {const int}: 待删除乘客的id

  • @return: 修改后的航次表

*/

SinglePassenger* RemovePassenger(SinglePassenger* head,

const int passenger_id) {

SinglePassenger* tmp = head;

while (tmp->passenger_info.passenger_id != passenger_id) {

tmp = tmp->next_passenger;

}

// 若为头结点

if (!tmp->prev_passenger) {

head = head->next_passenger;

}

// 若为尾结点

else if (!tmp->next_passenger) {

tmp->prev_passenger->next_passenger = NULL;

}

// 若为中间某个结点

else {

tmp->prev_passenger->next_passenger = tmp->next_passenger;

tmp->next_passenger->prev_passenger = tmp->prev_passenger;

}

return head;

}

/**

  • @description: 输出当前航次表

  • @param {type}

  • flight_info_list {SingleFlight *}: 航班信息表(航次表)

  • @return: void

*/

void PrintCurrentAirlineInfo(SingleFlight flight_info_list[]) {

for (int current_airline_index = 1; current_airline_index <= TOTAL_AIRLINE;

++current_airline_index) {

int remain_ticket_num =

flight_info_list[current_airline_index - 1].remain_tickets;

SinglePassenger* head =

flight_info_list[current_airline_index - 1].passenger_info_list;

// 输出

PrintPassengerList(head, flight_info_list, current_airline_index);

printf("-------------------------------------------------------------\n");

}

}

/**

  • @description: 打印某航次的乘客表

  • @param {type}

  • head {SinglePassenger*}: 乘客表的头结点

  • flight_info_list {SingleFlight *}: 航次表

  • @return:

*/

void Print the list of passengers from a SinglePassenger object, along with their corresponding flight information from a SingleFlight object.

int airline_id) {

if (!head) {

printf("%d航次无乘客订票!\n", airline_id);

} else {

printf("%d航次余票数为: %d, 其中:\n", airline_id,

flight_info_list[airline_id - 1].remain_tickets);

}

while (head) {

printf("ID为%d的乘客订票数为%d张\n", head->passenger_info.passenger_id,

head->passenger_info.ticket_number);

head = head->next_passenger;

}

printf("\n");

}

实现亮点

在每一个操作步骤中进行非法输入的处理,并以确保程序运行的稳定性。

鉴别root用户与非根用户,并确保仅根用户具备查看订票信息的能力

  1. 采用双向链表来管理乘客信息,在数据存取方面较之固定大小数组(它占用栈内存区域)更具优势(因为栈内存容量受限),同时相比动态数组(通常基于堆内存)也更为经济(避免了频繁的扩容需求)。在编程实现层面也较之前者更为便捷(无需编写复杂的动态内存分配代码),在减少开发复杂度方面表现同样出色(减少了结点删除操作的复杂性)。

实现缺点

1.只考虑了数字输入的情况,没有考虑字符及其他数据类型的输入

2.用链表存储导致不能随机访问,使查找操作复杂度始终为O(n) O(n)O(n)

运行结果

您好,欢迎使用此系统!

使用说明:

1. 本程序所有输入均为整数

2. 可供选择的航次编号为1-10, 每架次最大载客量为300

3. 如需购买票务,请键入1;如需退票,请键入-1;退出系统操作,请键入0;如需以root账户登录系统,则需输入root密码

使用说明到此结束,祝您使用愉快!

-------------------------------------------------------------

是否以root用户登录?若是,请输入1,否则请输入0:1

请输入root密码(按0退出root登录程序):123456

欢迎,root用户!输入11可查看当前航次表

-------------------------------------------------------------

请输入1, 0, -1或11中的一个数字: 1

可供选择的航次对应的编号为: 1 - 10

请输入您想预定的航次(输入0时退出订票程序): 1

若您原先已经订票,且想增加您的订票数,请输入1,否则请输入0: 0

请输入您的ID: 1

当前航次余票数为: 300

请输入您想预定(或增订)的票数: 12

预订成功!您现在共预订12张航次1的票

-------------------------------------------------------------

请输入1, 0, -1或11中的一个数字: 1

可供选择的航次对应的编号为: 1 - 10

请输入您想预定的航次(输入0时退出订票程序): 1

若您原先已经订票,且想增加您的订票数,请输入1,否则请输入0: 0

请输入您的ID: 2

当前航次余票数为: 288

请输入您想预定(或增订)的票数: 21

预订成功!您现在共预订21张航次1的票

-------------------------------------------------------------

请输入1, 0, -1或11中的一个数字: 1

可供选择的航次对应的编号为: 1 - 10

请输入您想预定的航次(输入0时退出订票程序): 1

若您原先已经订票,且想增加您的订票数,请输入1,否则请输入0: 0

请输入您的ID: 3

当前航次余票数为: 267

请输入您想预定(或增订)的票数: 32

预订成功!您现在共预订32张航次1的票

-------------------------------------------------------------

请输入1, 0, -1或11中的一个数字: 1

可供选择的航次对应的编号为: 1 - 10

请输入您想预定的航次(输入0时退出订票程序): 2

若您原先已经订票,且想增加您的订票数,请输入1,否则请输入0: 0

请输入您的ID: 32

当前航次余票数为: 300

请输入您想预定(或增订)的票数: 2

预订成功!您现在共预订2张航次2的票

-------------------------------------------------------------

请输入1, 0, -1或11中的一个数字: 1

可供选择的航次对应的编号为: 1 - 10

请输入您想预定的航次(输入0时退出订票程序): 10

若您原先已经订票,且想增加您的订票数,请输入1,否则请输入0: 0

请输入您的ID: 212

当前航次余票数为: 300

请输入您想预定(或增订)的票数: 123

预订成功!您现在共预订123张航次10的票

-------------------------------------------------------------

请输入1, 0, -1或11中的一个数字: 1

可供选择的航次对应的编号为: 1 - 10

请输入您想预定的航次(输入0时退出订票程序): 1

若您原先已经订票,且想增加您的订票数,请输入1,否则请输入0: 1

请输入您的ID: 1

当前航次余票数为: 235

您此前预订的票数为12张

请输入您想预定(或增订)的票数: -1

增订成功!您现在共预订11张航次1的票

-------------------------------------------------------------

请输入1, 0, -1或11中的一个数字: -1

可供选择的航次对应的编号为: 1 - 10

请输入您想退订的航次(输入0时退出订票程序): 1

请输入您的ID: 2

您当前预订的票数为: 21张

请输入您的退票数(输入0退出退票程序): 222

您提交的退票数量超过了您现有的订单!请再次输入退票数量(输入0退出退票功能): 2

您已成功退票,现在您1航次的余票为19张

-------------------------------------------------------------

请输入1, 0, -1或11中的一个数字: 1

可供选择的航次对应的编号为: 1 - 10

请输入您想预定的航次(输入0时退出订票程序): 10

若您原先已经订票,且想增加您的订票数,请输入1,否则请输入0: 32

您输入的是非法命令,请重新输入0(原先未订票)或1(原先已经订票):0

请输入您的ID: 322

当前航次余票数为: 177

请输入您想预定(或增订)的票数: 12

预订成功!您现在共预订12张航次10的票

-------------------------------------------------------------

请输入1, 0, -1或11中的一个数字: -1

可供选择的航次对应的编号为: 1 - 10

请输入您想退订的航次(输入0时退出订票程序): 10

请输入您的ID: 212

您当前预订的票数为: 123张

请输入您的退票数(输入0退出退票程序): 123

您已成功退票,现在您10航次的余票为0张

-------------------------------------------------------------

请输入1, 0, -1或11中的一个数字: 11

-------------------------------------------------------------

1航次余票数为: 238, 其中:

ID为1的乘客订票数为11张

ID为3的乘客订票数为32张

ID为2的乘客订票数为19张

-------------------------------------------------------------

2航次余票数为: 298, 其中:

ID为32的乘客订票数为2张

-------------------------------------------------------------

3航次无乘客订票!

-------------------------------------------------------------

4航次无乘客订票!

-------------------------------------------------------------

5航次无乘客订票!

-------------------------------------------------------------

6航次无乘客订票!

-------------------------------------------------------------

7航次无乘客订票!

-------------------------------------------------------------

8航次无乘客订票!

-------------------------------------------------------------

9航次无乘客订票!

-------------------------------------------------------------

10航次余票数为: 288, 其中:

ID为322的乘客订票数为12张

-------------------------------------------------------------

请输入1, 0, -1或11中的一个数字: 0

注:对于普通用户而言,在系统中无法进行查看全部乘客信息的功能操作,并且仅能获取自身的购票记录

更多学习资料请关注专题《管理系统开发》。

这就是本文的主要内容,请期待能为大家的学习带来帮助。也欢迎广大学子多多关注脚本之家

全部评论 (0)

还没有任何评论哟~