数据结构_航空客运订票系统(C实现)

article/2025/8/22 5:15:05

文章目录

  • 总述
  • 代码
    • 粗糙版
    • 修理版
  • 还可以修正的点:
      • 余票不足时仍然提示还剩下几张(而不是直接拒绝该用户的订票操作)
      • 对于购票者的id 不单单是说约定一个可以不重复的主键(命名规则),而且还要辅以必要的检查违约功能

总述

在这里插入代码片
1.	问题描述:(题目复述)
题目复述如下:使用缩进使要求直观.
(一)试设计一个航空客运定票系统。基本要求如下:1.	设计数据结构
a)	每条航线所涉及的信息有:
i.	终点站名、
ii.	航班号、
iii.	飞机号、
iv.	飞机周日(星期几)、
v.	乘员定额、
vi.	余票量、b)	订定票的客户名单(包括
i.	姓名、
ii.	订票量、(显然取决于客户的需求)
iii.	舱位等级123)
c)	等候替补的客户名单(包括
iv.	姓名、
v.	所需数量)。
2.	数据结构的基础上设计算法,使系统能实现的操作和功能如下:
1)	查询航线:根据客户提出的终点站名输出如下信息:
i.	航班号、
ii.	飞机号、
iii.	星期几飞行,
iv.	最近一天航班的日期和
v.	余票额;
2)	承办订票业务:根据客户提出的要求(航班号、订票数额)查询该航班票额情况,
i.	若有余票,则为客户办理订票手续,输出座位号;
ii.	若已满员或余票少余订票额,则需重新询问客户要求。
a)	若需要,可登记排队候补;
3)	承办退票业务:根据客户提出的情况(日期、航班号),为客户办理退票手续,
i.	然后查询该航班是否有人排队候补,首先询问排在第一的客户,若所退票额能满足他的要求,则为他办理订票手续,
ii.	否则依次询问其它排队候补的客户。2.	设计:
(1)	数据结构设计和核心算法设计描述;
主要描述程序采用的逻辑结构(线性表、队列、堆栈、树、图)和存储结构(顺序存储和链式存储),以及核心算法设计(比如Kruskal算法、Prim算法、Dijkstra、Floyd算法)
1.本程序主要采用了 单链表+链队列的逻辑结构;且都是基于链式存储的存储结构;/* 订定票的客户链表结点结构 */
typedef struct LNode_Cer {char name[MAXNAME];/*客户名字(订票的时候输入)名字的排序建议用插入排序以保持有序*/int num_tickets;/*订票量*/int rank;/*仓位等级class是保留字,用rank*/LNode_Cer* link;/*指针域*/
}LNode_Cer;/*link node of Certain */
/*航线链表的结点结构*/
typedef struct LFlightNode {char name_des[MAX];/*终点站名*/char flight_num[MAX];/*航班号:航班号某时某刻从某地飞往另一地的 航班航程的编号*/char plane_num[MAX];/*飞机号:飞机号相当于飞机的身份证*/int plane_weekday;/*星期几的航班*/int plane_crew;/*乘员定额(最大乘客量)*/int remaining_tickets;/*剩余票量*//*三种等级仓位的价格int price[3]*//*此外,可考虑还能够查出该航线由哪些乘客以及候补乘客LNode_Cer* customerName;LNode_Cer* candidateName;*/LFlightNode* next;
}LFlightNode;/*等候替补客户链队列节点*//*与顺序队列相比,就是队列结构里把数组用链表(头指针)替代(链表外置),虚拟指针用真正的指针替代*/
typedef struct  LQueueNode_Can {/*数据域(不同场景下条目可多可少,类型可以多样)*/char name[MAXNAME];/*候补客户名字*/int num_tickets;/*该客户需要的票数*/char flightNo[MAX];/*候补乘客想要的航班*//*附加的指针域*/LQueueNode_Can* link;
}LQueueNode_Can;/*can指candidate的缩写*//*等待候补客户链队列整体结构*/
typedef struct LQueue_Can {LQueueNode_Can* front;LQueueNode_Can* rear;
}LQueue_Can;
2.涉及的算法有:基于链表的主关键字排序;链队列的以及链表的增加记录+删除记录+检索记录.
(2)	主控及功能模块层次结构;(4)	功能模块之间的调用与被调用关系等。4.	使用说明和作业小结:
(1)	使用说明主要描述如何使用你的程序以及使用时的主要事项;
1.约定:本程序里的名字是指是个人 名字+身份ID号综合体 的简称(比如 chaoxin_1375,是具有唯一性的主关键词
2.本程序所指的座舱等级(1,2,3)是在飞机中额外提供的服务的品质,与坐位坐垫无关.(当然与实际生活中的标准不相同)
3.本程序生成座位号只生成第一张票的座位号(如果该乘客订了多张票,那么就默认是连续的号.(与实际生活的座位号有别)
(2)	在小结中说明程序的改进思想、经验和体会;
1.由于要求实现的功能较多,在安排主函数时应注意将各模块的功能分配到各个函数群中,是主函数更简洁,逻辑更清晰.
一上来就急于实现数据结构的基本操作使我感到吃力而且低效
2. 建立全局变量(在不至于混淆的情况下可以减少参数的传递);
在本实验中,纠正了我对全局变量传参的错误认识.
3.对带头结点的链表进行排序操作比较统一,得益于表头结点的使用;此外在使用同一算法对不带头结点的链表进行关键字排序时,用化归思想,补偿一个临时头结点给不带头结点的链表,待排序结束后,修正表头指针,并释放后期加设的头结点实现排序.;链队列比循环队列要更加灵活,虽然定义结构体稍加复杂,单实际基本操作却很方便.
4.编写本程序时,由于涉及的功能比较多,尤其是对异常处理的编写占了较多篇幅,刚开始写的时候比较担心自己能否组织好各个模块,花了较多时间在调试上,比较考验耐心.同时,我也收获了不少,尤其是对vs这个IDE的使用更加熟练,调试较长代码的经验使我受益匪浅.
5.本程序参照生活中的场景作了简化处理,留心生活中的各种应用,与写好程序不无关系.

在这里插入图片描述
3. 测试
测试范例,测试结果,测试结果的分析与讨论,测试过程中遇到的主要问题及所采用的解决措施。
///以下实例测试包括测试错误处理的可用性,但其中多出使用getch()来读出用户的功能选项,(输入没有显示在屏幕上,而是直接确认选项,比如: “输入y/Y确定继续”“按键1,2,3,4,5直接进入功能”)

在这里插入图片描述

代码

粗糙版

#define _CRT_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_DEPRECATE 
#define _CRT_NONSTDC_NO_DEPRECATE#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
#include <ctype.h>
#include <conio.h> /*getch()所在头文件是conio.h。而不是stdio.h*/
#define MAXLEN 100
#define MAX  60  
#define MAXNAME 10
/*  run   this
#define N 5/*航班号数量*//* 订定票的乘客链表结点结构 */
typedef struct LNode_Cer {char name[MAXNAME];/*乘客名字(订票的时候输入)名字的排序可以用插入的方式以保持有序*/int num_tickets;/*订票量*/int rank;/*仓位 等级class是保留字,用rank*/LNode_Cer* link;/*指针域*/
}LNode_Cer;/*link node of Certain */
/*航线链表的结点结构*/
typedef struct LFlightNode {char name_des[MAX];/*终点站名*/char flight_num[MAX];/*航班号:航班号某时某刻从某地飞往另一地的 航班航程的编号*/char plane_num[MAX];/*飞机号:飞机号相当于飞机的身份证*/int plane_weekday;/*星期几的航班*/int plane_crew;/*乘员定额(最大乘客量)*/int remaining_tickets;/*剩余票量*//*三种等级仓位的价格int price[3]*//*此外,可考虑还能够查出该航线由哪些乘客以及候补乘客LNode_Cer* customerName;LNode_Cer* candidateName;*/LFlightNode* next;
}LFlightNode;/*等候替补乘客链队列节点*//*与顺序队列相比,就是队列结构里把数组用链表(头指针)替代(链表外置),虚拟指针用真正的指针替代*/
typedef struct  LQueueNode_Can {/*数据域(不同场景下条目可多可少,类型可以多样)*/char name[MAXNAME];/*候补乘客名字*/int num_tickets;/*该乘客需要的票数*/
/**/char flightNo[MAX];/*候补乘客想要的航班*//*附加的指针域*/LQueueNode_Can* link;
}LQueueNode_Can;/*candidate*//*等待候补乘客链队列整体结构*/
typedef struct LQueue_Can {// LQueueNode_Can LQueue[MAXLEN];LQueueNode_Can* front;LQueueNode_Can* rear;
}LQueue_Can;/*建立全局变量(在不至于混淆的情况下可以减少参数的传递)*/
/*任何函数都可访问到全局变量(不需要通过传参即可之间从内部访问)*/
LFlightNode* Head = NULL;/*第一个航班结点,初始化为NULL*/
LFlightNode* p2;/*航班辅助指针(指向表尾结点)(如果不设立该全局变量,要使用表尾时也可以同从头遍历找到表尾*/LNode_Cer* LHead = 0;/*乘客链表表头表头*/
LNode_Cer* pLnow = 0;/*乘客链表表尾指针*/LQueue_Can LQ = { 0,0 };/*//这里的LQ不设置为指针,而是一个 链队列 类型的 变量,
会分配一个LQueue_Can类型变量大小的内存给LQ.(内部含有两个指针的变量类型),不方便直接初始赋值*//*编写自定义基本操作函数时*/
/*假设函数的功能都能够实现,内容的具体实现待逻辑框架设计好后再作填充编写(函数原型的调整)
(如果某个预想函数不易一步实现,则届时可以拆分实现(复合实现)还原到研究问题的本质上*//*f初始化链表(可以让它构建一个头结点并返回节点的指针创建链表(可以考虑将他写为复合函数(包含插入函数))*/
/*初始化订定票乘客链表(建一个头结点,返回头结点指针)*/
//LNode_Cer* InitLNode_Cer()/*//无参有返回值带出结果的函数版本(也可以使有参(间接传参保存结果)的版本)*/
//{
//    LNode_Cer* LNode;/*只分配了一个指针的空间*/
//    LNode = (LNode_Cer*)malloc(sizeof(LNode_Cer));/*申请一个节点的空间*/
//    if (!LNode)
//    {
//        printf("malloc failed!\n");
//        exit(1);
//    }
//    LNode->name[0] = 0;
//    LNode->num_tickets = 0;
//    LNode->rank = 0;
//    LNode->link = NULL;
//    return LNode;
//}
/*初始化链队列(申请一个表头结点,并且将处理结果保存再LQ中)
void InitLQueue_Can(LQueue_Can* LQ )
{LQ->front = LQ->rear = (LQueueNode_Can*)malloc(sizeof(LQueueNode_Can));if (!LQ->front){exit(1);}LQ->front->link = 0;
}
*/
/*备用的基本操作函数算法*//*插入新结点到队列尾*/
//void EnQueue(/**/LQueue_Can* LQ, char* name, int num_tickets)
//{
//    /*LQ->rear->link = (LQueueNode_Can*)malloc(sizeof(LQueueNode_Can));//直接挂钩新结点
//    scanf("%s", LQ->rear->name);
//    LQ->rear = LQ->rear->link;*/
//    /*如果引入辅助指针s,可以使得表达式更简洁(尽管步骤肯多点.*/
//    LQueueNode_Can* s = (LQueueNode_Can*)malloc(sizeof(LQueueNode_Can));
//    if (!s) exit(1);
//    strcpy(s->name, name);
//    s->num_tickets = num_tickets;
//    s->link = 0;
//
//    LQ->rear->link = s;
//    LQ->rear = s;
//}/*初始化队列节点
LQueueNode_Can* InitLQueueNode_Can()
{LQueueNode_Can* LQNode;LQNode = (LQueueNode_Can*)malloc(sizeof(LQueueNode_Can));LQNode->name[0] = '\0';LQNode->num_tickets = 0;LQNode->link = NULL;return LQNode;
}*/
/*插入新元素到链表尾*/
//void InsertToLinkTail(LNode_Cer* pHead)
//{
//    LNode_Cer* LNode = (LNode_Cer*)malloc(sizeof(LNode_Cer));
//    if (!LNode)
//    {
//        printf("malloc failed!\n");
//        exit(1);
//    }
//    /*新结点内容写入*/
//    scanf("%s", LNode->name);
//    scanf("%d", &LNode->num_tickets);
//    scanf("%d", &LNode->rank);
//    /*找到链表尾部*/
//    while (pHead->link)
//    {
//        pHead = pHead->link;
//    }/*指向当前表尾元素*/
//    /*插入新节点*/
//    pHead->link = LNode;
//}/*检查输入的航班号是否早已被占用,返会 是/否*/
int is_aready_have(LFlightNode* Head, char* flight_num)
{LFlightNode* p1 = Head;while (p1){if (!strcmp(p1->flight_num, flight_num)){return 1;}p1 = p1->next;}return 0;
}
/*f录入航班号(在停止之前一直录入)
需要注意的的是,航班号必须唯一,若发现重复录入,应给予提示:*/
void input_flights()/*line_add*/
{LFlightNode* p1;LFlightNode* ptemp;/*保存新申请的结点内存的指针*///p1 = Head;p2 = Head;char temp_flight_name[MAX];/*暂存输入的航班号名*/char c;/*接收是否继续录入的指令*/while (1){printf("继续执行录入操作?(按y/Y以外的键退出.)\n");c = getch();if ((c != 'y' && c != 'Y')){break;}/*创建并写入头结点*/if (Head == NULL){p2 = (LFlightNode*)malloc(sizeof(LFlightNode));p2->next = NULL;Head = p2;/*获得表头结点(这一步只需执行一次)*/}else{p2 = p2->next = (LFlightNode*)malloc(sizeof(LFlightNode));/*shen'qing申请+插入到表尾+更新表尾结点指针*///p2 = p2->next;/*gengxin更新表尾指针*/p2->next = NULL;/*这样直接赋值引发问题就是,p2被初始化为与Head一样地指向头结点,而头结点的指针域指向NULL,p2->next作为右值时就是NULL;p2->next作为左值时,是为了修改表头结点的指针域;*//*采用辅助指针ptemp的版本*///ptemp = (LFlightNode*)malloc(sizeof(LFlightNode));//if (!ptemp) exit(1);//ptemp->next = NULL;/*初始化新结点的指针域*///p2->next = ptemp;/*接入新结点*////*再更新表尾指针的对象*///p2 = ptemp;}/*向新结点写入数据*/printf("\n输入终点站名:");scanf("%s", p2->name_des);/*测试链表连通性,暂时屏蔽一些内容的填充:*/printf("\n请输入唯一的航班号:");while (1){/*scanf("%s", p2->flight_num);如果直接写入链表,那is_aready_have()就总返回已占用,所有要用临时变量暂存输入.*/scanf("%s", temp_flight_name);if (is_aready_have(Head, temp_flight_name)){printf("\n该航班号已被占用,请使用新的编号:");}else{strcpy(p2->flight_num, temp_flight_name);break;}}printf("\n输入飞机号:");scanf("%s", p2->plane_num);printf("\n输入出发出发日期(周几):");scanf("%d", &p2->plane_weekday);/*取成员->优先于取地址&*/printf("\n输入乘员定额:");scanf("%d", &p2->plane_crew);p2->remaining_tickets = p2->plane_crew;/*初始化余票额*/// scanf("%d", &p2->remaining_tickets);/*剩余票量由乘员定额-已被订购数决定*/}//while
}//input_flights()//目前读入功能正常
/**/
/*根据用户输入的终点站名,输出:航班号+飞机号+星期几飞行+最近一天的航班日期(额外开个函数,内部调用)+余票额*/
void print_flight_search()//line_search() 根据终点站名查找相关元素的详情.
{void print_closest_flight(int departure);char des_name[MAX];//临时接收一个名字字符串.LFlightNode* p1 = Head;/*p1用于遍历链表结点,一般被初始化为Head,表头开始遍历*/if (Head == NULL){printf("\n\t        尚未录入任何航班数据,无法提供有效查询!");//getch();/*等待用户确认提示后按任意键返回;(也可直接返回)(提示信息已打印)return;}/*若已经录入一定信息*/printf("\n\t 请输入要查询的终点站名:");scanf("%s", des_name);printf("\n\t 查询结果:\n");int is_has = 0;/*标识是否找到符合条件的航班*/while (p1){if (!strcmp(p1->name_des, des_name)){is_has++;printf("终点站名:%s\n航班号:%s\n飞机型号:%s\n星期:%d\n余票量:%d\n",p1->name_des, p1->flight_num, p1->plane_num, p1->plane_weekday, p1->remaining_tickets);}p1 = p1->next;}//whileif (!is_has) printf("\n\tsorry,没有该航班");else{printf("\n\t输入要出发的日期(星期几),查询最近一天且未过期的航班:");int departure;scanf("%d", &departure);print_closest_flight(departure);}return;}
/*配合print_search_ret()根据输入的终点打印最近一天的航班日期(当天即之后)
然而最小值并不一定只有一个!(二次遍历找到全部最小值*/
void print_closest_flight(int departure)
{LFlightNode* p1 = Head;LFlightNode* nearest_flight = p1;int delta = 0;int delta_min = 7;while (p1){if (p1->plane_weekday >= departure)/*筛选本周未过期的航班*/{/* delta = p1->plane_weekday - departure > 0 ?p1->plane_weekday - departure :departure - p1->plane_weekday ;delta = p1->plane_weekday - departure;if (delta < 0){delta = -1 * delta;}*//*找到最近的将来航班p.*/delta = p1->plane_weekday - departure;//必>=0if (delta < delta_min){delta_min = delta;nearest_flight = p1;/*保存当前为止的最近航班指针*/}}//if/* else{//可忽略.printf("\n此航班已过期,应该输入今天及之后的出发日期");}*/p1 = p1->next;}//while/*输出所有满足条件的最近hangban(航班)*/p1 = Head;/*复位*/while (p1){if (p1->plane_weekday == nearest_flight->plane_weekday){printf("航班:%s\n日期:%d\n", p1->flight_num, p1->plane_weekday);}p1 = p1->next;}}/*航班查看(所有航班)函数 */
int Line_See_all()
{/*声明函数*/int Empty_Flight();LFlightNode* p1;//system("cls");此处cls函数导致屏幕打印混乱.(vs才可下正常运行.) ;/*清屏*/p1 = Head;/*打印前检查是否已录入航班信息被录入:*/if (Empty_Flight()) return 0;printf("\n\n\t           航班信息:\n");while (p1 != NULL){{printf("终点站名:%s\n航班号:%s\n飞机型号:%s\n星期:%d\n余票量:%d\n\n",p1->name_des, p1->flight_num, p1->plane_num, p1->plane_weekday, p1->remaining_tickets);/*如果将整型数以%s输出会出错*/}p1 = p1->next;}printf("\n\t      按任意键确认返回!\n");getch();
}
/*判断航班是否为空函数(菜单调转)  */
int Empty_Flight()
{if (Head == NULL){//system("cls");此处cls函数导致屏幕打印混乱.(vs才可下正常运行.) ;printf("\n\t       sorry,尚不存在航班,按任意键返回!");getch();return 1;}else return 0;
}
/*操作异常/非法提示*/
void Error_warning()
{printf("\n\t遇到非法或异常操作!\n");
}/*承办业务系(订票)函数
首先查找是否有对应航班;
若有对应航班,检查是否有余票,若有,询问要订购几张票*/
/*对已定票的乘客名单按名字进行排序*/
void Lsort_names(/*LNode_Cer* LHead*/)//经调试,可正常工作.(调试排序算法,可以在两个循环处+边界收缩处各打一个断点,用一组降序数来试)
{LNode_Cer* pp,* p,* q,* last,* HHead;/*外加头结点*//*创建头结点:*/HHead = (LNode_Cer*)malloc(sizeof(LNode_Cer));HHead->link = LHead;last = HHead;/*通过遍历,使得last被初始化为表尾指针*/while (last->link){last = last->link;}/*外层循环*/while (last != HHead->link)/*控制排序趟数,last走到表头前,继续比较*/{pp = HHead;p = pp->link;/*内层循环(last是右元素的右边界)*/while (p != last)/*直到:q == last进入循环并完成比较)(即右边界参与了比较),随后p,q都再向后移动一个元素,这时要离开了,判断条件为p == last*/{q = p->link;if (strcmp(p->name, q->name) > 0){pp->link = q;/*1接3*/p->link = q->link;/*2接4*/q->link = p;/*3接2*//*在必要时修正被悄然前调的last*/if (last == q){last = p;}//if}//ifpp = (strcmp(p->name, q->name) < 0) ? p : q;p = pp->link;}//while(内存)last = pp;/*last向前回溯*/}//while(外层)LHead = HHead->link;free(HHead);/*释放掉补偿的头结点HHead*/return;
}
/*询问是否参加候补+登记候补*/
void inquiry_enroll_candidate(int num_book, char* flight)
{{/*加入候补队列*//*在本函数之外就将准备好一个初始化完毕的队列,以便随时插入.*/printf("输入您的名字:");if (LQ.front == 0 && LQ.rear == 0)/*链队列的队头与队尾指针同时为NULL,为空队充分但不必要条件(与具体的实现有关)*/{/*处理队头*//*在入队列的过程中,为队头front赋值只执行一次即可.*/LQ.front = LQ.rear = (LQueueNode_Can*)malloc(sizeof(LQueueNode_Can));/*专门填充队头元素*/scanf("%s", LQ.rear->name);LQ.rear->num_tickets = num_book;LQ.rear->link = 0;}else/*处理队身*/{// EnQueue()入队列(尾)/*不用辅助指针s*/LQ.rear->link = (LQueueNode_Can*)malloc(sizeof(LQueueNode_Can));/*申请新结点的同时+入队列(写入到当前节点的指针域)*/LQ.rear = LQ.rear->link;/*加入新结点空间后,更新表尾指针*//*及时初始化节点的指针域*/LQ.rear->link = 0;/*向新结点写入信息*/scanf("%s", LQ.rear->name);LQ.rear->num_tickets = num_book;strcpy(LQ.rear->flightNo, flight);/*该语句中入股flight是乱七八糟的东西可以导致尾节点指针域混乱(由NULL变成其他的东西)*/// printf("\nobserve");/*使用辅助指针s可以时表达式更短.*/
//s = (LQueueNode_Can*)malloc(sizeof(LQueueNode_Can));
//if (!s) exit(1);
//                  /*向新结点写入信息*/
//                  scanf("%s", s->name);//s->num_tickets = num_book;
//                  strcpy(s->flightNo, flight);/*原本想订的航班号:*/
//                  /*新结点入队列*///LQ.rear->link = s;//LQ.rear = s;/*更新队尾指针*/}//else/*处理队身*/}//if(若参与候补,否则pass该乘客,询问下一位乘客)//printf("\nobserve");return;
}//inquiry_enroll_candidate/*判断用户输入的 航班号+订票数量 检查对应航班是否有余票,同时办理订票+询问候补需要*/
void booking()
{/*声明函数:*/int find_flight_route(char* flight, LFlightNode * *Psave/*若找到对应航班,则将结果写在变量Psave中*//*LFlightNode* Head  Head是全局变量 无需传参即可使用*/);char c;/*接收用户选择*/char flight[MAX];int num_book = 0;LFlightNode* Psave = 0;/*通过函数find_flight_route(),将找到的航班结点的指针带回(修改Psave)*/LQueueNode_Can* s = 0;if (Empty_Flight()){return;}printf("\n当前可以订票");while (1){printf("\n输入行班号:");scanf("%s", flight);if (!find_flight_route(flight, &Psave)){printf("sorry,没有该航班!");}else if (Psave->remaining_tickets)/*找到该航班,检查改航班是否满员*/{printf("尚有余票,输入您想要定的票的数量:\n");scanf("%d", &num_book);if (num_book < Psave->remaining_tickets)/*余票chongzu充足*/{/*满足该乘客需求,登记购票*/printf("余票数量充足\n输入您的名字:");/*创建并向链表头写入数据*/if (!LHead){pLnow = (LNode_Cer*)malloc(sizeof(LNode_Cer));LHead = pLnow;/*保存头结点指针;pLnow 是辅助指针(而且是全局变量(可不必全局)*/pLnow->link = 0;/*初始化新结点的指针域*/}else/*链表身体*/{/*直接从当前节点接收新节点内存地址.(直接挂接到表尾.)*/pLnow->link = (LNode_Cer*)malloc(sizeof(LNode_Cer));pLnow = pLnow->link;/*更新pLnow*/pLnow->link = 0;/*初始化新结点的指针域*//*引入辅助指针+初始化新结点的指针域:*/}/*向新节点内写入内容*/pLnow->num_tickets = num_book;scanf("%s", pLnow->name);printf("购买几等票:");scanf("%d", &pLnow->rank);Psave->remaining_tickets -= num_book;/*输出座位号:*/printf("您的座位号:%d\n\n", Psave->plane_crew - Psave->remaining_tickets);}//ifelse/*余票不足*/{char c;/*接收用户选择*/char isCandidate;printf("余票不足,是否加入候补?(按y/Y)\n");isCandidate = getch();if (isCandidate == 'y' || isCandidate == 'Y')inquiry_enroll_candidate(num_book, flight);}//else/*余票不足*/printf("\n是否继续订票?\n输入y继续"); c = getch();if (c != 'y'){break;}//跳出(连续订票循环)}//if(若有余票)}//while(连续订票循环)/*订顶票乘客非空,则为乘客链表排序*/if (LHead)//Lsort_names(LHead);/*需要纠正的观念是,如果全局变量当初本地变量传入参数的话,可能使得修改白费(优先识别为传值传参),实在要传参,用间接传参&Head,函数声明可为Lsort_names(LNode_cer**)函数原型可为(LNode_cer** ppnode/LHead)*/{Lsort_names();}
}//booking()/*按航班号查找航班,若找到,返回1,并且将航班结点指针记录到Psave中;
为了带回多个/多种 结果,使用指针间接传参*/
int find_flight_route(char* flight,LFlightNode** Psave/*若找到对应航班,则将结果写在变量Psave中*/
/*LFlightNode* Head  Head是全局变量 无需传参即可使用*/)
{LFlightNode* p1 = Head;while (p1){if (!strcmp(p1->flight_num, flight)){(*Psave) = p1;/*保存找到的航班号的指针,以便修访问该结点*/return 1;/*表示已找到*/}p1 = p1->next;}return 0;
}/*承办退票业务系函数*////*判断是否有对应航班*/
//int is_find_flight(char* refund_flightNo)
//{
//    LFlightNode* p1 = Head;
//    while (p1)
//    {
//        if (strcmp(refund_flightNo, p1->flight_num))
//        {
//            return 1;
//        }
//        p1 = p1->next;
//    }
//    return 0;
//}/*根据传入的某个节点的指针,删除名单链表节点操作*/
void DeleteLNode_cer(LNode_Cer* p)/**/
{LNode_Cer* pre = LHead;/*特殊处理头结点的删除*/if (p == LHead){LHead = LHead->link;free(pre);return;}/*寻找pre的正确位置*/while (pre){if (pre->link == p)/*先找到要被删除的节点的 前驱节点pre*/{break;}pre = pre->link;/*没找到的话继续往后找*/}pre->link = p->link;free(p);
}
/*删除队头*/
void DeLQueueNode(LQueueNode_Can** pre)
{LQueueNode_Can* p1 = 0;/*LQueueNode_Can* pre = LQ.front;*//*用于辅助删除队列元素(由于链队列使用的空间是即使申请/释放的,不用考虑空间闲置的浪费问题(无需循环结构)*//*在候补队列中删除该名字*/p1 = *pre;*pre = (*pre)->link;/*队头前进.*/free(p1);/*释放旧队头节点*/return;
}
/*遍历询问候补乘客,直到遇到被退票(的航班)能够满足需求/都不满足需求为止,候补成功接受则要在候补队列中删除改名字*/
void inquiry_can_satisfy(LFlightNode* Psave)
{char c;printf("\n询问候补乘客,直到遇到被退票(的航班)能够满足需求/都不满足需求为止");LQueueNode_Can* p1 = 0;LQueueNode_Can* pre = LQ.front;/*用于辅助删除队列元素(由于链队列使用的空间是即使申请/释放的,不用考虑空间闲置的浪费问题(无需循环结构)*/int num_book = 0;char flight[MAX];while (pre){printf("\n航班%s是否能够满足您的目的地?(若是,输入y,并为您办理订票):", Psave->flight_num);c = getch();if (c == 'y'){booking();/*在候补队列中删除该名字*/DeLQueueNode(&LQ.front);/*注意参数写成&pre无法正确更改队头指针,当然可以尝试:DeLQueueNode(&pre);LQ.front=pre;*/printf("\n补办完成");return;}else{/*再次询问是否重新加入候补?*/char c;/*接收用户选择*/;char isCandidate;printf("\n余票不足,是否重新加入候补?(按y/Y)\n");isCandidate = getch();if (isCandidate == 'y' || isCandidate == 'Y'){printf("\n输入您想候补的航班号:");scanf("%s", flight);printf("\n输入您想要订的票数:");scanf("%d", &num_book);inquiry_enroll_candidate(num_book, flight);printf("\n候补完毕!");}/*否则删除该结点*/DeLQueueNode(&pre);} //else(仍不满足需求).           }//while(pre)遍历询问候补乘客printf("\n未满足任何以为候补顾客的需求.");
}/*根据用户提交的 航班号+日期,将对应票回收+1,删除已订票乘客名单里的名字;*/
void refund()
{/*char* refund_flightNo[MAX];糊涂了*/char refund_flightNo[MAX];char name[MAX];int refund_tickets_num = 0;/*保存被退的票的数量*/LNode_Cer* p1 = LHead;/*在名单中找到乘客名字*/LFlightNode* Psave;/*检查是否已录入航班信息,否则无法退票*/if (Empty_Flight()) return;while (1)/*直到输入正确的可退票行班,离开循环.*/{printf("\n\t可进行退票手续\n请输入您要退订的航班:");scanf("%s", refund_flightNo);if (find_flight_route(refund_flightNo, &Psave))/*搜索是否有对应航班号*/{/*约定:这里的名字是指是个人 名字+身份ID号综合体 的简称(比如 chaoxin_1375,是具有唯一性的主关键词*/printf("\n输入您的名字:");scanf("%s", name);printf("\n正在查找您的名字...\n");if (!p1){printf("\nsorry,没有该名字,请重新确认.\n");return;/*二级菜单*/}while (p1){if (!strcmp(p1->name, name)){refund_tickets_num = p1->num_tickets;/*执行删除操作(删除p1)*/printf("执行删除操作...\n");DeleteLNode_cer(p1);break;}p1 = p1->link;}//while(p1)printf("名字_ID 删除完毕\n");printf("\n回收机票...");/*回收机票*/Psave->remaining_tickets += refund_tickets_num;break;//离开外层循环}//ifelse{printf("\nsorry,没有找到该航班!请重新输入:");}}//while(1)printf("\n询问候补乘客的需求:\n");inquiry_can_satisfy(Psave);}//refund()/*主要复合函数*/
/*航班管理函数*/
void flightNo_manage()
{char c;//system("cls");此处cls函数导致屏幕打印混乱.(vs才可下正常运行.) ;/*清楚屏幕内容准备当前菜单的打印*/while (1){printf("\n\t\t          航班管理菜单:\n");printf("\n______________________________________________________________\n");printf("\t    1.                添加新的航班\n");printf("\t    2.                查询航班    \n");printf("\t    3.                查看航班    \n");printf("\t    4.               返回主菜单  \n");printf("\n\n______________________________________________________________\n");printf("\t       请选择您想要的服务(回车确定):");scanf("%c", &c);switch (c){case '1': input_flights(); break;/*添加新的航班*/case '2': print_flight_search(); break;/*查询航班*/case '3': Line_See_all(); break;/*查看航班(全部)*/case '4': return;default: Error_warning();}//switch()}//while}
/*查看当前乘客订单信息*/
void customer_check()
{char c;LNode_Cer* p1 = LHead;LQueueNode_Can* pQ = LQ.front, * pQrear = LQ.rear;printf("\n当前乘客订单信息");printf("\n\t1.订定票乘客信息");/*xin'xi*/printf("\n\t2.候补乘客信息");printf("\n\t选择您要的服务:");c = getch();switch (c){case '1':printf("\n订定票乘客信息\n按 名字_ID 主关键字升序排列:\n");while (p1){printf("\n\n乘客姓名:%s\n订票量:%d\n舱位等级:%d", p1->name, p1->num_tickets, p1->rank);p1 = p1->link;}break;/*如果不break,将总是会执行case'2'*/case '2':printf("\n候补乘客信息:");if (!pQ /*|| LQ.rear->link == pQ*/){printf("\n当前无候补乘客.");}while (pQ){printf("\n乘客姓名:%s\n订票量:%d\n", pQ->name, pQ->num_tickets);pQ = pQ->link;}break;default:break;}}/*主函数*/
int main()
{char c;/*接收一个字符,进入选中的菜单项*/do {//system("cls");//此处cls函数导致屏幕打印混乱.(vs才可下正常运行.) printf("\n\t\t 航空客运订票主系统菜单\n");printf("\t1.航班管理子菜单\n");printf("\t2.订票办理子菜单\n");printf("\t3.退票办理子菜单\n");printf("\t4.乘客信息查看子菜单\n");printf("\t5.退出\n");/*printf("\n\t请选择您想要的服务并回车确定:");scanf("%c", &c);*/printf("\n\t\t请选择您想要的服务:");c = getch();/*用switch执行调用相应函数执行相应功能*/switch (c){/*在4个复合函数中选择*/case '1': flightNo_manage(); break;/*航  班  管  理 (增) 菜  单*/case '2': booking(); break;/* 订  票  办  理 (增) 菜  单*/case '3': refund(); break;/*退  票  办  理 (增/删/查) 菜  单*/case '4':customer_check(); break;/*/'kʌstəmər/*/case '5': exit(0);/*退出系统*/default:; break;}  //switch} while (c != '5');return 0;
}

修理版

/*
1.设计数据结构
a)	每条航线所涉及的信息有:(填充5条航线,可以有相同的终点站但飞行日期等参数可以不同)
i.	终点站名、
ii.	航班号、
iii.飞机号、
iv.	飞机周日(星期几)、
v.	乘员定额、
vi.	余票量、b)	订定票的乘客名单(已订票乘客的线性表应按乘客姓名有序)(包括
i.	姓名、
ii.	订票量、(显然取决于乘客的需求)
iii.舱位等级1,2或3)
c)	等候替补的乘客名单(包括
iv.	姓名、
v.	所需数量)。2.	数据结构的基础上设计算法,使系统能实现的操作和功能如下:
1)	查询航线:根据乘客提出的 终点站名 输出如下信息:(读入用户输入,在各条航线里的对应成员相比较,若匹配则所有输出匹配航线的各项信息.)
i.	航班号、
ii.	飞机号、
iii.星期几飞行,
iv.	最近一天航班的日期和(将的到的所有匹配项,且日期大等于今日的航班做一个排序,并将最小日期输出)
v.	余票额;2)	承办订票业务:根据乘客提出的要求(航班号、订票数额)查询该航班票额情况,
i.	若有余票,则为乘客办理订票手续,输出座位号;
ii.	若已满员或余票少余订票额,则需重新询问乘客要求。
a)	若需要,可登记排队候补;
3)	承办退票业务:根据乘客提出的情况(日期、航班号),为乘客办理退票手续,
i.	然后查询该航班是否有人排队候补,首先询问排在第一的乘客,若所退票额能满足他的要求,则为他办理订票手续,
ii.	否则依次询问其它排队候补的乘客。
*//*外部问题:如何设计界功能菜单,选中并进入功能菜单?
使用printf()+switch()语句实现
scanf("%d", &a);
switch (a)
{
case 1: ;
}*/
/*约定,search()是根据关键字查询与该关键字相关的元素的各项详情(返回详情).是根据关键字查询有元素具有该关键字(返回是/否)*/
#define _CRT_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_DEPRECATE
#define _CRT_NONSTDC_NO_DEPRECATE#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
#include <ctype.h>
#include <conio.h> /*getch()所在头文件是conio.h。而不是stdio.h*/
#define MAXLEN 100
#define MAX 60
#define MAXNAME 10
/*  run   this
#define N 5/*航班号数量*//* 订定票的乘客链表结点结构 */
typedef struct LNode_Cer
{char name[MAXNAME]; /*乘客名字(订票的时候输入)名字的排序可以用插入的方式以保持有序*/int num_tickets;    /*订票量*/int rank;           /*仓位 等级class是保留字,用rank*/LNode_Cer *link; /*指针域*/
} LNode_Cer;         /*link node of Certain */
/*航线链表的结点结构*/
typedef struct LFlightNode
{char name_des[MAX];   /*终点站名*/char flight_num[MAX]; /*航班号:航班号某时某刻从某地飞往另一地的 航班航程的编号*/char plane_num[MAX];  /*飞机号:飞机号相当于飞机的身份证*/int plane_weekday;    /*星期几的航班*/int plane_crew;        /*乘员定额(最大乘客量)*/int remaining_tickets; /*剩余票量*//*三种等级仓位的价格int price[3]*//*此外,可考虑还能够查出该航线由哪些乘客以及候补乘客LNode_Cer* customerName;LNode_Cer* candidateName;*/LFlightNode *next;
} LFlightNode;/*等候替补乘客链队列节点*/ /*与顺序队列相比,就是队列结构里把数组用链表(头指针)替代(链表外置),虚拟指针用真正的指针替代*/
typedef struct LQueueNode_Can
{/*数据域(不同场景下条目可多可少,类型可以多样)*/char name[MAXNAME]; /*候补乘客名字*/int num_tickets;    /*该乘客需要的票数*//**/char flightNo[MAX]; /*候补乘客想要的航班*//*附加的指针域*/LQueueNode_Can *link;
} LQueueNode_Can; /*candidate*//*等待候补乘客链队列整体结构*/
typedef struct LQueue_Can
{// LQueueNode_Can LQueue[MAXLEN];LQueueNode_Can *front;LQueueNode_Can *rear;
} LQueue_Can;/*建立全局变量(在不至于混淆的情况下可以减少参数的传递)*/
/*任何函数都可访问到全局变量(不需要通过传参即可之间从内部访问)*/
LFlightNode *Head = NULL; /*第一个航班结点,初始化为NULL*/
LFlightNode *p2;          /*航班辅助指针(指向表尾结点)(如果不设立该全局变量,要使用表尾时也可以同从头遍历找到表尾*/LNode_Cer *LHead = 0; /*乘客链表表头表头*/
LNode_Cer *pLnow = 0; /*乘客链表表尾指针*/LQueue_Can LQ = {0, 0}; /*//这里的LQ不设置为指针,而是一个 链队列 类型的 变量,
会分配一个LQueue_Can类型变量大小的内存给LQ.(内部含有两个指针的变量类型),不方便直接初始赋值*//*检查输入的航班号是否早已被占用,返会 是/否*/
int is_already_have(LFlightNode *Head, char *flight_num)
{LFlightNode *p1 = Head;while (p1){if (!strcmp(p1->flight_num, flight_num)){return 1;}p1 = p1->next;}return 0;
}
/*f录入航班号(在停止之前一直录入)
需要注意的的是,航班号必须唯一,若发现重复录入,应给予提示:*/
void input_flights() /*line_add*/
{LFlightNode *p1;LFlightNode *ptemp; /*保存新申请的结点内存的指针*///p1 = Head;p2 = Head;char temp_flight_name[MAX]; /*暂存输入的航班号名*/char c;                     /*接收是否继续录入的指令*/while (1){printf("继续执行录入操作?(按y/Y以外的键退出.)\n");c = getch();if ((c != 'y' && c != 'Y')){break;}/*创建并写入头结点*/if (Head == NULL){p2 = (LFlightNode *)malloc(sizeof(LFlightNode));p2->next = NULL;Head = p2; /*获得表头结点(这一步只需执行一次)*/}else{p2 = p2->next = (LFlightNode *)malloc(sizeof(LFlightNode)); /*shen'qing申请+插入到表尾+更新表尾结点指针*///p2 = p2->next;/*gengxin更新表尾指针*/p2->next = NULL;/*这样直接赋值引发问题就是,p2被初始化为与Head一样地指向头结点,而头结点的指针域指向NULL,p2->next作为右值时就是NULL;p2->next作为左值时,是为了修改表头结点的指针域;*//*采用辅助指针ptemp的版本*///ptemp = (LFlightNode*)malloc(sizeof(LFlightNode));//if (!ptemp) exit(1);//ptemp->next = NULL;/*初始化新结点的指针域*///p2->next = ptemp;/*接入新结点*////*再更新表尾指针的对象*///p2 = ptemp;}/*向新结点写入数据*/printf("\n输入终点站名:");scanf("%s", p2->name_des);/*测试链表连通性,暂时屏蔽一些内容的填充:*/printf("\n请输入唯一的航班号:");while (1){/*scanf("%s", p2->flight_num);如果直接写入链表,那is_already_have()就总返回已占用,所有要用临时变量暂存输入.*/scanf("%s", temp_flight_name);if (is_already_have(Head, temp_flight_name)){printf("\n该航班号已被占用,请使用新的编号:");}else{strcpy(p2->flight_num, temp_flight_name);break;}}printf("\n输入飞机号:");scanf("%s", p2->plane_num);printf("\n输入出发出发日期(周几):");scanf("%d", &p2->plane_weekday); /*取成员->优先于取地址&*/printf("\n输入乘员定额:");scanf("%d", &p2->plane_crew);p2->remaining_tickets = p2->plane_crew; /*初始化余票额*/// scanf("%d", &p2->remaining_tickets);/*剩余票量由乘员定额-已被订购数决定*/} //while
} //input_flights()//目前读入功能正常
/**/
/*根据用户输入的终点站名,输出:航班号+飞机号+星期几飞行+最近一天的航班日期(额外开个函数,内部调用)+余票额*/
void print_flight_search() //line_search() 根据终点站名查找相关元素的详情.
{void print_closest_flight(int departure);char des_name[MAX];     //临时接收一个名字字符串.LFlightNode *p1 = Head; /*p1用于遍历链表结点,一般被初始化为Head,表头开始遍历*/if (Head == NULL){printf("\n\t        尚未录入任何航班数据,无法提供有效查询!");//getch();/*等待用户确认提示后按任意键返回;(也可直接返回)(提示信息已打印)return;} /*若已经录入一定信息*/printf("\n\t 请输入要查询的终点站名:");scanf("%s", des_name);printf("\n\t 查询结果:\n");int is_has = 0; /*标识是否找到符合条件的航班*/while (p1){if (!strcmp(p1->name_des, des_name)){is_has++;printf("终点站名:%s\n航班号:%s\n飞机型号:%s\n星期:%d\n余票量:%d\n",p1->name_des, p1->flight_num, p1->plane_num, p1->plane_weekday, p1->remaining_tickets);}p1 = p1->next;} //whileif (!is_has)printf("\n\tsorry,没有该航班");else{printf("\n\t输入要出发的日期(星期几),查询最近一天且未过期的航班:");int departure;scanf("%d", &departure);print_closest_flight(departure);}return;
}
/*配合print_search_ret()根据输入的终点打印最近一天的航班日期(当天即之后)
然而最小值并不一定只有一个!(二次遍历找到全部最小值*/
void print_closest_flight(int departure)
{LFlightNode *p1 = Head;LFlightNode *nearest_flight = p1;int delta = 0;int delta_min = 7;while (p1){if (p1->plane_weekday >= departure) /*筛选本周未过期的航班*/{/* delta = p1->plane_weekday - departure > 0 ?p1->plane_weekday - departure :departure - p1->plane_weekday ;delta = p1->plane_weekday - departure;if (delta < 0){delta = -1 * delta;}*//*找到最近的将来航班p.*/delta = p1->plane_weekday - departure; //必>=0if (delta < delta_min){delta_min = delta;nearest_flight = p1; /*保存当前为止的最近航班指针*/}} //if/* else{//可忽略.printf("\n此航班已过期,应该输入今天及之后的出发日期");}*/p1 = p1->next;} //while/*输出所有满足条件的最近hangban(航班)*/p1 = Head; /*复位*/while (p1){if (p1->plane_weekday == nearest_flight->plane_weekday){printf("航班:%s\n日期:%d\n", p1->flight_num, p1->plane_weekday);}p1 = p1->next;}
}/*航班查看(所有航班)函数 */
int Line_See_all()
{/*声明函数*/int Empty_Flight();LFlightNode *p1;//system("cls");此处cls函数导致屏幕打印混乱.(vs才可下正常运行.) ;/*清屏*/p1 = Head;/*打印前检查是否已录入航班信息被录入:*/if (Empty_Flight())return 0;printf("\n\n\t           航班信息:\n");while (p1 != NULL){{printf("终点站名:%s\n航班号:%s\n飞机型号:%s\n星期:%d\n余票量:%d\n\n",p1->name_des, p1->flight_num, p1->plane_num, p1->plane_weekday, p1->remaining_tickets); /*如果将整型数以%s输出会出错*/}p1 = p1->next;}printf("\n\t      按任意键确认返回!\n");getch();
}
/*判断航班是否为空函数(菜单调转)  */
int Empty_Flight()
{if (Head == NULL){//system("cls");此处cls函数导致屏幕打印混乱.(vs才可下正常运行.) ;printf("\n\t       sorry,尚不存在航班,按任意键返回!");getch();return 1;}elsereturn 0;
}
/*操作异常/非法提示*/
void Error_warning()
{printf("\n\t遇到非法或异常操作!\n");
}/*承办业务系(订票)函数
首先查找是否有对应航班;
若有对应航班,检查是否有余票,若有,询问要订购几张票*/
/*对已定票的乘客名单按名字进行排序*/
void Lsort_names(/*LNode_Cer* LHead*/) //经调试,可正常工作.(调试排序算法,可以在两个循环处+边界收缩处各打一个断点,用一组降序数来试)
{LNode_Cer *pp,*p,*q,*last,*HHead; /*外加头结点*//*创建头结点:*/HHead = (LNode_Cer *)malloc(sizeof(LNode_Cer));HHead->link = LHead;last = HHead;/*通过遍历,使得last被初始化为表尾指针*/while (last->link){last = last->link;}/*外层循环*/while (last != HHead->link) /*控制排序趟数,last走到表头前,继续比较*/{pp = HHead;p = pp->link;/*内层循环(last是右元素的右边界)*/while (p != last) /*直到:q == last进入循环并完成比较)(即右边界参与了比较),随后p,q都再向后移动一个元素,这时要离开了,判断条件为p == last*/{q = p->link;if (strcmp(p->name, q->name) > 0){pp->link = q;      /*1接3*/p->link = q->link; /*2接4*/q->link = p;       /*3接2*//*在必要时修正被悄然前调的last*/if (last == q){last = p;} //if} //ifpp = (strcmp(p->name, q->name) < 0) ? p : q;p = pp->link;} //while(内存)last = pp; /*last向前回溯*/} //while(外层)LHead = HHead->link;free(HHead); /*释放掉补偿的头结点HHead*/return;
}
/*询问是否参加候补+登记候补*/
void inquiry_enroll_candidate(int num_book, char *flight)
{{/*加入候补队列*//*在本函数之外就将准备好一个初始化完毕的队列,以便随时插入.*/printf("输入您的名字:");if (LQ.front == 0 && LQ.rear == 0) /*链队列的队头与队尾指针同时为NULL,为空队充分但不必要条件(与具体的实现有关)*/{                                  /*处理队头*//*在入队列的过程中,为队头front赋值只执行一次即可.*/LQ.front = LQ.rear = (LQueueNode_Can *)malloc(sizeof(LQueueNode_Can));/*专门填充队头元素*/scanf("%s", LQ.rear->name);LQ.rear->num_tickets = num_book;LQ.rear->link = 0;}else /*处理队身*/{// EnQueue()入队列(尾)/*不用辅助指针s*/LQ.rear->link = (LQueueNode_Can *)malloc(sizeof(LQueueNode_Can)); /*申请新结点的同时+入队列(写入到当前节点的指针域)*/LQ.rear = LQ.rear->link;                                          /*加入新结点空间后,更新表尾指针*//*及时初始化节点的指针域*/LQ.rear->link = 0;/*向新结点写入信息*/scanf("%s", LQ.rear->name);LQ.rear->num_tickets = num_book;strcpy(LQ.rear->flightNo, flight); /*该语句中入股flight是乱七八糟的东西可以导致尾节点指针域混乱(由NULL变成其他的东西)*/// printf("\nobserve");/*使用辅助指针s可以使表达式更短.*///s = (LQueueNode_Can*)malloc(sizeof(LQueueNode_Can));//if (!s) exit(1);//                  /*向新结点写入信息*///                  scanf("%s", s->name);//s->num_tickets = num_book;//                  strcpy(s->flightNo, flight);/*原本想订的航班号:*///                  /*新结点入队列*///LQ.rear->link = s;//LQ.rear = s;/*更新队尾指针*/} //else/*处理队身*/} //if(若参与候补,否则pass该乘客,询问下一位乘客)//printf("\nobserve");return;
} //inquiry_enroll_candidate/*判断用户输入的 航班号+订票数量 检查对应航班是否有余票,同时办理订票+询问候补需要*/
void booking()
{/*声明函数:*/int find_flight_route(char *flight, LFlightNode **Psave/*若找到对应航班,则将结果写在变量Psave中*/ /*LFlightNode* Head  Head是全局变量 无需传参即可使用*/);char c; /*接收用户选择*/char flight[MAX];int num_book = 0;LFlightNode *Psave = 0; /*通过函数find_flight_route(),将找到的航班结点的指针带回(修改Psave)*/LQueueNode_Can *s = 0;if (Empty_Flight()){return;}printf("\n当前可以订票");while (1){printf("\n输入行班号:");scanf("%s", flight);if (!find_flight_route(flight, &Psave)){printf("sorry,没有该航班!");}else if (Psave->remaining_tickets) /*找到该航班,检查改航班是否满员*/{printf("尚有余票,输入您想要定的票的数量:\n");scanf("%d", &num_book);if (num_book < Psave->remaining_tickets) /*余票chongzu充足*/{/*满足该乘客需求,登记购票*/printf("余票数量充足\n输入您的名字:");/*创建并向链表头写入数据*/if (!LHead){pLnow = (LNode_Cer *)malloc(sizeof(LNode_Cer));LHead = pLnow;   /*保存头结点指针;pLnow 是辅助指针(而且是全局变量(可不必全局)*/pLnow->link = 0; /*初始化新结点的指针域*/}else /*链表身体*/{/*直接从当前节点接收新节点内存地址.(直接挂接到表尾.)*/pLnow->link = (LNode_Cer *)malloc(sizeof(LNode_Cer));pLnow = pLnow->link; /*更新pLnow*/pLnow->link = 0;     /*初始化新结点的指针域*//*引入辅助指针+初始化新结点的指针域:*/}/*向新节点内写入内容*/pLnow->num_tickets = num_book;scanf("%s", pLnow->name);printf("购买几等票:");scanf("%d", &pLnow->rank);Psave->remaining_tickets -= num_book;/*输出座位号:*/printf("您的座位号:%d\n\n", Psave->plane_crew - Psave->remaining_tickets);}    //ifelse /*余票不足*/{char c; /*接收用户选择*/char isCandidate;printf("余票不足,是否加入候补?(按y/Y)\n");isCandidate = getch();if (isCandidate == 'y' || isCandidate == 'Y')inquiry_enroll_candidate(num_book, flight);} //else/*余票不足*/printf("\n是否继续订票?\n输入y继续");c = getch();if (c != 'y'){break;} //跳出(连续订票循环)}     //if(若有余票)}         //while(连续订票循环)/*订顶票乘客非空,则为乘客链表排序*/if (LHead)//Lsort_names(LHead);/*需要纠正的观念是,如果全局变量当初本地变量传入参数的话,可能使得修改白费(优先识别为传值传参),实在要传参,用间接传参&Head,函数声明可为Lsort_names(LNode_cer**)函数原型可为(LNode_cer** ppnode/LHead)*/{Lsort_names();}
} //booking()/*按航班号查找航班,若找到,返回1,并且将航班结点指针记录到Psave中;
为了带回多个/多种 结果,使用指针间接传参*/
int find_flight_route(char *flight,LFlightNode **Psave /*若找到对应航班,则将结果写在变量Psave中*//*LFlightNode* Head  Head是全局变量 无需传参即可使用*/)
{LFlightNode *p1 = Head;while (p1){if (!strcmp(p1->flight_num, flight)){(*Psave) = p1; /*保存找到的航班号的指针,以便修访问该结点*/return 1;      /*表示已找到*/}p1 = p1->next;}return 0;
}/*承办退票业务系函数*//*根据传入的某个节点的指针,删除名单链表节点操作*/
void DeleteLNode_cer(LNode_Cer *p) /**/
{LNode_Cer *pre = LHead;/*特殊处理头结点的删除*/if (p == LHead){LHead = LHead->link;free(pre);return;}/*寻找pre的正确位置*/while (pre){if (pre->link == p) /*先找到要被删除的节点的 前驱节点pre*/{break;}pre = pre->link; /*没找到的话继续往后找*/}pre->link = p->link;free(p);
}
/*删除队头*/
void DeLQueueNode(LQueueNode_Can **pre)
{LQueueNode_Can *p1 = 0;/*LQueueNode_Can* pre = LQ.front;*/ /*用于辅助删除队列元素(由于链队列使用的空间是即使申请/释放的,不用考虑空间闲置的浪费问题(无需循环结构)*//*在候补队列中删除该名字*/p1 = *pre;*pre = (*pre)->link; /*队头前进.*/free(p1);            /*释放旧队头节点*/return;
}
/*遍历询问候补乘客,直到遇到被退票(的航班)能够满足需求/都不满足需求为止,候补成功接受则要在候补队列中删除改名字*/
void inquiry_can_satisfy(LFlightNode *Psave)
{char c;printf("\n询问候补乘客,直到遇到被退票(的航班)能够满足需求/都不满足需求为止");LQueueNode_Can *p1 = 0;LQueueNode_Can *pre = LQ.front; /*用于辅助删除队列元素(由于链队列使用的空间是即使申请/释放的,不用考虑空间闲置的浪费问题(无需循环结构)*/int num_book = 0;char flight[MAX];while (pre){printf("\n航班%s是否能够满足您的目的地?(若是,输入y,并为您办理订票):", Psave->flight_num);c = getch();if (c == 'y'){booking();/*在候补队列中删除该名字*/DeLQueueNode(&LQ.front); /*注意参数写成&pre无法正确更改队头指针,当然可以尝试:DeLQueueNode(&pre);LQ.front=pre;*/printf("\n补办完成");return;}else{/*再次询问是否重新加入候补?*/char c; /*接收用户选择*/;char isCandidate;printf("\n余票不足,是否重新加入候补?(按y/Y)\n");isCandidate = getch();if (isCandidate == 'y' || isCandidate == 'Y'){printf("\n输入您想候补的航班号:");scanf("%s", flight);printf("\n输入您想要订的票数:");scanf("%d", &num_book);inquiry_enroll_candidate(num_book, flight);printf("\n候补完毕!");}/*否则删除该结点*/DeLQueueNode(&pre);} //else(仍不满足需求).}     //while(pre)遍历询问候补乘客printf("\n未满足任何以为候补顾客的需求.");
}/*根据用户提交的 航班号+日期,将对应票回收+1,删除已订票乘客名单里的名字;*/
void refund()
{/*char* refund_flightNo[MAX];糊涂了*/char refund_flightNo[MAX];char name[MAX];int refund_tickets_num = 0; /*保存被退的票的数量*/LNode_Cer *p1 = LHead;      /*在名单中找到乘客名字*/LFlightNode *Psave;/*检查是否已录入航班信息,否则无法退票*/if (Empty_Flight())return;while (1) /*直到输入正确的可退票行班,离开循环.*/{printf("\n\t可进行退票手续\n请输入您要退订的航班:");scanf("%s", refund_flightNo);if (find_flight_route(refund_flightNo, &Psave)) /*搜索是否有对应航班号*/{/*约定:这里的名字是指是个人 名字+身份ID号综合体 的简称(比如 chaoxin_1375,是具有唯一性的主关键词*/printf("\n输入您的名字:");scanf("%s", name);printf("\n正在查找您的名字...\n");if (!p1){printf("\nsorry,没有该名字,请重新确认.\n");return; /*二级菜单*/}while (p1){if (!strcmp(p1->name, name)){refund_tickets_num = p1->num_tickets;/*执行删除操作(删除p1)*/printf("执行删除操作...\n");DeleteLNode_cer(p1);break;}p1 = p1->link;} //while(p1)printf("名字_ID 删除完毕\n");printf("\n回收机票...");/*回收机票*/Psave->remaining_tickets += refund_tickets_num;break; //离开外层循环}          //ifelse{printf("\nsorry,没有找到该航班!请重新输入:");}} //while(1)printf("\n询问候补乘客的需求:\n");inquiry_can_satisfy(Psave);} //refund()/*主要复合函数*/
/*航班管理函数*/
void flightNo_manage()
{char c;//system("cls");此处cls函数导致屏幕打印混乱.(vs才可下正常运行.) ;/*清楚屏幕内容准备当前菜单的打印*/while (1){printf("\n\t\t          航班管理菜单:\n");printf("\n______________________________________________________________\n");printf("\t    1.                添加新的航班\n");printf("\t    2.                查询航班    \n");printf("\t    3.                查看航班    \n");printf("\t    4.               返回主菜单  \n");printf("\n\n______________________________________________________________\n");printf("\t       请选择您想要的服务(回车确定):");scanf("%c", &c);switch (c){case '1':input_flights();break; /*添加新的航班*/case '2':print_flight_search();break; /*查询航班*/case '3':Line_See_all();break; /*查看航班(全部)*/case '4':return;default:Error_warning();} //switch()}     //while
}
/*查看当前乘客订单信息*/
void customer_check()
{char c;LNode_Cer *p1 = LHead;LQueueNode_Can *pQ = LQ.front, *pQrear = LQ.rear;printf("\n当前乘客订单信息");printf("\n\t1.订定票乘客信息"); /*xin'xi*/printf("\n\t2.候补乘客信息");printf("\n\t选择您要的服务:");c = getch();switch (c){case '1':printf("\n订定票乘客信息\n按 名字_ID 主关键字升序排列:\n");while (p1){printf("\n\n乘客姓名:%s\n订票量:%d\n舱位等级:%d", p1->name, p1->num_tickets, p1->rank);p1 = p1->link;}break; /*如果不break,将总是会执行case'2'*/case '2':printf("\n候补乘客信息:");if (!pQ /*|| LQ.rear->link == pQ*/){printf("\n当前无候补乘客.");}while (pQ){printf("\n乘客姓名:%s\n订票量:%d\n", pQ->name, pQ->num_tickets);pQ = pQ->link;}break;default:break;}
}/*主函数*/
int main()
{char c; /*接收一个字符,进入选中的菜单项*/do{//system("cls");//此处cls函数导致屏幕打印混乱.(vs才可下正常运行.)printf("\n\t\t 航空客运订票主系统菜单\n");printf("\t1.航班管理子菜单\n");printf("\t2.订票办理子菜单\n");printf("\t3.退票办理子菜单\n");printf("\t4.乘客信息查看子菜单\n");printf("\t5.退出\n");/*printf("\n\t请选择您想要的服务并回车确定:");scanf("%c", &c);*/printf("\n\t\t请选择您想要的服务:");c = getch();/*用switch执行调用相应函数执行相应功能*/switch (c){/*在4个复合函数中选择*/case '1':flightNo_manage();break; /*航  班  管  理 (增) 菜  单*/case '2':booking();break; /* 订  票  办  理 (增) 菜  单*/case '3':refund();break; /*退  票  办  理 (增/删/查) 菜  单*/case '4':customer_check();break; /*/'kʌstəmər/*/case '5':exit(0); /*退出系统*/default:;break;} //switch} while (c != '5');return 0;
}

还可以修正的点:

余票不足时仍然提示还剩下几张(而不是直接拒绝该用户的订票操作)

(考虑到用户可能会先让一部分人买到票)

对于购票者的id 不单单是说约定一个可以不重复的主键(命名规则),而且还要辅以必要的检查违约功能

(就比如说,社会约定大家不犯罪,但是还是有个别人会犯罪,这就需要提供强制性检查并处分(拒接非法行为的执行),(就像航班号的重名检查并给出具体反馈)


http://chatgpt.dhexx.cn/article/Tf2LpwZh.shtml

相关文章

航空机票订票系统

项目介绍 主要功能是使订票系统可以录入航班情况&#xff0c;查询某个航线的情况、办理订票、办理退票、修改航班信息、查询订票信息等。完成此系统&#xff0c;需要综合运用数据结构课程中学到的几种典型数据结构&#xff0c;以及程序设计语言&#xff08;C语言&#xff09;&…

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

目录 前言 一、作业要求介绍 二、各个函数的实现 1.头文件总结需要的功能 &#xff08;1&#xff09;结构体的定义 &#xff08;2&#xff09;各个功能的函数 2.各个函数的具体实现 &#xff08;1&#xff09;初始化 &#xff08;2&#xff09;打印航班信息表 &#xff08;4&…

Java实现航空机票订票系统

1、要求&#xff1a; &#xff08;1&#xff09;设计每条航线所涉及的信息&#xff0c;如终点站名、航班号、飞机号、飞机周日&#xff08;星期几&#xff09;、乘员定额、余票量、订定票的客户名单&#xff08;包括姓名、订票量、舱位等级1&#xff0c;2或3&#xff09;等&…

c语言航空订票系统程序设计,C语言航空订票系统

C语言航空订票系统 这 是 一 篇 用 C 语 言 编 写 的 航 空 订 票 系 统 的 论 文 。 该 系 统 使 用 的 是十 字 链 表 结 构 &#xff0c; 包 含 有 订 票 &#xff0c; 退 票 &#xff0c; 录 入 航 班 信 息 &#xff0c; 查 询 航 班 余 票 &#xff0c; 查询 个 人 订 票…

航空订票系统C++课程设计

航空订票系统 项目实践完整源码 前言一、功能演示二、代码总结 提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 前言 编写程序模拟航空订票系统&#xff0c;要求实现以下功能&#xff1a; ① 允许增、删、改航班信息&#…

数据结构课设-航空客运订票系统(C语言实现)

航空客运订票系统&#xff08;C语言实现&#xff09; 系统框架已完成功能用户功能管理员功能其他 运行结果管理员添加航班客户订票添加候补客户退票 代码 系统框架 已完成功能 用户功能 查询航线&#xff1a;根据旅客提出的终点站名输出航班的信息。订票业务&#xff1a;根据…

C++课程设计:航空客运订票系统

航空客运订票系统 选题背景 方案论证 过程论述 运行结果 完整代码 选题背景 ①背景: 现在人们更多的使用飞机作为出行交通工具&#xff0c;因此机票票务市场也在快速发展。国内外航空事业在飞速发展&#xff0c;各航空公司对票务管理的要求也在不断的提高&#xff0c;对…

基于ssm的航空订票系统

基于ssm的航空订票系统 一、技术栈 ​ 前端 ​ vue全家桶、element-ui组件库、moment.js插件 ​ 后端 ​ springboot springmvc mybatis 二、功能描述 本系统是基于B/S架构的航空订票系统 系统分为三大用户–乘客、航空公司、后台管理员&#xff0c;本次课程设计主要实现…

课程设计之航空客运订票系统

/***************************************************** * 版权所有&#xff08;C&#xff09;2016&#xff0c;王力源 * *文件名称&#xff1a;A.C 航空售票系统 *文件标识&#xff1a;无 *内容摘要&#xff1a;航空售票系统 *其他说明&#xff1a;无 *当前版本&#xff1…

航空客运订票系统(数据结构课设)

前言&#xff1a; 广工数据结构课设&#xff0c;基本需求和选做内容以及一些小扩展均已实现&#xff0c;此博客仅展示一部分&#xff0c;实验报告文档、源代码和可运行程序&#xff08;.exe文件&#xff09;等可以去我的github或者码云上下载&#xff0c;如果对您有帮助&#…

python-数据结构-大学生-航空订票系统

python-数据结构-大学生-航空订票系统 1.问题描述及任务描述 1.1问题描述 航空订票系统&#xff1a;可以实现航空客运订票的主要业务活动 基本要求&#xff1a; &#xff08;1&#xff09;航线管理&#xff1a;每条航线所涉及的信息由&#xff1a;终点站名、航班号、飞机号、…

C语言航空订票系统课程设计

目录 1.设计目的&#xff1a; 2总体设计和功能&#xff1a; 3.菜单设计 4.各功能代码详解&#xff08;闲话少扯&#xff09;&#xff1a; 4.1.C语言文件的操作&#xff1a; 4.2.读取航班信息&#xff1a; C语言知识回顾 4.3.打印航班信息 5.根据要求查找航班&#xf…

C语言 数据结构课设 航空订票系统

目录 实现功能 部分功能测试截图 ​ 代码展示 实现功能 1.订票 2.退票 3.查询航班信息 4.修改航班信息 5.录入航班信息 6.打印订票信息 部分功能测试截图 功能选择界面 查询航班功能测试 订票功能测试 打印订票信息 代码展示 代码中需要的二个文件内容如下 第一个是代码中的…

【计算机毕业设计】41.航空订票系统

摘 要 网络的广泛应用给生活带来了十分的便利。所以把航空订票与现在网络相结合&#xff0c;利用JSP技术建设航空订票系统&#xff0c;实现航空订票的信息化。则对于进一步提高航班公司的发展&#xff0c;丰富航空订票经验能起到不少的促进作用。 航空订票系统能够通过互联网…

航空订票系统(javaweb项目)

航空订票系统课程设计 一、项目选题 航空订票系统 二、项目背景 当今社会知识经济高速发展&#xff0c;信息化在各个行业内正在被越来越广泛的应用。人们生活水平的不断提高&#xff0c;使得出行的交通工具也跟着发展起来。如今乘飞机出行的人越来越多&#xff0c;这方面的市…

数据结构课设——航空航天订票系统

文章目录 一、系统简介    1、业务活动    2、操作和功能二、系统功能模块图    1、系统功能模块图    2、函数功能模块三、详细描述    1、数据结构    2、设计思路四、运行结果    1、查询所有航班    2、根据起点终点搜索航班    3、订…

mysql导出表结构及数据的三种方法

navicat导出表一共有三中用法&#xff1a; 第一种&#xff1a;数据库上右键—>"转储SQL文件"&#xff0c;如图&#xff1a; "转储文件"是把整个数据库表全部导出&#xff0c;所有的表都是先drop然后create&#xff0c;insert。 第二种&#xff1a;部分表…

将mysql中的数据库表导出和导入

目录 导出数据库 导入数据库 导出数据库 如果你的mysql没有配置环境变量&#xff0c;首先需要进到你所安装的mysql目录下的bin目录 进入之后输入&#xff1a; mysqldump -uroot -p booksystem > booksystem.sql 其中booksystem是你要导出的数据库中的名字&#xff0c;book…

MySQL——表的导出和导入

有时会需要将MySQL数据4中的数据导出到外部存储文件中&#xff0c;MySQL数据库中的数据可以导出成qI文本文件、xml文件或者html文件&#xff0c;同样这些导出的文件也可以导入MySQL数据库中&#xff0c; 一. 表的导出 1. 用 SELECT…INTO OUTFILE 导出文本文件 在 MySQ…

C代码实现Mysql导出表数据,sql语句保存

概述 本人最近项目的要求&#xff0c;需要定时检查数据库变化&#xff0c;定时将变化的数据库数据导出来另外保存。 所以研究数据库数据导出功能&#xff0c;并记录下开发过程。因暂时没有需要&#xff0c;没有将数据库的结构保存。 软件环境 编译器&#xff1a;vs2022 数据…