我正在尝试创建一个函数;"干净";列表:释放元素和s_struct(->next((由ftlstdelone函数完成(。我遇到了一个问题:顶部的代码不起作用,而第二个代码起作用;有什么想法吗?
非工作代码
void ft_lstclear(t_list **lst, void (*del)(void*))
{
t_list *temp;
t_list *begin;
if (!lst || !*lst || !del)
return ;
begin = *lst;
while (begin)
{
temp = (begin)->next;
ft_lstdelone((begin), del);
(begin) = temp;
}
}
工作代码
void ft_lstclear(t_list **lst, void (*del)(void*))
{
t_list *begin;
if (!lst || !*lst)
return ;
while (*lst != NULL)
{
begin = (*lst)->next;
ft_lstdelone((*lst), del);
(*lst) = begin;
}
}
By"不工作";,我想你指的是调用程序中的变量没有更新。
第二个片段基本上是这样结束的:
...
*lst = NULL; // When `temp` eventually becomes `NULL`.
相当于
begin = *lst;
...
begin = NULL; // When `temp` eventually becomes `NULL`.
*lst = begin;
你错过了最后一行。您的代码段从不更新调用程序中的变量*lst
。
固定:
void ft_lstclear( t_list **lst, void ( *del )( void* ) )
{
t_list *begin = *lst;
while ( begin )
{
t_list *temp = begin->next;
ft_lstdelone( begin, del );
begin = temp;
}
*lst = NULL;
}
要修复第一个示例,只需执行:
*lst = begin;
在函数的末尾。
你没有发布结构定义或del
函数,所以我不得不合成它们。
以下是重构后的代码〔partial〕:
#include <stdlib.h>
typedef struct list {
struct list *next;
char *data;
} t_list;
// ft_lstfree -- release any storage
void
ft_lstfree(void *nodep)
{
t_list *node = nodep;
free(node->data);
free(node);
}
void
ft_lstdelone(t_list *lst,void (*del)(void *))
{
del(lst);
}
void
ft_lstclear1(t_list **lst, void (*del)(void *))
{
t_list *temp;
t_list *begin;
if (!lst || !*lst || !del)
return;
begin = *lst;
while (begin) {
temp = (begin)->next;
ft_lstdelone((begin), del);
(begin) = temp;
}
// NOTE/FIX: we must pass this back to caller
#if 1
*lst = begin;
#endif
}
void
ft_lstclear2(t_list **lst, void (*del)(void *))
{
t_list *begin;
#if 0
if (!lst || !*lst)
return;
#else
if (!lst || !*lst || !del)
return;
#endif
while (*lst != NULL) {
begin = (*lst)->next;
ft_lstdelone((*lst), del);
(*lst) = begin;
}
}
int
main(void)
{
t_list *list = NULL;
ft_lstclear1(&list,ft_lstfree);
return 0;
}
在上面的代码中,我使用了cpp
条件词来表示旧代码与新代码:
#if 0
// old code
#else
// new code
#endif
#if 1
// new code
#endif
注意:这可以通过unifdef -k
运行文件来清除
但是,您所称的t_list
实际上是[链表]的节点。
您通过传递双指针来创建列表。
我更喜欢单独的列表结构和单独的节点结构:
- 您总是传递指向列表的指针。并且,不是指向更改列表的函数的双指针和指向不更改列表的功能的单指针(例如
ft_lstprint
( - 您可以轻松添加
tail
指针 - 从单链表转换为双链表的早期准备
以下是我的操作方法:
#include <stdlib.h>
typedef struct node {
struct node *next;
char *data;
} t_node;
typedef struct {
t_node *head;
t_node *tail;
} t_list;
// ft_nodefree -- release any storage
void
ft_nodefree(void *nodep)
{
t_node *node = nodep;
free(node->data);
free(node);
}
void
ft_nodedelone(t_node *node,void (*del)(void *))
{
del(node);
}
void
ft_lstclear1(t_list *lst, void (*del)(void *))
{
t_node *temp;
t_node *begin;
// no list
if (lst == NULL)
return;
// no delete function
if (del == NULL)
return;
for (begin = lst->head; begin != NULL; begin = temp) {
temp = begin->next;
ft_nodedelone(begin,del);
}
lst->head = begin;
lst->tail = begin;
}
int
main(void)
{
t_list list = { NULL };
ft_lstclear1(&list,ft_nodefree);
return 0;
}
更新:
通过执行lst=begin,我只是在函数的末尾说"好的,让我们现在谈谈我的清单的末尾";,因为begin已经从begin=*lst移动到begin->下一个->下一个********************************void ft_lstdelone(t_list*lst,void(*del((void(({if(!lst(return;if((*delVicordeLeusse
我不确定我是否理解你。在代码中,您最终会得到一个空的列表。不再有结束。调用方的列表指针将以NULL
结束。
调用函数ft_lstclear
有点用词不当。根据它的作用,它可能被更好地称为ft_lstdestroy
。
对于您的代码来说,这可能是一个任意的区别,但是,对于一个单独的列表结构(如我最后的示例中所示(,我们需要一个独立的函数:
void
ft_lstdestroy(t_list *lst, void (*del)(void *))
{
ft_lstclear1(lst,del);
free(lst);
}