C语言课程设计:飞机订票系统
需求分析
-
功能需求
(图片来源网络,侵删)- 航班信息管理:能够添加、显示、修改和删除航班信息。
- 订票功能:用户可以根据出发地、目的地或航班号查询航班,并进行订票,订票成功后,相应航班的余票应减少。
- 退票功能:用户可以根据订单号或航班号退票,退票成功后,相应航班的余票应增加。
- 信息查询:
- 查询所有航班信息。
- 按条件(如出发地、目的地)查询航班。
- 查询所有订单信息。
- 数据持久化:系统关闭后,航班和订单信息不能丢失,需要保存在文件中(如
.txt或.dat文件),并在程序启动时自动加载。
-
性能需求
- 系统响应速度应足够快,尤其是在航班和订单数据量较大时。
- 用户界面应简洁、友好,易于操作。
-
用户界面
- 需要一个主菜单,引导用户选择功能(如订票、退票、查询、退出等)。
- 每个子功能也应有清晰的提示和输入输出界面。
系统设计
-
数据结构设计
为了管理航班和订单信息,我们需要定义两个核心的结构体:
(图片来源网络,侵删)-
航班信息结构体 (
Flight):flight_id: 航班号 (字符串,如 "CA1234")origin: 出发地 (字符串,如 "北京")destination: 目的地 (字符串,如 "上海")departure_time: 起飞时间 (字符串,如 "2025-12-25 08:00")arrival_time: 到达时间 (字符串,如 "2025-12-25 10:30")total_seats: 总座位数 (整数)available_seats: 剩余座位数 (整数)
-
订单信息结构体 (
Order):order_id: 订单号 (字符串,可由系统自动生成)flight_id: 关联的航班号passenger_name: 乘客姓名 (字符串)passenger_id: 乘客身份证号 (字符串)status: 订单状态 (字符串,如 "已出票", "已取消")
-
-
模块化设计
将系统功能分解为独立的函数,提高代码的可读性、可维护性和复用性。
(图片来源网络,侵删)- 主菜单模块 (
main_menu):显示主菜单并处理用户选择。 - 航班管理模块:
add_flight(): 添加新航班。display_all_flights(): 显示所有航班。modify_flight(): 修改航班信息。delete_flight(): 删除航班。
- 订票模块 (
book_ticket):search_flights(): 搜索航班。book_ticket_process(): 处理订票逻辑。
- 退票模块 (
cancel_ticket):cancel_ticket_process(): 处理退票逻辑。
- 查询模块 (
query_info):query_all_orders(): 查询所有订单。
- 文件操作模块:
save_flights_to_file(): 将航班数据保存到文件。load_flights_from_file(): 从文件加载航班数据。save_orders_to_file(): 将订单数据保存到文件。load_orders_from_file(): 从文件加载订单数据。
- 工具模块:
generate_order_id(): 生成唯一订单号。
- 主菜单模块 (
-
文件存储设计
- 使用文本文件(
.txt)存储数据,便于查看和调试。 flights.txt:存储所有航班信息,每行代表一个航班,字段用逗号或其他分隔符隔开。- 格式示例:
CA1234,北京,上海,2025-12-25 08:00,2025-12-25 10:30,180,150
- 格式示例:
orders.txt:存储所有订单信息,每行代表一个订单。- 格式示例:
ORD202512250001,CA1234,张三,110101199001011234,已出票
- 格式示例:
- 使用文本文件(
核心代码实现
下面是一个完整的、可直接编译运行的C语言代码示例。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h> // 用于 getch(),在Windows下实现“按任意键继续”
#include <time.h> // 用于生成订单号
// --- 常量定义 ---
#define MAX_FLIGHTS 100
#define MAX_ORDERS 1000
#define FILENAME_FLIGHTS "flights.txt"
#define FILENAME_ORDERS "orders.txt"
#define MAX_STRING_LEN 50
// --- 数据结构定义 ---
typedef struct {
char flight_id[MAX_STRING_LEN];
char origin[MAX_STRING_LEN];
char destination[MAX_STRING_LEN];
char departure_time[MAX_STRING_LEN];
char arrival_time[MAX_STRING_LEN];
int total_seats;
int available_seats;
} Flight;
typedef struct {
char order_id[MAX_STRING_LEN];
char flight_id[MAX_STRING_LEN];
char passenger_name[MAX_STRING_LEN];
char passenger_id[MAX_STRING_LEN];
char status[MAX_STRING_LEN]; // "已出票", "已取消"
} Order;
// --- 全局变量 ---
Flight flights[MAX_FLIGHTS];
Order orders[MAX_ORDERS];
int flight_count = 0;
int order_count = 0;
// --- 函数声明 ---
void main_menu();
void flight_management();
void add_flight();
void display_all_flights();
void modify_flight();
void delete_flight();
void booking_system();
void search_flights();
void book_ticket_process();
void cancellation_system();
void cancel_ticket_process();
void query_system();
void query_all_orders();
void file_operations();
void save_flights_to_file();
void load_flights_from_file();
void save_orders_to_file();
void load_orders_from_file();
void generate_order_id(char *id);
void clear_input_buffer();
// --- 主函数 ---
int main() {
load_flights_from_file();
load_orders_from_file();
main_menu();
return 0;
}
// --- 主菜单 ---
void main_menu() {
int choice;
while (1) {
system("cls"); // Windows下清屏,Linux/macOS用 system("clear");
printf("\n\n\n");
printf("\t\t\t|-----------------------------|\n");
printf("\t\t\t| 飞机订票系统 |\n");
printf("\t\t\t|-----------------------------|\n");
printf("\t\t\t| 1. 航班管理 |\n");
printf("\t\t\t| 2. 订票系统 |\n");
printf("\t\t\t| 3. 退票系统 |\n");
printf("\t\t\t| 4. 信息查询 |\n");
printf("\t\t\t| 0. 退出系统 |\n");
printf("\t\t\t|-----------------------------|\n");
printf("\t\t\t请输入您的选择: ");
scanf("%d", &choice);
clear_input_buffer(); // 清除输入缓冲区中的回车符
switch (choice) {
case 1: flight_management(); break;
case 2: booking_system(); break;
case 3: cancellation_system(); break;
case 4: query_system(); break;
case 0:
save_flights_to_file();
save_orders_to_file();
printf("\n\t\t\t感谢使用,再见!\n");
exit(0);
default:
printf("\t\t\t无效的选择,请重新输入!\n");
getch(); // 按任意键继续
}
}
}
// --- 航班管理模块 ---
void flight_management() {
int choice;
while (1) {
system("cls");
printf("\n\n\n");
printf("\t\t\t|-----------------------------|\n");
printf("\t\t\t| 航班管理 |\n");
printf("\t\t\t|-----------------------------|\n");
printf("\t\t\t| 1. 添加航班 |\n");
printf("\t\t\t| 2. 显示所有航班 |\n");
printf("\t\t\t| 3. 修改航班 |\n");
printf("\t\t\t| 4. 删除航班 |\n");
printf("\t\t\t| 0. 返回主菜单 |\n");
printf("\t\t\t|-----------------------------|\n");
printf("\t\t\t请输入您的选择: ");
scanf("%d", &choice);
clear_input_buffer();
switch (choice) {
case 1: add_flight(); break;
case 2: display_all_flights(); break;
case 3: modify_flight(); break;
case 4: delete_flight(); break;
case 0: return;
default:
printf("\t\t\t无效的选择!\n");
getch();
}
}
}
void add_flight() {
if (flight_count >= MAX_FLIGHTS) {
printf("\t\t\t航班数量已达上限,无法添加!\n");
getch();
return;
}
Flight f;
printf("\t\t\t请输入航班号: "); scanf("%s", f.flight_id); clear_input_buffer();
printf("\t\t\t请输入出发地: "); scanf("%s", f.origin); clear_input_buffer();
printf("\t\t\t请输入目的地: "); scanf("%s", f.destination); clear_input_buffer();
printf("\t\t\t请输入起飞时间(YYYY-MM-DD HH:MM): "); scanf("%s", f.departure_time); clear_input_buffer();
printf("\t\t\t请输入到达时间(YYYY-MM-DD HH:MM): "); scanf("%s", f.arrival_time); clear_input_buffer();
printf("\t\t\t请输入总座位数: "); scanf("%d", &f.total_seats); clear_input_buffer();
f.available_seats = f.total_seats;
flights[flight_count++] = f;
printf("\t\t\t航班添加成功!\n");
getch();
}
void display_all_flights() {
system("cls");
printf("\n\n\n");
printf("\t\t\t|----------------------------------------------------------------------------------------------------------------|\n");
printf("\t\t\t| 航班号 | 出发地 | 目的地 | 起飞时间 | 到达时间 | 总座位 | 剩余座位 |\n");
printf("\t\t\t|----------------------------------------------------------------------------------------------------------------|\n");
for (int i = 0; i < flight_count; i++) {
printf("\t\t\t| %-7s| %-7s| %-7s| %-14s| %-14s| %-8d| %-10d|\n",
flights[i].flight_id,
flights[i].origin,
flights[i].destination,
flights[i].departure_time,
flights[i].arrival_time,
flights[i].total_seats,
flights[i].available_seats);
}
printf("\t\t\t|----------------------------------------------------------------------------------------------------------------|\n");
printf("\n\t\t\t按任意键返回...");
getch();
}
void modify_flight() {
char fid[MAX_STRING_LEN];
printf("\t\t\t请输入要修改的航班号: "); scanf("%s", fid); clear_input_buffer();
for (int i = 0; i < flight_count; i++) {
if (strcmp(flights[i].flight_id, fid) == 0) {
printf("\t\t\t找到航班,请输入新的信息(不修改请直接回车):\n");
printf("\t\t\t出发地[%s]: ", flights[i].origin); char tmp[50]; gets(tmp); if(strlen(tmp) > 0) strcpy(flights[i].origin, tmp);
printf("\t\t\t目的地[%s]: ", flights[i].destination); gets(tmp); if(strlen(tmp) > 0) strcpy(flights[i].destination, tmp);
printf("\t\t\t起飞时间[%s]: ", flights[i].departure_time); gets(tmp); if(strlen(tmp) > 0) strcpy(flights[i].departure_time, tmp);
printf("\t\t\t到达时间[%s]: ", flights[i].arrival_time); gets(tmp); if(strlen(tmp) > 0) strcpy(flights[i].arrival_time, tmp);
printf("\t\t\t总座位数[%d]: ", flights[i].total_seats); int n; char num_str[10]; gets(num_str); if(strlen(num_str) > 0) { n = atoi(num_str); flights[i].total_seats = n; flights[i].available_seats = n; }
printf("\t\t\t航班信息修改成功!\n");
getch();
return;
}
}
printf("\t\t\t未找到该航班号!\n");
getch();
}
void delete_flight() {
char fid[MAX_STRING_LEN];
printf("\t\t\t请输入要删除的航班号: "); scanf("%s", fid); clear_input_buffer();
for (int i = 0; i < flight_count; i++) {
if (strcmp(flights[i].flight_id, fid) == 0) {
// 将最后一个元素移到当前位置,以避免数组空洞
for (int j = i; j < flight_count - 1; j++) {
flights[j] = flights[j + 1];
}
flight_count--;
printf("\t\t\t航班删除成功!\n");
getch();
return;
}
}
printf("\t\t\t未找到该航班号!\n");
getch();
}
// --- 订票系统模块 ---
void booking_system() {
int choice;
while (1) {
system("cls");
printf("\n\n\n");
printf("\t\t\t|-----------------------------|\n");
printf("\t\t\t| 订票系统 |\n");
printf("\t\t\t|-----------------------------|\n");
printf("\t\t\t| 1. 搜索航班 |\n");
printf("\t\t\t| 0. 返回主菜单 |\n");
printf("\t\t\t|-----------------------------|\n");
printf("\t\t\t请输入您的选择: ");
scanf("%d", &choice);
clear_input_buffer();
switch (choice) {
case 1: search_flights(); break;
case 0: return;
default:
printf("\t\t\t无效的选择!\n");
getch();
}
}
}
void search_flights() {
char keyword[MAX_STRING_LEN];
printf("\t\t\t请输入出发地、目的地或航班号进行搜索: "); scanf("%s", keyword); clear_input_buffer();
system("cls");
printf("\n\n\n");
printf("\t\t\t|----------------------------------------------------------------------------------------------------------------|\n");
printf("\t\t\t| 航班号 | 出发地 | 目的地 | 起飞时间 | 到达时间 | 总座位 | 剩余座位 |\n");
printf("\t\t\t|----------------------------------------------------------------------------------------------------------------|\n");
int found = 0;
for (int i = 0; i < flight_count; i++) {
if (strstr(flights[i].flight_id, keyword) || strstr(flights[i].origin, keyword) || strstr(flights[i].destination, keyword)) {
printf("\t\t\t| %-7s| %-7s| %-7s| %-14s| %-14s| %-8d| %-10d|\n",
flights[i].flight_id,
flights[i].origin,
flights[i].destination,
flights[i].departure_time,
flights[i].arrival_time,
flights[i].total_seats,
flights[i].available_seats);
found = 1;
}
}
if (!found) {
printf("\t\t\t未找到匹配的航班,\n");
}
printf("\t\t\t|----------------------------------------------------------------------------------------------------------------|\n");
if(found) {
printf("\n\t\t\t是否要进行订票?(y/n): ");
char confirm;
scanf("%c", &confirm);
if (confirm == 'y' || confirm == 'Y') {
book_ticket_process(keyword);
}
}
printf("\n\t\t\t按任意键返回...");
getch();
}
void book_ticket_process(char *keyword) {
char fid[MAX_STRING_LEN];
printf("\t\t\t请输入您要订票的航班号: "); scanf("%s", fid); clear_input_buffer();
Flight *selected_flight = NULL;
for (int i = 0; i < flight_count; i++) {
if (strcmp(flights[i].flight_id, fid) == 0) {
selected_flight = &flights[i];
break;
}
}
if (selected_flight == NULL) {
printf("\t\t\t航班号不存在!\n");
getch();
return;
}
if (selected_flight->available_seats <= 0) {
printf("\t\t\t该航班已无余票!\n");
getch();
return;
}
Order o;
generate_order_id(o.order_id);
strcpy(o.flight_id, selected_flight->flight_id);
printf("\t\t\t请输入乘客姓名: "); scanf("%s", o.passenger_name); clear_input_buffer();
printf("\t\t\t请输入乘客身份证号: "); scanf("%s", o.passenger_id); clear_input_buffer();
strcpy(o.status, "已出票");
orders[order_count++] = o;
selected_flight->available_seats--;
printf("\t\t\t订票成功!\n");
printf("\t\t\t您的订单号是: %s\n", o.order_id);
printf("\t\t\t请妥善保管您的订单号,\n");
getch();
}
// --- 退票系统模块 ---
void cancellation_system() {
int choice;
while (1) {
system("cls");
printf("\n\n\n");
printf("\t\t\t|-----------------------------|\n");
printf("\t\t\t| 退票系统 |\n");
printf("\t\t\t|-----------------------------|\n");
printf("\t\t\t| 1. 退票 |\n");
printf("\t\t\t| 0. 返回主菜单 |\n");
printf("\t\t\t|-----------------------------|\n");
printf("\t\t\t请输入您的选择: ");
scanf("%d", &choice);
clear_input_buffer();
switch (choice) {
case 1: cancel_ticket_process(); break;
case 0: return;
default:
printf("\t\t\t无效的选择!\n");
getch();
}
}
}
void cancel_ticket_process() {
char oid[MAX_STRING_LEN];
printf("\t\t\t请输入您的订单号进行退票: "); scanf("%s", oid); clear_input_buffer();
Order *order_to_cancel = NULL;
int order_index = -1;
for (int i = 0; i < order_count; i++) {
if (strcmp(orders[i].order_id, oid) == 0) {
order_to_cancel = &orders[i];
order_index = i;
break;
}
}
if (order_to_cancel == NULL) {
printf("\t\t\t订单号不存在!\n");
getch();
return;
}
if (strcmp(order_to_cancel->status, "已取消") == 0) {
printf("\t\t\t该订单已经退票,无需重复操作!\n");
getch();
return;
}
// 找到对应的航班并增加座位
for (int i = 0; i < flight_count; i++) {
if (strcmp(flights[i].flight_id, order_to_cancel->flight_id) == 0) {
flights[i].available_seats++;
break;
}
}
// 更新订单状态
strcpy(order_to_cancel->status, "已取消");
printf("\t\t\t退票成功!\n");
getch();
}
// --- 查询系统模块 ---
void query_system() {
int choice;
while (1) {
system("cls");
printf("\n\n\n");
printf("\t\t\t|-----------------------------|\n");
printf("\t\t\t| 信息查询 |\n");
printf("\t\t\t|-----------------------------|\n");
printf("\t\t\t| 1. 查询所有订单 |\n");
printf("\t\t\t| 0. 返回主菜单 |\n");
printf("\t\t\t|-----------------------------|\n");
printf("\t\t\t请输入您的选择: ");
scanf("%d", &choice);
clear_input_buffer();
switch (choice) {
case 1: query_all_orders(); break;
case 0: return;
default:
printf("\t\t\t无效的选择!\n");
getch();
}
}
}
void query_all_orders() {
system("cls");
printf("\n\n\n");
printf("\t\t\t|--------------------------------------------------------------------------------------|\n");
printf("\t\t\t| 订单号 | 航班号 | 乘客姓名 | 乘客身份证 | 订单状态 |\n");
printf("\t\t\t|--------------------------------------------------------------------------------------|\n");
for (int i = 0; i < order_count; i++) {
printf("\t\t\t| %-12s| %-7s| %-9s| %-17s| %-12s|\n",
orders[i].order_id,
orders[i].flight_id,
orders[i].passenger_name,
orders[i].passenger_id,
orders[i].status);
}
printf("\t\t\t|--------------------------------------------------------------------------------------|\n");
printf("\n\t\t\t按任意键返回...");
getch();
}
// --- 文件操作模块 ---
void save_flights_to_file() {
FILE *fp = fopen(FILENAME_FLIGHTS, "w");
if (fp == NULL) {
printf("无法打开航班文件进行写入!\n");
return;
}
for (int i = 0; i < flight_count; i++) {
fprintf(fp, "%s,%s,%s,%s,%s,%d,%d\n",
flights[i].flight_id,
flights[i].origin,
flights[i].destination,
flights[i].departure_time,
flights[i].arrival_time,
flights[i].total_seats,
flights[i].available_seats);
}
fclose(fp);
}
void load_flights_from_file() {
FILE *fp = fopen(FILENAME_FLIGHTS, "r");
if (fp == NULL) {
// 文件不存在是正常情况(首次运行)
return;
}
flight_count = 0;
while (fscanf(fp, "%49[^,],%49[^,],%49[^,],%49[^,],%49[^,],%d,%d\n",
flights[flight_count].flight_id,
flights[flight_count].origin,
flights[flight_count].destination,
flights[flight_count].departure_time,
flights[flight_count].arrival_time,
&flights[flight_count].total_seats,
&flights[flight_count].available_seats) == 7) {
flight_count++;
}
fclose(fp);
}
void save_orders_to_file() {
FILE *fp = fopen(FILENAME_ORDERS, "w");
if (fp == NULL) {
printf("无法打开订单文件进行写入!\n");
return;
}
for (int i = 0; i < order_count; i++) {
fprintf(fp, "%s,%s,%s,%s,%s\n",
orders[i].order_id,
orders[i].flight_id,
orders[i].passenger_name,
orders[i].passenger_id,
orders[i].status);
}
fclose(fp);
}
void load_orders_from_file() {
FILE *fp = fopen(FILENAME_ORDERS, "r");
if (fp == NULL) {
return;
}
order_count = 0;
while (fscanf(fp, "%49[^,],%49[^,],%49[^,],%49[^,],%49[^\n]\n",
orders[order_count].order_id,
orders[order_count].flight_id,
orders[order_count].passenger_name,
orders[order_count].passenger_id,
orders[order_count].status) == 5) {
order_count++;
}
fclose(fp);
}
// --- 工具函数 ---
void generate_order_id(char *id) {
time_t t;
time(&t);
struct tm *tm_info = localtime(&t);
sprintf(id, "ORD%04d%02d%02d%04d",
tm_info->tm_year + 1900,
tm_info->tm_mon + 1,
tm_info->tm_mday,
rand() % 10000); // 使用时间戳+随机数生成唯一ID
}
void clear_input_buffer() {
int c;
while ((c = getchar()) != '\n' && c != EOF);
}
如何运行和测试
- 编译:将以上代码保存为
ticket_system.c,使用GCC编译器进行编译:gcc ticket_system.c -o ticket_system
- 运行:
./ticket_system
- 测试流程:
- 初始化:首次运行,
flights.txt和orders.txt文件会被自动创建。 - 添加航班:进入“航班管理” -> “1. 添加航班”,输入几个示例航班信息。
- 订票:
- 进入“订票系统” -> “1. 搜索航班”,输入一个城市名或航班号。
- 从搜索结果中选择一个航班进行订票,输入乘客信息。
- 订票成功后,再次查看“所有航班”,会发现剩余座位数减少。
- 查看订单:进入“信息查询” -> “1. 查询所有订单”,确认订票信息已保存。
- 退票:
- 进入“退票系统” -> “1. 退票”,输入刚刚生成的订单号。
- 退票成功后,再次查看“所有航班”,会发现剩余座位数恢复。
- 再次查看“所有订单”,会发现该订单状态变为“已取消”。
- 数据持久化:关闭程序,然后重新打开,你会发现之前添加的航班和订单都还在。
- 初始化:首次运行,
课程设计扩展思路(拿高分的关键)
如果你想让这个课程设计更上一层楼,可以考虑以下扩展功能:
-
改进数据结构:
- 使用 链表 代替数组来存储航班和订单,这样可以突破
MAX_FLIGHTS和MAX_ORDERS的限制,更符合真实世界的动态数据管理需求。 - 使用 结构体指针 和动态内存分配 (
malloc,free) 来实现链表。
- 使用 链表 代替数组来存储航班和订单,这样可以突破
-
增强用户界面:
- 使用更高级的库,如
ncurses(Linux) 或EasyX(Windows) 来创建图形化界面,而不仅仅是控制台文本界面。 - 实现更美观的菜单布局和颜色提示。
- 使用更高级的库,如
-
增加更多功能:
- 用户系统:增加管理员和普通用户两种角色,管理员拥有所有权限,普通用户只能订票、退票和查询自己的订单。
- 航班排序:在查询航班时,可以按起飞时间或价格(如果增加价格字段)进行排序。
- 模糊查询与分页:当航班数量很多时,实现分页显示查询结果。
- 数据加密:对用户身份证号等敏感信息进行简单的加密存储(如异或加密),增加安全性。
- 日志系统:记录所有关键操作(如谁在什么时间订了什么票),方便审计。
-
改进文件存储:
- 使用二进制文件(
.dat)代替文本文件(.txt),二进制文件读写速度更快,文件体积更小,且数据格式不易被用户直接篡改。 - 实现文件的备份与恢复功能。
- 使用二进制文件(
-
代码质量提升:
- 错误处理:增加更健壮的错误处理机制,例如文件打开失败、内存分配失败等情况。
- 代码注释:确保你的代码注释清晰、规范,解释了每个函数和关键代码块的作用。
- 编写报告:一份高质量的课程设计报告是得分的重要组成部分,报告应包括需求分析、系统设计(流程图、结构图)、核心代码解释、测试用例和结果、总结与展望等。
这个项目覆盖了C语言的核心知识点,包括结构体、数组、文件操作、函数模块化设计等,是一个非常优秀的学习和练手项目,祝你课程设计顺利!
