扩展客运汽车售票管理系统的知识点包括以下几个方面:文件操作、结构体和数组、用户交互、数据验证和错误处理、功能扩展(如数据持久化和日志记录)、以及提高用户体验的方式。
1. 文件操作
文件操作是该系统的核心部分,用于读取和写入车次信息。
- 文件读取和写入: 使用
fopen
、fscanf
和fprintf
函数进行文件操作。 - 文件模式: 了解文件模式,如
"r"
(读取模式)、"w"
(写入模式,如果文件不存在则创建文件)、"a"
(追加模式) 等。 - 文件关闭: 使用
fclose
关闭文件,确保数据完整性和避免资源泄露。
2. 结构体和数组
结构体和数组用于存储和管理车次信息。
- 结构体: 定义结构体
BusInfo
来保存车次信息,包括车次编号、出发时间、终点站、行驶时间、票价和剩余座位数。 - 二维数组: 使用二维数组
bus_info[MAX_DAYS][MAX_BUSES_PER_DAY]
存储多个天数的车次信息。
3. 用户交互
通过菜单驱动的方式与用户进行交互。
- 菜单显示: 使用
printf
函数显示菜单选项。 - 用户输入: 使用
scanf
获取用户输入的数据,并进行相应的操作。 - 循环结构: 使用
do-while
循环结构让菜单反复显示,直到用户选择退出。
4. 数据验证和错误处理
确保用户输入的有效性和系统的稳定性。
- 数据范围检查: 检查用户输入的日期、时间和票数是否在有效范围内。
- 字符串比较: 使用
strcmp
函数比较字符串,确保终点站和出发时间的匹配。 - 错误提示: 对无效输入提供错误提示,并允许用户重新输入。
5. 功能扩展
增加更多功能以提升系统的实用性。
- 数据持久化: 确保系统关闭后数据仍然存在,并在下次启动时加载。
- 日志记录: 记录用户操作日志,如购票、退票等,以便后续分析和审计。
- 票务统计: 统计各车次的售票情况,如总票数、售出票数、剩余票数等。
6. 提高用户体验
提升用户交互的便捷性和系统的友好性。
- 输入提示: 提供详细的输入提示,避免用户误操作。
- 清晰的输出格式: 采用对齐方式展示车次信息,方便用户查看。
- 异常处理: 对文件读取失败、数据格式错误等异常情况进行处理,避免程序崩溃。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// 定义常量
#define MAX_DAYS 4
#define MAX_BUSES_PER_DAY 60
#define MAX_DESTINATIONS 10
#define SEATS_PER_BUS 48
// 车次信息结构体
typedef struct
{
int bus_number;
char departure_time[6]; // 格式 HH:MM
char destination[20];
int travel_time; // 行驶时间(分钟)
float ticket_price;
int remaining_seats;
} BusInfo;
// 函数声明
void load_bus_info(const char* filename, BusInfo bus_info[MAX_DAYS][MAX_BUSES_PER_DAY]);
void save_bus_info(const char* filename, BusInfo bus_info[MAX_DAYS][MAX_BUSES_PER_DAY]);
void initialize_bus_info(const char* filename);
void display_menu();
void query_by_destination(BusInfo bus_info[MAX_DAYS][MAX_BUSES_PER_DAY]);
void query_by_time_and_destination(BusInfo bus_info[MAX_DAYS][MAX_BUSES_PER_DAY]);
void sell_ticket(BusInfo bus_info[MAX_DAYS][MAX_BUSES_PER_DAY]);
void refund_ticket(BusInfo bus_info[MAX_DAYS][MAX_BUSES_PER_DAY]);
void display_all_bus_info(BusInfo bus_info[MAX_DAYS][MAX_BUSES_PER_DAY]);
int _main()
{
BusInfo bus_info[MAX_DAYS][MAX_BUSES_PER_DAY];
// 初始化文件(如果文件不存在,则创建并写入默认数据)
initialize_bus_info("bus_info.txt");
// 从文件加载车次信息
load_bus_info("bus_info.txt", bus_info);
int choice;
do
{
display_menu();
printf("请选择操作(1-6):");
scanf("%d", &choice);
switch (choice)
{
case 1:
query_by_destination(bus_info);
break;
case 2:
query_by_time_and_destination(bus_info);
break;
case 3:
sell_ticket(bus_info);
break;
case 4:
refund_ticket(bus_info);
break;
case 5:
display_all_bus_info(bus_info);
break;
case 6:
printf("谢谢使用!\n");
break;
default:
printf("无效的选择,请重新输入。\n");
break;
}
} while (choice != 6);
// 保存更新后的车次信息到文件
save_bus_info("bus_info.txt", bus_info);
return 0;
}
// 加载车次信息
void load_bus_info(const char* filename, BusInfo bus_info[MAX_DAYS][MAX_BUSES_PER_DAY])
{
FILE* file = fopen(filename, "r");
if (file == NULL)
{
printf("无法打开文件 %s\n", filename);
exit(1);
}
// 从文件读取每天的车次信息
for (int day = 0; day < MAX_DAYS; day++)
{
for (int i = 0; i < MAX_BUSES_PER_DAY; i++)
{
fscanf(file, "%d %s %s %d %f %d\n",
&bus_info[day][i].bus_number,
bus_info[day][i].departure_time,
bus_info[day][i].destination,
&bus_info[day][i].travel_time,
&bus_info[day][i].ticket_price,
&bus_info[day][i].remaining_seats);
}
}
fclose(file);
}
// 保存车次信息
void save_bus_info(const char* filename, BusInfo bus_info[MAX_DAYS][MAX_BUSES_PER_DAY])
{
FILE* file = fopen(filename, "w");
if (file == NULL)
{
printf("无法打开文件 %s\n", filename);
exit(1);
}
// 写入更新后的车次信息到文件
for (int day = 0; day < MAX_DAYS; day++)
{
for (int i = 0; i < MAX_BUSES_PER_DAY; i++)
{
fprintf(file, "%d %s %s %d %.2f %d\n",
bus_info[day][i].bus_number,
bus_info[day][i].departure_time,
bus_info[day][i].destination,
bus_info[day][i].travel_time,
bus_info[day][i].ticket_price,
bus_info[day][i].remaining_seats);
}
}
fclose(file);
}
// 初始化车次信息文件
void initialize_bus_info(const char* filename)
{
FILE* file = fopen(filename, "r");
if (file == NULL)
{
// 文件不存在,创建文件并写入默认数据
file = fopen(filename, "w");
if (file == NULL)
{
printf("无法创建文件 %s\n", filename);
exit(1);
}
// 初始化默认数据
for (int day = 0; day < MAX_DAYS; day++)
{
for (int i = 0; i < MAX_BUSES_PER_DAY; i++)
{
fprintf(file, "%d %02d:%02d %s %d %.2f %d\n",
day * MAX_BUSES_PER_DAY + i + 1, // bus_number
8 + i / 6, // departure_time hour
(i % 6) * 10, // departure_time minute
"Destination", // destination
60 + i * 5, // travel_time
20.0 + i * 0.5, // ticket_price
SEATS_PER_BUS); // remaining_seats
}
}
fclose(file);
}
else
{
// 文件存在,关闭文件
fclose(file);
}
}
// 显示菜单
void display_menu()
{
printf("\n========== 客运汽车售票管理系统 ==========\n");
printf("1. 查询当天开往某终点站的车次\n");
printf("2. 查询最近4天内某时刻后开往某终点站的车次\n");
printf("3. 购票\n");
printf("4. 退票\n");
printf("5. 查看所有车次信息\n");
printf("6. 退出系统\n");
}
// 根据终点站查询当天的车次信息
void query_by_destination(BusInfo bus_info[MAX_DAYS][MAX_BUSES_PER_DAY])
{
char destination[20];
printf("请输入终点站名称:");
scanf(" %[^\n]", destination);
// 获取当前日期
int current_day;
printf("请输入当前日期(1-%d):", MAX_DAYS);
scanf("%d", ¤t_day);
if (current_day < 1 || current_day > MAX_DAYS)
{
printf("无效的日期,请重新输入。\n");
return;
}
current_day--; // 数组索引从0开始
printf("\n当天开往 %s 的车次信息:\n", destination);
int found = 0;
for (int i = 0; i < MAX_BUSES_PER_DAY; i++)
{
if (strcmp(bus_info[current_day][i].destination, destination) == 0)
{
printf("车次编号:%d\t出发时间:%s\t剩余票数:%d\n",
bus_info[current_day][i].bus_number,
bus_info[current_day][i].departure_time,
bus_info[current_day][i].remaining_seats);
found = 1;
}
}
if (!found)
{
printf("没有找到开往 %s 的车次。\n", destination);
}
}
// 根据时间和终点站查询最近4天内的车次信息
void query_by_time_and_destination(BusInfo bus_info[MAX_DAYS][MAX_BUSES_PER_DAY])
{
char destination[20];
char time[6];
printf("请输入终点站名称:");
scanf(" %[^\n]", destination);
printf("请输入时间(HH:MM):");
scanf(" %s", time);
printf("\n最近4天内在 %s %s 之后开往 %s 的车次信息:\n", time, destination);
int found = 0;
for (int day = 0; day < MAX_DAYS; day++)
{
for (int i = 0; i < MAX_BUSES_PER_DAY; i++)
{
if (strcmp(bus_info[day][i].destination, destination) == 0 &&
strcmp(bus_info[day][i].departure_time, time) > 0)
{
printf("日期:%d\t车次编号:%d\t出发时间:%s\t剩余票数:%d\n",
day + 1, // 显示日期从1开始
bus_info[day][i].bus_number,
bus_info[day][i].departure_time,
bus_info[day][i].remaining_seats);
found = 1;
}
}
}
if (!found)
{
printf("没有找到满足条件的车次。\n");
}
}
// 购票操作
void sell_ticket(BusInfo bus_info[MAX_DAYS][MAX_BUSES_PER_DAY])
{
int day, bus_number, tickets;
char time[6], destination[20];
printf("请输入日期(1-%d):", MAX_DAYS);
scanf("%d", &day);
if (day < 1 || day > MAX_DAYS)
{
printf("无效的日期,请重新输入。\n");
return;
}
day--; // 转换为数组索引
printf("请输入出发时间(HH:MM):");
scanf(" %s", time);
printf("请输入终点站名称:");
scanf(" %[^\n]", destination);
printf("请输入购票数量:");
scanf("%d", &tickets);
// 查找符合条件的车次
int found = 0;
for (int i = 0; i < MAX_BUSES_PER_DAY; i++)
{
if (strcmp(bus_info[day][i].departure_time, time) == 0 &&
strcmp(bus_info[day][i].destination, destination) == 0 &&
bus_info[day][i].remaining_seats >= tickets)
{
// 更新剩余座位数
bus_info[day][i].remaining_seats -= tickets;
printf("成功购买 %d 张车票!\n", tickets);
found = 1;
break;
}
}
if (!found)
{
printf("无法购买指定数量的车票,请重新选择。\n");
}
}
// 退票操作
void refund_ticket(BusInfo bus_info[MAX_DAYS][MAX_BUSES_PER_DAY])
{
int day, bus_number;
printf("请输入日期(1-%d):", MAX_DAYS);
scanf("%d", &day);
if (day < 1 || day > MAX_DAYS)
{
printf("无效的日期,请重新输入。\n");
return;
}
day--; // 转换为数组索引
printf("请输入车次编号:");
scanf("%d", &bus_number);
// 查找对应的车次
int found = 0;
for (int i = 0; i < MAX_BUSES_PER_DAY; i++)
{
if (bus_info[day][i].bus_number == bus_number)
{
// 找到车次,假设退票金额为票价的80%
float refund_amount = 0.8 * bus_info[day][i].ticket_price;
// 更新数据:将票数增加,销售状态改变
bus_info[day][i].remaining_seats++; // 假设每张票占用一个座位,所以退票时剩余座位数增加
bus_info[day][i].ticket_price = 0; // 将票价置为0表示退票
printf("退票成功!退款金额为: %.2f\n", refund_amount);
found = 1;
break;
}
}
if (!found)
{
printf("未找到该车次,退票失败。\n");
}
}
// 显示所有车次信息
void display_all_bus_info(BusInfo bus_info[MAX_DAYS][MAX_BUSES_PER_DAY])
{
for (int day = 0; day < MAX_DAYS; day++)
{
printf("\n第 %d 天的车次信息:\n", day + 1);
for (int i = 0; i < MAX_BUSES_PER_DAY; i++)
{
printf("车次编号:%d\t出发时间:%s\t终点站:%s\t行驶时间:%d分钟\t票价:%.2f\t剩余座位:%d\n",
bus_info[day][i].bus_number,
bus_info[day][i].departure_time,
bus_info[day][i].destination,
bus_info[day][i].travel_time,
bus_info[day][i].ticket_price,
bus_info[day][i].remaining_seats);
}
}
}