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

news/2025/1/10 10:33:20 标签: 数据结构, 链表, 算法, c语言, 嵌入式软件
目标:航班查询系统:能够在 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.niftyadmin.cn/n/5818524.html

相关文章

【应用篇】09.实现简易的Shell命令行解释器

一、shell和bash的关系 shell是命令解释器&#xff0c;它接收用户的命令并将其传递给内核去执行。bash,即GNU Bourne-Again Shell&#xff0c;是shell的一种实现方式&#xff0c;也是大多数linux系统下默认的shell。 bash的原理 大多数的指令进程&#xff08;除了内建命令&…

【Cocos TypeScript 零基础 6.1】

目录 敌机敌机通用逻辑制作动画制作另外的敌机制作自动生成敌机整理自己实验写的 敌机 创建一个空节点 (绑定敌机逻辑,敌机相关都可以存在此节点下,编程更有逻辑,便于后续维护)制作 prefab制作销毁动画制作第二个敌机敌机0自动生成 敌机通用逻辑 老是创建了2个空节点? 父节…

物联网开发 的开发语言建议

对于物联网开发&#xff0c;选择合适的编程语言取决于具体的项目需求、硬件平台以及开发团队的技能。以下是几种常用的物联网开发语言及其适用场景&#xff0c;特别考虑到您当前的工作空间中包含 JavaScript 和 Vue 等技术栈&#xff1a; JavaScript (Node.js) 优点&#xff1a…

TaskBuilder前端组件简介

3.3.3.1前端组件的分类 前端页面是由众多组件层层嵌套构成的&#xff0c;这些组件是任讯信息自主研发的一套前端UI组件&#xff0c;称为tfp组件&#xff0c;这些组件根据其功能和特点又分为几大类&#xff0c;它们的继承关系如下图所示&#xff1a; 从图中可知&#xff0c;所…

多活架构的实现原理与应用场景解析

一、多活架构为何如此重要? 企业的业务运营与各类线上服务紧密相连,从日常的购物消费、社交娱乐,到金融交易、在线教育等关键领域,无一不依赖于稳定可靠的信息系统。多活架构的重要性愈发凸显,它宛如一位忠诚的卫士,为业务的平稳运行保驾护航。 回想那些因系统故障引发的…

【ROS2】☆ launch之Python

☆重点 ROS1和ROS2其中一个很大区别之一就是launch的编写方式。在ROS1中采用xml格式编写launch&#xff0c;而ROS2保留了XML 格式launch&#xff0c;还另外引入了Python和YAML 编写方式。选择哪种编写取决于每位开发人员的爱好&#xff0c;但是ROS2官方推荐使用Python方式编写…

Vscode 如何使用GitHub Copilot

一、“GitHub Copilot”进行登录 前提必须有github账号&#xff0c;如果没有就注册一个&#xff1b; 系统会提示您输入 GitHub 凭据。单击“登录 GitHub”&#xff0c;然后单击“允许”并输入您的 GitHub 凭据。 登录成功后&#xff1a; 二、 GitHub Copilot功能 1、预测代码 …

【技术分享】如何利用rdesktop实现Linux远程Windows桌面高效办公

文章目录 前言1. Windows 开启远程桌面2. Linux安装rdesktop工具3. Win安装Cpolar工具4. 配置远程桌面地址5. 远程桌面连接测试6. 设置固定远程地址7. 固定地址连接测试 前言 随着技术的飞速发展&#xff0c;我们有了越来越多的方法来实现远程办公。今天我要给大家介绍一个特别…