C语言实现飞机订票系统
问题描述与题目要求
问题描述:假定某民航有M个航次的班机,每个航次都只到达一个地方。试为该机场售票处设计一个自动订票和退票系统,要求系统具有以下功能:
(1) 订票:若该航次余票大于等于乘客订票数,则在该航次的乘客表中,插入订票乘客的信息项,并修改该航次有关数据,否则给出相应信息。
(2) 退票:若该航次当前退票数小于等于乘客原订票数,则在相应的乘客表中找到该乘客项,修改该航次及乘客表中有关数据;当某乘客由于退票使订票数为零时,则从乘客表中撤消该数据项。
要求:
(1)描述对航次表和乘客表选用的数据结构。
(2)编程实现飞机票订票和退票系统。
模型假设
1.假设所有输入均为整数且在int类型的表示范围内
2.假设航次是从1到n的连续整数
3.假设每个乘客ID均唯一
数据结构的选用
联想到图中的邻接链表,采用相似的数据结构描述该问题
航次表:用一个数组flight_info_list存储每个航次的乘客表,该数组下标即为航班航次,对应元素即为该航次相关信息(乘客表,航班编号及航班余票数)
乘客表:用双向链表存储每个航次的乘客表passenger_info_list,每个结点存储乘客的ID,订票数以及指向前、后结点的指针
编程实现(C语言实现)
/* *@Description:模拟航班的订票系统 *模型假设: *1.飞机最大载客量为300人 *2.共10个航次 *用双向链表存储乘客信息 *用array存储航班信息 *@Author:Fishermanykx *@Date:2019-09-2910:32:56 *@LastEditors:Fishermanykx *@LastEditTime:2019-09-3012:29:16 */ #include#include #include #defineMAX_CAPACITY300//假定飞机最大载客量为300 #defineTOTAL_AIRLINE10//假定不同航线最大数目为10 #defineBOOK_TICKET1 #defineREFUND-1 #defineEXIT_SYSTEM0 #definePRINT_INFO11 #defineROOT123456 //某航次航班 structSingleFlight{ intflight_id;//航班编号,从1开始,到TOTAL_AIRLINE为止 intremain_tickets;//该航班余票数 structSinglePassenger*passenger_info_list;//该航班乘客表 }; //某航次航班的某个乘客的信息 structPassengerInfo{ intpassenger_id;//乘客id intticket_number;//该乘客购买票数 }; //乘客表中的一个结点 structSinglePassenger{ structPassengerInfopassenger_info;//乘客信息 structSinglePassenger*prev_passenger;//指向前一个乘客的指针 structSinglePassenger*next_passenger;//指向后一个乘客的指针 }; typedefstructSingleFlightSingleFlight; typedefstructSinglePassengerSinglePassenger; //订票操作 SingleFlight*BookTicket(SingleFlightflight_info_list[]); SinglePassenger*GetNewPassenger(constintnew_passenger_id, constintbook_ticket_number); SinglePassenger*AddNewPassenger(SinglePassenger*head, constintnew_passenger_id, constintbook_ticket_number); //退票操作 SingleFlight*Refund(SingleFlightflight_info_list[]); SinglePassenger*RemovePassenger(SinglePassenger*head,constintpassenger_id); //判断操作 boolIsPassengerExist(SinglePassenger*head,constintpassenger_id); //打印操作 voidPrintCurrentAirlineInfo(SingleFlightflight_info_list[]); voidPrintPassengerList(SinglePassenger*head,SingleFlight*flight_info_list, intairline_id); intmain(void){ intorder,exit_loop=1; //初始化航班信息 SingleFlight*flight_info_list; flight_info_list= (SingleFlight*)malloc(TOTAL_AIRLINE*sizeof(SingleFlight)); for(inti=0;i TOTAL_AIRLINE){ printf("您要预定的航次不存在!\n"); printf("请重新输入一个正确的航次,或按0退出订票程序:"); }elseif(target_airline==0){ printf("-------------------------------------------------------------\n"); returnflight_info_list; }else break; } /*获取乘客id*/ intpassenger_id; intmodify_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"); returnflight_info_list; } } /*获取乘客预定票数*/ //获取当前航次余票数 intremain_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); } //获取乘客想预定的票数 inttarget_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退出订票程序:"); }elseif(target_ticket_num==0){ printf("-------------------------------------------------------------\n"); returnflight_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"); returnflight_info_list; } /** *@description:查找乘客表(双向链表)中某乘客是否存在 *@param{type} *head{SinglePassenger*}:双向链表头结点 *passenger_id{constint}:待查找的键值 *@return:若存在,返回true;否则返回false */ boolIsPassengerExist(SinglePassenger*head,constintpassenger_id){ SinglePassenger*tmp=head; boolexist=false; if(!head){ returnfalse; } while(tmp){ if(tmp->passenger_info.passenger_id==passenger_id){ exist=true; break; } tmp=tmp->next_passenger; } returnexist; } /** *@description:初始化一个新结点 *@param{type} *new_passenger_id{constint}:新增加的乘客的id *book_ticket_number{constint}:新增加乘客的订票数 *@return:初始化后的结点(前驱,后继均为空指针) */ SinglePassenger*GetNewPassenger(constintnew_passenger_id, constintbook_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; returnnew_passenger; } SinglePassenger*AddNewPassenger(SinglePassenger*head, constintnew_passenger_id, constintbook_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; } returnhead; } /** *@description:一次退票操作的模拟 *@param{type} *flight_info_list{SingleFlight*}:航次表 *@return:修改后的航次表 */ SingleFlight*Refund(SingleFlightflight_info_list[]){ /*获取乘客预定航次*/ inttarget_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退出退票程序:"); }elseif(target_airline==0){ printf("-------------------------------------------------------------\n"); returnflight_info_list; }else break; } /*获取乘客ID并判断其合法性*/ intpassenger_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"); returnflight_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); //读入退票数 intrefund_ticket_num; printf("请输入您的退票数(输入0退出退票程序):"); scanf("%d",&refund_ticket_num); //输入合法性检查 intcur_ticket=tmp->passenger_info.ticket_number;//当前该乘客预订的票数 while(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"); returnflight_info_list; } /** *@description:从乘客表中删除某个结点 *@param{type} *head{SinglePassenger*}:乘客表 *passenger_id{constint}:待删除乘客的id *@return:修改后的航次表 */ SinglePassenger*RemovePassenger(SinglePassenger*head, constintpassenger_id){ SinglePassenger*tmp=head; while(tmp->passenger_info.passenger_id!=passenger_id){ tmp=tmp->next_passenger; } //若为头结点 if(!tmp->prev_passenger){ head=head->next_passenger; } //若为尾结点 elseif(!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; } returnhead; } /** *@description:输出当前航次表 *@param{type} *flight_info_list{SingleFlight*}:航班信息表(航次表) *@return:void */ voidPrintCurrentAirlineInfo(SingleFlightflight_info_list[]){ for(intcurrent_airline_index=1;current_airline_index<=TOTAL_AIRLINE; ++current_airline_index){ intremain_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: */ voidPrintPassengerList(SinglePassenger*head,SingleFlight*flight_info_list, intairline_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"); }
实现亮点
1.每一步操作均有对非法输入的处理,最大限度上确保了程序运行的稳定性
2.区分root用户和普通用户,且只有root用户能够查看所有人的订票情况,从而保护了客户的隐私
3.使用双向链表存储乘客信息,一方面便于存取乘客的信息(定长数组分配的是栈内存,而栈内存小于堆内存,所以用链表进行存储更不容易造成内存溢出),另一方面降低了编程难度(既不需要实现对数组进行动态内存分配的一系列操作,又最大限度地降低了删除结点操作的复杂度)
实现缺点
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
注:普通用户不能执行查看所有乘客信息的操作,只能查看自己的购票信息
更多学习资料请关注专题《管理系统开发》。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。