基于void结构体的链表如何实现节点链接?附示例代码
实现基于void*的链表节点链接
我来帮你搞定这个问题——用void实现链表节点链接的核心难点,就是如何通过无类型指针访问节点的next成员,毕竟void本身没法直接解引用结构体成员。结合你给出的代码片段,我给你补全实现并解释清楚思路:
先明确你的链表节点结构
首先我假设你已经定义了struct tmpList(毕竟你的addToken2TmpList里在用它),它应该长这样:
struct tmpList { char *data; struct tmpList *next; };
你的cocatenateNodes用void做参数,本质是想做一个通用的节点拼接函数,但要让它能工作,我们得先明确:传入的void指针,实际指向的都是struct tmpList类型的节点(或者其他有相同next成员结构的节点)。
补全并修正cocatenateNodes函数
你写了函数的开头,下面是完整的可运行实现:
void *cocatenateNodes(void *node, void *headNode) { // 把void*转成具体的节点类型指针,才能访问next成员 struct tmpList *tmpHead = (struct tmpList *)headNode; struct tmpList *newNode = (struct tmpList *)node; if (headNode == NULL) { // 链表为空的话,新节点直接当表头 return node; } else { // 遍历到链表的最后一个节点 while (tmpHead->next != NULL) { tmpHead = tmpHead->next; } // 把新节点挂到链表尾部 tmpHead->next = newNode; // 返回原来的表头(因为表头没变化) return headNode; } }
这里的关键是类型转换:把void*转成struct tmpList*,这样就能正常访问next指针了。
进阶:做真正通用的void*链表(不依赖具体结构体)
如果你想让cocatenateNodes完全不绑定struct tmpList,可以用“嵌入通用节点头部”的技巧,让它能处理任意链表节点:
// 定义一个通用的链表节点头部,只包含next指针 struct GenericListNode { struct GenericListNode *next; }; // 你的具体节点结构体,把通用头部嵌在最前面 struct tmpList { struct GenericListNode node; char *data; };
然后cocatenateNodes可以改成完全通用的版本:
void *cocatenateNodes(void *node, void *headNode) { struct GenericListNode *genNode = (struct GenericListNode *)node; struct GenericListNode *genHead = (struct GenericListNode *)headNode; genNode->next = NULL; // 确保新节点的next是空的,避免乱指 if (genHead == NULL) { return node; } // 遍历到链表尾部 while (genHead->next != NULL) { genHead = genHead->next; } genHead->next = genNode; return headNode; }
这种方式下,任何嵌入了struct GenericListNode的结构体,都可以用这个函数来拼接,真正实现了通用的链表操作。
对你现有代码的小提醒
在你的addToken2TmpList里,直接把token赋值给tokenNode->data可能会有问题——如果token是栈上的临时字符串,函数返回后这个指针就变成野指针了。建议用strdup复制一份字符串:
struct tmpList *addToken2TmpList(struct tmpList *headTmpList, char *token) { struct tmpList *tokenNode = (struct tmpList *)malloc(sizeof(struct tmpList)); tokenNode->data = strdup(token); // 复制字符串到堆上,避免野指针 tokenNode->next = NULL; return (struct tmpList *)cocatenateNodes(tokenNode, headTmpList); }
记得最后释放链表的时候,要先释放data指向的内存,再释放节点本身哦。
内容的提问来源于stack exchange,提问作者FelX3
相关产品推荐
相关产品推荐

