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

链表中char*类型字段数据被覆盖问题的技术咨询

解决链表中char*字段被后续输入覆盖的问题

嘿,这个问题我太熟了!你这是踩了C语言指针和内存管理的经典坑——所有链表节点的data指针都指向了同一块内存区域,每次输入新字符串都会覆盖这块内存的内容,自然所有节点最后显示的都是最后输入的内容。

先看看你大概率写错的代码示例

你可能是像下面这样写的:

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

typedef struct Node {
    char* data;
    struct Node* next;
} Node;

Node* createNode(char* input) {
    Node* newNode = (Node*)malloc(sizeof(Node));
    // 错误核心:直接把输入缓冲区的指针赋值给data
    newNode->data = input; 
    newNode->next = NULL;
    return newNode;
}

int main() {
    Node* head = NULL;
    char buf[50]; // 所有输入都存在这个栈缓冲区里
    for (int i = 0; i < 3; i++) {
        printf("输入姓名:");
        scanf("%s", buf);
        Node* newNode = createNode(buf);
        // 头插法添加节点
        newNode->next = head;
        head = newNode;
    }
    // 遍历链表
    Node* p = head;
    while (p != NULL) {
        printf("%s ", p->data);
        p = p->next;
    }
    return 0;
}

运行这段代码的话,你会发现最后输出的全是第三次输入的字符串——因为三个节点的data都指向了buf数组的地址,每次输入都会覆盖buf里的内容,所有节点自然跟着变。

正确的解决思路:给每个节点分配独立的字符串内存

我们需要为每个节点的data单独在堆上申请内存,把输入的字符串拷贝进去,而不是直接复用同一个缓冲区的指针。

方法一:用strdup快速实现(最省心)

strdup函数会自动计算字符串长度、分配足够的堆内存,然后把字符串拷贝进去,非常方便:

Node* createNode(char* input) {
    Node* newNode = (Node*)malloc(sizeof(Node));
    if (newNode == NULL) return NULL;
    
    // 分配内存并拷贝字符串
    newNode->data = strdup(input); 
    newNode->next = NULL;
    
    // 检查内存分配是否成功
    if (newNode->data == NULL) {
        free(newNode);
        return NULL;
    }
    return newNode;
}

方法二:手动用malloc+strcpy实现(兼容性更强)

如果你的环境不支持strdup(比如某些嵌入式场景),可以手动分配内存再拷贝:

Node* createNode(char* input) {
    Node* newNode = (Node*)malloc(sizeof(Node));
    if (newNode == NULL) return NULL;
    
    // 计算字符串长度+1(要存字符串结束符'\0')
    int strLen = strlen(input) + 1;
    newNode->data = (char*)malloc(strLen);
    if (newNode->data == NULL) {
        // 内存分配失败,要先释放节点内存,避免内存泄漏
        free(newNode);
        return NULL;
    }
    
    // 把输入字符串拷贝到新分配的内存里
    strcpy(newNode->data, input);
    newNode->next = NULL;
    return newNode;
}

最后别忘了清理内存!

链表使用完后,一定要记得逐个节点释放内存,先释放data指向的字符串内存,再释放节点本身:

void freeLinkedList(Node* head) {
    Node* tempNode;
    while (head != NULL) {
        tempNode = head;
        head = head->next;
        // 先释放字符串内存
        free(tempNode->data);
        // 再释放节点本身
        free(tempNode);
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 07:41:17