设计要求
- 程序菜单功能
一个汽车站每天有n班通往各地的车,每班车都有唯一的车次号(00100,00101,00102,…),发车时间,固定的路线(起始站、终点站),大致的行车时间,固定的额定载客量等信息。每班车信息如下:
表1.汽车站汽车数据库列表
车次 | 发车时间 | 起点站 | 终点站 | 行车时间 | 票价 | 额定载量 | 已售票数 |
00101 | 6:00 | 南京 | 盐城 | 3.5 | 30 | 45 | |
00102 | 7:30 | 南京 | 连云港 | 4 | 40 | 40 | |
00103 | 8:00 | 南京 | 宿迁 | 6 | 55 | 40 |
要求设计一个车票管理系统,分别供管理员和顾客使用。进入主窗口后,选择1进入管理员窗口;选择2进入普通顾客窗口;选择3退出系统。主窗口及不同用户的窗口如表2所示。
表2.不同窗口内容
主窗口 | 管理员窗口 | 普通顾客窗口 |
请输入选择: |
请输入选择: |
请输入选择: |
1.管理员账户
(1)身份验证:要求通过用户名密码验证才能使用管理员账户(默认用户名为admin,密码为123)。注意:输入密码时要进行密码保护操作,即将输入的字母变成*号。如果用户密码错误,将会反复要求重新输入;
(2)当通过身份验证后,系统自动装载配置文件(即存放该汽车站汽车数据的文件)里的内容至数组timetables中,并进入管理员菜窗口(如表2第二列);在执行本功能前,请准备好配置文件,文件名请自行给出(如bus.txt)。文件格式如下(每行是一班车的信息,分别对应着车次号,发车时间(小时),发车时间(分钟),始发站,终点站,大约时长,票价,最大载客量,已售票数):
表3.配置文件内部基本信息(例)
00103 14 30 南京 北京 10 80 45 0 00104 15 10 南京 长沙 10 50 50 0 00105 17 20 南京 武汉 10 100 40 0 00106 10 20 南京 宿迁 4 40 40 0 |
(3)增加车次信息:增加车次时必须给定车次,发车时间(包括小时和分钟),起点,终点,行车时间,固定的额定载客量和票价。增加车次后要将信息写入配置文件中(如bus.txt)。注意:必须确保输入的车次号必须不重复,且如果当天的日志文件已生成,则增加的车次第二天生效。
(4)查看所有的车次信息:按行显示该汽车站所有车次的信息(包括车次,发车时间,起点,终点,行车时间,固定的额定载客量)。
(5)车辆信息查询:能够根据车次号和终点站分别进行查询,若车次或终点站不存在,则应该给出提示;如果存在,则显示该车辆信息。注意:如果按终点站查询,则要求显示所有的查询结果,且结果按发车时间升序排序。
(6)注销车次:输入要删除车次的车次号,首先查询该车辆是否存在,若该车不存在,则给出提示信息;如果存在则相应显示该车信息,并询问是否删除,如果是则删除该车次,并将信息写入配置文件中(如bus.txt); 注意:如果当天的日志文件已经生成,则注销车次第二天生效。
(7)退出:退出管理员账户,并将信息重新写入配置文件中(如bus.txt)。
2.顾客账户
(1)信息导入:整个汽车站的车次基本信息存放于配置文件bus.txt中。每天第一次使用顾客身份登录时,系统会从bus.txt中读取数据到数组timetables中(注意每辆车的已售票数的初始值为0),并将数组timetables的信息写入到一自动生成的日志文件(以当天日期命名,如2019-9-15.log)中。如果顾客身份不是第一次登录,则数据从当天的日志文件中读取数据到数组timetables中。
(2)车辆信息查询:能够根据车次号和终点站分别进行查询,若车次或终点站不存在,则应该给出提示;如果存在,则显示该车辆信息。注意:如果按终点站查询,则要求显示所有的查询结果,且结果按发车时间升序排序,且必须显示每辆车是否已停止服务。
(3)购买车票:输入要购买的车次,如果该车次不存在,给出提示。如果该车次存在则输出该车次的信息。注意:只有系统时间距发车时间大于十分钟时方可购票。如果小于10分钟则不可买票,否则输入购买的车票数目,并判断剩余的票是否大于等于要购买的票数,如果是则可以买票,同时更改已售车票数,并将相应信息写入当天的日志文件中;否则提示车票数不够。
(4)退票:输入要退票的车次,如果该车次不存在,给出提示;如果该车次存在则输出该车次的信息。注意:只有系统时间距发车时间大于十分钟时方可退票。如果小于10分钟则不可退票,否则输入退票数目,并判断售出的票是否大于等于要退的票数,如果是则可以退票,同时更改已售车票数,并将相应信息写入当天的日志文件中;否则提示用户输入错误。
(5)退出:退出顾客账户,将相应信息写入当天的日志文件中。
- 数据结构说明
1. 定义一个结构体数据结构用于存放每个车次的信息
struct Timetable //车辆信息结构
{ char no;//班次
int hour;//发车时间,小时
int minute;//发车时间,分钟
char Starting_station[10];//始发站
char Last_station[10];//终点站
float time;//行车时长
int fare; //票价
int max_number;//最大载客量
int sold_number;//已售票数
}
2. 该汽车站汽车班次信息用数组来存储,如果不考虑动态数组空间的话,开始可将数组长度设置得大一些。
3 数据文件
数据文件中的信息是可以永久保存的,而内存中的信息当程序结束后就不存在了。本课设用配置文件(如bus.txt)及日志文件(以每天日期做文件名,如2019-9-15.log)模拟实现“数据库(即数据文件)”,数据库中存储的是该汽车站汽车班次信息,可永久保存。当以管理员身份程序运行时,所有的汽车班次信息从bus.txt文件中搬入内存,即存储在内存中的timetables数组中;当以普通顾客身份运行程序时,汽车班次信息从当天的日志文件文件中搬入内存。程序结束运行时,所有的汽车班次信息均由内存搬到(存储到)相应的数据文件中(管理员身份写入到bus.txt,普通顾客写入到当天的日志文件中),下次运行时再次调入到内存中。
注意:文件对使用系统的用户来说是“看不见的”,是系统内部处理用到的。当管理员用户验证通过后或普通用户登录后将自动调用ReadFromFile()函数将相应文件内容加载到timetables数组中。当对timetables中的数据进行修改后,相应地调用WritetoFile ()函数将内存timetables数组的内容写入对应文件(管理员写入bus.txt中,普通顾客写入到当天日志文件中)。
- 课程设计实现说明
1.定义主函数,在主函数中定义一个Timetable型的数组timetables用于存放该汽车站所有车次信息。所有的操作都是针对该数组执行的。
2.本项目涉及二级菜单,请仿照上述菜单设计进行拓展,给出本题的菜单实现。在菜单设计时将菜单设计练习中的“cout<<" Function1"<<endl;”等替换成调用每一个菜单功能的实现函数。
3.主函数和对应于每个菜单功能的实现函数参见“四、部分函数代码提示”。
- 部分函数代码提示
1. 主函数以及各级菜单函数的定义:
int main()
{ int UserChoice;
Timetable timetables[100];
while(1)
{ switch(UserChoice = MainWindowSelect())
{
case 1: AdminMode(timetables,"bus.txt");break; //管理员模式
case 2: PassagerMode(timetables,"bus.txt");break; //顾客模式
case 3: if (Quit()!=1)continue; //退出
}
if (UserChoice==3) break;
}
return 0;
}
void AdminMode(Timetable *timetables,char *filename)
{ Signin();
int n=ReadFromFile(timetables,0,"bus.txt");
while(1)
{ int AdminChoice = AdminWindowSelect();
switch(AdminChoice)
{
case 1: n = AddBus(timetables,n) ;WritetoFile(timetables,n,filename);
system("pause");break; //增加车次信息,并及时写到文件中
case 2: ShowTimetable(timetables, n);system("pause");break; //浏览时刻表
case 3: Query(timetables,n);system("pause");break; //车辆信息查询 case 4: n = DelBus(timetables, n);system("pause");
WritetoFile(timetables,n,filename); break;//注销车次,并及时写到文件中
case 5: WritetoFile(timetables,n,filename);
return ;//返回上级菜单,并将信息保存回bus.txt文件
}
}
}
void PassagerMode(Timetable *timetables,char *filename)
{ char LogFileName[200];
GenerateLogFileName(LogFileName);//根据当前日期生成日志名
int n = InitializaionPassagerMode(timetables,LogFileName,filename);
int PassagerChoice;
while(1)
{ switch(PassagerChoice= PassagerWindowSelect())
{
case 1:Query(timetables,n);system("pause");break;//车辆信息查询
case 2:TicketOrder(timetables, n);WritetoFile(timetables,n,LogFileName);
system("pause");break;//购买车票,并更改文件信息
case 3:TicketDelete(timetables, n); WritetoFile(timetables,n,LogFileName);
system("pause");break;//退回车票,并更改文件信息
case 4:WritetoFile(timetables,n,LogFileName); system("pause");
return ;//返回上级菜单
}
}
}
int MainWindowSelect()// 主菜单实现(即用户选择窗口)
{ //请仿照菜单设计练习实现本菜单}
int AdminWindowSelect()// 管理员菜单实现
{ //请仿照菜单设计练习实现本菜单}
int PassagerWindowSelect ( ) // 普通顾客菜单实现
{ //请仿照菜单设计练习实现本菜单}
2.菜单功能处理函数
对应于菜单功能的每一项,编写处理函数(可能需要调用其他函数)。在处理函数中,给出一些必要的输入输出信息提示,并实现相应的功能。
初始时,可将菜单处理函数的函数体设置为空函数体,把程序框架搭好,然后逐步添加处理代码。
对应于菜单功能的每一项,参照前面给出的菜单功能描述。处理函数的原型和实现说明如下:
(1)void Signin():管理员用户登录函数。在此函数中,提示用户输入用户密码(默认用户名为admin,密码为123),若输入正确,则进入管理员窗口;如错误,则反复要求输入用户密码。注意:输入密码时要进行密码保护操作,即将输入的字母变成*号。
(2)int ReadFromFile(Timetable *timetables,int n,char *filename):从文件filename中导入数据。如果该文件无法打开,给出报错信息,程序退出。如果该文件存在,则将文件中的数据读到数组timetables中,正确读取返回文件中包含车次的数目,否则返回-1。
(3)int AddBus(Timetable *timetables,int n):添加车次。首先给定要添加车辆的车次号,如果该车次号已经存在,则给出提示信息,并要求重新输入;如果该车次号不存在,依次输入该车次信息(发车时间(小时和分钟),固定的路线(起始站、终点站),大致的行车时间,固定的额定载客量),并返回该汽车站的车次总数;注意:未生成当天日志文件前,增加的车次当天有效,否则第二天有效。
(4)int WritetoFile(Timetable *timetables,int n,char *filename):将数组timetables中的数据写入到filename中。正确写入返回非-1的数。
(5)void ShowBusInfo(Timetable *timetables,int n, int idx):显示数组timetables中第idx(下标)个元素的信息;
(6)void ShowTimetable(Timetable *timetables,int n); 显示汽车站中所有车次信息,并按发车时间进行升序排序,在此函数中需要调用ShowBusInfo(Timetable *timetables,int n, int idx)函数。
(7)void Query(Timetable *timetables, int n):查询操作,可以按车次和终点站分别进行查询。执行时,要求输入要查找的车次或是终点站名,然后调用find()函数(重载)进行查找,若找到相应结果,则显示;若没有则给出提示。注意:当以终点站名查询时,结果可能为多条,此时要求按发车时间顺序进行输出。
(8)int find(Timetable *timetables,int n,char *no):按车次进行查询,若找到,则返回该车次所在数组中的下标;否则返回-1;
(9)int find(Timetable *timetables,int n,char *Last_station,int *b): 按终点站名查询。若找到,则在b中记录终点站为Last_station的所有车次在数组中对应的下标,并返回该汽车站终点站为Last_station的车次数;否则返回-1;
(10)int DelBus(Timetable *timetables,int n):注销车次。输入要注销的车次号,如果不存在给出提示信息,否则询问是否注销该车次,是则删除整条记录,并返回该汽车站的车次总数。注意:未生成当天日志文件前,注销的车次当天有效,否则第二天有效。
(11)void GenerateLogFileName(char *LogFileName):根据当天日期生成日志名(如2019-9-19.log)。
(12)int InitializaionPassagerMode(Timetable *timetables,char *LogFileName,char *filename):判断当天日志文件LogFileName是否存在,若不存在,则将filename中的内容读至timetables中(注意要将sold_number成员置为0)并将timetables中的信息写入LogFileName;若日志文件存在,则直接从LogFileName中读取数据至数组timetables中。
(13)void TicketOrder(Timetable *timetables,int n):购买车票。输入要购买的车次,如果该车次不存在,给出提示;如果该车次存在则输出该车次的信息。如果当前系统时间距发车时间少于10分钟或该车次票已全部售出,则提示不可买票;否则要求输入购买的车票数目,并判断剩余的票是否大于等于要购买的票数,如果是则可以买票,同时更改已售车票数。否则提示车票数不够。
(14)void TicketDelete(Timetable *timetables,int n):退票。输入要退票的车次,如果该车次不存在,给出提示;如果该车次存在则输出该车次的信息。如果当前时间距离发车时间不足10分钟或售票数为0,则提示不可退票;否则要求输入退票的数目,并判断售出的票是否大于等于要退的票数,如果是则给予退票,同时更改已售车票数,否则给出退票数目不对提示信息。
(15)int StopService(Timetable *timetables,int n,char *no); 判断车次号为no的车的发车时间离当前时间是否小于10分钟或是小于当前时间,若是则返回1,停止售票退票;否则返回0。该函数需要获取系统当前时间,需要使用localtime函数获取。函数实现见样例。
(16)void SortbyTime(Timetable *timetables, int n):将timetables中的元素按发车时间进行升序排序;
(17)int Quit():询问是否要退出整个系统(y/n),输入’y’或’Y’时返回1,否则返回0。
3. StopService()函数实现样例
int StopSevice(Timetable *timetables,int n,char *no) //判断是否停止售退票,1:停止;0:不停止
{
struct tm *local; //时间结构体
time_t t; //把当前时间给t
t=time(NULL);
local = localtime(&t); /获取当前系统时间
int i = find(timetables,n,no);
if ((local->tm_hour*60 + local->tm_min) + 10 < (timetables[i].hour*60+timetables[i].minute))
return 0;
return 1;
}
>>其他说明
1. 应完成上述规定的基本功能。
2. 可根据需要增加或修改功能,如果完成得好,可加分。增加的功能例如:
(1)管理员将每个月的所有日志信息进行汇总分析,统计某班次车辆一个月的信息,计算上客率等;
(2)在显示多个车辆信息时(如管理员账户显示全部信息)对数据进行其他标准(如按终点站名)的排序。
(3)自行设计增加其他功能。
3. 本题目也可以使用通过类的定义对数据及相应操作进行封装来实现。
我自己写的参考代码,及思维导图分析(仅供参考)
VS2010版(之后会以资源的形式再上传一次)
运行无碍,但算法还存在优化空间,欢迎大家批评指正
#include "stdafx.h"
#include<iostream>
#include<cstdlib>
#include<fstream>
#include<iomanip>
#include<cstring>
#include<conio.h>
#include<cmath>
using namespace std;
struct Timetable
{
char no[10];//班次
int hour;//发车时间,小时
int minute;//发车时间,分钟
char Starting_station[10];//始发站
char Last_station[10];//终点站
float time;//行车时长
int fare;//票价
int max_number;//最大载客量
int sold_number;//已售票数
};
void Signin()//管理员登录函数
{
cout<<"\n*****管理员登录验证*****\n"<<endl;
char name[10],secret[10];
do
{
cout<<"用户名:";
cin>>name;
cout<<"密码:";
cin.sync();//清空cin输入流里面的内容
int i=0;
char ch;
while(1)
{
ch=getch();//getch()为头文件<conic.h>里面一个函数,从键盘上读取一个字符
if(ch=='\r')// \r表示回车键
break;
else if(ch=='\b')// \b表示退格键,此为允许用户输入时退格
{
cout<<"\b \b";
i--;
}
else
{
secret[i++]=ch;//将读取的字符存入密码数组中
cout<<"*";//密码保护实现
}
secret[i]='\0';//末尾增加结束标志
}
if(strcmp(name,"admin")==0&&strcmp(secret,"123")==0)//验证密码是否正确,验证成功则跳出循环,否则提示错误,一直输入
break;
else
cout<<endl<<"\n***用户名/密码输入错误,请重新输入***\n"<<endl;
}while(1);
cout<<endl<<"\n*****验证成功*****\n"<<endl;
system("pause");
}
int find(Timetable *timetables,int n,char *no)//按车次进行查询
{
int idx;
for(int i=0;i<n;i++)//顺序查找
{
if(strcmp(timetables[i].no,no)==0)
{
idx=i;
return idx;//将查询到的车次下标存入idx;
}
}
return -1;//没有找到
}
int find(Timetable *timetables,int n,char *Last_station,int *b)//按终点站名进行查询
{
int j=0;
for(int i=0;i<n;i++)
{
if(strcmp(timetables[i].Last_station,Last_station)==0)
b[j++]=i;//终点站相同的可能有多个结果,存入数组
}
if(j>0)//判断是否查询到相应车次
return j;
else
return -1;
}
void SortbyTime(Timetable *timetables,int n)
{
int i,j,min;
Timetable tmp;
for(int i=0;i<n;i++)//冒泡排序
{
int hmin=24,mmin=60;//hmin,mmin为时间的最大值,等同于将数组第一个数赋值给它
for(int j=i;j<n;j++)
{
if(hmin>timetables[j].hour)
{
min=j;
hmin=timetables[j].hour;
mmin=timetables[j].minute;
}
else if(hmin==timetables[j].hour)
{
if(hmin>timetables[j].minute)
{
min=j;
mmin=timetables[j].minute;
}
}
}
tmp=timetables[i];
timetables[i]=timetables[min];
timetables[min]=tmp;
}
}
int StopService(Timetable *timetables,int n,char *no)//判断是否停止售退票,1:停止;0:不停止
{
struct tm *local;//时间结构体
time_t t;//把当前时间给t
t=time(NULL);
local=localtime(&t);//获取当前系统时间
int i=find(timetables,n,no);
if((local->tm_hour *60+local->tm_min)+10<(timetables[i].hour*60+timetables[i].minute))
return 0;
return 1;
}
int ReadFromFile(Timetable *timetables,char *filename)
{
ifstream readfromfile;
readfromfile.open(filename);
if(!readfromfile)
return -1;
int i=0;
while(readfromfile.peek()!=EOF)
{
readfromfile>>timetables[i].no>>timetables[i].hour>>timetables[i].minute
>>timetables[i].Starting_station>>timetables[i].Last_station
>>timetables[i].time>>timetables[i].fare
>>timetables[i].max_number>>timetables[i].sold_number;
i++;
}
readfromfile.close();
return i;
}
int AddBus(Timetable *timetables,int n)//增加车次信息
{
Timetable timeb;//定义一个结构体存放用户端欲输入车次信息
char yn='y';
do
{
cout<<"请输入要添加的车辆的车次号:";
cin>>timeb.no;
int f;
f=find(timetables,n,timeb.no);
if(f!=-1)
cout<<"\n***该车次号已经存在***\n"<<endl;
else
{
cout<<"\n***该车次号不存在,请检查输入车次号是否正确***\n"<<endl;
cout<<"是否重新输入车次号(Y/N):";
cin>>yn;
}
}while(yn=='Y'||yn=='y');
if(yn=='N'||yn=='n')
{
cout<<"\n***录入新车次"<<timeb.no<<"的信息***\n"<<endl;
cout<<"发车时间(小时):";cin>>timeb.hour;
cout<<"发车时间(分钟):";cin>>timeb.minute;
cout<<"始发站:";cin>>timeb.Starting_station;
cout<<"终点站:";cin>>timeb.Last_station;
cout<<"行车时长:";cin>>timeb.time;
cout<<"票价:";cin>>timeb.fare;
cout<<"最大载客量:";cin>>timeb.max_number;
timeb.sold_number=0;
timetables[n]=timeb;
return n+1;
}
else
return n;
}
int WritetoFile(Timetable *timetables,int n,char *filename)
{
int i=0;
ofstream writetofile;
writetofile.open(filename);
if(!writetofile.is_open())
{
cout<<"\n***无法打开文件"<<filename<<"***\n"<<endl;
return 1;
}
else
for(i=0;i<n;++i)
{
writetofile<<timetables[i].no<<'\t'<<timetables[i].hour<<'\t'<<timetables[i].minute<<'\t'
<<timetables[i].Starting_station<<'\t'<<timetables[i].Last_station<<'\t'
<<timetables[i].time<<'\t'<<timetables[i].fare<<'\t'
<<timetables[i].max_number<<'\t'<<timetables[i].sold_number;
if(i<n-1)
writetofile<<endl;
}
writetofile.close();
return 0;//返回0表示成功
}
void numbertochar(int number,char *str)//****************把数字转换成字符数组((新定义函数))
{
int i=0,j;
if(number!=0)
{
do
{
str[i++]=number%10+'0';
number/=10;
}while(number!=0);
str[i]='\0';
i-=1;
}
else
{
str[0]='0';
str[1]='0';
str[2]='\0';
i=1;
}
char t;
for(j=0;j<i;j++,i--)
{
t=str[i];
str[i]=str[j];
str[j]=t;
}
}
void ShowBusInfo(Timetable *timetables,int idx)//显示指定下标的的车辆的全部信息
{
int n=ReadFromFile(timetables,"bus.txt");
char h[21]="",m[11]="";
numbertochar(timetables[idx].hour,h);
numbertochar(timetables[idx].minute,m);
strcat(h,":");
strcat(h,m);
cout<<setw(7)<<timetables[idx].no<<setw(10)<<h<<'\t'
<<timetables[idx].Starting_station<<setw(10)<<timetables[idx].Last_station<<setw(10)
<<timetables[idx].time<<setw(11)<<timetables[idx].fare<<setw(10)
<<timetables[idx].max_number<<setw(12)<<timetables[idx].sold_number;
int yn=StopService(timetables,n,timetables[idx].no);
if(yn==1)
cout<<setw(15)<<"停止检票\0"<<endl;
else
cout<<setw(11)<<"候车\0"<<endl;
}
void ShowTimetableTitle() // ******************((新定义函数))
{
cout<<setw(8)<<"车次"<<setw(12)<<"发车时间"
<<setw(10)<<"起点站"<<setw(10)<<"终点站"
<<setw(12)<<"行车时间"<<setw(8)<<"票价"
<<setw(12)<<"额定载量"<<setw(12)<<"已售票数"<<setw(8)<<"备注"<<endl;
}
void ShowTimetable(Timetable *timetables,int n)//显示全部车次信息
{
ShowTimetableTitle();
SortbyTime(timetables,n);
WritetoFile(timetables,n,"bus.txt");
for(int i=0;i<n;i++)
ShowBusInfo(timetables,i);
}
void Query(Timetable *timetables,int n)//查询操作,可以按车次和终点站名分别进行查询
{
cout<<"\n*****车辆信息查询界面*****\n"<<endl;
cout<<"请输入需要查找的车次或是终点站名:";
char search[20];
cin>>search;
int result1,f2,result2[20];
result1=find(timetables,n,search);
f2=find(timetables,n,search,result2);
if(result1==-1&&f2==-1)
{
cout<<"\n***未查找到相应车辆信息***\n"<<endl;
return;
}
else if(result1!=-1&&f2==-1)
{
cout<<"\n***车次"<<search<<"全部信息如下***\n"<<endl;
ShowTimetableTitle();
ShowBusInfo(timetables,result1);
system("pause");
return;
}
else
{
cout<<"\n***查询到终点站为"<<search<<"的车辆信息如下***\n"<<endl;
ShowTimetableTitle();
for(int j=0;j<f2;j++)
{
ShowBusInfo(timetables,result2[j]);
}
system("pause");
return;
}
}
int DelBus(Timetable *timetables,int n)
{
cout<<"\n*****车次注销界面*****\n"<<endl;
char no[10];//用于存放用户端输入的车次
int f,outloop,idx;
char choice;
Timetable timeb;//中间变量
do
{
cout<<"请输入要删除的车次:";
cin>>no;
f=find(timetables,n,no);
if(f!=-1)//需要删除的车次存在
{
idx=f;
cout<<"\n***车次"<<no<<"存在***\n";
cout<<"车次"<<no<<"的全部信息:"<<endl;
ShowTimetableTitle();
ShowBusInfo(timetables,idx);
cout<<"是否确认删除(Y/N):";
cin>>choice;
outloop=0;
}
else
{
cout<<"\n***该车次号"<<no<<"的信息不存在,请检查输入车次是否正确***\n"<<endl;
outloop=1;
}
}while(outloop==1);
if(choice=='Y'||choice=='y')
{
cout<<"\n***注销成功***\n"<<endl;
for(int i=idx;i<n-1;i++)//从查询到的下标idx处,逐一前移,将要删除的车次信息排到末尾
{
timeb=timetables[i];
timetables[i]=timetables[i+1];
timetables[i+1]=timeb;
}
n=n-1;
}
else
cout<<"\n***取消删除***\n"<<endl;
return n;
}
void GenerateLogFileName(char *LogFileName)//根据当天日期生成日志名(如 2019-9-19.log)
{
LogFileName[0]='\0';
struct tm*local;//时间结构体
time_t t;//把当前时间给t
t=time(NULL);
local=localtime(&t);//获取当前系统时间
char year[5],month[3],day[3];
numbertochar(1900+local->tm_year,year);
numbertochar(1+local->tm_mon,month);
numbertochar(local->tm_mday,day);
strcat(LogFileName,year);
strcat(LogFileName,"-");
strcat(LogFileName,month);
strcat(LogFileName,"-");
strcat(LogFileName,day);
strcat(LogFileName,".log");
}
int InitializationPassagerMode(Timetable *timetables,char *LogFileName,char *filename)//判断当天日志文件LogFileName是否存在。
{
int n=0;
ofstream out;
out.open(LogFileName);
n=ReadFromFile(timetables,filename);
if(!out)
{
cout<<"\n***当天的日志文件"<<LogFileName<<"不存在***\n"<<endl;
ifstream readfromfile;
readfromfile.open(filename);
if(!readfromfile)
return -1;
int i=0;
while(readfromfile.peek()!=EOF)//将filename中的内容读至timetables中
{
readfromfile>>timetables[i].no>>timetables[i].hour>>timetables[i].minute
>>timetables[i].Starting_station>>timetables[i].Last_station
>>timetables[i].time>>timetables[i].fare
>>timetables[i].max_number;
timetables[i].sold_number=0;//sold_number成员置为0
i++;
}
readfromfile.close();
WritetoFile(timetables,n,LogFileName);//将timetables中的信息写入LogFileName
}
else//直接从LogFileName中读取数据至数组timetables中
for(int j=0;j<n;j++)
{
out<<timetables[j].no<<'\t'<<timetables[j].hour<<'\t'<<timetables[j].minute<<'\t'
<<timetables[j].Starting_station<<'\t'<<timetables[j].Last_station<<'\t'
<<timetables[j].time<<'\t'<<timetables[j].fare<<'\t'
<<timetables[j].max_number<<'\t'<<timetables[j].sold_number<<'\t';
if(j<n-1)
out<<endl;
else;
}
out.close();
return n;
}
void TicketOrder(Timetable *timetables,int n)//购买车票
{
cout<<"\n*****购票界面*****\n"<<endl;
char no[10];
int f;
bool t=true;
int number,left,yn,YN;
do
{
cout<<"请输入要购买的车次:";
cin>>no;
f=find(timetables,n,no);
if(f==-1)
{
cout<<"\n***该车次不存在/输入错误,***\n"<<endl;
return;
}
else
t=false;
}while(t);
if(t==false)
{
cout<<"\n***车次"<<no<<"存在***\n"<<endl;
cout<<"车次"<<no<<"的全部信息如下:"<<endl;
ShowTimetableTitle();
ShowBusInfo(timetables,f);
yn=StopService(timetables,n,no);
left=timetables[f].max_number-timetables[f].sold_number;
if(yn==1&&left>0)
cout<<"\n***现在距离发车时间少于10分钟,不可买票***\n"<<endl;
else if(left==0)
cout<<"\n***该车次票已经全部售出,不可买票***\n"<<endl;
else
{
cout<<"请输入需要购买的车票数目:";
cin>>number;
if(left>=number)
{
timetables[f].sold_number+=number;
cout<<"\n***购买成功***\n"<<endl;
}
else
cout<<"\n***车票仅剩"<<left<<"张,请选择其他班次***\n"<<endl;
return;
}
}
}
void TicketDelete(Timetable *timetables,int n)
{
cout<<"\n*****退票界面*****\n"<<endl;
char no[10],again;
bool t=true;
int f,x,num;
do
{
do
{
cout<<"请输入要退票的车次:";
cin>>no;
f=find(timetables,n,no);
x=StopService(timetables,n,no);
if(f==-1)//判断该车次是否存在
{
cout<<"\n***该车次不存在/输入错误***\n";
cout<<"是否重新输入(Y/N):"<<endl;
cin>>again;
if(again=='n'||again=='N')
return;
}
else
{
if(x==1)
{
cout<<"\n***该车次已停止服务***\n"<<endl;
return;
}
else
t=false;//车次存在且继续服务
again='y';
}
}while(again=='n'||again=='N');
}while(t);
char yn;
if(t==false)
{
do
{
cout<<"\n***请确认退票信息***\n"<<endl;
ShowTimetableTitle();
ShowBusInfo(timetables,f);//显示要删除的车次的基础信息
cout<<"请输入需要退票的数量:"<<endl;
cin>>num;
if(num>timetables[f].sold_number)
{
cout<<"\n***退票数大于购票数,请重新确认退票数量***\n"<<endl;
cout<<"是否继续退票(Y/N):";
cin>>yn;
}
else
{
timetables[f].sold_number-=num;
cout<<"\n***退票成功***\n"<<endl;
return;
}
}while(yn=='y'||yn=='Y');
if(yn=='n'||yn=='N')
{
cout<<"\n***取消退票***\n"<<endl;
return;
}
}
}
int Quit()
{
cin.sync();
cout<<"是否要退出整个系统(y/n):";
char c;
cin>>c;
if(c=='y'||c=='Y')
return 1;
else
return 0;
}
int MainWindowSelect()//主菜单实现
{
cout<<"\n*****主菜单*****\n"<<endl;
char *m[4]={"1.管理员登录",
"2.普通顾客登录",
"3.退出"};
int i=0;
while(m[i])
{
cout<<m[i]<<endl;
i++;
}
cout<<"\n****************\n"<<endl;
cout<<"请输入选择:";
int n;
do
{
cin>>n;
}while(n<0||n>3);
return n;
}
int AdminWindowSelect()//管理员菜单实现
{
cout<<"\n*****管理员菜单*****\n"<<endl;
char *m[6]={"1.增加车次信息",
"2.查看所有车次信息",
"3.车辆信息查询",
"4.注销车次",
"5.退出"};
for(int i=0;m[i];i++)
cout<<m[i]<<endl;
cout<<"\n********************\n"<<endl;
cout<<"请输入选择:";
int n;
do
{
cin>>n;
}while(n<0||n>5);
return n;
}
int PassagerWindowSelect()//普通顾客菜单实现
{
cout<<"\n*****普通顾客菜单*****\n"<<endl;
char *m[5]={"1.车辆信息查询",
"2.购买车票",
"3.退票",
"4.退出"};
for(int i=0;m[i];i++)
cout<<m[i]<<endl;
cout<<"\n**********************\n"<<endl;
cout<<"请输入选择:";
int n;
do
{
cin>>n;
}while(n<0||n>4);
return n;
}
void AdminMode( Timetable *timetables,char *filename )//管理员模式
{
Signin();//登录
int n=ReadFromFile(timetables,"bus.txt");
while(1)
{
system("cls");
int AdminChoice = AdminWindowSelect();
switch(AdminChoice)
{
case 1:
system("cls");
n = AddBus(timetables,n);
WritetoFile(timetables,n,filename);//增加车次信息,并及时写到文件中
system("pause");
break;
case 2:
system("cls");
ShowTimetable(timetables,n);//浏览时刻表
system("pause");
break;
case 3:
system("cls");
Query(timetables,n);//车辆信息查询
system("pause");
break;
case 4:
system("cls");
n = DelBus(timetables,n);
system("pause");
WritetoFile(timetables,n,filename);//注销车次,并及时更改文件
break;
case 5:
system("cls");
WritetoFile(timetables,n,filename);//返回上级菜单,并将信息保存回 bus.txt 文件
return;
}
}
}
void PassagerMode( Timetable *timetables,char *filename )//乘客模式
{
char LogFileName[200];
GenerateLogFileName(LogFileName);//根据当前日期生成日志名
int n = InitializationPassagerMode(timetables,LogFileName,filename);
n=ReadFromFile(timetables,"bus.txt");
int PassagerChoice;
while(1)
{
system("cls");
switch(PassagerChoice = PassagerWindowSelect())
{
case 1:
system("cls");
Query(timetables,n);//车辆信息查询
system("pause");
break;
case 2:
system("cls");
TicketOrder(timetables,n);
WritetoFile(timetables,n,filename);//购买车票,并更改文件信息
system("pause");
break;
case 3:
system("cls");
TicketDelete(timetables,n);
WritetoFile(timetables,n,filename);//退回车票,并更改文件信息
system("pause");
break;
case 4:
system("cls");
WritetoFile(timetables,n,filename);
return;//返回上级菜单
}
}
}
int main()
{
int UserChoice;
Timetable timetables[100];
while(1)
{
switch( UserChoice = MainWindowSelect() )//用户选择窗口
{
case 1:
system("cls");
AdminMode(timetables,"bus.txt");//进入管理员窗口
break;
case 2:
system("cls");
PassagerMode(timetables,"bus.txt");//进入乘客窗口
break;
case 3:
system("cls");
if(Quit()!=1)
continue;
}
if(UserChoice==3)
break;
}
return 0;
}