本文为数据结构与算法课设《航空客运订票系统》的分享与实践,采用了顺序表和链表两种数据结构。贴近生活采用了系统选择来区别用户和管理员。
目录
1.设计内容与要求
2.功能实现和程序调试
功能实现
函数原型清单
程序调试
3.代码实现
(1)结构体定义
(2)管理员菜单和密码识别
(3)航班信息导入
(4)乘客信息导入
(5)航班信息修改
(6)信息显示函数
(7)信息导入文件
(8)用户菜单和证件号识别
(9)航班情况查询
(10)用户情况显示
(11)用户订票操作
(12)用户退票操作
(*13)完整代码
4.问题反思与总结
1.设计内容与要求
设计内容: 飞机订票系统包括:查询航线、客票预订和办理退票等。具体功能有: (1)录入:可以录入航班情况(数据可以存储在一个数据文件中,数据结构、具体数据结合实际情况自定); (2)修改航班信息:可以修改航班数据文件。 (3)客户资料:包括姓名,证件号,订票数量及航班情况,订单要有编号; (4) 查询:可以查询某趟航线的情况(如,输入航班号,查询起降时间,起飞抵达城市,航班票价,票价折扣,确定航班是否满仓);可以输入起飞抵达城市,查询飞机航班情况; (5)订票:订票情况可以存在一个数据文件中,结构自己设定;如果该航班已经无票,可以提供相关可选择航班; (6)退票:退票后修改相关数据文件; 设计要求: (1) 符合课题要求,实现相应功能; (2) 要求界面友好美观,操作方便易行; (3) 注意程序的实用性、安全性; |
2.功能实现和程序调试
功能实现
该流程图主要在区分系统工作的流程。具体功能实现参照代码展示。
函数原型清单
/*函数声明部分*/
void Choice();
void security();
void Register();
void Menu();
void Menu_1();
void Menu_2();
void Menuport_1(Parent* current);
void Menuport_2();
void flie_Flight();
void Printf_flight();
void file_parent();
void Printdf_parent();
void Amend();
int Search_flightID(int ID);
void Out_file_1();
void Out_file_2();
void Search_flight();
void Search_parent(Parent* current);
void Reserve(Parent* current);
void Cancel(Parent* current);
程序调试
进入主菜单选择
管理员系统
3.代码实现
(1)结构体定义
typedef struct {
int flightID; // 航班号
char departureCity[50]; // 起飞城市
char arrivalCity[50]; // 抵达城市
char departureTime[20]; // 起飞时间
char arrivalTime[20]; // 抵达时间
int ticketPrice; // 票价
float discount; // 折扣
int totalSeats; // 总座位数
int bookedSeats; // 已预订座位数
} Flight;
typedef struct p {
char name[50];
char Id[20];
int num_flight = 0;
int arr_flight[2][N]; //存储该用户的订单信息 乘坐的航班和订单编号
struct p* next;
}Parent;
Flight fli[N]; // 全局变量数组存储航班信息
int num_fli = 0;
Parent* head = NULL; //存储乘客信息的链表
Parent* Float = head; //存储乘客信息的链表
Parent* tail = NULL;
int Max_sum = 0;
程序主体的函数是通过调用的全局变量信息。
(2)管理员菜单和密码识别
这里的密码识别是不完善的,只能提前存储修改密码。只是贴合实际的设计了一个页面。
void security() {
system("cls");
printf("\n ***********************************\n");
printf(" ** **\n");
printf(" ** 管理员密码验证 **\n");
printf(" ** **\n");
printf(" ***********************************\n");
char Sec[10] = { "050501" };
char Key[10];
int sum = 0;
while (1) {
printf("请输入密码:");
scanf("%s",Key);
if (strcmp(Sec, Key) == 0) { printf(" 密码正确 !!!\n\n 欢迎使用管理员系统\n"); printf(" 正在加载。"); for (int i = 0; i < 4; i++) { Sleep(1000); printf("。"); }system("cls"); Menu_2(); Menuport_2(); return; }
else { printf("密码错误 请重新输入\n\n"); sum++;
if (sum == 3) { printf("错误次数已达上限\n已退出系统\n"); break; }
printf("(还有%d次输入机会)\n",3-sum); }
}
}
分两个菜单是考虑到不是所有用户都可以进行航班信息修改和导入以及所有用户信息的查找和显示。所以设计了管理源系统来实现这些功能。
void Menu_2() {
system("cls");
printf("\n ***********************************\n");
printf(" ** **\n");
printf(" ** 管理员系统 **\n");
printf(" ** **\n");
printf(" ** 1.导入航班信息 **\n");
printf(" ** 2.显示航班信息 **\n");
printf(" ** 3.修改航班信息 **\n");
printf(" ** 4.导入乘客信息 **\n");
printf(" ** 5.显示当前订单 **\n");
printf(" ** 6.导出当前信息 **\n");
printf(" ** 0.退出管理员系统 **\n");
printf(" ** **\n");
printf(" ** **\n");
printf(" ***********************************\n");
}
void Menuport_2() {
int input;
while (1) {
printf("请选择你的操作:");
scanf("%d", &input);
switch (input) {
case 1: {
Menu_2();
printf("\n ***********************************\n");
printf(" ** **\n");
printf(" ** 当前为航班导入窗口 **\n");
printf(" ** **\n");
printf(" ***********************************\n\n");
file_Flight();
break;
}
case 2: {
Menu_2();
printf("\n ***********************************\n");
printf(" ** **\n");
printf(" ** 当前为航班显示窗口 **\n");
printf(" ** **\n");
printf(" ***********************************\n\n");
Print_flight();
break;
}
case 3: {
Menu_2();
printf("\n ***********************************\n");
printf(" ** **\n");
printf(" ** 当前为航班修改窗口 **\n");
printf(" ** **\n");
printf(" ***********************************\n\n");
Amend();
break;
}
case 4: {
Menu_2();
printf("\n ***********************************\n");
printf(" ** **\n");
printf(" ** 当前为乘客导入窗口 **\n");
printf(" ** **\n");
printf(" ***********************************\n\n");
file_parent();
break;
}
case 5: {
Menu_2();
printf("\n ***********************************\n");
printf(" ** **\n");
printf(" ** 当前为乘客显示窗口 **\n");
printf(" ** **\n");
printf(" ***********************************\n\n");
Printf_parent();
break;
}
case 6: {
Menu_2();
printf("\n ***********************************\n");
printf(" ** **\n");
printf(" ** 当前为航班信息导出窗口 **\n");
printf(" ** **\n");
printf(" ***********************************\n\n");
Out_file_1();
Menu_2();
printf("\n ***********************************\n");
printf(" ** **\n");
printf(" ** 当前为乘客信息导出窗口 **\n");
printf(" ** **\n");
printf(" ***********************************\n\n");
Out_file_2();
break;
}
case 0: {
printf("系统已成功退出,感谢您的使用\n");
return;
}
default: {
printf("无效的选择,请重新输入\n");
}
}
}
}
(3)航班信息导入
文件中信息存储格式以 “,”为分割符,按照顺序逐个读取。函数开头的getchar()函数是为了吸收之前在菜单选择时的换行符。避免缓冲区等待数据对于文件名的输入产生影响。
void file_Flight() {
getchar();
char filename[50];
printf("请输入导入文件的名称(不含扩展名): ");
if (fgets(filename, sizeof(filename), stdin) != NULL) {
size_t len = strlen(filename);
if (len > 0 && filename[len - 1] == '\n') {
filename[len - 1] = '\0'; // 去除换行符
}
strcat(filename, ".txt"); // 添加扩展名
FILE* file = fopen(filename, "r");
if (file == NULL) {
printf("无法打开文件 %s!\a\n", filename);
return;
}
char line[1256];
while (fgets(line, sizeof(line), file) && num_fli < N) {
line[strcspn(line, "\n")] = 0; // 去除行尾换行符
char* token = strtok(line, ",");
int fieldIndex = 0; // 用于记录字段索引
while (token != NULL && fieldIndex < 9) {
switch (fieldIndex) {
case 0: sscanf(token, "%d", &fli[num_fli].flightID); break;
case 1: strncpy(fli[num_fli].departureCity, token, 50); break;
case 2: strncpy(fli[num_fli].departureTime, token, 20); break;
case 3: sscanf(token, "%50s", fli[num_fli].arrivalCity); break;
case 4: sscanf(token, "%20s", fli[num_fli].arrivalTime);break;
case 5: sscanf(token, "%d", &fli[num_fli].ticketPrice); break;
case 6: sscanf(token, "%f", &fli[num_fli].discount); break;
case 7: sscanf(token, "%d", &fli[num_fli].totalSeats); break;
case 8: sscanf(token, "%d", &fli[num_fli].bookedSeats); break;
}
fieldIndex++;
token = strtok(NULL, ",");
}
num_fli++;
}
fclose(file);
printf("成功从文件 %s 导入数据!\n", filename);
}
else {
printf("读取文件名失败\n");
}
}
(4)乘客信息导入
void file_parent() {
getchar();
char filename[50];
printf("请输入导入文件的名称(不含扩展名): ");
if (fgets(filename, sizeof(filename), stdin) != NULL) {
size_t len = strlen(filename);
if (len > 0 && filename[len - 1] == '\n') {
filename[len - 1] = '\0';
}
strcat(filename, ".txt");
FILE* file = fopen(filename, "r");
if (file == NULL) {
printf("无法打开文件 %s!\a\n", filename);
return;
}
char line[1256];
Parent* head = NULL, * newparent;
while (fgets(line, sizeof(line), file)) {
line[strcspn(line, "\n")] = 0; // 去除行尾换行符
newparent = (Parent*)malloc(sizeof(Parent));
newparent->next = NULL;
if (!newparent) {
perror("Memory allocation failed");
fclose(file);
return;
}
char* token = strtok(line, ",");
int fieldIndex = 0;
while (token != NULL && fieldIndex < 3) {
switch (fieldIndex) {
case 0: sscanf(token, "%20s", newparent->name);break;
case 1: sscanf(token, "%s", newparent->Id); break;
case 2: {
sscanf(token, "%d", &newparent->num_flight);
if (newparent->num_flight > Max_sum) {
Max_sum = newparent->num_flight;
}
for (int i = 0; i < newparent->num_flight && token != NULL; i++) {
token = strtok(NULL, ",");
if (token) {
sscanf(token, "%d", &newparent->arr_flight[0][i]);
token = strtok(NULL, ",");
if (token) {
sscanf(token, "%d", &newparent->arr_flight[1][i]);
}
}
}
break;
}
}
fieldIndex++;
token = strtok(NULL, ",");
}
if (!head) {
head = newparent;
tail = newparent;
}
else {
tail->next = newparent;
tail = newparent;
}
}
Float = head; // 更新全局链表头
printf("已由文件成功导入\n");
fclose(file);
}
}
(5)航班信息修改
void Amend() {
int newname;
int input;
printf("\n请输入要修改的航班编号\n");
scanf("%d",&newname);
int wei = Search_flightID(newname);
Menu_2();
printf("\n ***********************************\n");
printf(" ** **\n");
printf(" ** 当前为航班修改窗口 **\n");
printf(" ** **\n");
printf(" ** 1.航班起飞时间 **\n");
printf(" ** 2.航班抵达时间 **\n");
printf(" ** 3.航班荷载人数 **\n");
printf(" ** 0.退出修改窗口 **\n");
printf(" ** **\n");
printf(" ***********************************\n\n");
while (1) {
printf("请选择修改内容\n");
scanf("%d", &input);
switch (input) {
case 1: {char time[20]; printf("请输入修改后的时间:"); scanf("%s", time); strcpy(fli[wei].departureTime, time); break; }
case 2: {char time[20]; printf("请输入修改后的时间:"); scanf("%s", time); strcpy(fli[wei].arrivalTime, time); break; }
case 3: {int num; printf("请输入当前所荷载人数:"); scanf("%d", &num); fli[wei].totalSeats = num; break; }
case 0: {printf("\n已退出航班修改\n"); return;}
}
}
}
(6)信息显示函数
void Print_flight() {
if (num_fli == 0) { printf("当前无航班信息 请导入\n"); return;}
printf("┌───────────────┬─────────────────────┬─────────────────────┬─────────────────────┬─────────────────────┬─────────────────────┬─────────────────────┐\n");
printf("│ 编号 │ 起飞城市 │ 起飞时间 │ 抵达城市 │ 抵达时间 │ 总座位数 │ 已预订座位数 │\n");
printf("├───────────────┼─────────────────────┼─────────────────────┼─────────────────────┼─────────────────────┼─────────────────────┼─────────────────────┤\n");
for (int i = 0; i < num_fli; i++) {
printf("│");
int padding = (length_1 - 8) / 2; for (int i = 0; i < padding; i++) { printf(" "); } /*if (fli[i].flightID > 9) { padding++; if (fli[i].flightID > 99) { padding++; } }*/
printf("%d", fli[i].flightID); for (int i = 0; i < length_1 - 8 - padding; i++) { printf(" "); }
printf("│");
int padd = (length_2 - strlen(fli[i].departureCity)) / 2; for (int k1 = 0; k1 < padd; k1++) { printf(" "); }
printf("%s",fli[i].departureCity); for (int j1 = 0; j1 < (length_2 - padd - strlen(fli[i].departureCity)); j1++) { printf(" "); }
printf("│");
padd = (length_2 - strlen(fli[i].departureTime)) / 2; for (int k2 = 0; k2 < padd; k2++) { printf(" "); }
printf("%s",fli[i].departureTime); for (int j2 = 0; j2 < (length_2 - padd - strlen(fli[i].departureTime)); j2++) { printf(" "); }
printf("│");
padd = (length_2 - strlen(fli[i].arrivalCity)) / 2; for (int k3 = 0; k3 < padd; k3++) { printf(" "); }
printf("%s", fli[i].arrivalCity); for (int j3 = 0; j3 < (length_2 - padd - strlen(fli[i].arrivalCity)); j3++) { printf(" "); }
printf("│");
padd = (length_2 - strlen(fli[i].arrivalTime)) / 2; for (int k4 = 0; k4 < padd; k4++) { printf(" "); }
printf("%s", fli[i].arrivalTime); for (int j4 = 0; j4 < (length_2 - padd - strlen(fli[i].arrivalTime)); j4++) { printf(" "); }
printf("│");
padding = (length_2 - 1) / 2; for (int i = 0; i < padding; i++) { printf(" "); } if (fli[i].totalSeats > 9) { padding++; if (fli[i].totalSeats > 99) { if (fli[i].totalSeats > 999) { padding++; } padding++; } }
printf("%d", fli[i].totalSeats);for (int j5 = 0; j5 < length_2 - 1 - padding; j5++) { printf(" "); }
printf("│");
padding = (length_2 - 1) / 2; for (int i = 0; i < padding; i++) { printf(" "); } if (fli[i].bookedSeats > 9) { padding++; if (fli[i].bookedSeats > 99) { if (fli[i].bookedSeats > 999) { padding++; } padding++; } }
printf("%d", fli[i].bookedSeats); for (int j5 = 0; j5 < length_2 - 1 - padding; j5++) { printf(" "); }
printf("│\n");
if (i + 1 == num_fli) { printf("└───────────────┴─────────────────────┴─────────────────────┴─────────────────────┴─────────────────────┴─────────────────────┴─────────────────────┘\n"); }
else { printf("├───────────────┼─────────────────────┼─────────────────────┼─────────────────────┼─────────────────────┼─────────────────────┼─────────────────────┤\n"); }
}
printf("\n显示完成\n");
}
void Printf_parent() {
Parent* current = Float; if (current == NULL) { printf("当前无乘客信息 请导入\n"); return;}
printf("┌─────────────────────┬─────────────────────┬─────────────────────┬"); for (int i = 0; i < Max_sum-1; i++) { printf("──────────────────────"); } printf("─────────────────────┐\n"); //表头第一行
printf("│ 姓名 │ 证件号 │ 航班数量 │");
int padding = ((length_2+1) * Max_sum -1- strlen("航班订单")) / 2; for (int ki = 0; ki < padding; ki++) { printf(" "); } printf("航班信息"); for (int kp = 0; kp < ((length_2+1) * Max_sum -1 - padding - strlen("航班订单")); kp++) { printf(" "); }printf("│\n");//表头第二行
printf("├─────────────────────┼─────────────────────┼─────────────────────┼"); for (int i = 0; i < Max_sum-1; i++) { printf("─────────────────────┬"); }printf("─────────────────────┤\n");//表头第三行
while (current != NULL) {
int padding, padd;
printf("│ │ │ ");
for (int i = 0; i < Max_sum; i++) {
if (i < current->num_flight) {
printf("│");
padd = (length_2 - 8) / 2; for (int k2 = 0; k2 < padd; k2++) { printf(" "); }
printf("%d", current->arr_flight[0][i]); for (int j2 = 0; j2 < (length_2 - padd - 8); j2++) { printf(" "); }
}
else {
printf("│"); for (int ko = 0; ko < length_2; ko++) { printf(" "); }
}
}printf("│\n");
//数据输出第一行
printf("│");
padd = (length_2 - strlen(current->name)) / 2; for (int k1 = 0; k1 < padd; k1++) { printf(" "); }
printf("%s", current->name); for (int j1 = 0; j1 < (length_2 - padd - strlen(current->name)); j1++) { printf(" "); }
printf("│");
padd = (length_2 - strlen(current->Id)) / 2; for (int k2 = 0; k2 < padd; k2++) { printf(" "); }
printf("%s", current->Id); for (int j2 = 0; j2 < (length_2 - padd - strlen(current->Id)); j2++) { printf(" "); }
printf("│");
padd = (length_2 - 1) / 2; for (int k2 = 0; k2 < padd; k2++) { printf(" "); }if (current->num_flight > 9) { padd++; if (current->num_flight > 99) { padd++; } }
printf("%d", current->num_flight); for (int j2 = 0; j2 < (length_2 - padd - 1); j2++) { printf(" "); }
printf("├");
for (int as = 0; as < Max_sum - 1; as++) { printf("─────────────────────┼"); }printf("─────────────────────┤\n");
//数据输出第二行
printf("│