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
相关产品推荐
相关产品推荐

