火车票订票系统(DEVC++)
1.开发背景
火车票订票系统主要服务于旅客群体对列车时刻表信息的检索与在线下单。此外还支持存储列车运行计划数据以及订票记录。
如何实现菜单的选择功能
如何将新输入的信息添加到存放火车票信息的链表中
如何输出满足条件的信息
如何将信息保存到指定的磁盘文件中
2.需求分析
该系统通过网络平台为用户提供便捷的在线订票服务;实时更新并展示所有可选车次及其详细信息;支持查询各车次剩余座位数量,并允许用户根据当前情况决定是否继续预订;一旦订单生成成功后,则会自动保存用户的订票记录及相关信息
3.系统设计
3.1系统目标
显示火车车次信息及可供订票数
对输入车次或要到达的城市提供查询
输入要到达城市的车次信息,确定是否订票
可对输入的火车车次信息进行修改
显示火车车票信息
对火车车票信息及订票人的信息进行保存
3.2系统功能结构

3.3系统操作
在主界面上录入数字"1"后会切换至购票信息页面,在线填写所需购票信息:列车车次、乘车起点与终点地点、发车时刻与到站时刻以及票价金额及可购买的数量。
通过界面录入'2',可以获取火车票信息。
在界面上键入数值3后会切换至订票页面,在系统中按照指示录入目的地城市信息后会显示相关航班详情,请根据指引判断是否需要进行订票操作并收集用户的基本信息
在界面上输入4,进入修改界面,根据提示输入要修改的内容。
在界面上输入5,显示所有的火车票信息。
界面上录入乘客信息和订单数据到指定的硬盘文件中,并切换至保存页面完成操作
4.预处理模块
4.1预处理模块概述
为增强程序的可读性,在预处理模块中进行了充分的准备工作
4.2预处理模块实现
#include<conio.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<dos.h>
#define HEADER1 "----------------------BOOK TICKET-----------------------\n"
#define HEADER2 "| number | start city | reach city | take off time | receivetime | price | ticketnumber |\n"
#define HEADER3 "|----------|------------|------------|---------------|-------------|-------|--------------|\n"
#define FORMAT "| %-10s | %-10s | %-10s | %-10s | %-10s | %5d | %5d |\n"
#define DATA p->data.num,p->data.startcity,p->data.reachcity,p->data.takeofftime,p->data.receivetime,p->data.price,p->data.ticketnum
/*定义存储火车票信息的结构体*/
struct train
{
char num[10]; /*序列号*/
char startcity[10]; /*出发城市*/
char reachcity[10]; /*目的城市*/
char takeofftime[10]; /*发车时间*/
char receivetime[10]; /*到达时间*/
int price; /*票价*/
int ticketnum; /*票数*/
};
/*订票人信息*/
struct man
{
char num[10]; /*ID*/
char name[10]; /*姓名*/
int bookNum; /*订票数*/
};
/*定义火车票信息链表的节点结构*/
typedef struct node
{
struct train data; /*声明train结构体类型的变量*/
struct node*next;
}Node,*Link;
/*订票人链表的节点结构*/
typedef struct Man
{
struct man data;
struct Man *next;
}book,*bookLink;
通过typedef定义了一个名为Node的新类型,并将其归类为node结构体;随后定义了一个名为Link的指针变量,默认其对应的node指针类型的属性;同时定义了一个名为book的Man结构体及其指针类型的书签;其相应的书签变量书签变量指向该类型的存储位置。
5.主函数设计
5.1主函数概述
在火车订票系统中main()函数通过执行menu()函数来完成功能选择菜单的显示
main()函数不仅实现了从菜单中选择相应操作的功能,并且在执行时会根据提供的选项提示输入对应的数字以实现相应的操作流程。
5.2技术分析
在调用main()函数时, 我们需将火车票信息以及订票人信息存储到该临时文件里, 因此在执行操作之前必须先检查该文件是否存在记录.
通过读写操作实现的fopen()函数打开了一个二进制文件。一旦成功执行了以读写方式开启该二进制资源的过程,则会执行后续步骤来判断是否存在存储的数据。当检测到该二进制资源中没有存储任何数据时,则会关闭该资源。反之,在发现该资源存储了至少一组数据时,则会建立一个链表并从磁盘上读取这些数据。
保存火车票信息的train.txt文件
保存订票人信息的man.txt文件
5.3主函数实现
在显示功能模块中涉及的菜单项主要利用了puts()函数,在控制台上输出普通文本信息和其他特殊符号。
主函数主要运用switch语句实现多分支选择机制,并负责调用菜单中的各项功能。
6.输入模块设计
6.1输入模块概述
录入并存档火车车次信息、始发站信息、终点站信息、始发时间信息、到站时间信息以及票价与剩余票数等详细数据
为了防止添加的车次出现重复情况,在系统中采用了比较函数来判断某个车次是否已经被占用。如果未被占用,则会根据用户的提示信息将相关信息加入到指定的位置,并将其加入到链表中。
strcmp()函数的主要功能是用于比较两个字符串的内容。该函数会将第一个字符串(字符串1)与第二个字符串(字符串2)进行逐个字符比对,并基于ASCII编码值大小进行判断。具体来说,在逐个比对的过程中会从左端开始依次检查每个对应位置上的字符;如果找到了相同字符或者遇到了终止符'\0'时则停止比较操作
6.2功能实现
新增一条火车票相关的信息。按照提示获取列车车次,并检查该列车车次是否已存在记录。如果当前查询的车次未被记录,则需要进一步获取乘客的相关信息和订单编号等细节,并将其存储到链表中的对应节点位置,并设置全局标志变量saveflag为True
7.查询模块设计
以输入的车次或城市为基础进行信息检索,在有序列表中依次查看是否存在相关信息
/* 打印火车票信息 */
void printheader() /*格式化输出表头*/
{
printf(HEADER1);
printf(HEADER2);
printf(HEADER3);
}
void printdata(Node *q) /*格式化输出表中数据*/
{
Node* p;
p=q;
printf(FORMAY,DATA);
}
void searchtrain(Link l)
{
Node *s[10],*r;
int sel,k,i=0;
char str1[5],str2[10];
if(!l->next)
{
printf("There is not any record!");
return;
}
printf("Choose the way:\n1:according to the number of train;\n2:according to the city:\n");
scanf("%d",&sel); //输入选择的序号
if(sel==1) //若输入的序号等于1,则根据车次查询
{
printf("Input the number of train:");
scanf("%s",str1); //输入火车车次
r=l->next;
while(r!=NULL)
if(strcmp(r->data.num,str1)==0) //检索是否有与输入的车号匹配的火车车次
{
s[i]=r;
i++;
break;
}
else
r=r->next; //没有查找到火车车次则指针r后移一位
}
else if(sel==2)
{
printf("Input the city you want to go:");
scanf("%s",str2); //输入查询的城市
r=l->next;
while(r!=NULL)
if(strcmp(r->data.reachcity,str2)==0) //检索是否有与输入城市相匹配的火车车次
{
s[i]=r;
i++;
r=r->next;
}
else
{
r=r->next;
}
}
if(i==0)
printf("can not find!");
else
{
printheader(); //输出表头
for(k=0;k<i;k++)
printdata(s[k]); //输出火车车票信息
}
}

8.订票模块设计
基于用户提供的城市信息进行搜索,在显示界面呈现符合条件的车次列表,并从结果中挑选出您希望预订的车票,请按照屏幕上的提示录入相关个人信息。
一旦订票操作顺利完成,则必须先计算出正确的票数,并且必须对train类型中的ticket字段进行引用
r[t]->data.ticketnum=r[t]->data.ticketnum-num;
9.修改模块设计
采用了字符串比较函数strcmp对输入的列车信息与现有的列车信息进行比对。一旦发现有匹配的列车信息,则按照指示逐步更新相关列车票务数据,并将其标记变量saveflag设置为1即可判断返回主程序时列车票务信息是否发生变更。
10.显示模块设计
检查链表中的各个节点。如果发现某个节点的next域为空,则表示该列车段无票可售;接着遍历当前p所指向的节点,并调用printdata()函数获取相关信息。系统将显示出列车的基本信息如车次号码、出发车站名称、到达车站名称等

11.保存模块设计
一部分包含输入的火车票信息;另一部分包含订票人的相关信息。保存模块的主要功能是将数据存储到预设的硬盘文件中。
在处理输出数据块时我们采用fwrite()函数将数据传输至磁盘文件中;若文件采用二进制格式打开则该函数具备读取或写入任何数据类型的特性。一旦确认数据正确写入后端系统将更新指针位置
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
//#include<dos.h>
#include <windows.h>
#include<conio.h>
#define HEADER1 "----------------------BOOK TICKET-----------------------\n"
#define HEADER2 "| number | start city | reach city | take off time | receivetime | price | ticketnumber |\n"
#define HEADER3 "|----------|------------|------------|---------------|-------------|-------|--------------|\n"
#define FORMAT "| %-10s | %-10s | %-10s | %-10s | %-10s | %5d | %5d |\n"
#define DATA p->data.num,p->data.startcity,p->data.reachcity,p->data.takeofftime,p->data.receivetime,p->data.price,p->data.ticketnum
int saveflag;
/*定义存储火车票信息的结构体*/
struct train
{
char num[10]; /*序列号*/
char startcity[10]; /*出发城市*/
char reachcity[10]; /*目的城市*/
char takeofftime[10]; /*发车时间*/
char receivetime[10]; /*到达时间*/
int price; /*票价*/
int ticketnum; /*票数*/
};
/*订票人信息*/
struct man
{
char num[10]; /*ID*/
char name[10]; /*姓名*/
int bookNum; /*订票数*/
};
/*定义火车票信息链表的节点结构*/
typedef struct node
{
struct train data; /*声明train结构体类型的变量*/
struct node *next;
}Node,*Link;
/*订票人链表的节点结构*/
typedef struct Man
{
struct man data;
struct Man *next;
}book,*bookLink;
/* 打印火车票信息 */
void printheader() /*格式化输出表头*/
{
printf(HEADER1);
printf(HEADER2);
printf(HEADER3);
}
void printdata(Node *q) /*格式化输出表中数据*/
{
Node *p;
p=q;
printf(FORMAT,DATA);
}
void menu()
{
puts("\n\n");
puts("\t\t|--------------------------------------------------|");
puts("\t\t| BOOKing Tickets |");
puts("\t\t|--------------------------------------------------|");
puts("\t\t| 0:quit the system |");
puts("\t\t| 1:Insert a train information |");
puts("\t\t| 2:Search a train information |");
puts("\t\t| 3:Book a train ticket |");
puts("\t\t| 4:Modify the train information |");
puts("\t\t| 5:Show the train information |");
puts("\t\t| 6:Save information to file |");
puts("\t\t|--------------------------------------------------|");
}
void searchtrain(Link l)
{
Node *s[10],*r;
int sel,k,i=0;
char str1[5],str2[10];
if(!l->next)
{
printf("There is not any record!");
return;
}
printf("Choose the way:\n1:according to the number of train;\n2:according to the city:\n");
scanf("%d",&sel); //输入选择的序号
if(sel==1) //若输入的序号等于1,则根据车次查询
{
printf("Input the number of train:");
scanf("%s",str1); //输入火车车次
r=l->next;
while(r!=NULL)
if(strcmp(r->data.num,str1)==0) //检索是否有与输入的车号匹配的火车车次
{
s[i]=r;
i++;
break;
}
else
r=r->next; //没有查找到火车车次则指针r后移一位
}
else if(sel==2)
{
printf("Input the city you want to go:");
scanf("%s",str2); //输入查询的城市
r=l->next;
while(r!=NULL)
if(strcmp(r->data.reachcity,str2)==0) //检索是否有与输入城市相匹配的火车车次
{
s[i]=r;
i++;
r=r->next;
}
else
{
r=r->next;
}
}
if(i==0)
printf("can not find!");
else
{
printheader(); //输出表头
for(k=0;k<i;k++)
printdata(s[k]); //输出火车车票信息
}
}
void Bookticket(Link l,bookLink k)
{
Node *r[10],*p;
char ch[2],tnum[10],str[10],str1[10],str2[10];
book *q,*h;
int i=0,t=0,flag=0,dnum;
q=k;
while(q->next!=NULL)
q=q->next;
printf("Input the city you want ti go:");
scanf("%s",&str); //输入要到达的城市
p=l->next;
while(p!=NULL) //遍历指针p
{
/*比较输入的城市与输入的火车终点站是否有匹配的*/
if(strcmp(p->data.reachcity,str)==0)
{
r[i]=p; //将满足的条件记录到数组r中
i++;
}
p=p->next;
}
printf("\n\nthe number of record have %d\n",i);
printheader();
for(t=0;t<i;t++)
printdata(r[i]); //循环输出数组中的火车票信息
if(i==0)
printf("\nSorry! Can't find the train for you!\n");
else
{
printf("\ndo you want to book it?<y/n>\n");
scanf("%s",ch);
if(strcmp(ch,"Y")==0||strcmp(ch,"y")==0) //判断是否订票
{
h=(book*)malloc(sizeof(book));
printf("Input your name:");
scanf("%s",&str1); //输入订票人姓名
strcpy(h->data.name,str1);
printf("Input your id:");
scanf("%s",&str2);
strcpy(h->data.num,str2); /*与存储信息进行比较*/
printf("please input the number of the train:");
scanf("%s",tnum); /*输入要预定的车次*/
for(t=0;t<i;t++)
if(strcmp(r[t]->data.num,tnum)==0) //比较车次,看是否存在该车次
{
if(r[t]->data.ticketnum<1)
{
printf("no ticket!");
Sleep(2);
return;
}
printf("remain %d tickets\n",r[t]->data.ticketnum);
flag=1;
break;
}
if(flag==0)
{
printf("input error!");
Sleep(2);
return;
}
printf("Input your bookNum:");
scanf("%d",&dnum); //输入要预定的票数
r[t]->data.ticketnum=r[t]->data.ticketnum-dnum; //预定成功则可供预定的票数相应减少
h->data.bookNum=dnum; //将订票数赋给订票人信息
h->next=NULL;
q->next=h;
q=h;
printf("\nLucky! you have booked a ticket!");
getch();
saveflag=1;
}
}
}
void Modify(Link l)
{
Node *p;
char tnum[10],ch;
p=l->next;
if(!p)
{
printf("\nthere isn't record for you to modify!\n");
return;
}
else
{
printf("\nDo you want to modify it?(y/n)\n");
getchar();
scanf("%c",&ch); //输入是否想要修改的字符
if(ch=='y'||ch=='Y')
{
printf("\nInput the number of the train:");
scanf("%s",tnum); //输入需要修改的车次
while(p!=NULL)
if(strcmp(p->data.num,tnum)==0)
break;
else
p=p->next;
if(p)
{
printf("Input new number of train:");
scanf("%s",&p->data.num);
printf("Input new city the train will start:");
scanf("%s",&p->data.startcity);
printf("Input the city where the train will reach:");
scanf("%s",&p->data.reachcity);
printf("Input the time which the train take off:");
scanf("%s",&p->data.takeofftime);
printf("Input the time which the train receive:");
scanf("%s",&p->data.receivetime);
printf("Input the price of ticket:");
scanf("%d",&p->data.price);
printf("Input nes number of people who have booked ticket:");
scanf("%d",&p->data.ticketnum); //输入预定票数
printf("\nmodifying record is sucessful!\n");
saveflag=1;
}
else
printf("\tcan't find the record!");
}
}
}
void showtrain(Link l)
{
Node *p;
p=l->next;
printheader();
if(l->next==NULL)
printf("no records!");
else
while(p!=NULL)
{
printdata(p); //输出所有火车数据
p=p->next;
}
}
void SaveTrainInfo(Link l)
{
FILE *fp;
Node *p;
int count=0,flag=1;
fp=fopen("D:\ train.txt","wb"); //打开只写的二进制文件
if(fp==NULL)
{
printf("the file can't be opened!");
return;
}
p=l->next;
while(p)
{
if(fwrite(p,sizeof(Node),1,fp)==1) //向磁盘文件写入数据块
{
p=p->next;
count++;
}
else
{
flag=0;
break;
}
}
if(flag)
{
printf("saved %d train records\n",count);
saveflag=0;
}
fclose(fp);
}
/*保存订票人信息*/
void SaveBookInfo(bookLink k)
{
FILE*fp;
book *p;
int count=0,flag=1;
fp=fopen("D:\ man.txt","wb");
if(fp==NULL)
{
printf("the file can't be opened!");
return;
}
p=k->next;
while(p)
{
if(fwrite(p,sizeof(book),1,fp)==1)
{
p=p->next;
count++;
}
else
{
flag=0;
break;
}
}
if(flag)
{
printf("saved %d booking records\n",count);
saveflag=0;
}
fclose(fp);
}
void Traininfo(Link linkhead)
{
struct node *p,*r,*s;
char num[10];
r=linkhead;
s=linkhead->next;
while(r->next!=NULL)
r=r->next;
while(1)
{
printf("please input the number of the train(0-return)");
scanf("%s",num);
if(strcmp(num,"0") == 0)
{
break;
}
/*判断车次是否存在*/
while(s)
{
if(strcmp(s->data.num,num)==0)
{
printf("the train '%s' is existing!\n",num);
return;
}
s=s->next;
}
p=(struct node*)malloc(sizeof(struct node));
strcpy(p->data.num,num); //复制车号
printf("Input the city where the train will start:");
scanf("%s",p->data.startcity);
printf("Input the city where the train will reach:");
scanf("%s",p->data.reachcity);
printf("Input the time which the train take off:");
scanf("%s",p->data.takeofftime);
printf("Input the time which the train receive:");
scanf("%s",p->data.receivetime);
printf("Input the price of ticket:");
scanf("%d",&p->data.price);
printf("Input the number of booked tickets:");
scanf("%d",&p->data.ticketnum); //输入预定票数
p->next=NULL;
r->next=p; //插入链表
r=p;
saveflag=1; //保存标志
}
}
int main()
{
FILE*fp1,*fp2;
Node *p,*r;
char ch1,ch2;
Link l;
bookLink k;
book *t,*h;
int sel;
l=(Node*)malloc(sizeof(Node));
l->next=NULL;
r=l;
k=(book*)malloc(sizeof(Node));
k->next=NULL;
h=k;
fp1=fopen("D:\ train.txt","ab+"); /*打开存储车票信息的文件*/
if((fp1==NULL))
{
printf("can't open the file!");
return 0;
}
while(!feof(fp1))
{
p=(Node*)malloc(sizeof(Node));
if(fread(p,sizeof(Node),1,fp1)==1) /*从指定磁盘文件读取记录*/
{
p->next=NULL;
r->next=p; /*构造链表*/
r=p;
}
}
fclose(fp1);
fp2=fopen("D:\ man.txt","ab+");
if((fp2==NULL))
{
printf("can't open the file!");
return 0;
}
while(!feof(fp2))
{
t=(book*)malloc(sizeof(book));
if(fread(t,sizeof(book),1,fp2)==1) /*从指定磁盘文件读取记录*/
{
t->next=NULL;
h->next=t; /*构造链表*/
h=t;
}
}
fclose(fp2);
while(1)
{
system("CLS");
menu();
printf("\tplease choose (0~6): ");
scanf("%d",&sel);
system("CLS");
if(sel==0)
{
if(saveflag==1) //当退出系统时判断信息是否保存
{
getchar();
printf("\nthe file have been changed!do you want to save it(y/n)?\n");
scanf("%c",&ch1);
if(ch1=='y'||ch1=='Y')
{
SaveBookInfo(k);
SaveTrainInfo(l);
}
}
printf("\nThank you!!You are welcome too\n");
break;
}
switch(sel)
{
case 1:
Traininfo(l); break;
case 2:
searchtrain(l); break;
case 3:
Bookticket(l,k); break;
case 4:
Modify(l); break;
case 5:
showtrain(l); break;
case 6:
SaveTrainInfo(l);
SaveBookInfo(k); break;
case 0:
return 0;
}
printf("\nplease press any key to continue......");
getch();
}
}
