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

C语言向链表末尾添加节点后打印仅重复输出最后一个节点问题求助

问题排查

  • 核心触发打印全是最后一个节点的原因:newNode->url = url 仅拷贝了指针地址,没有拷贝字符串内容。如果你调用add_page时,每次都是复用同一个字符数组存储传入的url,所有节点的url指针都会指向同一块内存,后续内存内容被覆盖后,所有节点读取到的url都会是最后一次写入的值。
  • 去重逻辑错误:用==比较字符串,实际对比的是两个指针的内存地址,不是字符串本身的内容,无法正确识别相同内容的不同url指针。
  • 内存泄漏:所有return语句后的free(newNode)都是死代码,永远不会执行,遇到重复url时申请的newNode内存会直接泄漏。
  • 去重逻辑遗漏最后一个节点:循环终止条件是curr->next != NULL,循环只会遍历到倒数第二个节点,不会校验链表最后一个节点的url是否和新节点重复。

修复后代码

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

struct page *add_page (struct page *web, char *url){
    // 先做重复校验,确认不存在再申请内存,避免提前申请导致泄漏
    struct page *curr = web;
    while(curr != NULL){
        // 用strcmp比较字符串内容
        if(strcmp(url, curr->url) == 0){
            printf("URL \"%s\" is already on the web\n", url);
            return web;
        }
        curr = curr->next;
    }

    // 确认无重复再申请新节点
    struct page *newNode = (struct page*) malloc(sizeof(struct page));
    if (newNode == NULL) {
        perror("malloc failed");
        return web;
    }
    // 申请新内存存储url内容,避免共用同一块地址
    newNode->url = (char*)malloc(strlen(url) + 1);
    if (newNode->url == NULL) {
        perror("malloc url failed");
        free(newNode);
        return web;
    }
    strcpy(newNode->url, url);
    newNode->next = NULL;
    
    if(web == NULL){
        web = newNode;
    }else{
        curr = web;
        while(curr->next != NULL){
            curr = curr->next;
        }
        curr->next = newNode;
    }
    return web;
}

额外注意点

  • 后续销毁链表时,需要先释放每个节点的url指针,再释放节点本身,避免二次内存泄漏。
  • 如果你的业务场景可以保证传入的url指针指向的内存永远不会被修改、且生命周期和链表完全一致,可以省去单独申请内存存储url的步骤,只需把字符串比较逻辑替换为strcmp即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 05:15:07