当前位置: 首页 > article >正文

【数据结构】航班查询系统:链表的实际运用

目标:航班查询系统:能够在 Linux 系统 中运行,并用 Makefile 管理项目。
项目文件结构:
flight_system/
├── flight.h   # 头文件,声明数据结构与函数
├── flight.c   # 实现文件,定义功能函数
├── main.c     # 主程序文件,负责菜单交互
├── Makefile   # 项目构建文件

功能描述:
	信息录入:用户可以输入航班信息,将其存储到链表中。
	信息显示:按照起飞时间升序显示航班信息。
	信息查询:支持根据关键字(如航班号、起点站、终点站等)进行查询。
	删除功能:删除航班功能。
	使用 Makefile 管理项目的构建。
	
方案1(单向链表)
1. 新增功能:修改航班功能设计
用户输入航班号,系统查找对应的航班信息。如果找到该航班,用户可以选择修改以下字段:
	1. 起点站
	2. 终点站
	3. 班期
	4. 机型
	5. 起飞时间
	6. 到达时间
	7. 票价
修改后更新链表中的数据。

2. 按票价范围查询功能:
用户输入票价的最低值和最高值,系统遍历链表,查找票价在该范围内的所有航班,并显示结果。如果没有符合条件的航班,提示用户没有找到。

3. 航班信息排序功能:用户可以选择按 起飞时间 或其他字段(如票价)对航班信息进行排序。排序后的结果将更新链表,并按指定顺序显示所有航班信息。
排序方式:
 * 按起飞时间排序(升序)
 * 按票价排序(升序)

4. 为了防止程序崩溃,需要对用户输入进行更严谨的验证
	4.1 常见问题
	非法输入:用户输入非预期格式的内容(例如,需要整数时输入了字符串)。
	缓冲区溢出:用户输入的数据超出预定义缓冲区长度。
	空输入:用户没有输入任何数据。
	不符合规则的输入:例如,起飞时间超出 24 小时制范围。
	
	4.2 使用更安全的输入方法
	使用 fgets 读取输入,避免缓冲区溢出。
	对输入内容进行解析和验证,确保输入符合预期格式。
	提供提示,要求用户重新输入合法值。
	
	运行测试
	测试非法输入:
		1. 输入非整数值(如 abc)时,程序会提示重新输入。
		2. 输入超出范围的值(如票价 -100 或起飞时间 2500),程序会提示重新输入。
	测试正常功能:
		1. 正常输入航班信息,确保数据正确保存。
		2. 修改航班信息,确保更新后的值有效且没有崩溃。
		
5. 支持用户通过多种条件查询航班信息,例如:
	根据 起点站 查询。
	根据 终点站 查询。
	根据 班期 查询。
	根据 起飞时间范围 查询。
	根据 到达时间范围 查询。
	支持组合查询(例如,起点站 + 起飞时间范围)。
	
	方案:
	5.1 增加查询条件的函数
	为每种查询条件单独实现查询逻辑,例如按起点站查询、按终点站查询、按时间范围查询等。

	5.2 添加通用查询函数
	使用一个通用查询函数,根据用户选择的条件进行筛选。每个查询条件通过布尔值或特定参数进行判断。

	5.3 动态菜单
	提供动态查询菜单,允许用户选择单一条件或组合条件查询。
	
6. 清除输入缓冲区
	在每次调用 scanf 读取数字后,立即清除输入缓冲区中的换行符。可以通过以下方法实现:
	6.1 在每次调用 scanf 读取整数后,调用 clearInputBuffer。
	6.2 改用 fgets 处理所有输入:使用 fgets 替代 scanf,然后通过 sscanf 解析用户输入。fgets 可以更安全地读取整行输入,并防止缓冲区溢出。

方案2(双向链表)
将程序改为使用 双向链表 实现对航班信息的管理,可以更高效地进行删除、插入和遍历操作:
	1. 由于代码实现逻辑与单向链表完全一致,文章的篇幅问题,其他功能如排序、查询(按起点站、终点站、时间范围等)和自定义查询可以类似实现,遍历链表时根据条件筛选节点。
	
	双向链表的优点
	 * 高效删除:可以直接通过前驱指针调整节点,不需要重新遍历链表。
	 * 灵活插入:可以在任意位置快速插入新节点。
	 * 易于实现排序:双向链表可以从头或尾进行遍历。
	 * 可以轻松添加更多功能(如按票价排序、时间范围查询)。
	 * 支持复杂的自定义查询条件。
	 
方案3(内核链表) 
 Linux 内核链表 (Kernel Linked List) 实现,可以利用内核链表的高效设计,简化链表操作。
 Linux 内核链表通过Linux系统中提供的头文件 <linux/list.h> 提供了强大的链表操作函数,能够减少自己实现链表结构和功能所需的代码。
 
 内核链表本身也是双向循环链表,具备以下优点:
	 * 通用性强:通过嵌入 struct list_head,可以将链表功能添加到任何结构体。
	 * 操作简便:提供了宏和函数用于插入、删除、遍历等操作,简化链表管理。
	 * 性能高:设计高效,避免了许多常见的链表实现问题。

方案一(单向链表实现)

文件:flight.c
#include "flight.h"

// 使用 getchar 循环清空缓冲区
int clearInputBuffer() {
    int c;
    while ((c = getchar()) != '\n' && c != EOF);
    return c;
}

// 录入: 将用户输入的航班信息插入到链表中,并保持链表按照 起飞时间升序排列。
void insertFlight(node_list **head) {
    // 分配新节点
    node_list *newNode = (node_list *)malloc(sizeof(node_list));
    if (!newNode) {
        printf("内存分配失败!\n");
        exit(1);
    }

    // 输入航班信息
/*     printf("请输入航班号: ");
    scanf("%s", newNode->info.number);
    printf("请输入起点站: ");
    scanf("%s", newNode->info.staddress);
    printf("请输入终点站: ");
    scanf("%s", newNode->info.arraddress);
    printf("请输入班期: ");
    scanf("%s", newNode->info.DATE);
    printf("请输入机型: ");
    scanf("%s", newNode->info.TYPE);
    printf("请输入起飞时间(24小时制,例如1330): ");
    scanf("%d", &newNode->info.stime);
    printf("请输入到达时间(24小时制,例如1530): ");
    scanf("%d", &newNode->info.atime);
    printf("请输入票价: ");
    scanf("%d", &newNode->info.value); */
	
	// 输入航班信息
    getValidString("请输入航班号: ", newNode->info.number, sizeof(newNode->info.number));
    getValidString("请输入起点站: ", newNode->info.staddress, sizeof(newNode->info.staddress));
    getValidString("请输入终点站: ", newNode->info.arraddress, sizeof(newNode->info.arraddress));
    getValidString("请输入班期: ", newNode->info.DATE, sizeof(newNode->info.DATE));
    getValidString("请输入机型: ", newNode->info.TYPE, sizeof(newNode->info.TYPE));

    newNode->info.stime = getValidInt("请输入起飞时间(24小时制,例如1330): ", 0, 2359);
    newNode->info.atime = getValidInt("请输入到达时间(24小时制,例如1530): ", 0, 2359);
    newNode->info.value = getValidInt("请输入票价: ", 0, 100000);

    // 插入到链表中,按起飞时间排序
    newNode->next = NULL;
    if (*head == NULL || (*head)->info.stime > newNode->info.stime) {
        // 插入到链表头部
        newNode->next = *head;
        *head = newNode;
    } else {
        // 插入到链表中间或尾部
        node_list *current = *head;
        while (current->next && current->next->info.stime <= newNode->info.stime) {
            current = current->next;
        }
        newNode->next = current->next;
        current->next = newNode;
    }

    printf("航班信息录入成功!\n");
}

// 显示(按起飞时间排序):遍历链表,按照起飞时间的顺序打印所有航班信息(链表已经按起飞时间排序)。
void displayFlights(node_list *head) {
    if (head == NULL) {
        printf("没有航班信息!\n");
        return;
    }

    printf("\n航班信息(按起飞时间排序):\n");
    printf("航班号 起点站 终点站 班期 机型 起飞时间 到达时间 票价\n");

    while (head) {
        printf("%s %s %s %s %s %04d %04d %d\n",
               head->info.number, head->info.staddress, head->info.arraddress,
               head->info.DATE, head->info.TYPE, head->info.stime,
               head->info.atime, head->info.value);
        head = head->next;
    }
}

// 查询:支持根据 航班号、起点站 或 终点站 查询航班信息。
void searchFlight(node_list *head) {
    if (head == NULL) {
        printf("没有航班信息!\n");
        return;
    }

    char keyword[18];
    printf("请输入查询关键字(航班号/起点站/终点站): ");
    scanf("%s", keyword);

    int found = 0;
    printf("\n查询结果:\n");
    printf("航班号 起点站 终点站 班期 机型 起飞时间 到达时间 票价\n");

    while (head) {
        if (strcmp(head->info.number, keyword) == 0 ||
            strcmp(head->info.staddress, keyword) == 0 ||
            strcmp(head->info.arraddress, keyword) == 0) {
            found = 1;
            printf("%s %s %s %s %s %04d %04d %d\n",
                   head->info.number, head->info.staddress, head->info.arraddress,
                   head->info.DATE, head->info.TYPE, head->info.stime,
                   head->info.atime, head->info.value);
        }
        head = head->next;
    }

    if (!found) {
        printf("没有找到符合条件的航班信息。\n");
    }
}

// 删除航班功能
void deleteFlight(node_list **head, const char *flightNumber) {
    if (*head == NULL) {
        printf("链表为空,没有航班可以删除!\n");
        return;
    }

    node_list *current = *head;
    node_list *previous = NULL;

    // 遍历链表,寻找匹配的航班号
    while (current != NULL) {
        if (strcmp(current->info.number, flightNumber) == 0) {
            // 找到目标节点
            if (previous == NULL) {
                // 删除的是头节点
                *head = current->next;
            } else {
                // 删除的是非头节点
                previous->next = current->next;
            }

            printf("航班号 %s 的航班已删除!\n", flightNumber);
            free(current); // 释放内存
            return;
        }

        // 继续遍历
        previous = current;
        current = current->next;
    }
    printf("未找到航班号为 %s 的航班!\n", flightNumber);
}

// 修改航班信息
void modifyFlight(node_list *head, const char *flightNumber) {
    if (head == NULL) {
        printf("链表为空,没有航班可以修改!\n");
        return;
    }

    node_list *current = head;

    // 遍历链表,找到对应航班号的节点
    while (current != NULL) {
        if (strcmp(current->info.number, flightNumber) == 0) {
            printf("找到航班号为 %s 的航班信息。\n", flightNumber);

            // 显示当前信息
            printf("\n当前信息:\n");
            printf("起点站: %s\n", current->info.staddress);
            printf("终点站: %s\n", current->info.arraddress);
            printf("班期: %s\n", current->info.DATE);
            printf("机型: %s\n", current->info.TYPE);
            printf("起飞时间: %04d\n", current->info.stime);
            printf("到达时间: %04d\n", current->info.atime);
            printf("票价: %d\n", current->info.value);

            // 修改信息
/*             printf("\n请输入新的信息(若不修改,请输入原值):\n");
            printf("起点站: ");
            scanf("%s", current->info.staddress);
            printf("终点站: ");
            scanf("%s", current->info.arraddress);
            printf("班期: ");
            scanf("%s", current->info.DATE);
            printf("机型: ");
            scanf("%s", current->info.TYPE);
            printf("起飞时间(24小时制,例如1330): ");
            scanf("%d", &current->info.stime);
            printf("到达时间(24小时制,例如1530): ");
            scanf("%d", &current->info.atime);
            printf("票价: ");
            scanf("%d", &current->info.value); */
			
			printf("\n请输入新的信息(若不修改,请输入原值):\n");
            getValidString("起点站: ", current->info.staddress, sizeof(current->info.staddress));
            getValidString("终点站: ", current->info.arraddress, sizeof(current->info.arraddress));
            getValidString("班期: ", current->info.DATE, sizeof(current->info.DATE));
            getValidString("机型: ", current->info.TYPE, sizeof(current->info.TYPE));
            current->info.stime = getValidInt("起飞时间(24小时制,例如1330): ", 0, 2359);
            current->info.atime = getValidInt("到达时间(24小时制,例如1530): ", 0, 2359);
            current->info.value = getValidInt("票价: ", 0, 100000);

            printf("航班信息修改成功!\n");
            return;
        }
        current = current->next;
    }
    printf("未找到航班号为 %s 的航班!\n", flightNumber);
}

// 按票价范围查询航班信息
void searchFlightsByPriceRange(node_list *head, int minPrice, int maxPrice) {
    if (head == NULL) {
        printf("链表为空,没有航班信息!\n");
        return;
    }

    int found = 0; // 标记是否找到符合条件的航班
    printf("\n票价范围 [%d - %d] 的航班信息:\n", minPrice, maxPrice);
    printf("航班号 起点站 终点站 班期 机型 起飞时间 到达时间 票价\n");

    while (head) {
        if (head->info.value >= minPrice && head->info.value <= maxPrice) {
            found = 1;
            printf("%s %s %s %s %s %04d %04d %d\n",
                   head->info.number, head->info.staddress, head->info.arraddress,
                   head->info.DATE, head->info.TYPE, head->info.stime,
                   head->info.atime, head->info.value);
        }
        head = head->next;
    }

    if (!found) {
        printf("未找到票价范围 [%d - %d] 的航班信息。\n", minPrice, maxPrice);
    }
}

// 航班信息排序:使用 冒泡排序 对链表进行排序。
void sortFlights(node_list **head, int mode) {
    if (*head == NULL || (*head)->next == NULL) {
        printf("链表为空或只有一个航班信息,无需排序!\n");
        return;
    }

    int swapped;
    node_list *current;
    node_list *last = NULL;

    do {
        swapped = 0;
        current = *head;

        while (current->next != last) {
            int swapCondition = 0;

            // 根据 mode 判断排序方式
            if (mode == 1) {
                // 按起飞时间排序(升序)
                if (current->info.stime > current->next->info.stime) {
                    swapCondition = 1;
                }
            } else if (mode == 2) {
                // 按票价排序(升序)
                if (current->info.value > current->next->info.value) {
                    swapCondition = 1;
                }
            }

            if (swapCondition) {
                // 交换节点数据
                datatype temp = current->info;
                current->info = current->next->info;
                current->next->info = temp;

                swapped = 1;
            }

            current = current->next;
        }

        last = current;
    } while (swapped);

    if (mode == 1) {
        printf("航班信息已按起飞时间排序(升序)。\n");
    } else if (mode == 2) {
        printf("航班信息已按票价排序(升序)。\n");
    }
}

// 安全输入函数 getValidInt 和 getValidString:
// 获取有效整数(带范围的验证)
int getValidInt(const char *prompt, int min, int max) {
    char buffer[32]; // 缓冲区
    int value;
    while (1) {
        printf("%s", prompt);
        if (fgets(buffer, sizeof(buffer), stdin)) {
            // 尝试解析整数
            if (sscanf(buffer, "%d", &value) == 1 && value >= min && value <= max) {
                return value;
            }
        }
        printf("无效输入,请输入一个范围在 [%d, %d] 的整数。\n", min, max);
    }
}

// 获取有效字符串(长度限制)
void getValidString(const char *prompt, char *dest, size_t maxLen) {
    char buffer[128]; // 缓冲区
    while (1) {
        printf("%s", prompt);
        if (fgets(buffer, sizeof(buffer), stdin)) {
            size_t len = strlen(buffer);

            // 去掉换行符
            if (len > 0 && buffer[len - 1] == '\n') {
                buffer[len - 1] = '\0';
                len--;
            }

            // 检查长度
            if (len > 0 && len < maxLen) {
                strncpy(dest, buffer, maxLen);
                dest[maxLen - 1] = '\0'; // 确保字符串以 null 结尾
                return;
            }
        }
        printf("无效输入,请输入一个长度小于 %zu 的字符串。\n", maxLen);
    }
}

// 多种查询条件:
// 查询条件:按起点站查询
void searchFlightsByStart(node_list *head, const char *start) {
    if (head == NULL) {
        printf("链表为空,没有航班信息!\n");
        return;
    }

    int found = 0;
    printf("\n起点站为 '%s' 的航班信息:\n", start);
    printf("航班号 起点站 终点站 班期 机型 起飞时间 到达时间 票价\n");

    while (head) {
        if (strcmp(head->info.staddress, start) == 0) {
            found = 1;
            printf("%s %s %s %s %s %04d %04d %d\n",
                   head->info.number, head->info.staddress, head->info.arraddress,
                   head->info.DATE, head->info.TYPE, head->info.stime,
                   head->info.atime, head->info.value);
        }
        head = head->next;
    }

    if (!found) {
        printf("未找到起点站为 '%s' 的航班信息。\n", start);
    }
}

// 查询条件:按终点站查询
void searchFlightsByDestination(node_list *head, const char *destination) {
    if (head == NULL) {
        printf("链表为空,没有航班信息!\n");
        return;
    }

    int found = 0;
    printf("\n终点站为 '%s' 的航班信息:\n", destination);
    printf("航班号 起点站 终点站 班期 机型 起飞时间 到达时间 票价\n");

    while (head) {
        if (strcmp(head->info.arraddress, destination) == 0) {
            found = 1;
            printf("%s %s %s %s %s %04d %04d %d\n",
                   head->info.number, head->info.staddress, head->info.arraddress,
                   head->info.DATE, head->info.TYPE, head->info.stime,
                   head->info.atime, head->info.value);
        }
        head = head->next;
    }

    if (!found) {
        printf("未找到终点站为 '%s' 的航班信息。\n", destination);
    }
}

// 查询条件:按班期查询
void searchFlightsByDay(node_list *head, const char *day) {
    if (head == NULL) {
        printf("链表为空,没有航班信息!\n");
        return;
    }

    int found = 0;
    printf("\n班期为 '%s' 的航班信息:\n", day);
    printf("航班号 起点站 终点站 班期 机型 起飞时间 到达时间 票价\n");

    while (head) {
        if (strcmp(head->info.DATE, day) == 0) {
            found = 1;
            printf("%s %s %s %s %s %04d %04d %d\n",
                   head->info.number, head->info.staddress, head->info.arraddress,
                   head->info.DATE, head->info.TYPE, head->info.stime,
                   head->info.atime, head->info.value);
        }
        head = head->next;
    }

    if (!found) {
        printf("未找到班期为 '%s' 的航班信息。\n", day);
    }
}

// 查询条件:按时间范围查询
void searchFlightsByTimeRange(node_list *head, int minTime, int maxTime) {
    if (head == NULL) {
        printf("链表为空,没有航班信息!\n");
        return;
    }

    int found = 0;
    printf("\n起飞时间范围 [%04d - %04d] 的航班信息:\n", minTime, maxTime);
    printf("航班号 起点站 终点站 班期 机型 起飞时间 到达时间 票价\n");

    while (head) {
        if (head->info.stime >= minTime && head->info.stime <= maxTime) {
            found = 1;
            printf("%s %s %s %s %s %04d %04d %d\n",
                   head->info.number, head->info.staddress, head->info.arraddress,
                   head->info.DATE, head->info.TYPE, head->info.stime,
                   head->info.atime, head->info.value);
        }
        head = head->next;
    }

    if (!found) {
        printf("未找到起飞时间范围 [%04d - %04d] 的航班信息。\n", minTime, maxTime);
    }
}

// 查询条件:自定义组合查询
void searchFlightsByCustomConditions(node_list *head) {
    char start[18] = "";
    char destination[18] = "";
    int minTime = -1, maxTime = -1;

    printf("请输入起点站(留空表示忽略此条件): ");
    fgets(start, sizeof(start), stdin);
    if (start[strlen(start) - 1] == '\n') start[strlen(start) - 1] = '\0';

    printf("请输入终点站(留空表示忽略此条件): ");
    fgets(destination, sizeof(destination), stdin);
    if (destination[strlen(destination) - 1] == '\n') destination[strlen(destination) - 1] = '\0';

    printf("请输入起飞时间范围(例如 0800 1000,输入 0 0 表示忽略此条件): ");
    scanf("%d %d", &minTime, &maxTime);
    getchar(); // 清除换行符

    printf("\n符合条件的航班信息:\n");
    printf("航班号 起点站 终点站 班期 机型 起飞时间 到达时间 票价\n");

    int found = 0;
    while (head) {
        int matches = 1;

        // 检查起点站
        if (strlen(start) > 0 && strcmp(head->info.staddress, start) != 0) {
            matches = 0;
        }

        // 检查终点站
        if (strlen(destination) > 0 && strcmp(head->info.arraddress, destination) != 0) {
            matches = 0;
        }

        // 检查起飞时间范围
        if (minTime > 0 && maxTime > 0 && 
            (head->info.stime < minTime || head->info.stime > maxTime)) {
            matches = 0;
        }

        if (matches) {
            found = 1;
            printf("%s %s %s %s %s %04d %04d %d\n",
                   head->info.number, head->info.staddress, head->info.arraddress,
                   head->info.DATE, head->info.TYPE, head->info.stime,
                   head->info.atime, head->info.value);
        }

        head = head->next;
    }

    if (!found) {
        printf("未找到符合条件的航班信息。\n");
    }
}
文件:flight.h
#ifndef FLIGHT_H
#define FLIGHT_H

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// 航班信息数据结构
typedef struct flight {
    char number[18];    // 航班号
    char staddress[18]; // 起点站
    char arraddress[18]; // 终点站
    char DATE[12];      // 班期
    char TYPE[8];       // 机型
    int stime;          // 起飞时间 (24小时制,例如 1330 表示 13:30)
    int atime;          // 到达时间
    int value;          // 票价
} datatype;

// 单向链表节点结构
typedef struct Node {
    datatype info;      // 航班信息
    struct Node *next;  // 指向下一个节点
} node_list;

// 函数声明
int clearInputBuffer();
void insertFlight(node_list **head);  //增
void displayFlights(node_list *head);  //遍历链表,查看数据
void searchFlight(node_list *head);  //查询数据
void deleteFlight(node_list **head, const char *flightNumber);  //删除数据
void modifyFlight(node_list *head, const char *flightNumber); //修改航班信息
void searchFlightsByPriceRange(node_list *head, int minPrice, int maxPrice); //按票价范围查询功能
void sortFlights(node_list **head, int mode); //排序功能 参数1:按起飞时间排序(升序);参数2:按票价排序(升序)

//多种查询条件
void searchFlightsByStart(node_list *head, const char *start);
void searchFlightsByDestination(node_list *head, const char *destination);
void searchFlightsByDay(node_list *head, const char *day);
void searchFlightsByTimeRange(node_list *head, int minTime, int maxTime);
void searchFlightsByCustomConditions(node_list *head);

int getValidInt(const char *prompt, int min, int max);
void getValidString(const char *prompt, char *dest, size_t maxLen);

#endif // FLIGHT_H
主函数:main.c
#include "flight.h"
#include <stdio.h>

int main() {
    node_list *head = NULL;  // 链表头指针
	char input[32];          // 用于读取用户输入
    int choice;

    while (1) {
        printf("\n航班查询系统菜单:\n");
        printf("1. 信息录入\n");
        printf("2. 信息显示\n");
        printf("3. 信息查询\n");
        printf("4. 删除航班信息\n");
		printf("5. 修改航班信息\n");
		printf("6. 按票价范围查询航班\n");
		printf("7. 航班信息排序\n");
		printf("8. 按起点站查询\n");
		printf("9. 按终点站查询\n");
		printf("10. 按班期查询\n");
		printf("11. 按时间范围查询\n");
		printf("12. 自定义组合查询\n");
		printf("13. 退出\n");
        printf("请输入您的选择: ");

		// 使用 fgets 读取用户输入
        if (fgets(input, sizeof(input), stdin)) {
            // 尝试解析为整数
            if (sscanf(input, "%d", &choice) != 1) {
                printf("无效输入,请输入数字。\n");
                continue; // 回到菜单
            }
        } else {
            printf("输入错误,请重试。\n");
            continue; // 回到菜单
        }

		 // 处理用户选择
        switch (choice) {
            case 1:
                insertFlight(&head);
                break;
            case 2:
                displayFlights(head);
                break;
            case 3:
                searchFlight(head);
                break;
			case 4: {
				char flightNumber[18];
				getValidString("请输入要删除的航班号: ", flightNumber, sizeof(flightNumber));
				deleteFlight(&head, flightNumber);
				break;
			}	
			case 5: {
				char flightNumber[18];
				getValidString("请输入要修改的航班号: ", flightNumber, sizeof(flightNumber));
				modifyFlight(head, flightNumber);
				break;
			}
			case 6: {
				 int minPrice, maxPrice;
				 printf("请输入票价范围(最低值 最高值): ");
				 if (fgets(input, sizeof(input), stdin)) {
                    if (sscanf(input, "%d %d", &minPrice, &maxPrice) == 2) {
                        searchFlightsByPriceRange(head, minPrice, maxPrice);
                    } else {
                        printf("无效输入,请输入两个数字。\n");
                    }
                }
                break;
			}
            case 7: {
				int mode;
				printf("请选择排序方式:\n");
                printf("1. 按起飞时间排序\n");
                printf("2. 按票价排序\n");
                printf("请输入选择: ");
				if (fgets(input, sizeof(input), stdin)) {
                    if (sscanf(input, "%d", &mode) == 1) {
                        if (mode == 1 || mode == 2) {
                            sortFlights(&head, mode);
                            displayFlights(head);
                        } else {
                            printf("无效选择,请输入 1 或 2。\n");
                        }
                    } else {
                        printf("无效输入,请输入数字。\n");
                    }
                }
                break;
			}
			case 8: {
				char start[18];
                getValidString("请输入起点站: ", start, sizeof(start));
                searchFlightsByStart(head, start);
                break;
			}
			case 9: {
				char destination[18];
                getValidString("请输入终点站: ", destination, sizeof(destination));
                searchFlightsByDestination(head, destination);
                break;
			}
			case 10: {
				char day[12];
                getValidString("请输入班期: ", day, sizeof(day));
                searchFlightsByDay(head, day);
                break;
			}
			case 11: {
				int minTime, maxTime;
                printf("请输入起飞时间范围(最低值 最高值): ");
                if (fgets(input, sizeof(input), stdin)) {
                    if (sscanf(input, "%d %d", &minTime, &maxTime) == 2) {
                        searchFlightsByTimeRange(head, minTime, maxTime);
                    } else {
                        printf("无效输入,请输入两个数字。\n");
                    }
                }
                break;
			}
			case 12:
				searchFlightsByCustomConditions(head);
				break;
			case 13:
                printf("退出系统。\n");
                return 0;
            default:
                printf("无效选择,请重新输入!\n");
        }
    }
    return 0;
}

方案二(双向链表实现)

文件:flight_cyc.c
#include "flight_cyc.h"

// 创建一个空的航班链表
FlightList* createFlightList() {
    FlightList *list = (FlightList *)malloc(sizeof(FlightList));
    if (!list) {
        printf("内存分配失败!\n");
        exit(1);
    }
    list->head = NULL;
    list->tail = NULL;
    return list;
}

// 创建一个新节点
Node* createNode(FlightInfo flight) {
    Node *newNode = (Node *)malloc(sizeof(Node));
    if (!newNode) {
        printf("内存分配失败!\n");
        exit(1);
    }
    newNode->info = flight;
    newNode->prev = NULL;
    newNode->next = NULL;
    return newNode;
}

// 插入航班信息:将新航班插入到链表尾部
void insertFlight(FlightList *list) {
    FlightInfo flight;

    // 输入航班信息
    printf("请输入航班号: ");
    scanf("%s", flight.number);
    printf("请输入起点站: ");
    scanf("%s", flight.staddress);
    printf("请输入终点站: ");
    scanf("%s", flight.arraddress);
    printf("请输入班期: ");
    scanf("%s", flight.DATE);
    printf("请输入机型: ");
    scanf("%s", flight.TYPE);
    printf("请输入起飞时间(24小时制,例如1330): ");
    scanf("%d", &flight.stime);
    printf("请输入到达时间(24小时制,例如1530): ");
    scanf("%d", &flight.atime);
    printf("请输入票价: ");
    scanf("%d", &flight.value);

    // 创建新节点
    Node *newNode = createNode(flight);

    // 插入到链表尾部
    if (list->tail == NULL) {
        list->head = newNode;
        list->tail = newNode;
    } else {
        newNode->prev = list->tail;
        list->tail->next = newNode;
        list->tail = newNode;
    }

    printf("航班信息插入成功!\n");
}

// 显示航班信息
void displayFlights(FlightList *list) {
    if (list->head == NULL) {
        printf("链表为空,没有航班信息!\n");
        return;
    }

    printf("\n航班信息如下:\n");
    printf("航班号 起点站 终点站 班期 机型 起飞时间 到达时间 票价\n");

    Node *current = list->head;
    while (current) {
        printf("%s %s %s %s %s %04d %04d %d\n",
               current->info.number, current->info.staddress, current->info.arraddress,
               current->info.DATE, current->info.TYPE, current->info.stime,
               current->info.atime, current->info.value);
        current = current->next;
    }
}

// 删除航班信息:根据航班号删除对应节点
void deleteFlight(FlightList *list, const char *flightNumber) {
    if (list->head == NULL) {
        printf("链表为空,没有航班信息可删除!\n");
        return;
    }

    Node *current = list->head;

    // 查找目标航班号
    while (current) {
        if (strcmp(current->info.number, flightNumber) == 0) {
            if (current->prev) {
                current->prev->next = current->next;
            } else {
                list->head = current->next;
            }

            if (current->next) {
                current->next->prev = current->prev;
            } else {
                list->tail = current->prev;
            }

            free(current);
            printf("航班号为 '%s' 的航班信息已删除。\n", flightNumber);
            return;
        }
        current = current->next;
    }

    printf("未找到航班号为 '%s' 的航班信息。\n", flightNumber);
}

//修改航班信息:根据航班号修改节点数据
void modifyFlight(FlightList *list, const char *flightNumber) {
    if (list->head == NULL) {
        printf("链表为空,没有航班可以修改!\n");
        return;
    }

    Node *current = list->head;

    // 查找目标航班号
    while (current) {
        if (strcmp(current->info.number, flightNumber) == 0) {
            printf("找到航班号为 '%s' 的航班信息。\n", flightNumber);

            printf("请输入新的起点站: ");
            scanf("%s", current->info.staddress);
            printf("请输入新的终点站: ");
            scanf("%s", current->info.arraddress);
            printf("请输入新的班期: ");
            scanf("%s", current->info.DATE);
            printf("请输入新的机型: ");
            scanf("%s", current->info.TYPE);
            printf("请输入新的起飞时间: ");
            scanf("%d", &current->info.stime);
            printf("请输入新的到达时间: ");
            scanf("%d", &current->info.atime);
            printf("请输入新的票价: ");
            scanf("%d", &current->info.value);

            printf("航班信息修改成功!\n");
            return;
        }
        current = current->next;
    }

    printf("未找到航班号为 '%s' 的航班信息。\n", flightNumber);
}
文件:flight_cyc.h
#ifndef FLIGHT_CYC_H
#define FLIGHT_CYC_H

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// 航班信息数据结构
typedef struct FlightInfo {
    char number[18];       // 航班号
    char staddress[18];    // 起点站
    char arraddress[18];   // 终点站
    char DATE[10];         // 班期
    char TYPE[12];         // 机型
    int stime;             // 起飞时间 (24小时制)
    int atime;             // 到达时间 (24小时制)
    int value;             // 票价
} FlightInfo;

// 双向链表节点结构
typedef struct Node {
    FlightInfo info;       // 航班信息
    struct Node *prev;     // 前驱指针
    struct Node *next;     // 后继指针
} Node;

// 链表管理结构
typedef struct FlightList {
    Node *head;            // 链表头指针
    Node *tail;            // 链表尾指针
} FlightList;

// 函数声明
FlightList* createFlightList();
Node* createNode(FlightInfo flight);
void insertFlight(FlightList *list);
void displayFlights(FlightList *list);
void deleteFlight(FlightList *list, const char *flightNumber);
void modifyFlight(FlightList *list, const char *flightNumber);
void searchFlight(FlightList *list);
void sortFlights(FlightList *list, int mode);
void searchFlightsByStart(FlightList *list, const char *start);
void searchFlightsByDestination(FlightList *list, const char *destination);
void searchFlightsByDay(FlightList *list, const char *day);
void searchFlightsByTimeRange(FlightList *list, int minTime, int maxTime);
void searchFlightsByCustomConditions(FlightList *list);

#endif // FLIGHT_H
文件:main_cyc.c
#include "flight_cyc.h"

int main() {
    FlightList *list = createFlightList();
    int choice;

    while (1) {
        printf("\n航班查询系统菜单:\n");
        printf("1. 信息录入\n");
        printf("2. 信息显示\n");
        printf("3. 信息查询\n");
        printf("4. 删除航班信息\n");
        printf("5. 修改航班信息\n");
        printf("6. 退出\n");
        printf("请输入您的选择: ");
        scanf("%d", &choice);

        switch (choice) {
            case 1:
                insertFlight(list);
                break;
            case 2:
                displayFlights(list);
                break;
            case 3:
                searchFlight(list);
                break;
            case 4: {
                char flightNumber[18];
                printf("请输入要删除的航班号: ");
                scanf("%s", flightNumber);
                deleteFlight(list, flightNumber);
                break;
            }
            case 5: {
                char flightNumber[18];
                printf("请输入要修改的航班号: ");
                scanf("%s", flightNumber);
                modifyFlight(list, flightNumber);
                break;
            }
            case 6:
                printf("退出系统。\n");
                return 0;
            default:
                printf("无效选择,请重新输入!\n");
        }
    }

    return 0;
}

方案三(内核链表实现)

文件:flight_kernel.c
#include "flight.h"
#include "list.h"

// 初始化链表头:LIST_HEAD 是内核链表提供的宏,用于声明和初始化一个链表头。
LIST_HEAD(flightList);

// 插入航班:在链表尾部插入新航班
void insertFlight(struct list_head *head) {
    // 创建新航班节点
    FlightInfo *newFlight = (FlightInfo *)malloc(sizeof(FlightInfo));
    if (!newFlight) {
        printf("内存分配失败!\n");
        return;
    }

    // 输入航班信息
    printf("请输入航班号: ");
    scanf("%s", newFlight->number);
    printf("请输入起点站: ");
    scanf("%s", newFlight->staddress);
    printf("请输入终点站: ");
    scanf("%s", newFlight->arraddress);
    printf("请输入班期: ");
    scanf("%s", newFlight->DATE);
    printf("请输入机型: ");
    scanf("%s", newFlight->TYPE);
    printf("请输入起飞时间(24小时制,例如1330): ");
    scanf("%d", &newFlight->stime);
    printf("请输入到达时间(24小时制,例如1530): ");
    scanf("%d", &newFlight->atime);
    printf("请输入票价: ");
    scanf("%d", &newFlight->value);

    // 添加到链表尾部
    list_add_tail(&newFlight->list, head);
    printf("航班信息插入成功!\n");
}

// 显示航班:遍历链表并显示所有航班
void displayFlights(struct list_head *head) {
    if (list_empty(head)) {
        printf("链表为空,没有航班信息!\n");
        return;
    }

    printf("\n航班信息如下:\n");
    printf("航班号 起点站 终点站 班期 机型 起飞时间 到达时间 票价\n");

    struct list_head *pos;
    FlightInfo *flight;

    // 遍历链表
    list_for_each(pos, head) {
        flight = list_entry(pos, FlightInfo, list);
        printf("%s %s %s %s %s %04d %04d %d\n",
               flight->number, flight->staddress, flight->arraddress,
               flight->DATE, flight->TYPE, flight->stime,
               flight->atime, flight->value);
    }
}

// 删除航班:根据航班号删除航班
void deleteFlight(struct list_head *head, const char *flightNumber) {
    if (list_empty(head)) {
        printf("链表为空,没有航班信息可删除!\n");
        return;
    }

    struct list_head *pos, *tmp;
    FlightInfo *flight;

    // 遍历链表并查找目标航班
    list_for_each_safe(pos, tmp, head) {
        flight = list_entry(pos, FlightInfo, list);
        if (strcmp(flight->number, flightNumber) == 0) {
            list_del(&flight->list); // 从链表中删除
            free(flight);            // 释放内存
            printf("航班号为 '%s' 的航班信息已删除。\n", flightNumber);
            return;
        }
    }

    printf("未找到航班号为 '%s' 的航班信息。\n", flightNumber);
}

// 修改航班:根据航班号修改航班信息
void modifyFlight(struct list_head *head, const char *flightNumber) {
    if (list_empty(head)) {
        printf("链表为空,没有航班可以修改!\n");
        return;
    }

    struct list_head *pos;
    FlightInfo *flight;

    // 遍历链表并查找目标航班
    list_for_each(pos, head) {
        flight = list_entry(pos, FlightInfo, list);
        if (strcmp(flight->number, flightNumber) == 0) {
            printf("找到航班号为 '%s' 的航班信息。\n", flightNumber);

            printf("请输入新的起点站: ");
            scanf("%s", flight->staddress);
            printf("请输入新的终点站: ");
            scanf("%s", flight->arraddress);
            printf("请输入新的班期: ");
            scanf("%s", flight->DATE);
            printf("请输入新的机型: ");
            scanf("%s", flight->TYPE);
            printf("请输入新的起飞时间: ");
            scanf("%d", &flight->stime);
            printf("请输入新的到达时间: ");
            scanf("%d", &flight->atime);
            printf("请输入新的票价: ");
            scanf("%d", &flight->value);

            printf("航班信息修改成功!\n");
            return;
        }
    }

    printf("未找到航班号为 '%s' 的航班信息。\n", flightNumber);
}
文件:flight_kernel.h
#ifndef FLIGHT_H
#define FLIGHT_H

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// 内核链表头文件
#include "list.h"

// 航班信息结构体
typedef struct FlightInfo {
    char number[18];       // 航班号
    char staddress[18];    // 起点站
    char arraddress[18];   // 终点站
    char DATE[10];         // 班期
    char TYPE[12];         // 机型
    int stime;             // 起飞时间
    int atime;             // 到达时间
    int value;             // 票价
    struct list_head list; // 内核链表节点
} FlightInfo;

void insertFlight(struct list_head *head);
void displayFlights(struct list_head *head);
void deleteFlight(struct list_head *head, const char *flightNumber);
void modifyFlight(struct list_head *head, const char *flightNumber);
void searchFlight(struct list_head *head);
void sortFlights(struct list_head *head, int mode);
void searchFlightsByStart(struct list_head *head, const char *start);
void searchFlightsByDestination(struct list_head *head, const char *destination);
void searchFlightsByDay(struct list_head *head, const char *day);
void searchFlightsByTimeRange(struct list_head *head, int minTime, int maxTime);
void searchFlightsByCustomConditions(struct list_head *head);

#endif // FLIGHT_H
文件:main_kernel.c
#include "flight.h"

int main() {
    int choice;

    while (1) {
        printf("\n航班查询系统菜单:\n");
        printf("1. 信息录入\n");
        printf("2. 信息显示\n");
        printf("3. 删除航班信息\n");
        printf("4. 修改航班信息\n");
        printf("5. 退出\n");
        printf("请输入您的选择: ");
        scanf("%d", &choice);

        switch (choice) {
            case 1:
                insertFlight(&flightList);
                break;
            case 2:
                displayFlights(&flightList);
                break;
            case 3: {
                char flightNumber[18];
                printf("请输入要删除的航班号: ");
                scanf("%s", flightNumber);
                deleteFlight(&flightList, flightNumber);
                break;
            }
            case 4: {
                char flightNumber[18];
                printf("请输入要修改的航班号: ");
                scanf("%s", flightNumber);
                modifyFlight(&flightList, flightNumber);
                break;
            }
            case 5:
                printf("退出系统。\n");
                return 0;
            default:
                printf("无效选择,请重新输入!\n");
        }
    }
    return 0;
}

以上代码经过测试,可以直接复制粘贴即可使用,希望该内容对您有帮助,感谢!

以上。仅供学习与分享交流,请勿用于商业用途!转载需提前说明。

我是一个十分热爱技术的程序员,希望这篇文章能够对您有帮助,也希望认识更多热爱程序开发的小伙伴。
感谢!


http://www.kler.cn/a/501014.html

相关文章:

  • Microsoft Sql Server 2019 函数理解
  • 企业级PHP异步RabbitMQ协程版客户端 2.0 正式发布
  • HTML5实现好看的端午节网页源码
  • elasticsearch中IK分词器
  • java通过ocr实现识别pdf中的文字
  • 快速实现一个快递物流管理系统:实时更新与状态追踪
  • 大数据学习(34)-mapreduce详解
  • 指令的修饰符
  • STM32F103ZET6战舰版单片机开发板PCB文件 电路原理图
  • 基类指针指向派生类对象,基类指针的首地址永远指向子类从基类继承的基类首地址
  • 【Hystrix-2】使用 Hystrix 实现服务容错与降级:Java 案例代码详解
  • 30_Redis哨兵模式
  • 未来十年:科技重塑生活的全景展望
  • 如何实现图片选择功能
  • 【Rust自学】11.10. 集成测试
  • js逆向说明
  • Python中定位包含特定文本信息的元素
  • 网络安全 | DevSecOps:将安全融入DevOps开发生命周期
  • 5. DL深度学习(Deep Learning)
  • 【2025 Rust学习 --- 15 迭代器的消耗】
  • [创业之路-242]:《华为双向指挥系统》-1-组织再造-企业普遍采用的5种组织结构形式
  • 苍穹外卖07——来单提醒和客户催单(涉及SpringTask、WebSocket协议、苍穹外卖跳过微信支付同时保证可以收到订单功能)
  • 排序算法(归并排序、快速排序)
  • Type-C双屏显示器方案
  • android studio使用Material Design中的ToolBar
  • CentOS安装Git