我将代码分为两个文件,.h和.c函数名称的定义在.h中,函数的实现在.c 中
在我的主文件中:
struct no
{
tipo info;
struct no *ant;
struct no *nxt;
};
struct list
{
no_t *head;
no_t *tail;
int size;
};
这在我的.h文件中:
typedef struct no no_t;
typedef struct list list_t;
typedef int tipo;
再次在主中
void list_destroy(list_t **l)
{
if ((*l) == NULL || l == NULL)
return;
if (!(*l)->head)
return;
no_t *next = (*l)->head; //create two variables for iterating through the list
no_t *aux; //set aux to free
while (next->nxt) //the pointer for next node, in the last node, is NULL
{ //by that I believe I'm able to iterate through all nodes
aux = next;
free(aux);
next = next->nxt;
}
free(*l);
(*l) = NULL;
}
是一个非常简单的代码,但我看不出我在这里遗漏了什么
next = next->nxt;
对于编译器来说,这毫无区别。但对于某些人,甚至是你来说,很难阅读next = next->nxt
的内容。还是不是?
一个可能的替代方案(使用您的代码(和一个简短的测试程序
so-list.h
#include <stdio.h>
#include <stdlib.h>
typedef int Tipo;
typedef struct st_no
{
Tipo info;
struct st_no* prev;
struct st_no* next;
} Node;
typedef struct
{
Node* head;
Node* tail;
unsigned size;
} List;
List* list_create();
List* list_destroy(List*);
int list_insert(const Tipo, List*);
- 在标题中,只有typedefs和函数原型
- 只有第一个大写字母的名称在此处保留给已定义的名称。一个有用的惯例
- 而不是使用CCD_ 2通常更清楚的是只返回指向列表的指针。通过这种方式,可以更容易地使指针无效,并创建链接列表,如
List* my_list = list_create();
my_list = list_destroy(my_list);
当使用**
时,不需要像您需要的那样测试两个间接级别
main.c:一个最低限度的测试集
#include "so-list.h"
int main(void)
{
List* my_list = list_create();
my_list = list_destroy(my_list);
my_list = list_create();
for (int i = 1; i <= 5; i += 1)
printf("insert(%d,list) returned %dn",
i, list_insert(i,my_list)
);
my_list = list_destroy(my_list);
my_list = list_create();
for (int i = 11; i <= 15; i += 1)
printf("insert(%d,list) returned %dn",
i, list_insert(i, my_list)
);
my_list = list_destroy(my_list);
return 0;
}
创建一个列表,然后销毁
使用相同的指针,创建一个列表,插入值1到5,然后删除该列表。
使用相同的指针,创建一个列表,插入值11到15,然后再次删除该列表。
输出
List created!
List deleted!
List created!
insert(1,list) returned 1
insert(2,list) returned 2
insert(3,list) returned 3
insert(4,list) returned 4
insert(5,list) returned 5
1 deleted
2 deleted
3 deleted
4 deleted
5 deleted
List deleted!
List created!
insert(11,list) returned 1
insert(12,list) returned 2
insert(13,list) returned 3
insert(14,list) returned 4
insert(15,list) returned 5
11 deleted
12 deleted
13 deleted
14 deleted
15 deleted
List deleted!
destroy_list()
的代码
List* list_destroy(List* l)
{
if (l == NULL) return NULL;
// delete the ´size´ nodes, 1 by 1
Node* p = NULL;
for (unsigned i = 0; i < l->size; i += 1)
{
p = l->head->next; // save pointer
printf("%d deletedn", l->head->info); // just for the demo
free(l->head); // free head
l->head = p; // advance head
}
free(l); // free list
printf("List deleted!nn"); // just for the demo
return NULL;
}
此函数总是返回NULL
,作为在与pList = destroy_list(pList);
相同的表达式中使调用方中的指针无效的一种方式
这与您编写的代码有些不同。我们只是一个接一个地删除元素,因为我们知道列表中有size
元素。循环中使用本地指针来保存下一个元素的地址。它似乎更容易阅读。
so list.c的完整代码
#include "so-list.h"
List* list_create()
{
List* one = (List*)malloc(sizeof(List));
one->head = NULL;
one->tail = NULL;
one->size = 0;
printf("List created!n");
return one;
}
List* list_destroy(List* l)
{
if (l == NULL) return NULL;
// delete the ´size´ nodes, 1 by 1
Node* p = NULL;
for (unsigned i = 0; i < l->size; i += 1)
{
p = l->head->next; // save pointer
printf("%d deletedn", l->head->info);
free(l->head); // free head
l->head = p; // advance head
}
free(l); // free list
printf("List deleted!nn");
return NULL;
}
// just for test, insert ´info´ at the end, returns size
int list_insert(const Tipo info, List* l)
{
// insert node at the end, just for test
Node* one = (Node*)malloc(sizeof(Node));
one->info = info;
one->next = NULL;
one->prev = l->tail;
if (l->size == 0)
l->head = one; // 1st node
else
l->tail->next = one;
l->tail = one;
l->size += 1;
return l->size;
};
关于您的list_destroy((版本
那里的逻辑有点错误,但错误在另一个答案中得到了很好的描述。在这种情况下,我建议不要使用**
。但这是可以肯定的。
所以列出.c
这只是运行测试的最低要求
#include "so-list.h"
List* list_create()
{
List* one = (List*)malloc(sizeof(List));
one->head = NULL;
one->tail = NULL;
one->size = 0;
printf("List created!n");
return one;
}
List* list_destroy(List* l)
{
if (l == NULL) return NULL;
// delete the ´size´ nodes, 1 by 1
Node* p = NULL;
for (unsigned i = 0; i < l->size; i += 1)
{
p = l->head->next; // save pointer
printf("%d deletedn", l->head->info);
free(l->head); // free head
l->head = p; // advance head
}
free(l); // free list
printf("List deleted!nn");
return NULL;
}
// just for test, insert ´info´ at the end, returns size
int list_insert(const Tipo info, List* l)
{
// insert node at the end, just for test
Node* one = (Node*)malloc(sizeof(Node));
one->info = info;
one->next = NULL;
one->prev = l->tail;
if (l->size == 0)
l->head = one; // 1st node
else
l->tail->next = one;
l->tail = one;
l->size += 1;
return l->size;
};
这有一个问题
no_t *next = (*l)->head;
no_t *aux;
while (next->nxt)
{
aux = next; // aux point to the same object as next
free(aux); // free aux, which is the same as next
next = next->nxt; // deference next, which just got free'd. OOPS!
}
在aux上调用free
,这也是对next
的别名。然后你试着尊重next->nxt
。next
在之前的声明中刚刚发布。此外,正如我在评论中指出的,您正在泄露列表中的最后一个元素。
固定:
no_t* aux = (*l)->head;
while (aux)
{
no_t* next = aux->nxt;
free(aux);
aux = next;
}
您应该查看您的"免费的";以及您的";下一个->nxt";声明。愿它能帮你解决问题。