数据结构课程设计说明书
学 院、系: | 软件学院 | ||
专 业: | 软件工程 | ||
班 级: | |||
学 生 姓 名: | 范 | 学 号: | |
设 计 题 目: | 飞机订票系统 | ||
| |||
起 迄 日 期: | 2024年6月18日~ 2024年7月2日 | ||
指 导 教 师: |
日期: 2024年7月2日
1 设计目的
本课程设计旨在通过开发一个航班订票系统,让学生在实践中理解和掌握数据结构与算法的基本原理和应用。通过项目的实际开发,学生将熟悉链表、队列等基本数据结构在实际应用中的实现方法,掌握C语言的编程技巧,并提高综合应用所学知识解决实际问题的能力。
课程设计的主要目标包括:
- 掌握链表和队列的基本操作及其在实际系统中的应用。
- 熟悉面向过程编程思想和模块化设计方法。
- 提高程序设计、调试及优化能力。
- 培养团队协作、任务分配及项目管理能力。
课程设计的意义在于,通过模拟真实的航班订票系统,学生可以直观地理解数据结构和算法在解决实际问题中的作用,提升编程能力和综合素质,为以后从事软件开发及相关工作打下坚实基础。
2 任务概述
本课程设计的任务是开发一个飞机订票系统。该系统的主要功能包括航班管理和票务管理。通过使用C语言编程,结合文件操作和图形界面库,实现用户对航班信息的管理和对票务信息的查询和操作。具体任务包括:
1. 航班管理
- 添加航班:用户可以输入航班号、出发城市、到达城市、出发时间、到达时间、票价、折扣和可用座位数,系统将该航班信息保存到文件中。
- 修改航班:用户可以根据航班号查询并修改航班信息。
- 按航班号查询:用户可以输入航班号查询对应的航班信息。
- 按城市查询:用户可以输入出发城市和到达城市,查询符合条件的航班信息。
- 查询所有航班:系统将显示所有航班的详细信息。
2. 票务管理
- 订票:用户可以输入姓名、身份证号和航班号进行订票,系统将检查该航班的可用座位数并保存订票信息。
- 退票:用户可以输入身份证号退票,系统将删除用户的订票记录并更新航班的可用座位数。
- 查询航班座位剩余情况:用户可以输入航班号查询该航班的座位剩余情况,如果座位已满,系统将推荐其他航班。
- 查询用户订票情况:用户可以输入身份证号查询该用户的订票信息。
该系统采用结构体存储航班信息和用户信息,通过文件操作实现数据的持久化,并结合图形界面库实现用户友好的操作界面。通过该设计,可以提升对C语言文件操作和图形界面编程的理解和应用能力,并锻炼解决实际问题的能力。
3 本设计采用的数据结构
3.1 航班信息结构体
typedef struct {
char flightNumber[10]; // 航班号
char departureCity[20]; // 出发地
char arrivalCity[20]; // 目的地
char departureTime[10]; // 开始时间
char arrivalTime[10]; // 结束时间
float price; // 票价
float discount; // 折扣
int seatsAvailable; // 剩余座位
} FlightInfo;
采用结构体存储航班信息,便于对航班信息进行增删改查操作。
3.2 客户信息结构体
typedef struct {
char name[50]; // 名字
char idNumber[20]; // 身份证号
int ticketCount; // 订票数量
char flightNumber[10]; // 航班号
int orderId; // 订单号
} CustomerInfo;
采用结构体存储客户信息,便于管理客户的订票和退票操作。
4 系统功能模块结构图及主要函数说明
4.1 系统功能模块结构图
图 4.1 软件显示页面
图 4.2 软件整体流程图
4.2 主要函数说明
4.2.1 addFlight
功能:添加航班信息到文件中。
基本算法思路:
1. 提示用户输入航班信息。
2. 将航班信息写入文件。
图 4.3 addFlight流程图
4.2.2 modifyFlight
功能:修改已有的航班信息。
基本算法思路:
1. 提示用户输入要修改的航班号。
2. 查找并读取该航班信息。
3. 提示用户输入新的航班信息并更新文件。
流程图:
图 4.4 modifyFlight流程图
4.2.3 queryFlightByNumber
功能:按航班号查询航班信息。
基本算法思路:
1. 提示用户输入要查询的航班号。
2. 查找并显示该航班信息。
流程图:
图 4.5 queryFlightByNumber流程图
4.2.4 queryFlightByCities
功能:按出发城市和到达城市查询航班信息。
基本算法思路:
1. 提示用户输入出发城市和到达城市。
2. 查找并显示符合条件的航班信息。
流程图:
图 4.6 queryFlightByCities流程图
4.2.5 queryAllFlights
功能:查询所有航班信息。
基本算法思路:
1. 读取文件中所有航班信息并显示。
流程图:
4.2.6 bookTicket
功能:订票功能。
基本算法思路:
1. 提示用户输入姓名、身份证号、航班号等信息。
2. 查找该航班信息,检查座位是否足够。
3. 更新航班信息和客户信息。
流程图:
图 4.8 bookTicket
4.2.7 cancelTicket
功能:退票功能。
基本算法思路:
1. 提示用户输入身份证号。
2. 查找客户信息和航班信息。
3. 更新航班座位数并删除客户信息。
流程图:
图 4.9 cancelTicket流程图
4.2.8 checkFlightAvailability
功能:查询航班座位剩余情况。
基本算法思路:
1. 提示用户输入航班号。
2. 查找该航班信息并显示座位剩余情况。
3. 如果座位已满,推荐其他航班。
流程图:
图 4.10 checkFlightAvailability流程图
4.2.9 queryCustomerTickets
功能:查询用户订票情况。
基本算法思路:
1. 提示用户输入身份证号。
2. 查找并显示客户的订票信息。
流程图:
图 4.11 queryCustomerTickets流程图
5 程序运行数据及其结果
图 5.1 飞机订票系统前端页面
图 5.2 飞机订票系统运行界面
图 5.3 飞机订票系统运行界面
图 5.4 飞机订票系统飞行数据存储界面
图 5.5 飞机订票系统用户数据存储界面
6 课程设计心得
在本次课程设计过程中,我学到了如何使用结构体来管理复杂的数据,学会了文件的读写操作以及如何使用easyx库进行图形界面的设计。通过开发一个飞机订票系统,我不仅掌握了C语言编程的基础知识,还深刻理解了编程中的数据组织和管理。
使用结构体来管理航班信息和用户信息让我体会到结构体在处理复杂数据时的优势。结构体允许我们将不同类型的数据组合在一起,形成一个逻辑上的整体,使得代码更具可读性和可维护性。在本次设计中,我定义了FlightInfo和CustomerInfo两个结构体,分别用于存储航班信息和用户订票信息。这种设计不仅使得数据管理变得更加简洁,还为后续的文件操作奠定了基础。
文件的读写操作是本次设计的另一个重点。在C语言中,文件操作是实现数据持久化的重要手段。通过学习和实践,我掌握了文件的打开、关闭、读写等基本操作,并学会了如何处理文件操作中的各种异常情况。在本次设计中,所有的航班信息和用户订票信息都保存在文件中,这不仅确保了数据的持久性,还实现了数据的共享和传递。通过多次的调试和测试,我逐步掌握了文件操作的细节,能够准确地读取和写入数据。
使用easyx库进行图形界面的设计是本次设计的一大亮点。相比于传统的控制台程序,图形界面程序更加直观和用户友好。在本次设计中,我通过easyx库实现了一个简单的图形界面,用户可以通过点击按钮来执行不同的功能。这不仅提高了程序的可用性,还增强了用户的操作体验。在设计图形界面的过程中,我学会了如何加载和显示图片、如何处理鼠标事件等技术。这些技能的掌握,使得我对图形界面的设计有了更加全面的理解。
在设计过程中也遇到了一些困难。例如,在文件操作中,如何确保数据的正确读写和如何处理文件操作中的异常情况,是一个需要仔细考虑的问题。通过查阅资料和请教老师,我学会了如何通过错误码来判断文件操作的成功与否,并在遇到错误时及时处理。另一个难点是图形界面的显示调整。在初次实现图形界面时,界面布局和显示效果并不理想。通过反复的调试和优化,最终实现了一个较为满意的界面效果。
本次设计使我更加深刻地理解了C语言编程的基本思想和方法。通过亲自实践,我不仅巩固了课堂上学到的知识,还学会了如何将这些知识应用到实际的编程中。特别是在处理复杂数据和设计用户界面时,如何合理地组织代码和数据、如何通过调试和测试来确保程序的正确性和可靠性,是我在本次设计中最大的收获。同时,我也意识到在设计程序时要注意细节和测试的重要性。一个细小的错误,可能会导致整个程序的失败;而充分的测试,可以发现和解决潜在的问题,确保程序的稳定性和可靠性。
附录:#define _CRT_SECURE_NO_WARNINGS 1#include <stdio.h>#include <stdlib.h>#include <string.h>#include <easyx.h>#include <conio.h>#include <graphics.h>#define FLIGHTS_FILE "flights.txt"#define CUSTOMERS_FILE "customers.txt"#define BACKGROUND_IMAGE "1.jpg"typedef struct {char flightNumber[10];//航班号char departureCity[20];//出发地char arrivalCity[20];//目的地char departureTime[10];//开始时间char arrivalTime[10];//结束时间float price;//价格float discount;//折扣int seatsAvailable;//剩余位置} FlightInfo;typedef struct {char name[50];//名字char idNumber[20];//身份证号int ticketCount;char flightNumber[10];//航班号int orderId;} CustomerInfo;void addFlight();void modifyFlight();void queryFlightByNumber();void queryFlightByCities();void queryAllFlights();void bookTicket();void cancelTicket();void drawMenu();void handleMouseClick(int x, int y);void checkFlightAvailability();void queryCustomerTickets();int main() {initgraph(640, 480);setbkcolor(WHITE);cleardevice();// 加载并显示背景图片IMAGE bg;loadimage(&bg, BACKGROUND_IMAGE , 700, 600);putimage(0, 0, &bg);drawMenu();MOUSEMSG msg;while (1) {msg = GetMouseMsg();if (msg.uMsg == WM_LBUTTONDOWN) {handleMouseClick(msg.x, msg.y);}}closegraph();return 0;}void drawMenu() {settextcolor(BLACK);settextstyle(30, 0, _T("Arial"));outtextxy(220, 50, _T("飞机订票系统"));settextstyle(20, 0, _T("Arial"));outtextxy(270, 120, _T("中北大学范振宇2313042124"));outtextxy(270, 150, _T("1. 添加航班"));outtextxy(270, 180, _T("2. 修改航班"));outtextxy(270, 210, _T("3. 按航班号查询"));outtextxy(270, 240, _T("4. 按城市查询"));outtextxy(270, 270, _T("5. 查询所有航班"));outtextxy(270, 300, _T("6. 订票"));outtextxy(270, 330, _T("7. 退票"));outtextxy(270, 360, _T("8. 查询订票情况"));outtextxy(270, 390, _T("9. 查询用户订票情况"));outtextxy(270, 420, _T("0. 退出"));}void handleMouseClick(int x, int y) {if (x >= 270 && x <= 370) {if (y >= 150 && y <= 170) {addFlight();}else if (y >= 180 && y <= 200) {modifyFlight();}else if (y >= 210 && y <= 230) {queryFlightByNumber();}else if (y >= 240 && y <= 260) {queryFlightByCities();}else if (y >= 270 && y <= 290) {queryAllFlights();}else if (y >= 300 && y <= 320) {bookTicket();}else if (y >= 330 && y <= 350) {cancelTicket();}else if (y >= 360 && y <= 380) {checkFlightAvailability();}else if (y >= 390 && y <= 410) {queryCustomerTickets();}else if (y >= 420 && y <= 440) {exit(0);}}}void addFlight() {FlightInfo flight;FILE* file = fopen(FLIGHTS_FILE, "ab");if (file == NULL) {printf("无法打开文件 %s\n", FLIGHTS_FILE);return;}printf("输入航班号: ");scanf("%9s", flight.flightNumber);flight.flightNumber[9] = '\0';printf("输入出发城市: ");scanf("%19s", flight.departureCity);flight.departureCity[19] = '\0';printf("输入到达城市: ");scanf("%19s", flight.arrivalCity);flight.arrivalCity[19] = '\0';printf("输入出发时间: ");scanf("%9s", flight.departureTime);flight.departureTime[9] = '\0';printf("输入到达时间: ");scanf("%9s", flight.arrivalTime);flight.arrivalTime[9] = '\0';printf("输入票价: ");scanf("%f", &flight.price);printf("输入折扣: ");scanf("%f", &flight.discount);printf("输入可用座位数: ");scanf("%d", &flight.seatsAvailable);fwrite(&flight, sizeof(FlightInfo), 1, file);fclose(file);printf("航班添加成功!\n");}void modifyFlight() {char flightNumber[10];FlightInfo flight;int found = 0;printf("输入要修改的航班号: ");scanf("%9s", flightNumber);flightNumber[9] = '\0';FILE* file = fopen(FLIGHTS_FILE, "rb+");if (file == NULL) {printf("无法打开文件 %s\n", FLIGHTS_FILE);return;}while (fread(&flight, sizeof(FlightInfo), 1, file)) {if (strcmp(flight.flightNumber, flightNumber) == 0) {printf("输入新的出发城市: ");scanf("%19s", flight.departureCity);flight.departureCity[19] = '\0';printf("输入新的到达城市: ");scanf("%19s", flight.arrivalCity);flight.arrivalCity[19] = '\0';printf("输入新的出发时间: ");scanf("%9s", flight.departureTime);flight.departureTime[9] = '\0';printf("输入新的到达时间: ");scanf("%9s", flight.arrivalTime);flight.arrivalTime[9] = '\0';printf("输入新的票价: ");scanf("%f", &flight.price);printf("输入新的折扣: ");scanf("%f", &flight.discount);printf("输入新的可用座位数: ");scanf("%d", &flight.seatsAvailable);fseek(file, -(int)sizeof(FlightInfo), SEEK_CUR);fwrite(&flight, sizeof(FlightInfo), 1, file);found = 1;break;}}fclose(file);if (found) {printf("航班修改成功!\n");}else {printf("未找到航班。\n");}}void queryFlightByNumber() {char flightNumber[10];FlightInfo flight;int found = 0;printf("输入要查询的航班号: ");scanf("%9s", flightNumber);flightNumber[9] = '\0';FILE* file = fopen(FLIGHTS_FILE, "rb");if (file == NULL) {printf("无法打开文件 %s\n", FLIGHTS_FILE);return;}while (fread(&flight, sizeof(FlightInfo), 1, file)) {if (strcmp(flight.flightNumber, flightNumber) == 0) {printf("航班号: %s\n", flight.flightNumber);printf("出发城市: %s\n", flight.departureCity);printf("到达城市: %s\n", flight.arrivalCity);printf("出发时间: %s\n", flight.departureTime);printf("到达时间: %s\n", flight.arrivalTime);printf("票价: %.2f\n", flight.price);printf("折扣: %.2f\n", flight.discount);printf("可用座位数: %d\n", flight.seatsAvailable);found = 1;break;}}fclose(file);if (!found) {printf("未找到航班。\n");}}void queryFlightByCities() {char departureCity[20], arrivalCity[20];FlightInfo flight;int found = 0;printf("输入出发城市: ");scanf("%19s", departureCity);departureCity[19] = '\0';printf("输入到达城市: ");scanf("%19s", arrivalCity);arrivalCity[19] = '\0';FILE* file = fopen(FLIGHTS_FILE, "rb");if (file == NULL) {printf("无法打开文件 %s\n", FLIGHTS_FILE);return;}while (fread(&flight, sizeof(FlightInfo), 1, file)) {if (strcmp(flight.departureCity, departureCity) == 0 && strcmp(flight.arrivalCity, arrivalCity) == 0) {printf("航班号: %s\n", flight.flightNumber);printf("出发城市: %s\n", flight.departureCity);printf("到达城市: %s\n", flight.arrivalCity);printf("出发时间: %s\n", flight.departureTime);printf("到达时间: %s\n", flight.arrivalTime);printf("票价: %.2f\n", flight.price);printf("折扣: %.2f\n", flight.discount);printf("可用座位数: %d\n", flight.seatsAvailable);found = 1;}}fclose(file);if (!found) {printf("未找到航班。\n");}}void queryAllFlights() {FlightInfo flight;FILE* file = fopen(FLIGHTS_FILE, "rb");if (file == NULL) {printf("无法打开文件 %s\n", FLIGHTS_FILE);return;}while (fread(&flight, sizeof(FlightInfo), 1, file)) {printf("航班号: %s\n", flight.flightNumber);printf("出发城市: %s\n", flight.departureCity);printf("到达城市: %s\n", flight.arrivalCity);printf("出发时间: %s\n", flight.departureTime);printf("到达时间: %s\n", flight.arrivalTime);printf("票价: %.2f\n", flight.price);printf("折扣: %.2f\n", flight.discount);printf("可用座位数: %d\n", flight.seatsAvailable);printf("-----------------------------\n");}fclose(file);}void bookTicket() {CustomerInfo customer;FlightInfo flight;int found = 0;FILE* flightFile = fopen(FLIGHTS_FILE, "rb+");if (flightFile == NULL) {printf("无法打开文件 %s\n", FLIGHTS_FILE);return;}printf("输入姓名: ");scanf("%49s", customer.name);customer.name[49] = '\0';printf("输入身份证号: ");scanf("%19s", customer.idNumber);customer.idNumber[19] = '\0';printf("输入航班号: ");scanf("%9s", customer.flightNumber);customer.flightNumber[9] = '\0';while (fread(&flight, sizeof(FlightInfo), 1, flightFile)) {if (strcmp(flight.flightNumber, customer.flightNumber) == 0) {found = 1;if (flight.seatsAvailable > 0) {fseek(flightFile, -(int)sizeof(FlightInfo), SEEK_CUR);fwrite(&flight, sizeof(FlightInfo), 1, flightFile);fclose(flightFile);FILE* customerFile = fopen(CUSTOMERS_FILE, "ab");if (customerFile == NULL) {printf("无法打开文件 %s\n", CUSTOMERS_FILE);return;}printf("输入订票数量: ");scanf("%d", &customer.ticketCount);if(flight.seatsAvailable - customer.ticketCount > 0){static int orderId = 1;customer.orderId = orderId++;flight.seatsAvailable -= customer.ticketCount;fwrite(&customer, sizeof(CustomerInfo), 1, customerFile);fclose(customerFile);printf("订票成功!\n");}elseprintf("购买票数已超出座位数,无法订票。\n");}else {printf("座位已满,无法订票。\n");fclose(flightFile);}break;}}if (!found) {printf("未找到航班。\n");fclose(flightFile);}}void cancelTicket() {char idNumber[20];CustomerInfo customer;FlightInfo flight;int foundCustomer = 0;int foundFlight = 0;printf("输入要退票的身份证号: ");scanf("%19s", idNumber);idNumber[19] = '\0';FILE* customerFile = fopen(CUSTOMERS_FILE, "rb");FILE* tempFile = fopen("temp.txt", "wb");if (customerFile == NULL || tempFile == NULL) {printf("无法打开文件。\n");return;}while (fread(&customer, sizeof(CustomerInfo), 1, customerFile)) {if (strcmp(customer.idNumber, idNumber) == 0) {foundCustomer = 1;FILE* flightFile = fopen(FLIGHTS_FILE, "rb+");if (flightFile == NULL) {printf("无法打开文件 %s\n", FLIGHTS_FILE);fclose(customerFile);fclose(tempFile);return;}while (fread(&flight, sizeof(FlightInfo), 1, flightFile)) {if (strcmp(flight.flightNumber, customer.flightNumber) == 0) {foundFlight = 1;flight.seatsAvailable += customer.ticketCount;fseek(flightFile, -(int)sizeof(FlightInfo), SEEK_CUR);fwrite(&flight, sizeof(FlightInfo), 1, flightFile);break;}}fclose(flightFile);}else {fwrite(&customer, sizeof(CustomerInfo), 1, tempFile);}}fclose(customerFile);fclose(tempFile);remove(CUSTOMERS_FILE);rename("temp.txt", CUSTOMERS_FILE);if (foundCustomer && foundFlight) {printf("退票成功!\n");}else if (!foundCustomer) {printf("未找到客户信息。\n");}else {printf("未找到航班信息。\n");}}void checkFlightAvailability() {char flightNumber[10];FlightInfo flight;int found = 0;printf("输入要查询的航班号: ");scanf("%9s", flightNumber);flightNumber[9] = '\0';FILE* file = fopen(FLIGHTS_FILE, "rb");if (file == NULL) {printf("无法打开文件 %s\n", FLIGHTS_FILE);return;}while (fread(&flight, sizeof(FlightInfo), 1, file)) {if (strcmp(flight.flightNumber, flightNumber) == 0) {found = 1;if (flight.seatsAvailable > 0) {printf("航班号: %s 还有 %d 个座位可用\n", flight.flightNumber, flight.seatsAvailable);}else {printf("航班号: %s 已满仓,推荐其他航班:\n", flight.flightNumber);// 推荐其他航班rewind(file); // Reset file pointer to startwhile (fread(&flight, sizeof(FlightInfo), 1, file)) {if (flight.seatsAvailable > 0) {printf("航班号: %s, 出发城市: %s, 到达城市: %s, 出发时间: %s, 票价: %.2f\n",flight.flightNumber, flight.departureCity, flight.arrivalCity, flight.departureTime, flight.price);}}}break;}}fclose(file);if (!found) {printf("未找到航班。\n");}}void queryCustomerTickets() {char idNumber[20];CustomerInfo customer;int found = 0;printf("输入要查询的身份证号: ");scanf("%19s", idNumber);idNumber[19] = '\0';FILE* file = fopen(CUSTOMERS_FILE, "rb");if (file == NULL) {printf("无法打开文件 %s\n", CUSTOMERS_FILE);return;}while (fread(&customer, sizeof(CustomerInfo), 1, file)) {if (strcmp(customer.idNumber, idNumber) == 0) {printf("客户姓名: %s\n", customer.name);printf("身份证号: %s\n", customer.idNumber);printf("航班号: %s\n", customer.flightNumber);printf("订票数量: %d\n", customer.ticketCount);printf("订单号: %d\n", customer.orderId);found = 1;}}fclose(file);if (!found) {printf("未找到客户的订票信息。\n");}}