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

C语言创建存储字符的双向链表时节点赋值无效问题求助

问题分析与修复方案

看起来你的双向链表创建和填充过程中有两个关键问题,导致节点字符无法正确存储,同时链表的双向指针结构也完全混乱了。让我们一步步拆解并解决问题:

1. crearLista中的双向指针赋值逻辑错误

这是最核心的问题——你在构建链表时,prev指针的赋值顺序完全搞反了,导致节点的prev没有正确指向前一个节点,甚至出现了自引用的情况,直接破坏了双向链表的结构。

看你原来的循环代码:

if(i + 1 != num_nodos) {
    actual->next = (struct nodo*)(malloc)(sizeof(struct nodo));
    actual->prev = prev;
    actual = actual->next;
    prev = actual; // 这里是错误根源!你把新节点赋值给了prev,而非前一个节点
}

举个例子,当创建第二个节点时:

  • 你把prev设置成了刚创建的第二个节点,导致下一次循环中,第三个节点的prev会错误地指向第二个节点,而第二个节点自己的prev也会指向自己,完全打乱了链表的双向关联。

修正后的crearLista循环部分

我们需要调整顺序:先给当前节点设置正确的prev,再把当前节点保存为下一个节点的prev,最后移动到下一个节点:

struct listaDoble crearLista(int num_nodos) {
    struct listaDoble *result = (struct listaDoble *)malloc(sizeof(struct listaDoble));
    if(num_nodos > 0) {
        result->first = (struct nodo *)malloc(sizeof(struct nodo));
        struct nodo *actual = result->first;
        struct nodo *prev = NULL;
        struct nodo *last;
        for(int i = 0; i < num_nodos; i++) {
            actual->prev = prev; // 先给当前节点绑定正确的前驱指针
            if(i + 1 != num_nodos) {
                actual->next = malloc(sizeof(struct nodo));
                prev = actual; // 将当前节点保存为下一个节点的前驱
                actual = actual->next;
            } else {
                actual->next = NULL;
                last = actual;
            }
        }
        result->last = last;
        result->size = num_nodos;
    } else {
        result->first = NULL;
        result->last = NULL;
        result->size = 0;
    }
    return *result;
}

2. crearMiADN中的冗余判断与效率问题

你的crearMiADN函数里有两个完全不必要的判断:

  • miDni[i] != '\0':你已经用strlen(miDni)作为循环上限,循环只会遍历到字符串的有效字符,不会碰到'\0'
  • miDni[i] != EOF:EOF是文件读取的结束标记,内存中的字符串不会包含这个值,完全不需要判断

另外,把strlen(miDni)放在循环条件里会导致每次循环都重新计算字符串长度(虽然编译器可能优化,但提前存起来更稳妥)。修正后的crearMiADN:

struct listaDoble crearMiADN() {
    char miDni[] = "1234";
    int len = strlen(miDni);
    struct listaDoble listado = crearLista(len);
    struct nodo *actual = listado.first;
    for(int i = 0; i < len; i++) {
        actual->tuNombre[0] = miDni[i];
        actual->tuNombre[1] = '\0';
        actual = actual->next;
    }
    return listado;
}

额外优化:解决内存泄漏问题

注意你的crearLista函数存在内存泄漏:你malloc了一个struct listaDoble,却返回它的副本,原来malloc的内存永远无法被释放。如果要解决这个问题,可以让crearLista返回指针类型:

struct listaDoble *crearLista(int num_nodos) {
    struct listaDoble *result = (struct listaDoble *)malloc(sizeof(struct listaDoble));
    if(num_nodos > 0) {
        // 保持修正后的循环逻辑不变
    } else {
        result->first = NULL;
        result->last = NULL;
        result->size = 0;
    }
    return result;
}

对应的crearMiADN和调用代码也要同步修改:

struct listaDoble *crearMiADN() {
    char miDni[] = "1234";
    int len = strlen(miDni);
    struct listaDoble *listado = crearLista(len);
    struct nodo *actual = listado->first;
    for(int i = 0; i < len; i++) {
        actual->tuNombre[0] = miDni[i];
        actual->tuNombre[1] = '\0';
        actual = actual->next;
    }
    return listado;
}

// 调用示例
struct listaDoble *dni = crearMiADN();
// 使用完记得手动释放整个链表和结构体内存

按照上面的修正,你的双向链表应该能正确存储每个字符,双向指针也能正常指向前后节点了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 16:07:27