这里有一段不起作用的代码。 问题是当我尝试删除节点时。 我注意到当我查看内存地址时,指针* next指向一个不正确的节点。然后,当我尝试删除节点时,该列表仅与firts和last节点一起使用。它失去了中间节点。
typedef struct node{
int value;
struct node *next;
struct node *prev;
}node;
typedef struct struct_list{
int count;
struct node *header;
struct node *tailer;
}struct_list;
void init_list(struct_list *list)
{
(*list).count=0;
(*list).header=(*list).tailer=NULL;
}
void insert(struct_list *list, int new_value){
node *new_node=(node*)malloc(sizeof(node));
(*new_node).value=new_value;
(*new_node).next=NULL;
if(((*list).header)!=NULL){
(*new_node).prev=(*list).tailer;
list->tailer->next=new_node;
(*list).tailer=new_node;
}
if(((*list).header)==NULL){
(*new_node).prev=NULL;
(*list).header=(*list).tailer=new_node;
}
(*list).count++;
};
void delete(struct_list *list, int j){
node tmp;
tmp=sub_search((*list).header, j);// This function sub_search
\\works and return the address of node I want delete
if(tmp.next != NULL){
tmp.prev->next=tmp.next;
tmp.next->prev=tmp.prev;
}else{
tmp.prev->next=NULL;
}
free(&tmp); // Here the new symbol & because free needs the
//address.Its just for testing.
list->count--;
}
int main(int argc, char** argv) {
int n,i,new_value,j;
struct_list list;
init_list(&list);
printf("How much nodes do you want?:\n");
scanf("%d",&n);
for(i=0;i<n;i++)
{printf("Insert node of node:\n");
scanf("%d",&new_value);
insert(&list, new_value);
}
printf("Insert node to delete:\n");
scanf("%d",&j);
delete(&list, j);
return (0);
}
答案 0 :(得分:0)
如评论中所述,如果您的编译器接受您发布的代码段,我会非常惊讶。问题是您在.
函数内修改了->
和delete
。这两行应该归咎于:
tmp.prev->next=tmp.next;
tmp.next->prev=tmp.prev;
现在,为了分析这是做什么,让我们去除->
语法(为了清晰起见,添加了额外的括号):
(*(tmp.prev)).next=tmp.next;
(*(tmp.next)).prev=tmp.prev;
看一下,你可以看到你的代码说它需要访问prev
的{{1}}字段(注意:不是 struct
)在变量struct*
内,并期望 指向tmp
struct*
字段struct
。因此,您会得到您不想要的行为。我做了以下快速测试,这应该有效:
next
贬低这一点,我们看到它做了我们想要的事情(一切都被正确地预期为tmp->prev->next = tmp->next;
tmp->next->prev = tmp->prev;
):
struct*
另外,还有两条关于代码的评论:
作为个人偏好,我一直认为使用(*((*tmp).prev)).next = (*(tmp)).next;
(*((*tmp).next)).prev = (*(tmp)).prev;
代替(*ptr).field
是不好的风格。最重要的是,避免它会阻止这样的错误。
除非我弄错了,否则您在删除后似乎忘记更新ptr->field
:)
以下只是猜想,但我认为这很有趣:
假设您的编译器接受了您发布的代码段。为什么没有崩溃?我想可能发生的事情是这样的:
您的编译器期望tailer
成为tmp
而不是node
。那是什么意思?好吧,node*
(注意:这从编译器到编译器各不相同)在内存中看起来像这样:
node
让我们说,为了练习,这些都是+----------+
| value |
+----------+
| prev |
+----------+
| next |
+----------+
大小的条目(32位)。
指针只是其中一个块的大小:
int
+----------+
| *tmp |
+----------+
| XXXX |
+----------+
| XXXX |
+----------+
是谁知道什么。
当您尝试在XXXX
上查找这些字段作为普通结构时会发生什么?你得到那些tmp
内容(因为它们相对于XXXX
在内存中的位置,这些字段的位置)。
现在,如果您的堆栈是以正确的 方式设置的,那么您可能会遇到这样的行为,哦,我不知道......除了标题和报尾之外总是会删除所有内容列表。
用C调试很有趣。