我必须使用链接列表(因此指针)在c中打印一个集合的列表。但是,当我删除列表的第一个元素并尝试打印列表时,它只会在彼此之下显示很多地址。有什么问题的建议吗?谢谢!
删除功能:
int delete(set_element* src, int elem){
if (src==NULL) {
fputs("The list is empty.\n", stderr);
}
set_element* currElement;
set_element* prevElement=NULL;
for (currElement=src; currElement!=NULL; prevElement=currElement, currElement=currElement->next) {
if(currElement->value==elem) {
if(prevElement==NULL){
printf("Head is deleted\n");
if(currElement->next!=NULL){
*src = *currElement->next;
} else {
destroy(currElement);
}
} else {
prevElement->next = currElement->next;
}
// free(currElement);
break;
}
}
return 1;
}
void print(set_element* start)
{
set_element *pt = start;
while(pt != NULL)
{
printf("%d, ",pt->value);
pt = pt->next;
}
}
答案 0 :(得分:0)
警告:此答案包含推断代码。
C中的典型链接列表看起来像这样:
typedef struct _list List;
typedef struct _list_node ListNode;
struct _list {
ListNode *head;
}
struct _list_node {
void *payload;
ListNode *next;
}
为了正确删除列表中的第一个元素,需要执行以下序列:
List *aList; // contains a list
if (aList->head)
ListNode *newHead = aList->head->next;
delete_payload(aList->head->payload); // Depending on what the payload actually is
free(aList->head);
aList->head = newHead;
此处的操作顺序非常重要!试图在没有先释放旧值的情况下移动磁头将导致内存泄漏;并且在没有首先获得新头部的正确值的情况下释放旧头部会产生未定义的行为。
附录:有时,上述代码的_list
部分将被完全省略,将列表和列表节点保持为相同;但是从你描述的症状来看,我猜这可能不是这种情况。
然而,在这种情况下,步骤基本上保持相同,但没有aList->
位。
修改强>
现在我看到了你的代码,我可以给你一个更完整的答案。
您的代码中的一个关键问题是它遍布整个地方。但是,这里有一行特别糟糕:
*src = *currElement->next;
这不起作用,并且是导致您崩溃的原因。
在您的情况下,解决方案是以某种方式容器包装链表,如上面的struct _list构造;或者重写现有代码以接受指向set元素的指针,以便您可以将指针传递给set元素(这是你想要做的)。
就性能而言,这两种解决方案可能很接近,因此没有任何可能性,但使用包装列表结构有助于沟通意图。它还有助于防止其他指向列表的指针因头部删除而变得乱码,所以就是这样。
答案 1 :(得分:0)
当您删除不属于您的指针(实际上是一块内存)时,通常会发生这种情况。仔细检查你的函数,确保你没有释放你已经释放的同一个指针,或释放你没有用“malloc”创建的指针。
答案 2 :(得分:0)
如果列表指针与指向第一个元素的指针相同,那么当您free
第一个元素时,列表指针不再有效。
这个问题有两种解决方案:
让所有列表方法都使用指向列表的指针,以便在需要时可以更新它。这种方法的问题是,如果你在另一个变量中有一个指针的副本,那么该指针也会失效。
不要让列表指针指向第一个元素。让它指向第一个元素的指针。
示例代码:'
typedef struct node_struct {
node_struct *next;
void *data;
} Node;
typedef struct {
Node *first;
} List;