C++飞机订票管理系统(完整代码在最后)
引言
本文将系统拆解为八大核心模块,深入解析每个模块的设计逻辑与代码实现,结合控制台交互与文件存储,完整呈现一个功能齐全的飞机订票系统。
一、初始化与界面控制模块
模块功能:
负责控制台环境初始化、颜色管理和界面元素绘制,提供统一的视觉交互体验。
核心函数
1. loadingScreen()
- 加载界面
void loadingScreen() {
initConsole(); // 初始化UTF-8和大字体
setColor(11); // 青色背景
// 隐藏光标
CONSOLE_CURSOR_INFO cursor = { sizeof(cursor), 0, FALSE };
SetConsoleCursorInfo(hConsole, &cursor);
// 渐变进度条(使用Unicode块字符)
wcout << L"\n 系统加载中 \n";
for (int i = 0; i <= 50; ++i) {
wcout << L"[";
for (int j = 0; j < 50; ++j) {
setColor(BACKGROUND_BLUE | (j % 15 + 1)); // 15种颜色渐变
wcout << (j < i ? L"\u2588" : L" "); // 填充块
}
wcout << L"] " << i * 2 << L" %\r";
wcout.flush();
Sleep(50 + rand() % 20); // 随机延迟模拟加载
}
// 恢复光标和颜色
setColor(7);
cursor.bVisible = TRUE;
SetConsoleCursorInfo(hConsole, &cursor);
}
技术亮点:
- 使用
\u2588
(全角块)实现进度条填充,BACKGROUND_BLUE
配合颜色值实现渐变效果。 - 通过
Sleep()
模拟真实加载延迟,增强用户体验。
2. initConsole()
- 控制台初始化
void initConsole() {
SetConsoleOutputCP(65001); // 设置UTF-8编码
CONSOLE_FONT_INFOEX font = { sizeof(font), 0, 0, 18, 0,
L"Consolas", 0 }; // 18号Consolas字体
SetCurrentConsoleFontEx(hConsole, FALSE, &font);
}
作用:确保控制台正确显示中文和Unicode字符,大字体提升可读性。
二、用户认证模块
模块功能:
处理用户注册、登录逻辑,验证用户身份并区分管理员与普通用户。
核心函数
1. registing()
- 用户注册
void registing() {
system("cls");
drawTitleBox("用户注册", 50);
// 用户名验证(唯一+合法字符)
do {
cout << "用户名(字母/数字/下划线):";
cin >> username;
} while (isUsernameExist(username) || !isValidUsername(username));
// 密码验证(复杂度+确认)
string pwd;
do {
cout << "密码(6-15位,含大小写/数字/符号):";
scand(); // 输入显示为*
pwd = sf;
} while (!isValidPassword(pwd));
// 写入用户文件
ofstream out("user.txt", ios::app);
out << username << " " << pwd << endl;
cout << "注册成功!" << endl;
}
验证逻辑:
isValidUsername
:正则匹配^[a-zA-Z0-9_]+$
。isValidPassword
:必须包含[A-Za-z0-9!@#$%^&*]
且长度合规。
2. londing()
- 登录验证
void londing() {
system("cls");
drawTitleBox("用户登录", 50);
cout << "用户名:"; cin >> username;
cout << "密码:"; scand(); // 隐藏输入
// 验证管理员
ifstream adminFile("admin.txt");
string line;
while (getline(adminFile, line)) {
if (line == username + " " + sf) { Meoa(); return; }
}
// 验证普通用户
ifstream userFile("user.txt");
while (getline(userFile, line)) {
if (line == username + " " + sf) { Meou(); return; }
}
cout << "登录失败!" << endl;
}
区分身份:
- 管理员数据存储于
admin.txt
,普通用户存储于user.txt
,登录时分别校验。
三、航班管理模块(管理员功能)
模块功能:
提供航班的增、删、改、查功能,管理航班基础数据与座位信息。
核心函数
1. addFlight()
- 添加航班
void addFlight() {
system("cls");
drawTitleBox("新增航班", 50);
Flight f;
// 中文验证(出发地/目的地)
cin >> f.place; while (!isChinese(f.place)) { cout << "请输入中文!"; cin >> f.place; }
cin >> f.dest; while (!isChinese(f.dest)) { cout << "请输入中文!"; cin >> f.dest; }
// 时间验证(YYYY-MM-DD HH:MM)
cin >> f.stm; while (!isValidDateTime(f.stm)) { cin >> f.stm; }
cin >> f.ftm; while (!isValidDateTime(f.ftm) || strcmp(f.ftm, f.stm) <= 0) { cin >> f.ftm; }
// 写入二进制文件
ofstream out("flights.dat", ios::app | ios::binary);
out.write((char*)&f, sizeof(Flight));
cout << "航班添加成功!" << endl;
}
数据存储:
- 使用二进制文件
flights.dat
存储Flight
结构体,确保数据紧凑性。
2. showAllFlights()
- 显示航班列表
void showAllFlights() {
system("cls");
drawTitleBox("航班总览", 50);
ifstream in("flights.dat", ios::binary);
Flight f;
printFlightHeader(); // 绘制表头
while (in.read((char*)&f, sizeof(Flight))) {
printFlightRow(f); // 绘制行数据
}
printFlightFooter(); // 绘制表尾
in.close();
}
void printFlightRow(const Flight& f) {
printf("│ %-8s %-4s │ %-8s │ %-8s │ %-19s │ %-19s │ %4d/%4d │ %6.1f │\n",
f.comp, f.num, f.place, f.dest, f.stm, f.ftm, f.sit, f.ssit, f.pri * f.cot / 10);
}
表格设计:
- 使用Unicode框线字符(
┌├└
)和printf
格式控制实现专业表格显示。
四、用户操作模块
模块功能:
支持用户查询航班(含中转方案)、预订座位及生成订单。
核心函数
1. searchFlights()
- 航班查询
void searchFlights(const string& user) {
system("cls");
drawTitleBox("航班查询", 50);
string from, to;
cin >> from >> to;
// 直达航班查询
vector<Flight> direct = getDirectFlights(from, to);
printFlights(direct);
// 中转方案推荐
cout << "需要中转方案?(Y/N) ";
if (toupper(cin.get()) == 'Y') {
vector<TransferPlan> plans = getTransferPlans(from, to);
for (auto& p : plans) printTransferPlan(p);
}
}
中转逻辑:
- 通过两次文件遍历匹配同一中转城市的航班,要求中转时间≥1小时。
2. bookFlight()
- 航班预订
void bookFlight(const string& user) {
system("cls");
drawTitleBox("航班预订", 50);
string fnum; cin >> fnum;
Flight f = getFlight(fnum); // 获取航班信息
showSeatMap(f); // 显示座位图
string seat = selectSeat(f); // 选择座位
// 生成订单
Order order = createOrder(user, fnum, seat);
ofstream out("orders.dat", ios::app | ios::binary);
out.write((char*)&order, sizeof(Order));
// 更新航班余票
updateFlightSeat(fnum, seat, true);
cout << "预订成功!订单号:" << order.orderId << endl;
}
座位选择:
showSeatMap
使用▓
(已占用)和[ ]
(可选)可视化座位状态。selectSeat
通过正则表达式验证座位格式(如12A
)。
五、订单管理模块
模块功能:
处理用户订单的查看、退票、改签操作,维护订单状态与航班座位的一致性。
核心函数
1. showUserOrders()
- 查看订单
void showUserOrders(const string& user) {
system("cls");
drawTitleBox("我的订单", 50);
vector<Order> orders = getOrdersByUser(user);
printOrders(orders); // 表格显示订单
cout << "操作(1-退票,2-改签,0-返回):";
int opt; cin >> opt;
if (opt == 1 || opt == 2) {
int idx; cin >> idx;
Order& o = orders[idx-1];
opt == 1 ? cancelOrder(o) : modifyOrder(o);
}
}
订单状态:
status=1
(有效),status=0
(已取消),通过颜色区分显示。
2. cancelOrder(Order& order)
- 退票
void cancelOrder(Order& order) {
// 标记订单为已取消
order.status = 0;
// 恢复航班座位
Flight& f = getFlight(order.flightNumber);
int row = stoi(order.seat.substr(0, order.seat.size()-1)) - 1;
char col = order.seat.back();
f.seatMap[row][col - 'A'] = false;
f.sit++;
// 写入更新
updateFlight(f);
updateOrder(order);
cout << "退票成功!" << endl;
}
数据一致性:
- 同时修改订单状态和航班余票,确保业务逻辑正确。
六、辅助工具函数模块
模块功能:
提供通用工具函数,包括输入处理、格式验证、二维码生成等。
核心函数
1. scand()
- 密码输入隐藏
void scand() {
sf.clear();
char c;
while ((c = getch()) != '\r') {
if (c == '\b') { // 退格处理
if (!sf.empty()) {
sf.pop_back();
cout << "\b \b";
}
} else {
sf += c;
cout << '*';
}
}
}
作用:输入密码时显示为*
,支持退格删除。
2. generateRandomQRCode(int size)
- 二维码生成
vector<vector<bool>> generateRandomQRCode(int size) {
vector<vector<bool>> qr(size, vector<bool>(size, false));
// 添加定位图案(简化版)
for (int i = 0; i < 7; ++i)
for (int j = 0; j < 7; ++j)
qr[i][j] = (i < 2 || i > 4 || j < 2 || j > 4); // 左上角定位块
// 随机填充其他区域
for (int i = 7; i < size; ++i)
for (int j = 0; j < size; ++j)
qr[i][j] = rand() % 2;
return qr;
}
用途:模拟支付二维码生成,用于演示预订成功后的支付环节。
七、主流程与菜单模块
模块功能:
定义系统主流程,提供菜单导航,衔接各功能模块。
核心函数
1. begin()
- 主菜单
void begin() {
system("cls");
drawTitleBox("主菜单", 50);
cout << "1. 登录\n2. 注册\n0. 退出\n选择:";
int opt; cin >> opt;
switch (opt) {
case 1: londing(); break;
case 2: registing(); break;
case 0: exit(0);
default: begin();
}
}
流程控制:
- 作为程序入口,引导用户进入登录、注册或退出系统。
2. Meoa()
/Meou()
- 管理员/用户菜单
void Meoa() { // 管理员菜单
system("cls");
drawTitleBox("管理员面板", 50);
cout << "1. 添加航班\n2. 删除航班\n3. 查看所有航班\n0. 返回\n选择:";
int opt; cin >> opt;
// 调用对应功能函数
}
void Meou() { // 用户菜单
system("cls");
drawTitleBox("用户中心", 50);
cout << "1. 搜索航班\n2. 我的订单\n0. 返回\n选择:";
int opt; cin >> opt;
// 调用对应功能函数
}
权限区分:
- 管理员菜单包含航班管理功能,用户菜单仅允许查询和订单操作。
八、数据处理与验证模块
模块功能:
负责数据格式验证、时间处理和文件操作,确保数据合法性。
核心函数
1. isValidID(const char* id)
- 身份证验证
bool isValidID(const char* id) {
if (strlen(id) != 18) return false;
// 校验码计算
int weight[] = {7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2};
char check[] = "10X98765432";
int sum = 0;
for (int i = 0; i < 17; ++i)
sum += (id[i] - '0') * weight[i];
return check[sum % 11] == toupper(id[17]);
}
验证规则:
- 18位长度,前17位加权和模11计算校验码,支持
X
大写/小写。
2. parseDateTime(const char* dt)
- 时间解析
time_t parseDateTime(const char* dt) {
tm tm = {0};
sscanf(dt, "%d-%d-%d %d:%d", &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, &tm.tm_min);
tm.tm_year -= 1900; // 转换为1900纪元
tm.tm_mon -= 1; // 0-11月
return mktime(&tm); // 转换为时间戳
}
作用:将字符串时间转换为time_t
,便于时间比较和计算。
总结
系统框架图
模块交互流程示例
扩展方向
- 数据库升级:使用SQLite替代文件存储,提升大数据量下的查询效率。
- 功能增强:
- 多乘客预订、儿童票等特殊票务处理。
- 对接实时航班API,动态更新价格和起降时间。
- 界面优化:引入图形界面(如Qt)或支持鼠标操作的控制台交互。
通过八大模块的协同工作,系统实现了从用户认证到订单管理的完整业务闭环,适合作为C++控制台程序开发的进阶实践案例。
完整代码
#include<windows.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<malloc.h>
#include <time.h>
#include<locale.h>
#include <conio.h>
#include<fstream>
#include <iostream>
#include <string>
#include <regex>
#include <locale>
#include <fstream>
#include <iomanip>
#ifdef _WIN32
#include <fcntl.h>
#include <io.h>
#endif
using namespace std;
void loadingScreen() {
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
// 设置控制台模式支持扩展ASCII
#ifdef _WIN32
_setmode(_fileno(stdout), _O_U16TEXT);
#endif
// 隐藏光标
CONSOLE_CURSOR_INFO cursorInfo;
GetConsoleCursorInfo(hConsole, &cursorInfo);
cursorInfo.bVisible = false;
SetConsoleCursorInfo(hConsole, &cursorInfo);
SetConsoleTextAttribute(hConsole, 11); // 青色
// 进度条参数
const int totalSteps = 50;
const int barWidth = 50;
// 绘制进度条
SetConsoleTextAttribute(hConsole, 15); // 白色
wcout << L"\n Plase waiting \n";
for (int i = 0; i <= totalSteps; ++i) {
// 计算进度百分比
float progress = (float)i / totalSteps;
int pos = static_cast<int>(barWidth * progress + 0.5); // 四舍五入
// 更新进度条
wcout << L"[";
for (int j = 0; j < barWidth; ++j) {
if (j < pos) {
// 使用标准颜色组合(蓝底白字渐变)
SetConsoleTextAttribute(hConsole, BACKGROUND_BLUE | (j%15 + 1));
wcout << L"\u2588"; // 使用Unicode块字符
} else {
SetConsoleTextAttribute(hConsole, BACKGROUND_INTENSITY | FOREGROUND_INTENSITY);
wcout << L" ";
}
}
SetConsoleTextAttribute(hConsole, 15);
wcout << L"] " << int(progress * 100.0) << L" %\r";
wcout.flush();
// 更自然的延时模拟
Sleep(50 + (i%3)*20);
}
// 恢复设置
#ifdef _WIN32
_setmode(_fileno(stdout), _O_TEXT);
#endif
SetConsoleTextAttribute(hConsole, 7);
cursorInfo.bVisible = true;
SetConsoleCursorInfo(hConsole, &cursorInfo);
wcout << L"\n\n";
}
string username;
string sf,sf2,sure;
void begin();
void Meoa();
void Meou();
void showAllFlights();
void searchFlightsAdmin();
bool isValidID(const char *id);
void remanding();
void bookFlight(const string& username);
void showUserOrders(const string& username);
bool isValidFlightNumber(const char* num);
bool isUsernameExist(const string& username);
bool isFlightExist(const string& flightNumber);
void cancelOrder(const string& username, const string& orderId);
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
void modifyOrder(const string& username, const string& orderId, const char* fromPlace, const char* toDest);
#pragma pack(push, 1)
struct Flight {
char place[20];
char dest[20];
char stm[20];
char ftm[20];
char comp[50];
char num[20];
int sit;
int ssit;
double pri;
double cot;
bool seatMap[84][6];
};
#pragma pack(pop)
void setColor(int color) {
SetConsoleTextAttribute(hConsole, color);
}
void drawTitleBox(const string& title, int width) {
setColor(11);
cout << "╔" << string(width-2, '=') << "╗" << endl;
cout << "║";
setColor(14);
cout << " >> ";
cout<<title;
int spa=title.size();
while(spa<14)
{
cout<<' ';
spa++;
}
cout << "<< ";
setColor(11);
cout << "║" << endl;
cout << "╚" << string(width-2, '=') << "╝" << endl;
setColor(7);
}
void initConsole() {
SetConsoleOutputCP(65001); // UTF-8编码
CONSOLE_FONT_INFOEX font = { sizeof(font) };
font.dwFontSize.Y = 18;
SetCurrentConsoleFontEx(hConsole, FALSE, &font);
}
void printFlightHeader() {
setColor(13);
cout << "┌───────────────────────┬──────────┬──────────┬─────────────────────┬─────────────────────┬───────────┬────────┐" << endl;
cout << "│ 航班号 │ 出发地 │ 目的地 │ 起飞时间 │ 到达时间 │ 余票 │ 价格 │" << endl;
cout << "├───────────────────────┼──────────┼──────────┼─────────────────────┼─────────────────────┼───────────┼────────┤" << endl;
}
void printFlightRow(const Flight& f) {
//setColor(13);
printf("│ %-8s %-4s │ %-8s │ %-8s │ %-19s │ %-19s │ %-4d/%-4d │¥%6.1f│\n",
f.comp,f.num, f.place, f.dest, f.stm, f.ftm, f.sit, f.ssit, f.pri*f.cot/10.0);
}
void printFlightFooter() {
cout << "└───────────────────────┴──────────┴──────────┴─────────────────────┴─────────────────────┴───────────┴────────┘" << endl;
}
vector<vector<bool>> generateRandomQRCode(int size) {
vector<vector<bool>> qrCode(size, vector<bool>(size, false));
// 设置随机种子
srand(static_cast<unsigned int>(time(nullptr)));
// 生成随机矩阵(不包括定位图案)
for (int y = 0; y < size; ++y) {
for (int x = 0; x < size; ++x) {
// 跳过定位图案区域
bool isPositioningPattern =
(x >= 0 && x <= 6 && y >= 0 && y <= 6) || // 左上角
(x >= size-7 && x < size && y >= 0 && y <= 6) || // 右上角
(x >= 0 && x <= 6 && y >= size-7 && y < size); // 左下角
if (!isPositioningPattern) {
qrCode[y][x] = (rand() % 2 == 0);
}
}
}
// 设置三个定位图案
for (int y = 0; y <= 6; ++y) {
for (int x = 0; x <= 6; ++x) {
bool isBorder = (x == 0 || x == 6 || y == 0 || y == 6) ||
(x >= 2 && x <= 4 && y >= 2 && y <= 4);
qrCode[y][x] = isBorder;
}
}
for (int y = 0; y <= 6; ++y) {
for (int x = size-7; x < size; ++x) {
bool isBorder = (x == size-7 || x == size-1 || y == 0 || y == 6) ||
(x >= size-5 && x <= size-3 && y >= 2 && y <= 4);
qrCode[y][x] = isBorder;
}
}
for (int y = size-7; y < size; ++y) {
for (int x = 0; x <= 6; ++x) {
bool isBorder = (x == 0 || x == 6 || y == size-7 || y == size-1) ||
(x >= 2 && x <= 4 && y >= size-5 && y <= size-3);
qrCode[y][x] = isBorder;
}
}
// 设置校正图案(简化版)
if (size > 21) {
int centerX = size / 2;
int centerY = size / 2;
for (int y = centerY - 2; y <= centerY + 2; ++y) {
for (int x = centerX - 2; x <= centerX + 2; ++x) {
bool isBorder = (x == centerX - 2 || x == centerX + 2 ||
y == centerY - 2 || y == centerY + 2) ||
(x == centerX && y == centerY);
qrCode[y][x] = isBorder;
}
}
}
return qrCode;
}
void printQRCode(const vector<vector<bool>>& qrCode) {
const char blackChar = '#';
const char whiteChar = ' ';
// 顶部边框
cout << "+";
for (int i = 0; i < qrCode.size(); ++i) {
cout << "--";
}
cout << "+" << endl;
// 二维码内容
for (const auto& row : qrCode) {
cout << "|";
for (bool cell : row) {
cout << (cell ? blackChar : whiteChar) << (cell ? blackChar : whiteChar);
}
cout << "|" << endl;
}
// 底部边框
cout << "+";
for (int i = 0; i < qrCode.size(); ++i) {
cout << "--";
}
cout << "+" << endl;
}
time_t parseDateTime(const char* datetime) {
struct tm tm = {0};
sscanf(datetime, "%d-%d-%d %d:%d",
&tm.tm_year, &tm.tm_mon, &tm.tm_mday,
&tm.tm_hour, &tm.tm_min);
tm.tm_year -= 1900;
tm.tm_mon -= 1;
tm.tm_isdst = -1; // 不考虑夏令时
return mktime(&tm);
}
void clearInputBuffer() {
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
}
struct TransferPlan {
Flight firstFlight;
Flight secondFlight;
double totalPrice;
time_t totalDuration;
};
struct Order {
char orderId[32];
char username[32];
char flightNumber[16];
char bookTime[50];
char name[32];
char IDnum[20];
int status;
int sitx;
int sity;
char seat[5];
Order() { // 添加默认构造函数
memset(this, 0, sizeof(Order));
}
// 修改后的构造函数
Order(const string& oid, const string& user, const string& fnum,
const string& btime, const string& name, const string& id,const string& seat)
{
memset(this, 0, sizeof(Order));
strncpy(orderId, oid.c_str(), sizeof(orderId)-1);
strncpy(username, user.c_str(), sizeof(username)-1);
strncpy(flightNumber, fnum.c_str(), sizeof(flightNumber)-1);
strncpy(bookTime, btime.c_str(), sizeof(bookTime)-1);
strncpy(this->name, name.c_str(), sizeof(this->name)-1);
strncpy(IDnum, id.c_str(), sizeof(IDnum)-1);
// 确保字符串终止
orderId[sizeof(orderId)-1] = '\0';
username[sizeof(username)-1] = '\0';
flightNumber[sizeof(flightNumber)-1] = '\0';
bookTime[sizeof(bookTime)-1] = '\0';
this->name[sizeof(this->name)-1] = '\0';
IDnum[sizeof(IDnum)-1] = '\0';
status = 1;
strncpy(this->seat, seat.c_str(), sizeof(this->seat)-1);
this->seat[sizeof(this->seat)-1] = '\0';
}
};
string formatDuration(time_t seconds) {
int hours = seconds / 3600;
int mins = (seconds % 3600) / 60;
return to_string(hours) + "小时" + to_string(mins) + "分钟";
}
void printTransferPlan(const TransferPlan& plan) {
setColor(14);
cout << " 中转方案 \n";
cout << " ┌───────────────────────────────┐\n";
printf(" │ %-5s → %-3s → %-8s │\n",
plan.firstFlight.place,
plan.firstFlight.num,
plan.firstFlight.dest);
cout <<" │ ▼ " << formatDuration(plan.totalDuration);
int spa=formatDuration(plan.totalDuration).size();
while(spa<13)
{
cout<<' ';
spa++;
}
cout<< " 中转 │\n";
printf(" │ %-5s → %-3s → %-8s │\n",
plan.secondFlight.place,
plan.secondFlight.num,
plan.secondFlight.dest);
cout << " └───────────────────────────────┘\n";
setColor(11);
cout<<"总时长: "<< formatDuration(parseDateTime(plan.secondFlight.ftm) - parseDateTime(plan.firstFlight.stm));
printf(" 总价格: ¥%.2f\n",plan.totalPrice);
cout << "航班1:"<<plan.firstFlight.comp<<plan.firstFlight.num<<" "<<plan.firstFlight.place<<'-'<<plan.firstFlight.dest<<" "<< plan.firstFlight.stm << " - " << plan.firstFlight.ftm<<" "<<plan.firstFlight.sit<<'/'<<plan.firstFlight.ssit<<" "<<plan.firstFlight.pri<<" "<<plan.firstFlight.cot<<endl;
cout << "航班2:"<<plan.secondFlight.comp<<plan.secondFlight.num<<" "<<plan.secondFlight.place<<'-'<<plan.secondFlight.dest<<" "<< plan.secondFlight.stm << " - " << plan.secondFlight.ftm<<" "<<plan.secondFlight.sit<<'/'<<plan.secondFlight.ssit<<" "<<plan.secondFlight.pri<<" "<<plan.secondFlight.cot<<endl;
setColor(7);
}
bool isFlightExist(const string& flightNumber) {
ifstream fin("flights.dat", ios::binary);
Flight f;
while(fin.read((char*)&f, sizeof(Flight))) {
if(strcmp(f.num, flightNumber.c_str()) == 0) {
return true;
}
}
return false;
}
bool isValidFlightNumber(const char* num) {
if(strlen(num) != 4) return false;
for(int i=0; i<4; ++i) {
if(!isdigit(num[i])) return false;
}
return true;
}
bool isUsernameExist(const string& username) {
ifstream fin("user.txt");
string line;
while(getline(fin, line)) {
if(line.find(username + ' ') == 0) {
return true;
}
}
return false;
}
bool isChineseString(const char *str) {
const unsigned char *p = (const unsigned char *)str;
while (*p) {
if (*p < 0x80) {
return false;
}
if (*(p + 1) == '\0') {
return false;
}
p += 2;
}
return true;
}
bool isValidDateTime(const char *datetime) {
struct timeb now;
ftime(&now);
time_t current_time = now.time;
char temp[20];
strncpy(temp, datetime, 19);
temp[19] = '\0';
int year, month, day, hour, minute;
bool validFormat = true;
if(sscanf(temp, "%d-%d-%d %d:%d", &year, &month, &day, &hour, &minute) != 5 ||
strlen(temp) != 16 || temp[4] != '-' || temp[7] != '-' || temp[10] != ' ' || temp[13] != ':') {
return false;
}
struct tm input_tm = {0};
input_tm.tm_year = year - 1900;
input_tm.tm_mon = month - 1;
input_tm.tm_mday = day;
input_tm.tm_hour = hour;
input_tm.tm_min = minute;
time_t input_time = mktime(&input_tm);
return input_time >= current_time;
if(!validFormat) {
cout<<"时间格式应为 YYYY-MM-DD HH:MM(如:2023-12-31 14:30)"<<endl;
return false;
}
if(input_time < current_time) {
cout<<"时间不能早于当前时间!"<<endl;
return false;
}
return true;
}
bool isValidDate(const char* date) {
int year, month, day;
if (sscanf(date, "%d-%d-%d", &year, &month, &day) != 3)
return false;
if (year < 1900 || month < 1 || month > 12 || day < 1 || day > 31)
return false;
// 简单月份天数验证
const int daysInMonth[] = {31,28,31,30,31,30,31,31,30,31,30,31};
int maxDay = daysInMonth[month-1];
if (month == 2 && (year%400 == 0 || (year%100 != 0 && year%4 == 0)))
maxDay = 29;
return day <= maxDay;
}
void exit(){
cout<<"感谢您的使用"<<endl;
return ;
}
void showSeatMap(const Flight& f) {
setColor(10);
cout << " A B C D E F\n";
cout << " ┌───┬───┬───┐ ┌───┬───┬───┐\n";
int suml;
int yh;
int ins=0;
suml=f.ssit/6;
yh=f.ssit%6;
if(yh>0)
suml++;
for(int row=0; row<suml; ++row){
printf("%2d│", row+1);
for(int col=0; col<6; ++col){
if(++ins>f.ssit) {
break;
}
if(col == 3) cout << " │";
if(f.seatMap[row][col]) {
setColor(12); // 红色表示已占用
cout << "▓▓▓";
setColor(10);
} else {
setColor(10); // 绿色表示可用
cout << "[ ]";
}
cout << "│";
}
cout << endl;
if(ins>f.ssit) break;
if(row <suml) cout << " ├───┼───┼───┤ ├───┼───┼───┤\n";
}
cout << " └───┴───┴───┘ └───┴───┴───┘\n";
setColor(14);
cout << "▓:已占用 [ ]:可选\n";
setColor(7);
}
string selectSeat(Flight& flight) {
drawTitleBox("选择座位",50);
showSeatMap(flight);
while(true) {
cout << "请选择座位(如12A):";
string input;
cin >> input;
// 使用正则表达式验证格式
regex pattern(R"(^(?:[1-9]|[1-7]\d|8[0-4]|85)([A-Fa-f])$)");
if(!regex_match(input, pattern)) {
cout << "无效的座位格式!" << endl;
continue;
}
// 解析座位号
int row = stoi(input.substr(0, input.length()-1)) - 1;
char colChar = toupper(input.back());
int col = colChar - 'A';
// 处理过
if(row <0 || row >=((flight.ssit)/6+1) || col <0 || col >=6||row*6+col>flight.ssit) {
cout << "无效的座位范围!" << endl;
continue;
}
if(flight.seatMap[row][col]) {
cout << "该座位已被占用!" << endl;
} else {
flight.seatMap[row][col] = true;
flight.sit--;
return input;
}
}
}
void scamrd(){
cout<<"名称不能包含除英文字母,数字和下划线以外的符号"<<endl;
username="";
char a;
bool f=0;
while(1)
{
a=getch();
if(a=='\r')
break;
if(a=='\b')
{
putchar('\b');
putchar(' ');
putchar('\b');
username+='\b';
}
else
{
if((a>'z'&&a<'a')&&(a>'Z'&&a<'A')&&('0'>a&&a>'9')&&a!='_')
f=1;
username+=a;
putchar(a);
}
}
if(f==1)
{
cout<<endl;
scamrd();
}
}
void scand(){
sf="";
char a;
while(1)
{
a=getch();
if(a=='\r')
break;
if(a=='\b')
{
putchar('\b');
putchar(' ');
putchar('\b');
sf+='\b';
}
else
{
sf+=a;
putchar('*');
}
}
}
bool isValidID(const char *id) {
int len = strlen(id);
if (len != 18)
{
cout<<"身份证号长度应为18位!"<<endl;
return false;
}
// 校验日期部分
char datePart[9];
if (len == 18) {
strncpy(datePart, id + 6, 8);
datePart[8] = '\0';
} else {
strncpy(datePart, "19", 2);
strncpy(datePart + 2, id + 6, 6);
datePart[8] = '\0';
}
char formattedDate[11];
snprintf(formattedDate, sizeof(formattedDate), "%.4s-%.2s-%.2s",
datePart, datePart+4, datePart+6);
bool dateValid = isValidDate(formattedDate);
if(!dateValid) {
cout<<"身份证出生日期无效!"<<endl;
return false;
}
// return isValidDate(formattedDate);
if(len == 18) {
int factor[] = {7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2};
char checkCode[] = "10X98765432";
int sum = 0;
for(int i=0; i<17; ++i) {
sum += (id[i]-'0') * factor[i];
}
bool checkCodeValid = (checkCode[sum%11] == toupper(id[17]));
if(!checkCodeValid) {
cout<<"身份证校验码不正确!"<<endl;
return false;
}
}
return true;
}
void scanrd(){
cout<<"密码不得少于6个字符,不得多于15个字符且密码必须包含大小写字母,数字和特殊符号(不含空格)各一种"<<endl;
bool f1=0,f3=0,f4=0;
sf="";
char a;
int x=0;
while(1)
{
a=getch();
if(a=='\r')
break;
if(a=='\b')
{
putchar('\b');
putchar(' ');
putchar('\b');
sf+='\b';
x--;
}
else
{
sf+=a;
if(('A'<=a&&a<='Z')||('a'<=a&&a<='z'))
f1=1;
else if('0'<=a&&a<='9')
f3=1;
else
f4=1;
x++;
putchar('*');
}
}
if(f1!=1||f3!=1||f4!=1||x<6||x>15)
{
cout<<endl;
scanrd();
}
}
void scanrrd(){
sure="";
char a;
while(1)
{
a=getch();
if(a=='\r')
break;
if(a=='\b')
{
putchar('\b');
putchar(' ');
putchar('\b');
sure+='\b';
}
else
{
sure+=a;
putchar('*');
}
}
}
void registing(){
bool fx=0;
do {
cout<<"请输入账户名"<<endl;
scamrd();
if(isUsernameExist(username)) {
cout<<"用户名已存在,请重新输入!"<<endl;
username = "";
}
} while(username.empty());
cout<<endl;
do
{
cout<<"请输入密码"<<endl;
scanrd();
cout<<endl;
cout<<"请确认密码"<<endl;
scanrrd();
if(sure!=sf)
{
cout<<"两次密码不一样"<<endl;
}
}while(sure!=sf);
cout<<endl;
string tit;
cout<<"输入您的电话号码";
cin>>tit;
ofstream outfu("user.txt",ios::app);
outfu<<username<<' '<<sf<<'\n';
outfu.close();
system("cls");
begin();
}
void londing(){
system("cls");
cout<<"请输入账号名"<<endl;
cin>>username;
cout<<"请输入密码"<<endl;
scand();
string s,ad;
ad=username+' '+sf;
cout<<endl;
ifstream infa("admin.txt");
int f=0;
while(getline(infa,s))
{
if(ad==s)
{
f=1;
break;
}
}
infa.close();
ifstream infu("user.txt");
while(getline(infu,s))
{
if(ad==s)
{
f=2;
break;
}
}
infu.close();
if(f==0)
{
cout<<endl<<"账户名或密码错误"<<endl;
system("pause");
londing();
}
else
{
cout<<"登录成功"<<endl;
system("pause");
if(f==1)
Meoa();
else if(f==2)
Meou();
}
system("pause");
londing();
}
void zhinan() {
setColor(11);
cout << "\n┌───────────────────────── 乘机指南 ────────────────────────┐" << endl;
cout << "│ 1. 行前准备 │" << endl;
cout << "│ ┌─────────────────────────────────────────────────────┐ │" << endl;
cout << "│ │ (1) 订票:使用身份证、护照等有效证件通过系统预订 │ │" << endl;
cout << "│ │ (2) 值机:起飞前48小时可手机办理,或前往机场办理 │ │" << endl;
cout << "│ │ (3) 关注航班动态:留意航司通知及短信 │ │" << endl;
cout << "│ │ (4) 前往机场时间: │ │" << endl;
cout << "│ │ 国内航班提前2小时 | 国际航班提前3小时 │ │" << endl;
cout << "│ └─────────────────────────────────────────────────────┘ │" << endl;
cout << "│ 2. 抵达机场流程 │" << endl;
cout << "│ ┌─────────────────────────────────────────────────────┐ │" << endl;
cout << "│ │ (1) 值机柜台查询 | 临时乘机证明办理 │ │" << endl;
cout << "│ │ (2) 托运行李 | 安全检查注意事项 │ │" << endl;
cout << "│ │ (3) 登机口有序登机 │ │" << endl;
cout << "│ └─────────────────────────────────────────────────────┘ │" << endl;
cout << "│ 3. 飞行途中 │" << endl;
cout << "│ ┌─────────────────────────────────────────────────────┐ │" << endl;
cout << "│ │ 全程系好安全带 | 遵守客舱安全指引 │ │" << endl;
cout << "│ └─────────────────────────────────────────────────────┘ │" << endl;
cout << "│ 4. 抵达后流程 │" << endl;
cout << "│ ┌─────────────────────────────────────────────────────┐ │" << endl;
cout << "│ │ (1) 行李提取:核对行李票 | 异常处理 │ │" << endl;
cout << "│ │ (2) 报销凭证:7日内领取行程单 │ │" << endl;
cout << "│ └─────────────────────────────────────────────────────┘ │" << endl;
cout << "└───────────────────────────────────────────────────────────┘" << endl;
setColor(7);
system("pause");
remanding();
}
void gonggao() {
setColor(12);
cout << "\n┌───────────────────────── 重要公告 ────────────────────────┐" << endl;
cout << "│ 1. 安全乘机告知 │" << endl;
cout << "│ ┌─────────────────────────────────────────────────────┐ │" << endl;
cout << "│ │ 严禁在航空器上: │ │" << endl;
cout << "│ │ 抢占座位/行李架 辱骂殴打机组人员 │ │" << endl;
cout << "│ │ 破坏机上设施 扰乱客舱秩序 │ │" << endl;
cout << "│ │ 违者将依法追究治安/刑事责任 │ │" << endl;
cout << "│ └─────────────────────────────────────────────────────┘ │" << endl;
cout << "│ 2. 防诈骗提示 │" << endl;
cout << "│ ┌─────────────────────────────────────────────────────┐ │" << endl;
cout << "│ │ 警惕假冒航司短信/电话索要银行卡信息 │ │" << endl;
cout << "│ │ 航班变动请通过官方渠道核实 │ │" << endl;
cout << "│ │ 客服电话:4008812306 │ │" << endl;
cout << "│ └─────────────────────────────────────────────────────┘ │" << endl;
cout << "└───────────────────────────────────────────────────────────┘" << endl;
setColor(7);
system("pause");
remanding();
}
void shengming() {
setColor(13);
cout << "\n┌───────────────────────── 服务声明 ────────────────────────┐" << endl;
cout << "│ 1. 航班销售声明 │" << endl;
cout << "│ ┌─────────────────────────────────────────────────────┐ │" << endl;
cout << "│ │ 支持航司:东航/国航/南航/春秋等40余家航空公司 │ │" << endl;
cout << "│ │ 航班延误/取消可能导致后续行程损失,需自行承担 │ │" << endl;
cout << "│ └─────────────────────────────────────────────────────┘ │" << endl;
cout << "│ 2. 特殊票务说明 │" << endl;
cout << "│ ┌─────────────────────────────────────────────────────┐ │" << endl;
cout << "│ │ 暂不支持军人/警察优待票在线购买 │ │" << endl;
cout << "│ │ 特殊旅客请直接联系航司客服办理 │ │" << endl;
cout << "│ │ 东方航空 95530 中国国航 95583 │ │" << endl;
cout << "│ │ 春秋航空 95524 四川航空 95378 │ │" << endl;
cout << "│ │ 厦门航空 95557 深圳航空 95361 南方航空 95539 │ │" << endl;
cout << "│ └─────────────────────────────────────────────────────┘ │" << endl;
cout << "└───────────────────────────────────────────────────────────┘" << endl;
setColor(7);
system("pause");
remanding();
}
void remanding(){
system("cls");
setColor(14);
puts("+-------------------------------------------------+");
puts("| 1.乘机指南 2.公告 |");
puts("| 3.声明 4.返回菜单界面 |");
puts("| 遇到问题?拨打客服电话4008812306以寻求帮助 |");
puts("+-------------------------------------------------+");
cout << "\n>> 请选择操作 [1-4]: ";
while(true) {
int x;
cin>>x;
setColor(14);
switch (x)
{
case 1:{
zhinan();
break;
}
case 2:{
gonggao();
break;
}
case 3:{
shengming();
break;
}
case 4:{
Meou();
system("cls");
break;
}
// 正确退出循环
default:
cout << "无效输入!" << endl;
system("pause");
}
}
}
void showAllFlights() {
ifstream fin("flights.dat",ios::binary);
if(!fin){
cout<<"航班数据文件打开失败!"<<endl;
system("pause");
Meoa();
return ;
}
system("cls");
drawTitleBox("所有航班信息",50);
Flight f;
int total=0;
printFlightHeader();
setColor(7);
while(fin.read(reinterpret_cast<char*>(&f), sizeof(Flight))) {
printFlightRow(f);
total++;
}
printFlightFooter();
fin.close();
if(total == 0) {
cout << "当前没有航班信息!" << endl;
}
cout << "总计航班数量: " << total << endl;
while (true) {
cout << "\n输入航班号查看座位详情(输入0返回): ";
string flightNumber;
cin >> flightNumber;
if (flightNumber == "0") {
break;
}
ifstream fin("flights.dat", ios::binary);
Flight f;
bool found = false;
while (fin.read(reinterpret_cast<char*>(&f), sizeof(Flight))) {
if (strcmp(f.num, flightNumber.c_str()) == 0) {
found = true;
break;
}
}
fin.close();
if (found) {
system("cls");
drawTitleBox("航班座位详情", 50);
cout << "航班号: " << f.num << " " << f.place << " → " << f.dest << endl;
cout << "总座位数: " << f.ssit << " 剩余座位: " << f.sit << "\n" << endl;
showSeatMap(f);
system("pause");
system("cls");
// 重新显示航班列表
showAllFlights();
return;
} else {
cout << "未找到该航班!" << endl;
}
}
system("pause");
Meoa();
}
void searchFlightsAdmin() {
// 查询条件输入
string from, to;
cout << "输入出发地:";
cin >> from;
cout << "输入目的地:";
cin >> to;
cin.ignore(numeric_limits<streamsize>::max(), '\n');
// 打开文件
fstream file("flights.dat", ios::in | ios::out | ios::binary);
if (!file) {
cerr << "错误:无法打开航班数据文件!" << endl;
system("pause");
Meoa();
}
// 查询和显示结果
vector<streampos> positions; // 记录文件位置
Flight f;
int index = 0;
bool found = false;
cout << "\n查询结果:" << endl;
cout << "====================================================================================" << endl;
cout << left
<< setw(4) << "序号"
<< setw(12) << "航班号"
<< setw(15) << "出发地"
<< setw(15) << "目的地"
<< setw(20) << "起飞时间"
<< setw(20) << "到达时间"
<< setw(8) << "座位"
<< setw(10) << "票价"
<< setw(8) << "折扣"
<< endl;
while (file.read(reinterpret_cast<char*>(&f), sizeof(Flight))) {
// 匹配查询条件
bool matchFrom = from.empty() || (strcmp(f.place, from.c_str())) == 0;
bool matchTo = to.empty() || (strcmp(f.dest, to.c_str())) == 0;
if (matchFrom && matchTo) {
positions.push_back(file.tellg() - static_cast<streampos>(sizeof(Flight)));
cout << left
<< setw(4) << ++index
<< setw(12) << f.num
<< setw(15) << f.place
<< setw(15) << f.dest
<< setw(20) << f.stm
<< setw(20) << f.ftm
<< setw(8) << f.sit
<< fixed << setprecision(2) << setw(10) << f.pri
<< setw(8) << f.cot
<< endl;
found = true;
}
}
if (!found) {
cout << "未找到符合条件的航班" << endl;
system("pause");
Meoa();
}
cout << "====================================================================================" << endl;
// 选择要修改的航班
int choice;
cout << "\n输入要修改的航班序号(0取消):";
cin >> choice;
if (choice < 1 || choice > index) {
cout << "操作已取消" << endl;
system("pause");
Meoa();
}
// 定位到选择的位置
streampos pos = positions[choice-1];
file.clear();
file.seekg(pos);
file.read(reinterpret_cast<char*>(&f), sizeof(Flight));
// 显示当前信息
cout << "\n当前航班信息:" << endl;
cout << "----------------------------------------" << endl;
cout << "1. 座位数: " << f.sit << endl;
cout << "2. 基准票价: " << f.pri << endl;
cout << "3. 折扣率: " << f.cot << endl;
// 修改字段选择
cout << "\n选择要修改的字段(1-3,0保存修改):";
int field;
while (true) {
cin >> field;
if (field == 0) break;
switch (field) {
case 1: {
do {
cout << "输入新座位数(当前:" << f.sit << "): ";
cin >> f.sit;
} while (f.sit < 0);
break;
}
case 2: {
do {
cout << "输入新基准票价(当前:" << f.pri << "): ";
cin >> f.pri;
} while (f.pri <= 0);
break;
}
case 3: {
do {
cout << "输入新折扣率(0.1-9.9,当前:" << f.cot << "): ";
cin >> f.cot;
} while (f.cot < 0.1 || f.cot > 9.9);
break;
}
default:
cout << "无效选择!";
}
cout << "选择要修改的字段(1-3,0保存修改):";
}
// 写回修改
file.clear();
file.seekp(pos);
file.write(reinterpret_cast<char*>(&f), sizeof(Flight));
file.close();
cout << "\n修改已保存!" << endl;
system("pause");
Meoa();
}
void addAdmin() {
string newUser, newPass;
do {
cout << "输入新管理员用户名:";
cin >> newUser;
} while(newUser.empty() || newUser.find(' ') != string::npos || isUsernameExist(newUser));
if(newUser.empty() || newUser.find(' ') != string::npos) {
cout << "用户名包含非法字符!" << endl;
return;
}
ifstream fin("admin.txt");
string line;
while(getline(fin, line)) {
if(line.find(newUser + ' ') == 0) {
cout << "该管理员已存在!" << endl;
fin.close();
return;
}
}
fin.close();
cout << "输入密码:";
scanrd();
newPass = sf;
cout << endl;
ofstream fout("admin.txt", ios::app);
fout << newUser << " " << newPass << endl;
fout.close();
cout << "管理员添加成功!" << endl;
system("pause");
Meoa();
}
void viewUsers() {
ifstream fin("user.txt");
if(!fin) {
cout << "用户数据文件打开失败!" << endl;
return;
}
cout << "\n用户列表:" << endl;
cout << "====================" << endl;
string username, password;
int count = 0;
while(fin >> username >> password) {
cout << left << setw(20) << username
<< endl;
count++;
}
fin.close();
if(count == 0) {
cout << "暂无注册用户" << endl;
} else {
cout << "====================" << endl;
cout << "总计用户数量: " << count << endl;
}
system("pause");
Meoa();
}
void addFlight() {
Flight f;
// 出发地验证
bool fe=0;
do {
cout << "输入起始地(中文):";
cin >> f.place;
fe=(isChineseString(f.place));
if(!fe)cout<<"请输入中文"<<endl;
} while(!fe);
// 目的地验证
bool fd=0;
do {
cout << "输入目的地(中文):";
cin >> f.dest;
fd=(isChineseString(f.dest));
if(!fd)cout<<"请输入中文"<<endl;
} while(!fd);
getchar();
char stm[20], ftm[20];
time_t t1, t2;
do {
do {
printf("输入预计起飞时间(YYYY-MM-DD HH:MM):");
fgets(stm, sizeof(stm), stdin);
stm[strcspn(stm, "\n")] = 0;
} while(!isValidDateTime(stm));
do {
printf("输入预计到达时间(YYYY-MM-DD HH:MM):");
fgets(ftm, sizeof(ftm), stdin);
ftm[strcspn(ftm, "\n")] = 0;
} while(!isValidDateTime(ftm));
// 转换为时间戳比较
struct tm tm1 = {}, tm2 = {};
sscanf(stm, "%d-%d-%d %d:%d", &tm1.tm_year, &tm1.tm_mon, &tm1.tm_mday,
&tm1.tm_hour, &tm1.tm_min);
sscanf(ftm, "%d-%d-%d %d:%d", &tm2.tm_year, &tm2.tm_mon, &tm2.tm_mday,
&tm2.tm_hour, &tm2.tm_min);
tm1.tm_year -= 1900;
tm1.tm_mon -= 1;
tm1.tm_isdst = -1;
tm2.tm_year -= 1900;
tm2.tm_mon -= 1;
tm2.tm_isdst = -1;
t1 = mktime(&tm1);
t2 = mktime(&tm2);
if(difftime(t2, t1) <= 0) {
cout << "错误:到达时间必须晚于起飞时间!\n";
cout << "起飞时间:" << stm << endl;
cout << "当前到达时间:" << ftm << endl;
}
} while(difftime(t2, t1) <= 0); // 循环直到到达时间正确
strcpy(f.stm, stm);
strcpy(f.ftm, ftm);
int airlineChoice;
const vector<string> airlines = {
"东方航空(MU)", "中国国航(CA)", "南方航空(CZ)",
"春秋航空(9C)", "四川航空(3U)", "厦门航空(MF)", "深圳航空(ZH)"
};
do {
cout << "选择航空公司:" << endl;
for(int i=0; i<airlines.size(); ++i) {
cout << i+1 << ". " << airlines[i] << endl;
}
cin >> airlineChoice;
} while(airlineChoice <1 || airlineChoice>7);
string selectedAirline = airlines[airlineChoice-1];
strncpy(f.comp, selectedAirline.c_str(), sizeof(f.comp)-1);
f.comp[sizeof(f.comp)-1] = '\0';
// 航班号验证
bool fn=0;
do {
cout << "请输入航班号(4位数字):";
cin >> f.num;
if(!isValidFlightNumber(f.num)) {
cout<<"航班号必须为4位数字(如:1234)"<<endl;
}
if(isFlightExist(f.num)) {
cout<<"航班号 "<<f.num<<" 已存在!"<<endl;
}
} while(!isValidFlightNumber(f.num) || isFlightExist(f.num));
bool fs=0;
do {
cout << "请输入座位数(1-500):";
cin >> f.sit;
if(f.sit <= 0) {
cout<<"座位数必须大于0!"<<endl;
} else if(f.sit > 500) {
cout<<"座位数不能超过500!"<<endl;
}
} while(f.sit <= 0 || f.sit > 500);
bool fp=0;
do {
cout << "输入票价:";
cin >> f.pri;
fp=(f.pri<=0);
if(fp)cout<<"价格不得小于等于0"<<endl;
} while(fp);
bool fc=0;
do {
cout << "输入折扣(0.1-9.9):";
cin >> f.cot;
fc=(f.cot<0.1||f.cot>9.9);
if(fc)cout<<"价格不得小于0.1不得大于9.9"<<endl;
} while(fc);
memset(f.seatMap, 0, sizeof(f.seatMap));
f.ssit=f.sit;
ofstream outf("flights.dat",ios::app|ios::binary);
outf.write(reinterpret_cast<char*>(&f), sizeof(Flight));
outf.close();
cout << "航班添加成功!" << endl;
system("pause");
Meoa();
}
void deleteFlight() {
string target;
cout << "输入要删除的航班号:";
cin >> target;
cin.ignore(numeric_limits<streamsize>::max(), '\n'); // 清空输入缓冲区
// 打开文件流
ifstream fin("flights.dat", ios::binary);
ofstream temp("temp.dat", ios::binary);
if (!fin.is_open() || !temp.is_open()) {
cerr << "错误:无法打开数据文件!" << endl;
system("pause");
return;
}
Flight f;
bool found = false;
int deleteCount = 0;
// 遍历航班数据
while (fin.read(reinterpret_cast<char*>(&f), sizeof(Flight))) {
// 比较航班号(使用C字符串比较)
if (strcmp(f.num, target.c_str()) == 0) {
found = true;
cout << "\n找到匹配航班:" << endl;
cout << "----------------------------------------" << endl;
cout << "航空公司: " << f.comp << endl;
cout << "出发地: " << f.place << " -> 目的地: " << f.dest << endl;
cout << "起飞时间: " << f.stm << " 到达时间: " << f.ftm << endl;
cout << "剩余座位: " << f.sit << " 票价: " << f.pri * f.cot / 10.0 << endl;
// 确认删除
cout << "\n是否确认删除?(Y/N): ";
char confirm;
cin >> confirm;
cin.ignore(numeric_limits<streamsize>::max(), '\n');
if (toupper(confirm) == 'Y') {
deleteCount++;
continue; // 跳过写入
}
}
// 写入保留的记录
temp.write(reinterpret_cast<char*>(&f), sizeof(Flight));
}
// 关闭文件流
fin.close();
temp.close();
// 文件替换操作
if (found) {
if (remove("flights.dat") != 0) {
perror("删除原文件失败");
system("pause");
return;
}
if (rename("temp.dat", "flights.dat") != 0) {
perror("重命名文件失败");
system("pause");
return;
}
cout << "\n成功删除 " << deleteCount << " 个航班记录" << endl;
} else {
remove("temp.dat"); // 清理临时文件
cout << "未找到航班号: " << target << endl;
}
// 错误状态清除
fin.clear();
temp.clear();
system("pause");
Meoa();
}
void searchFlights(const string& username) {
string from,to;
cout << "输入出发地:";
cin >> from;
cout << "输入目的地:";
cin >> to;
ifstream fin("flights.dat",ios::binary);
if (!fin) {
cout << "无法打开航班数据!" << endl;
system("pause");
Meou();
return ;
}
Flight f;
int index = 0;
bool found = false;
cout << "\n查询结果:" << endl;
cout << "=============================================================================================================" << endl;
cout << left
<< setw(4) << "序号"
<< setw(20) << "航班号"
<< setw(15) << "出发地"
<< setw(15) << "目的地"
<< setw(20) << "起飞时间"
<< setw(20) << "到达时间"
<< setw(8) << "余票"
<< setw(10) << "价格"
<< endl;
while (fin.read(reinterpret_cast<char*>(&f), sizeof(Flight))) {
bool matchFrom = from.empty() || (strcmp(f.place, from.c_str()) == 0);
bool matchTo = to.empty() || (strcmp(f.dest, to.c_str()) == 0);
if (matchFrom && matchTo && f.sit > 0) {
cout << left
<< setw(4) << ++index
<< setw(2) <<f.comp
<< setw(8) << f.num
<< setw(15) << f.place
<< setw(10) << f.dest
<< setw(20) << f.stm
<< setw(22) << f.ftm
<< setw(0) << f.sit <<'/'
<< setw(6) << f.ssit
<< fixed << setprecision(2) << setw(10) << f.pri * f.cot / 10.0
<< endl;
found = true;
}
}
if(!found) {
cout << "无相应航班!" << endl;
}
cout << "============================================================================================================" << endl;
fin.close();
vector<TransferPlan> transferPlans;
cout << "\n以上是直达航班,是否需要中转方案?(Y/N)";
char input;
cin >> input;
if(toupper(input) == 'Y') {
vector<Flight> firstLeg;
ifstream fin("flights.dat", ios::binary);
Flight f;
while(fin.read(reinterpret_cast<char*>(&f), sizeof(Flight))) {
if(strcmp(f.place, from.c_str()) == 0 &&
strcmp(f.dest, to.c_str()) != 0) {
firstLeg.push_back(f);
}
}
fin.close();
// 遍历每个第一段航班找第二段
for(auto& leg1 : firstLeg) {
const char* transferCity = leg1.dest;
time_t arrival1 = parseDateTime(leg1.ftm);
// 找第二段航班(中转城市->目的地)
ifstream fin2("flights.dat", ios::binary);
Flight leg2;
while(fin2.read(reinterpret_cast<char*>(&leg2), sizeof(Flight))) {
if(strcmp(leg2.place, transferCity) == 0 &&
strcmp(leg2.dest, to.c_str()) == 0) {
time_t depart2 = parseDateTime(leg2.stm);
// 检查时间是否衔接
if(depart2 > arrival1 + 3600) { // 至少1小时中转时间
TransferPlan plan;
plan.firstFlight = leg1;
plan.secondFlight = leg2;
plan.totalPrice = leg1.pri * leg1.cot /10.0 +
leg2.pri * leg2.cot /10.0;
plan.totalDuration = depart2 - arrival1;
transferPlans.push_back(plan);
}
}
}
fin2.close();
}
// 显示中转方案
if(!transferPlans.empty()) {
for(auto& plan : transferPlans)
printTransferPlan(plan);
}
else {
cout << "\n暂无中转方案\n" << endl;
}
}
setColor(14);
while(1)
{
char tw;
cout<<"是否需要订单(Y/N)";
cin>>tw;
if(tw=='Y')
{
bookFlight(username);
}
else break;
}
system("pause");
system("cls");
Meou();
}
void bookFlight(const string& username) {
printf("注意:预约航班只能从即日起往后1年内的航班,预定即日起一个月后的航班有航变风险,请谨慎预定\n");
string flightNumber;
cout<<"输入要预订的航班号:";
cin>>flightNumber;
fstream file("flights.dat",ios::in|ios::out|ios::binary);
Flight target;
bool found=0;
streampos flightPos;
while(file.read((char*)&target,sizeof(Flight))) {
if(strcmp(target.num, flightNumber.c_str()) == 0 && target.sit>0) {
found=1;
flightPos = file.tellg() - streampos(sizeof(Flight));
break;
}
}
if(!found) {
cout <<"无此航班或座位已满"<< endl;
file.close();
system("pause");
Meou();
}
string namex, num;
bool fn = false;
do {
cout << "请输入乘客姓名(中文):";
cin >> namex;
fn = isChineseString(namex.c_str());
if (!fn) cout << "请输入有效的中文姓名!\n";
} while (!fn);
bool fi = false;
do {
cout << "请输入身份证号:";
cin >> num;
fi = isValidID(num.c_str());
if (!fi) cout << "身份证格式错误!\n";
} while (!fi);
showSeatMap(target);
// 选择座位
string seat;
setColor(14);
while(true) {
cout << "请选择座位(如12A):";
cin >> seat;
// 验证并解析座位
regex pattern(R"(^(?:[1-9]|[1-7]\d|8[0-4]|85)([A-Fa-f])$)");
if(!regex_match(seat, pattern)) {
cout << "无效的座位格式!" << endl;
continue;
}
int row = stoi(seat.substr(0, seat.length()-1)) - 1;
char colChar = toupper(seat.back());
int col = colChar - 'A';
if(row <0 || row >(target.ssit+5)/6|| col <0 || col >=6||row*6+col>=target.ssit) {
cout << "无效的座位范围!" << endl;
continue;
}
if(target.seatMap[row][col]) {
cout << "该座位已被预订,请您选择别的位置,感谢您的配合!" << endl;
} else {
target.seatMap[row][col] = true;
target.sit--;
break;
}
}
// 更新航班数据
file.seekp(flightPos);
file.write((char*)&target, sizeof(Flight));
time_t now = time(0);
struct tm *timeinfo = localtime(&now);
char timeStr[32];
strftime(timeStr, sizeof(timeStr), "%Y-%m-%d %H:%M:%S", timeinfo);
Order newOrder(
to_string(now) + username,
username,
flightNumber,
timeStr, // 修改后的时间字符串
namex,
num,
seat
);
ofstream orderFile("orders.dat",ios::app|ios::binary);
if (!orderFile) {
cerr << "无法打开订单文件!" << endl;
system("pause");
Meou();
}
orderFile.write(reinterpret_cast<char*>(&newOrder), sizeof(Order));
orderFile.close();
file.seekp(-static_cast<int>(sizeof(Flight)), ios::cur);
file.write((char*)&target, sizeof(Flight));
file.close();
int pay;
setColor(14);
do{
cout<<"请选择您的支付方式: 1.微信支付 2.支付宝支付"<<endl;
cin>>pay;
}while(pay>2||pay<1);
cout<<"请扫码下方二维码支付"<<endl;
// 生成随机二维码
setColor(7);
vector<vector<bool>> qrCode = generateRandomQRCode(25);
// 打印二维码
printQRCode(qrCode);
cout<<endl;
setColor(14);
system("pause");
cout<<"正在处理您的订单,请稍候\n";
loadingScreen();
setColor(14);
cout<<"预订成功!您的订单已生成,订单号:"<< newOrder.orderId<<endl;
cout<<endl;
return;
}
void showUserOrders(const string& username) {
system("cls");
ifstream orderFile("orders.dat", ios::binary);
if (!orderFile) {
cout << "无法打开订单文件!" << endl;
system("pause");
Meou();
}
vector<Order> orders;
Order tempOrder;
// 读取订单数据
while(orderFile.read(reinterpret_cast<char*>(&tempOrder), sizeof(Order))) {
if (strcmp(tempOrder.username, username.c_str()) == 0) {
orders.push_back(tempOrder);
}
}
orderFile.close();
if(orders.empty()) {
cout << "当前没有有效订单!" << endl;
system("pause");
Meou();
}
setColor(7);
cout << "\n您的订单列表:" << endl;
cout << "=======================================================================================================" << endl;
cout << left
<< setw(5) << "序号"
<< setw(20) << "订单号"
<< setw(12) << "航班号"
<< setw(8) << "座位" // 新增列
<< setw(25) << "预订时间"
<< setw(20) << "乘客姓名"
<< setw(8) << "状态"
<< endl;
for (size_t i = 0; i < orders.size(); ++i) {
cout << left << setw(5) << i+1
<< setw(20) << orders[i].orderId
<< setw(12) << orders[i].flightNumber
<< setw(8) << orders[i].seat
<< setw(25) << orders[i].bookTime
<< setw(20) << orders[i].name
<< setw(8) << (orders[i].status ? "有效" : "已取消")
<< endl;
}
// 操作选择
cout << "=======================================================================================================" << endl;
int choice;
int orderIndex;
setColor(14);
while(1)
{
cout << "\n请选择操作:\n1.退票\n2.改签\n0.返回\n请输入:";
cin >> choice;
if(choice == 0) Meou();
if(choice == 1 || choice == 2) {
break;
}
}
while(1)
{
cout << "输入订单序号:";
cin >> orderIndex;
if(orderIndex < 1 || orderIndex > orders.size()) {
cout << "无效的订单序号!"<< endl;
system("pause");
}
else break;
}
Order selectedOrder = orders[orderIndex-1];
if(choice == 1) {
cancelOrder(username, selectedOrder.orderId);
showUserOrders(username);
}
else if(choice == 2) {
// 获取原航班信息
ifstream flightFile("flights.dat", ios::binary);
Flight originalFlight;
bool foundFlight = false;
while(flightFile.read((char*)&originalFlight, sizeof(Flight))) {
if(strcmp(originalFlight.num, selectedOrder.flightNumber) == 0) {
foundFlight = true;
break;
}
}
flightFile.close();
if(foundFlight) {
modifyOrder(username, selectedOrder.orderId,
originalFlight.place, originalFlight.dest);
} else {
cout << "原航班信息已不存在,无法改签!" << endl;
system("pause");
Meou();
}
}
}
void cancelOrder(const string& username, const string& orderId) {
// 处理订单文件
fstream orderFile("orders.dat", ios::in | ios::out | ios::binary);
if (!orderFile) {
cout << "无法打开订单文件!" << endl;
system("pause");
Meou();
}
Order tempOrder;
bool found = false;
while(orderFile.read(reinterpret_cast<char*>(&tempOrder), sizeof(Order))) {
if (strcmp(tempOrder.orderId, orderId.c_str()) == 0 &&
strcmp(tempOrder.username, username.c_str()) == 0) {
// 标记订单为已取消
tempOrder.status = 0;
streampos pos = orderFile.tellg() - streampos(sizeof(Order));
orderFile.seekp(pos);
orderFile.write((char*)&tempOrder, sizeof(Order));
found = true;
break;
}
}
orderFile.close();
Flight f;
fstream flightFile("flights.dat", ios::in|ios::out|ios::binary);
while(flightFile.read((char*)&f, sizeof(Flight))) {
if(strcmp(f.num, tempOrder.flightNumber) == 0) {
// 解析座位
string seat = tempOrder.seat;
int row = stoi(seat.substr(0, seat.size()-1)) - 1;
char colChar = toupper(seat.back());
int col = colChar - 'A';
if(row >=0 && row < (f.ssit+5)/6 && col >=0 && col <6) {
f.seatMap[row][col] = false;
f.sit++;
}
// 更新航班
flightFile.seekp(-sizeof(Flight), ios::cur);
flightFile.write((char*)&f, sizeof(Flight));
break;
}
}
flightFile.close();
cout << "退票成功!" << endl;
system("pause");
return ;
}
void modifyOrder(const string& username, const string& oldOrderId, const char* fromPlace, const char* toDest) {
// 获取原订单信息
Order oldOrder;
Flight originalFlight;
{
ifstream orderFile("orders.dat", ios::binary);
while(orderFile.read(reinterpret_cast<char*>(&oldOrder), sizeof(Order))) {
if(strcmp(oldOrder.orderId, oldOrderId.c_str()) == 0) break;
}
ifstream flightFile("flights.dat", ios::binary);
while(flightFile.read(reinterpret_cast<char*>(&originalFlight), sizeof(Flight))) {
if(strcmp(originalFlight.num, oldOrder.flightNumber) == 0) break;
}
}
// 自动取消原订单
// 查找可用航班
vector<Flight> availableFlights;
vector<streampos> flightPositions;
{
fstream flightFile("flights.dat", ios::in | ios::out | ios::binary);
Flight f;
while(flightFile.read(reinterpret_cast<char*>(&f), sizeof(Flight))) {
if(strcmp(f.place, fromPlace) == 0 &&
strcmp(f.dest, toDest) == 0 &&
f.sit > 0 &&
strcmp(f.num, oldOrder.flightNumber) != 0) {
availableFlights.push_back(f);
flightPositions.push_back(flightFile.tellg() - streampos(sizeof(Flight)));
}
}
flightFile.close();
}
// 显示可选航班
cout << "\n可改签航班列表:" << endl;
cout << "=====================================================================" << endl;
cout << left << setw(4) << "NO." << setw(12) << "航班号"
<< setw(20) << "起飞时间" << setw(20) << "到达时间"
<< setw(8) << "余票" << setw(10) << "票价" << endl;
for(size_t i=0; i<availableFlights.size(); ++i) {
const Flight& f = availableFlights[i];
cout << left << setw(4) << i+1
<< setw(12) << f.num
<< setw(20) << f.stm
<< setw(20) << f.ftm
<< setw(8) << f.sit
<< fixed << setprecision(2) << setw(10) << f.pri * f.cot / 10.0
<< endl;
}
// 选择航班
int choice;
do {
cout << "\n选择要改签的航班序号(1-" << availableFlights.size()
<< ",0取消):";
cin >> choice;
} while(choice <0 || choice > availableFlights.size());
if(choice == 0) {
cout << "改签已取消" << endl;
return;
}
// 处理新航班
fstream flightFile("flights.dat", ios::in | ios::out | ios::binary);
flightFile.seekg(flightPositions[choice-1]);
Flight selectedFlight;
flightFile.read(reinterpret_cast<char*>(&selectedFlight), sizeof(Flight));
// 选择座位
string newSeat = selectSeat(selectedFlight);
// 更新航班数据
flightFile.seekp(flightPositions[choice-1]);
flightFile.write(reinterpret_cast<char*>(&selectedFlight), sizeof(Flight));
flightFile.close();
// 创建新订单
time_t now = time(0);
char timeStr[32];
strftime(timeStr, sizeof(timeStr), "%Y-%m-%d %H:%M:%S", localtime(&now));
Order newOrder(
to_string(now) + username,
username,
selectedFlight.num,
timeStr,
oldOrder.name,
oldOrder.IDnum,
newSeat
);
ofstream orderFile("orders.dat", ios::app | ios::binary);
if (!orderFile) {
cerr << "无法创建新订单!" << endl;
system("pause");
return;
}
orderFile.write(reinterpret_cast<char*>(&newOrder), sizeof(Order));
orderFile.close();
cout<<"正在处理,请稍候\n";
loadingScreen();
setColor(14);
cout << "新订单详情:" << endl
<< "航班号: " << selectedFlight.num << endl
<< "座位号: " << newSeat << endl
<< "价格: " << selectedFlight.pri * selectedFlight.cot / 10.0 << endl;
cancelOrder(username, oldOrderId);
Meou();
}
void Meoa(){
system("cls");
drawTitleBox("管理员菜单", 50);
setColor(10);
puts("+------------------------------------------------+");
puts("| 1.添加航班 2.删除航班 |");
puts("| 3.查询航班 4.显示所有航班 |");
puts("| 5.新增管理员 6.查看用户列表 |");
puts("| 7.返回登录界面 |");
puts("+------------------------------------------------+");
setColor(12);
bool m=0;
while(m==0) {
cout << "\n>> 请选择操作 [1-7]: ";
int c;
cin>>c;
setColor(14);
switch(c){
case 1: {
addFlight();
m=1;
break;
}
case 2: {
deleteFlight();
m=1;
break;
}
case 3: {
searchFlightsAdmin();
m=1;
break;
}
case 4: {
showAllFlights();
m=1;
break;
}
case 5: {
addAdmin();
m=1;
break;
}
case 6: {
viewUsers();
m=1;
break;
}
case 7:{
begin();
system("cls");
break;
}
default: cout << "无效输入!" << endl;
}
system("pause");
}
}
void Meou(){
system("cls");
drawTitleBox("用户菜单", 50);
setColor(10);
puts("+-------------------------------------------------+");
puts("| 1.查询航班 2.查看订单 |");
puts("| 3.查看提醒 4.返回登录界面 |");
puts("+-------------------------------------------------+");
setColor(12);
cout << "\n>> 请选择操作 [1-4]: ";
while(true) {
int x;
cin>>x;
setColor(14);
switch (x)
{
case 1:{
searchFlights(username);
break;
}
case 2:{
showUserOrders(username);
break;
}
case 3:{
remanding();
break;
}
case 4:{
begin();
system("cls");
break;
}
// 正确退出循环
default:
cout << "无效输入!" << endl;
system("pause");
}
}
}
void begin(){
system("cls");
setColor(7);
int x;
puts("+------------------------------------------------+");
puts("| 欢迎来到飞机订票系统 |");
puts("|------------------------------------------------|");
puts("| 输入数字以选择功能(0-2) |");
puts("|------------------------------------------------|");
puts("| 1.登录 2.注册 |");
puts("| 0.离开 |");
puts("+------------------------------------------------+");
cin>>x;
if(x==1)
{
system("cls");
londing();
}
else if(x==2)
{
system("cls");
registing();
}
else if(x==0)
{
system("cls");
exit();
return ;
}
else
{
cout<<"输入错误"<<endl;
system("pause");
begin();
}
}
int main(){
puts(" ▂ ▄ ▄ ▓ ▄ ▄ ▂");
puts(" ▄ ▓ ▄▄ ");
puts(" ◢ ◤ █欢迎来到█ █ █ ▄ ▄ ◢ ◤");
puts(" █飞机订票系统 █ … … ╬");
puts(" ◥ █ █ █ █ █ ◤");
puts(" ═ ═ ╩ ═ ═ ╩ ═ ═ ═ ");
loadingScreen(); // 添加加载画面
begin();
return 0;
}