You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在含动态char*的Passport结构体程序中引入LinkedList

用链表重构你的护照管理程序

嗨,我来帮你把现有的护照管理程序改成基于链表的实现!链表的好处是不用预先限制护照的数量(比如原来的MAX_NUM_PASSPORTS),可以动态添加任意多的条目,灵活性更高。下面是具体的改造步骤和完整代码:

第一步:定义链表节点结构

我们需要一个链表节点结构体,它要包含你的Passport数据,以及一个指向下一个节点的指针:

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

// 先定义Passport结构体(和你原来的一致,优化了变量名)
typedef struct passport {
    char *firstName;  // 把冗长的变量名简化,提升可读性
    unsigned long long int id;
} Passport;

// 定义链表节点:包含Passport数据和下一个节点的指针
typedef struct linked_list_node {
    Passport data;
    struct linked_list_node *next;
} LinkedListNode;

第二步:修改主函数逻辑

原来的代码用动态数组存储多个Passport,现在我们改成用链表头指针来管理,每次新增一个护照就创建一个新节点,加到链表的末尾:

完整修改后的代码

#define MAX_BUFF_SIZE 100  // 补上你原来缺失的缓冲区大小定义

// 实现一个简单的get_input函数(替代你原代码中的自定义函数)
void get_input(char *buffer, int max_len) {
    fgets(buffer, max_len, stdin);
    // 移除fgets读取到的换行符
    buffer[strcspn(buffer, "\n")] = '\0';
}

int main() {
    LinkedListNode *head = NULL;  // 链表头指针,初始为空
    LinkedListNode *tail = NULL;  // 链表尾指针,方便快速添加新节点
    int passport_count = 0;  // 用来生成递增的护照ID

    // 这里暂时保留原来的5个限制,你可以改成无限循环直到用户输入终止指令
    while (passport_count < 5) {
        passport_count++;

        // 1. 为新链表节点分配内存
        LinkedListNode *new_node = (LinkedListNode*)malloc(sizeof(LinkedListNode));
        if (new_node == NULL) {
            fprintf(stderr, "Failed to allocate node memory!\n");
            exit(1);
        }

        // 2. 设置护照ID
        new_node->data.id = passport_count;

        // 3. 获取用户输入的名字
        char *firstname = (char*)malloc(MAX_BUFF_SIZE * sizeof(char));
        if (firstname == NULL) {
            fprintf(stderr, "Failed to allocate input buffer!\n");
            exit(2);
        }
        printf("Please enter first name of the owner for Passport with ID=%d: \n", passport_count);
        get_input(firstname, MAX_BUFF_SIZE - 1);

        // 4. 为名字分配内存并复制内容
        new_node->data.firstName = (char*)malloc(strlen(firstname) + 1);
        if (new_node->data.firstName == NULL) {
            fprintf(stderr, "Passport Name Malloc Failed!\n");
            free(firstname);
            free(new_node);
            exit(3);
        }
        strcpy(new_node->data.firstName, firstname);
        free(firstname);  // 临时输入缓冲区用完即释放

        // 5. 将新节点添加到链表末尾
        new_node->next = NULL;
        if (head == NULL) {
            // 链表为空时,头和尾都指向新节点
            head = new_node;
            tail = new_node;
        } else {
            // 链表不为空时,尾节点的next指向新节点,更新尾指针
            tail->next = new_node;
            tail = new_node;
        }
    }

    // 遍历链表打印所有护照信息
    printf("\n--- All Passport Information ---\n");
    LinkedListNode *current = head;
    while (current != NULL) {
        printf("Passport id:%llu has been successfully renewed. It belongs to %s\n",
               current->data.id, current->data.firstName);
        current = current->next;
    }

    // 重要:释放链表所有内存,避免内存泄漏
    current = head;
    while (current != NULL) {
        LinkedListNode *temp = current;
        free(current->data.firstName);  // 先释放名字的动态内存
        current = current->next;
        free(temp);  // 再释放链表节点本身
    }

    return 0;
}

关键改动说明

  • 链表节点封装:新增LinkedListNode结构体,把Passport数据和下一个节点的指针绑定,实现动态串联多个条目。
  • 高效节点添加:用头指针head和尾指针tail配合,新增节点时直接加到链表末尾,时间复杂度为O(1)。
  • 内存管理优化:添加了完整的内存释放逻辑,修复了原代码中未释放内存的问题;临时输入缓冲区用完后及时释放。
  • 修复原代码问题:修正了原代码中循环变量大写I的错误,补上了缺失的MAX_BUFF_SIZE定义。
  • 可读性提升:简化了变量名,让代码更易读。

扩展建议

如果你想让程序更灵活,可以把循环条件改成让用户选择是否继续添加护照(比如输入q退出),这样就完全摆脱固定数量的限制,这也是链表相对于静态/动态数组最大的优势之一。

内容的提问来源于stack exchange,提问作者user14072798

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 20:12:49