实习报告
题目:2.7 编写一个模拟航空客运定票系统的程序
班级: 姓名: 学号:完成日期:
一. 需求分析:
1. 程序需要模拟航空客运订票系统所处理的业务包括:A航线查询 B客户预定机票C办理退票。
2. 航线查询:
i.系统里储存了每条航线信息包括:终点站名,航班号,飞机号,飞行星期,日期,乘员定额,余票量,已定客户名单,以及等候替补的客户名单。
由于本程序只是示意系统,因此不采用文件输入,需要由(后台)管理员直接输入内存,输入信息包括:终点站名,航班号,飞机号,飞行星期,日期,乘员定额。
当系统内还没有录入航线信息时给出提示,无信息可以查询。
ii.系统按照客户键入的终点站名,输出对应航线的有关信息包括:终点站名,航班号,飞机号,飞行星期,日期,余票量。
3. 客户预订机票:
i.首先由客户输入航班号,订票数量。
ii.系统根据航班号在相应的航线顺序表中查找该航线,如果没找到该航线则告之客户输入信息有误;如果找到则比较该航线剩余票数量与订票数量,剩余票数量大于或者等于用户订票数量则填写客户信息包括(姓名,订票量,船舱等级)然后将用户插入到此航线的已定客户名单中,剩余票数量相应减少,同时为客户输出相应的座位号。如果剩余票数量小于用户订票数量,则告之票不够,是否登记不票,如是则将客户排在该航线的等候替补名单中,
4. 客户退票:
i.由客户输入订票航班号和日期。
ii.系统根据航班号,日期在相应的航线顺序表中查找该航线,如果没找到该航线则告之客户输入信息有误;如果找到则填写客户信息包括(姓名,订票量,船舱等级)然后将用户此航线的已定客户名单中删除,剩余票数量相应增加。
iii.查看替补客户名单,若有人排队则查看该客户的订票量,若退票额满足他的要求则将他插入到此航线的已定客户名单中,并从等候替补的客户名单中删除。若退票额不满足他的要求,则依次询问。
5. 设计一个人机交互界面:在屏幕上显示命令操作的提示信息,由用户从键盘上输入命令执行。
6. 本程序执行的命令包括:
A航线查询 B定票 C退票 D后台操作 E退出系统
其中后台需要密码操作又管理员录入。
7.为了便于演示,本程序假定每条航线由航班号唯一确定,而每一个办理业务的客户都不同名字。
8.测试数据为:
a.管理员录入3条航线信息:
航线排列 |
终点站名 |
航班号 |
飞机号 |
飞行星期 |
日期 |
乘员定额 |
1 |
北京 |
K2 |
123 |
星期六 |
2008.11.8 |
20 |
2 |
北京 |
K3 |
456 |
星期五 |
2008.11.7 |
23 |
3 |
成都 |
K4
|
789 |
星期四 |
2008.11.6 |
25 |
b.查询:
终点站名:北京 输出航线1,3.
c.订票:
航班号:k2 订票量:10 客户姓名:张三 船舱等级:2
航班号:k1 订票量:10 客户姓名:李四 船舱等级:2
航班号:k2 订票量:12 客户姓名:王二 船舱等级:2
为张三订票,无法为李四订票,打印无此航班,王二所定票超过了余票,询问是否替补排队,则是排队,不是则退出。
d.退票:
订票日期:2008.11.8 航班号:k2 客户姓名:李四 船舱等级:2 订票量:10
订票日期:2008.11.7 航班号:k2 客户姓名:张三 船舱等级:2 订票量:10
订票日期:2008.11.8 航班号:k2 客户姓名:张三 船舱等级:2 订票量:10
说明:李四没有定票,来退票,系统应做出正确处理。可能用户张三忘了自己的订票日期为:2008.11.8,而输成了2008.11.7,系统对于输入的错误命令也应该做出正常处理。
e.假设王二登记排队,这时张三已经退了票,则为王二订票。王二又来退票时就可以退票。
二. 总体设计:
1.由需求分析可知:应按顺序表存储每一条航线信息,已定客户名单为了插入和删除方便应采用线性链表存储并按客户名字的字母表顺序排列;等候替补的客户名单由于预约的客户无法预计并且按照先来先安排的原则,采用链队列存储。下面是系统的存储结构示意图:元素类型:客户
客户姓名: |
订票量: |
船舱等级: |
航线顺序表
终点站名 destination |
航班号 fnumber |
飞机号 pnumber |
飞行星期 week |
日期 date |
乘员定额 amounts |
余票量 ltickets |
已定客户名单 Linklist l |
等候替补的客户名单 Linkqueue Q |
航线总条数: |
航线1….n |
航线i:
已订客户组成的链表:
NULL |
元素客户 |
*next |
|
等候替补的客户所组成的队列:
NULL |
元素客户 |
*next |
|
2.数据对象:上图中的元素——客户,
3.数据关系:上图所示。
4.基本操作:
链表的初始化::initlist (Linklist &l)
把已经订的客户插入链表,按姓名排序:listinsert (Linklist&l,client e)
按姓名删除已经订票的客户,并将客户信息放入e返回,假定客户名互不相同:listdelete (Linklist&l,client &e)
***************************************************************************
构造一个空队列:initqueue (Linkqueue &Q)
插入e为新的队尾元素:enqueue (Linkqueue&Q,client e)
如果队列不空,退票数量满足客户要求则删除:dequeue (Linkqueue&Q,int a,client &e )//a为退票数量
***************************************************************************
打印屏幕提示信息:print ()
由后台完成对整个航线顺序表的初始化:create (sqlist &fl)
系统的订票功能:order (sqlist & fl)
其他操作由于很简单无需单独写一方法实现,可直接在主函数中完成。
5.程序模块:
void main ()
{ …..
Do{
接受命令;
处理命令;
}while(命令!=”退出”);
}
三. 详细设计:
1. 所用数据类型的定义:
typedef struct {//元素类型
char name[20];
int order;
int rank;
}client;
typedef struct Lnode{//已经定票的客户名单,链表存储的结点类型
client el;//
Lnode *next;
}Lnode,*Linklist;
typedef struct Qnode{//需要补票的客户,链队列存储的结点类型
client ele;
Qnode *next;
}Qnode,*Queue;
typedef struct {//用一结构体封装链队列的头尾指针
Queue front;
Queue rear;
}Linkqueue;
typedef struct flightline {//顺序表元素类型
char destination[20];
char fnumber[10];
char pnumber[10];
char week[20];
char date[20];
int amounts;
int ltickets;
Linklist l;
Linkqueue Q;
}flightline;
typedef struct {//顺序表的定义
flightline elem [N];
int length;
}sqlist;
2. 主要操作的伪码算法:
#include <stdlib.h>
#include <string.h>
#define N 500
#define ok 1
int initlist (Linklist &l)
{//链表的初始化
l=new Lnode;
if(l==NULL) exit (1);
l->next=NULL;
return ok;
}
int listinsert (Linklist&l,client e)
{//把已经订的客户插入链表,按姓名排序
*p=l;//设置两个指针一前一后便于查找和插入,后面用法也相似
*q=p->next;
while(p&&q&&strcmp(e.name,(q->el).name))
{//按姓名进行查找
p=p->next;q=p->next;
}
Lnode *s=new Lnode;
s->el=e;
s->next=q;
p->next =s;
return ok;
}
int listdelete (Linklist &l,client&e)
{//按姓名删除已经订票的客户,并将客户信息放入e返回,假定客户名互不相同
*p=l;*q=p->next;
while (q) {
if(!strcmp((q->el).name,e.name))
{p->next=q->next; delete(q);returnok;break; }
p=p->next;q=p->next;//没找到指针继续下移
}
if(!q){//如果表查找完也没有找到该客户则返回0
return 0;
}
}
int initqueue (Linkqueue &Q)
{//构造一个空队列
Q.front=Q.rear=new Qnode;
if( Q.front==NULL) exit (1);
Q.front->next=NULL;
return ok;
}
int enqueue (Linkqueue &Q,cliente)
{//插入e为新的队尾元素
Qnode *p=new Qnode;
if(p==NULL) exit (1);
p->ele=e;
Q.rear->next=p;p->next=NULL;Q.rear=p;
returnok;
}
int dequeue (Linkqueue &Q,int a,client&e )//a为剩票数量
{//如果队列不空,退票数量满足客户要求则删除。说明:此队列并非严格意义上的队列,因其要满足用户的订票小于退票量,才能将他从队列中删除
if(Q.front=Q.rear) return0;
Qnode*p=Q.front,*q=p->next;
while (q&&a){
if((q->ele).order<=a)
{
p->next=q->next;delete (q);break;
}
p=p->next;q=p->next;
}
return ok;
}
void print ()
{//打印屏幕提示信息
cout<<"t请按以下命令进行操作n";
cout<<"********************************n";
cout<<"tA航线查询n";
cout<<"tB定票n";
cout<<"tC退票n";
cout<<"tD后台操作n";
cout<<"tE退出系统n";
}
void create (sqlist&fl)//由后台完成对整个航线顺序表的初始化
{
cout<<"请输入航线总条数n"; cin>>x;
fl.length=x;
for (i=0;i<x;i++)
{
Cin>>fl.elem[i];(依次输入航线信息这儿就不再具体实现);
fl.elem[i].ltickets=fl.elem[i].amounts;//余票初始化
initlist(fl.elem[i].l); initqueue(fl.elem[i].Q);//顺序表的两个指向已经订票的链表和替补的链队列初始化
}
cout<<"完成创建n";
}
void order (sqlist & fl)
//由于此功能太长,另写一函数实现系统的订票功能
{
charfn[10];
int counts,i;
cin>>fn; //输入航班号
cin>>counts;//定票数量
for ( i=0;i<fl.length;i++)//在航线表中按航班号查找相应的航线
{
if (!strcmp(fl.elem [i].fnumber,fn))
{
if(fl.elem[i].ltickets>=counts)//如果余票量满足客户的订票数则填客户信息
{
client c;
cin>>c;(具体需要一个一个赋值)
listinsert(fl.elem[i].l ,c); //然后将其插入已经定票客户链表
for(intj=1;j<=counts;j++)//打印座位号
{
cout<<fl.elem[i].amounts-fl.elem[i].ltickets+j<<'t';
}
fl.elem[i].ltickets -=c.order;//相应余票减少
cout<<"尊敬的客户您已经成功预定机票!n";
}
else//如果余票小于客户所定票则询问是否排队
{
char ch; cin>>ch;
if(ch=='y'||ch=='Y')
{
client d;
//填写客户信息
cin>>d;
enqueue(fl.elem[i].Q ,d);//排队,插入队尾
}
if(ch=='n'||ch=='N')
{
cout<<"谢谢使用!n";
}
}
break;
}
}
if(i>fl.length)//出错处理
{
cout<<"您键入的信息有误!n";
}
}
3. 主函数中实现调用功能函数和一些小的模块:
void main ()
{ //由于程序很长,不便一一写出,详细请参见源代码
print();sqlist fl;fl.length=0;
cout<<"请输入命令n";
cin>>ch;
while(ch!='E'&&ch!='e')
{
switch (ch)
{
case 'd':
case 'D': //密码处理
case 'a':
case 'A': if(fl.length){ // 实现系统的查询功能
}
else{cout<<"n无可用信息查询n";}
break;
case 'b':
case 'B': if (fl.length) { order (fl);}
else{cout<<"n系统内无航线信息,无法订票n";}
break;
case 'c':
case 'C': if(fl.length) {//退票处理}
else{cout<<"n系统内无航线信息,无法订票n";}
break;
default: cout<<"您输入的命令有误,请输入正确的命令!n";
}
cin>>ch;
}
}
四.调试分析:
本程序编译中除了忘了加很多分号外,编译顺利通过,但出现了运行错。
1.一开始数据定义中诸多需要用户输入的字类型的数据如航班号,飞机号,客户姓名等,使用字符指针,但发现不能录入,程序不能继续运行。
2. 一开始很多异常情况未考虑,无法对错误的命令做出处理。
3. 一开始功能不够完善,程序使用了太多的判断语句 。
五.用户手册:
1.本程序的运行环境为DOS,执行文件为:航空客运定票模拟系统.exe
2.用户根据界面提示进行操作即可。
六.测试预期结果与运行结果比较:
运行后出现的界面及结果:
请按以下命令进行操作
********************************
A航线查询
B定票
C退票
D后台操作
E退出系统
请输入命令
a
无可用信息查询
d
请输入密码
789198
请输入航线总条数
3
第1条航线信息按航线终点站名的字母顺序依次输入终点站名
北京
航班号 k2
飞机号 123
星期 星期六
日期 2008.11.8
乘客的定额 20
第2条航线信息按航线终点站名的字母顺序依次输入终点站名
北京
航班号 k3
飞机号 456
星期 星期五
日期 2008.11.7
乘客的定额 23
第3条航线信息按航线终点站名的字母顺序依次输入终点站名
成都
航班号 k4
飞机号 789
星期 星期四
日期 2008.11.6
乘客的定额 25
完成创建
a
请输入终点站名
北京
终点站名 航班号 飞机号 星期 日期 余票量
北京 k2 123 星期六 2008.11.8 20
终点站名 航班号 飞机号 星期 日期 余票量
北京 k3 456 星期五 2008.11.7 23
b
请输入航班号
k2
定票数量
10
请填写客户信息:客户全名
张三
所订票数量 10
舱位等级 2
您的座位号为:
1 2 3 4 5 6 7 8 9
尊敬的客户您已经成功预定机票!
b
请输入航班号
k1
定票数量
10
您键入的信息有误!
b
请输入航班号
k2
定票数量
12
无足够的票,是否登记排队?Y/N
y
请填写客户信息:客户全名
王二
所订票数量:
12
舱位等级:
2
尊敬的客户已经为你排好队!
c
请输入退票航班号: k2
日期: 2008.11.8
请填写客户信息:客户全名
李四
所订票数量: 10
舱位等级: 2
您还没有订票,订票请按b,B!
c
请输入退票航班号: k2
日期: 2008.11.7
信息错误!
c
请输入退票航班号: k2
日期: 2008.11.8
请填写客户信息:客户全名
张三
所订票数量: 10
舱位等级: 2
您已经成功退票,谢谢使用!