C语言飞机订票系统如何实现核心功能?

99ANYc3cd6
预计阅读时长 54 分钟
位置: 首页 C语言 正文

C语言飞机订票系统课程设计

项目概述与需求分析

项目目标 设计并实现一个基于控制台的飞机订票系统,该系统应能够模拟航空公司的订票业务,包括航班信息的录入、查询、订票、退票以及信息保存与加载等核心功能,通过本课程设计,旨在巩固和运用C语言的核心知识,如结构体、文件操作、指针、函数模块化编程等。

c语言飞机订票系统课程设计
(图片来源网络,侵删)

功能需求分析

系统主要面向两类用户:管理员和普通乘客(系统内部通过菜单切换模拟)。

A. 管理员功能

  1. 航班信息录入:可以添加新的航班信息,包括航班号、起点站、终点站、日期、时间、总座位数、已订票数、票价等。
  2. 航班信息浏览:以表格形式列出所有航班的详细信息。
  3. 航班信息查询:可以根据航班号或航线(起点-终点)查询特定航班。
  4. 航班信息修改:修改指定航班的某些信息(如票价、总座位数)。
  5. 航班信息删除:删除某个已取消的航班。

B. 乘客功能

c语言飞机订票系统课程设计
(图片来源网络,侵删)
  1. 航班查询:乘客可以根据航线(起点-终点)和日期查询所有符合条件的航班。
  2. 订票功能:在查询结果中选择一个航班进行订票,系统需要检查是否有余票,并更新订票信息。
  3. 退票功能:乘客可以根据自己的姓名和身份证号(或航班号)查询已订的机票并进行退票,释放座位。
  4. 个人信息查询:查询自己已预订的航班信息。

C. 公共/核心功能

  1. 数据持久化:所有航班信息和订票信息必须保存在文件中(如 flights.datbookings.dat),确保程序关闭后数据不丢失,程序启动时能自动从文件中加载数据。
  2. 菜单驱动界面:提供清晰、友好的文本用户界面,引导用户进行操作。

系统设计

数据结构设计

为了高效地管理数据,我们使用结构体来定义核心数据对象。

  • 航班信息结构体 (Flight)

    c语言飞机订票系统课程设计
    (图片来源网络,侵删)
    typedef struct {
        char flight_id[20];    // 航班号, 如 "CA1234"
        char origin[20];       // 起点站
        char destination[20];  // 终点站
        char date[20];         // 日期, 如 "2025-12-25"
        char time[20];         // 时间, 如 "08:00"
        int total_seats;       // 总座位数
        int booked_seats;      // 已订票数
        float price;           // 票价
    } Flight;
  • 订票信息结构体 (Booking) 为了方便退票和个人查询,需要一个结构体来记录谁订了哪个票。

    typedef struct {
        char flight_id[20];    // 关联的航班号
        char passenger_name[50]; // 乘客姓名
        char id_card[19];      // 乘客身份证号
    } Booking;

功能模块设计

将整个系统划分为多个独立的函数模块,提高代码的可读性和可维护性。

模块名称 主要功能
主菜单模块 (main函数) 显示主菜单,处理管理员/乘客选择,调用相应模块。
管理员模块 (admin_menu) 显示管理员子菜单,并调用航班管理的增删改查函数。
乘客模块 (passenger_menu) 显示乘客子菜单,并调用查询、订票、退票函数。
航班管理模块 add_flight(), list_flights(), search_flight(), modify_flight(), delete_flight()
订票业务模块 search_flights_for_booking(), book_ticket(), cancel_ticket(), my_bookings()
文件操作模块 save_flights(), load_flights(), save_bookings(), load_bookings()
工具模块 clear_input_buffer(), get_input() (用于安全输入)

文件设计

  • flights.dat:二进制文件,用于存储所有 Flight 结构体数组。
  • bookings.dat:二进制文件,用于存储所有 Booking 结构体数组。

使用二进制文件进行读写,效率高,且能直接保存结构体数据。


核心代码实现

以下是一个完整可运行的源代码示例,你可以直接复制到你的IDE(如 Dev-C++, VS Code, Code::Blocks)中编译运行。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h> // 用于 getch(),实现不回显的输入
// 定义常量
#define MAX_FLIGHTS 100
#define MAX_BOOKINGS 1000
#define FLIGHTS_FILE "flights.dat"
#define BOOKINGS_FILE "bookings.dat"
// --- 数据结构定义 ---
typedef struct {
    char flight_id[20];
    char origin[20];
    char destination[20];
    char date[20];
    char time[20];
    int total_seats;
    int booked_seats;
    float price;
} Flight;
typedef struct {
    char flight_id[20];
    char passenger_name[50];
    char id_card[19];
} Booking;
// --- 全局变量 ---
Flight flights[MAX_FLIGHTS];
Booking bookings[MAX_BOOKINGS];
int flight_count = 0;
int booking_count = 0;
// --- 函数声明 ---
void admin_menu();
void passenger_menu();
void load_data();
void save_data();
// --- 管理员功能函数 ---
void add_flight();
void list_flights();
void search_flight();
void modify_flight();
void delete_flight();
// --- 乘客功能函数 ---
void search_flights_for_booking();
void book_ticket();
void cancel_ticket();
void my_bookings();
// --- 工具函数 ---
void clear_input_buffer();
void press_any_key_to_continue();
// --- 主函数 ---
int main() {
    load_data(); // 程序启动时加载数据
    int choice;
    while (1) {
        system("cls"); // 清屏 (Windows), Linux/macOS 用 "clear"
        printf("\n\n\t\t\t 飞机订票系统\n");
        printf("\n\t\t\t 1. 管理员入口");
        printf("\n\t\t\t 2. 乘客入口");
        printf("\n\t\t\t 0. 退出系统");
        printf("\n\n\t\t\t 请选择您的身份: ");
        scanf("%d", &choice);
        clear_input_buffer();
        switch (choice) {
            case 1:
                admin_menu();
                break;
            case 2:
                passenger_menu();
                break;
            case 0:
                save_data(); // 退出前保存数据
                printf("\n\t\t\t 感谢使用,再见!\n");
                exit(0);
            default:
                printf("\n\t\t\t 无效输入,请重新选择!");
                press_any_key_to_continue();
        }
    }
    return 0;
}
// --- 文件操作函数 ---
void load_data() {
    FILE *fp_flights = fopen(FLIGHTS_FILE, "rb");
    if (fp_flights) {
        fread(&flight_count, sizeof(int), 1, fp_flights);
        fread(flights, sizeof(Flight), flight_count, fp_flights);
        fclose(fp_flights);
    }
    FILE *fp_bookings = fopen(BOOKINGS_FILE, "rb");
    if (fp_bookings) {
        fread(&booking_count, sizeof(int), 1, fp_bookings);
        fread(bookings, sizeof(Booking), booking_count, fp_bookings);
        fclose(fp_bookings);
    }
}
void save_data() {
    FILE *fp_flights = fopen(FLIGHTS_FILE, "wb");
    if (fp_flights) {
        fwrite(&flight_count, sizeof(int), 1, fp_flights);
        fwrite(flights, sizeof(Flight), flight_count, fp_flights);
        fclose(fp_flights);
    }
    FILE *fp_bookings = fopen(BOOKINGS_FILE, "wb");
    if (fp_bookings) {
        fwrite(&booking_count, sizeof(int), 1, fp_bookings);
        fwrite(bookings, sizeof(Booking), booking_count, fp_bookings);
        fclose(fp_bookings);
    }
}
// --- 管理员菜单和功能 ---
void admin_menu() {
    int choice;
    while (1) {
        system("cls");
        printf("\n\n\t\t\t 管理员菜单\n");
        printf("\n\t\t\t 1. 添加航班");
        printf("\n\t\t\t 2. 浏览所有航班");
        printf("\n\t\t\t 3. 查询航班");
        printf("\n\t\t\t 4. 修改航班");
        printf("\n\t\t\t 5. 删除航班");
        printf("\n\t\t\t 0. 返回主菜单");
        printf("\n\n\t\t\t 请选择: ");
        scanf("%d", &choice);
        clear_input_buffer();
        switch (choice) {
            case 1: add_flight(); break;
            case 2: list_flights(); break;
            case 3: search_flight(); break;
            case 4: modify_flight(); break;
            case 5: delete_flight(); break;
            case 0: return;
            default: printf("\n\t\t\t 无效输入!"); press_any_key_to_continue();
        }
    }
}
void add_flight() {
    if (flight_count >= MAX_FLIGHTS) {
        printf("\n\t\t\t 航班数量已达上限,无法添加!\n");
        press_any_key_to_continue();
        return;
    }
    Flight f;
    printf("\n\t\t\t 请输入航班号: "); gets(f.flight_id);
    printf("\t\t\t 请输入起点站: "); gets(f.origin);
    printf("\t\t\t 请输入终点站: "); gets(f.destination);
    printf("\t\t\t 请输入日期 (YYYY-MM-DD): "); gets(f.date);
    printf("\t\t\t 请输入时间 (HH:MM): "); gets(f.time);
    printf("\t\t\t 请输入总座位数: "); scanf("%d", &f.total_seats);
    printf("\t\t\t 请输入票价: "); scanf("%f", &f.price);
    clear_input_buffer();
    f.booked_seats = 0;
    flights[flight_count++] = f;
    printf("\n\t\t\t 航班添加成功!\n");
    press_any_key_to_continue();
}
void list_flights() {
    if (flight_count == 0) {
        printf("\n\t\t\t 当前没有航班信息!\n");
        press_any_key_to_continue();
        return;
    }
    printf("\n%-15s %-10s %-10s %-12s %-8s %-10s %-10s %s\n", 
           "航班号", "起点", "终点", "日期", "时间", "总座位", "已订", "票价");
    printf("--------------------------------------------------------------------------------\n");
    for (int i = 0; i < flight_count; i++) {
        printf("%-15s %-10s %-10s %-12s %-8s %-10d %-10d %.2f\n",
               flights[i].flight_id, flights[i].origin, flights[i].destination,
               flights[i].date, flights[i].time, flights[i].total_seats,
               flights[i].booked_seats, flights[i].price);
    }
    press_any_key_to_continue();
}
// ... (其他管理员函数 search_flight, modify_flight, delete_flight 的实现逻辑类似)
// search_flight: 遍历数组,按航班号或航线查找并显示。
// modify_flight: 按航班号查找,然后允许用户修改除航班号外的其他信息。
// delete_flight: 按航班号查找,找到后将其后所有元素前移,flight_count--。
// --- 乘客菜单和功能 ---
void passenger_menu() {
    int choice;
    while (1) {
        system("cls");
        printf("\n\n\t\t\t 乘客菜单\n");
        printf("\n\t\t\t 1. 查询航班");
        printf("\n\t\t\t 2. 订票");
        printf("\n\t\t\t 3. 退票");
        printf("\n\t\t\t 4. 我的订单");
        printf("\n\t\t\t 0. 返回主菜单");
        printf("\n\n\t\t\t 请选择: ");
        scanf("%d", &choice);
        clear_input_buffer();
        switch (choice) {
            case 1: search_flights_for_booking(); break;
            case 2: book_ticket(); break;
            case 3: cancel_ticket(); break;
            case 4: my_bookings(); break;
            case 0: return;
            default: printf("\n\t\t\t 无效输入!"); press_any_key_to_continue();
        }
    }
}
void search_flights_for_booking() {
    char origin[20], destination[20], date[20];
    printf("\n\t\t\t 请输入起点站: "); gets(origin);
    printf("\t\t\t 请输入终点站: "); gets(destination);
    printf("\t\t\t 请输入日期 (YYYY-MM-DD): "); gets(date);
    printf("\n%-15s %-10s %-10s %-12s %-8s %-10s %-10s %s\n", 
           "航班号", "起点", "终点", "日期", "时间", "总座位", "已订", "票价");
    printf("--------------------------------------------------------------------------------\n");
    int found = 0;
    for (int i = 0; i < flight_count; i++) {
        if (strcmp(flights[i].origin, origin) == 0 && 
            strcmp(flights[i].destination, destination) == 0 &&
            strcmp(flights[i].date, date) == 0) {
            printf("%-15s %-10s %-10s %-12s %-8s %-10d %-10d %.2f\n",
                   flights[i].flight_id, flights[i].origin, flights[i].destination,
                   flights[i].date, flights[i].time, flights[i].total_seats,
                   flights[i].booked_seats, flights[i].price);
            found = 1;
        }
    }
    if (!found) {
        printf("\n\t\t\t 未找到符合条件的航班!\n");
    }
    press_any_key_to_continue();
}
void book_ticket() {
    char flight_id[20];
    printf("\n\t\t\t 请输入您要预订的航班号: "); gets(flight_id);
    int flight_index = -1;
    for (int i = 0; i < flight_count; i++) {
        if (strcmp(flights[i].flight_id, flight_id) == 0) {
            flight_index = i;
            break;
        }
    }
    if (flight_index == -1) {
        printf("\n\t\t\t 错误:未找到该航班!\n");
        press_any_key_to_continue();
        return;
    }
    if (flights[flight_index].booked_seats >= flights[flight_index].total_seats) {
        printf("\n\t\t\t 抱歉,该航班已满座!\n");
        press_any_key_to_continue();
        return;
    }
    Booking b;
    strcpy(b.flight_id, flight_id);
    printf("\n\t\t\t 请输入您的姓名: "); gets(b.passenger_name);
    printf("\t\t\t 请输入您的身份证号: "); gets(b.id_card);
    bookings[booking_count++] = b;
    flights[flight_index].booked_seats++;
    printf("\n\t\t\t 订票成功!祝您旅途愉快!\n");
    press_any_key_to_continue();
}
void cancel_ticket() {
    char id_card[19];
    printf("\n\t\t\t 请输入您的身份证号以查找订单: "); gets(id_card);
    int booking_index = -1;
    for (int i = 0; i < booking_count; i++) {
        if (strcmp(bookings[i].id_card, id_card) == 0) {
            booking_index = i;
            break;
        }
    }
    if (booking_index == -1) {
        printf("\n\t\t\t 未找到您的订票记录!\n");
        press_any_key_to_continue();
        return;
    }
    // 找到订单,开始退票
    char flight_id_to_cancel[20];
    strcpy(flight_id_to_cancel, bookings[booking_index].flight_id);
    // 1. 从订票记录中删除
    for (int i = booking_index; i < booking_count - 1; i++) {
        bookings[i] = bookings[i + 1];
    }
    booking_count--;
    // 2. 更新航班的已订票数
    for (int i = 0; i < flight_count; i++) {
        if (strcmp(flights[i].flight_id, flight_id_to_cancel) == 0) {
            flights[i].booked_seats--;
            break;
        }
    }
    printf("\n\t\t\t 退票成功!\n");
    press_any_key_to_continue();
}
void my_bookings() {
    char id_card[19];
    printf("\n\t\t\t 请输入您的身份证号: "); gets(id_card);
    printf("\n%-15s %-20s %-19s\n", "航班号", "乘客姓名", "身份证号");
    printf("------------------------------------------------\n");
    int found = 0;
    for (int i = 0; i < booking_count; i++) {
        if (strcmp(bookings[i].id_card, id_card) == 0) {
            printf("%-15s %-20s %-19s\n",
                   bookings[i].flight_id, bookings[i].passenger_name, bookings[i].id_card);
            found = 1;
        }
    }
    if (!found) {
        printf("\n\t\t\t 未找到您的订票记录!\n");
    }
    press_any_key_to_continue();
}
// --- 工具函数实现 ---
void clear_input_buffer() {
    while (getchar() != '\n');
}
void press_any_key_to_continue() {
    printf("\n\n\t\t\t 按任意键继续...");
    getch();
}

系统测试与运行指南

  1. 编译运行:将以上代码保存为 ticket_system.c,使用C语言编译器(如 gcc ticket_system.c -o ticket_system)进行编译,然后运行生成的可执行文件。
  2. 管理员操作
    • 选择 1 进入管理员菜单。
    • 选择 1 添加几个示例航班,
      • 航班号: MU5101, 起点: 北京, 终点: 上海, 日期: 2025-12-25, 时间: 09:00, 总座位: 150, 票价: 1200
      • 航班号: CZ3102, 起点: 广州, 终点: 成都, 日期: 2025-12-25, 时间: 14:30, 总座位: 180, 票价: 900
    • 选择 2 浏览所有航班,检查添加是否成功。
    • 选择 0 返回主菜单。
  3. 乘客操作
    • 选择 2 进入乘客菜单。
    • 选择 1 查询航班,输入起点 北京,终点 上海,日期 2025-12-25,应能看到刚才添加的 MU5101 航班。
    • 选择 2 订票,输入航班号 MU5101,然后输入一个假姓名和身份证号(如 张三, 110101199001011234)。
    • 再次选择 1 查询航班,会发现 MU5101 的已订票数增加了。
    • 选择 4 我的订单,输入身份证号 110101199001011234,应能看到自己的订票记录。
    • 选择 3 退票,输入身份证号 110101199001011234,成功退票后,再次查询 MU5101,已订票数会减少。
  4. 数据持久化测试
    • 完成上述操作后,直接关闭程序。
    • 重新打开程序,你会发现之前添加的航班和订票记录都还在,这说明数据保存和加载功能正常工作。

项目扩展与优化建议

如果想让你的课程设计更出彩,可以考虑以下扩展方向:

  1. 用户账户系统:为乘客和管理员增加用户名和密码,而不是通过菜单选择身份,密码需要加密存储(如使用简单的异或加密或调用更安全的库)。
  2. 更复杂的查询:增加按价格范围、起飞时间范围等条件进行查询。
  3. 数据结构优化:使用链表代替数组来存储航班和订票信息,这样可以动态分配内存,避免数组大小限制,插入和删除也更高效。
  4. 图形用户界面:如果学过相关库(如 EasyX for Windows, GTK for Linux),可以尝试将文本界面升级为图形界面,提升用户体验。
  5. 排序功能:在浏览航班列表时,可以增加按起飞时间、票价等字段进行排序的功能。
  6. 航班状态管理:增加“已起飞”、“已到达”、“已取消”等状态,并据此控制订票和退票。
  7. 多线程/并发:这是一个高阶扩展,可以模拟多个用户同时订票的场景,使用多线程来处理,并引入锁机制来防止“超卖”问题(即多个线程同时检查到有票,同时进行订票操作,导致实际票数不够)。

这个项目涵盖了C语言课程设计的绝大部分核心知识点,是一个非常好的练习,祝你顺利完成!

-- 展开阅读全文 --
头像
热门标签打不开,问题出在哪?
« 上一篇 今天
织梦如何指定某子分类内容输出?
下一篇 » 今天
取消
微信二维码
支付宝二维码

目录[+]