列表操作

时间:2015-06-02 12:22:09

标签: c list struct operation

这里有一段不起作用的代码。 问题是当我尝试删除节点时。 我注意到当我查看内存地址时,指针* 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);
}

1 个答案:

答案 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*

另外,还有两条关于代码的评论:

  1. 作为个人偏好,我一直认为使用(*((*tmp).prev)).next = (*(tmp)).next; (*((*tmp).next)).prev = (*(tmp)).prev; 代替(*ptr).field是不好的风格。最重要的是,避免它会阻止这样的错误。

  2. 除非我弄错了,否则您在删除后似乎忘记更新ptr->field:)

  3. 以下只是猜想,但我认为这很有趣:

    假设您的编译器接受了您发布的代码段。为什么没有崩溃?我想可能发生的事情是这样的:

    您的编译器期望tailer成为tmp而不是node。那是什么意思?好吧,node*(注意:这从编译器到编译器各不相同)在内存中看起来像这样:

    node

    让我们说,为了练习,这些都是+----------+ | value | +----------+ | prev | +----------+ | next | +----------+ 大小的条目(32位)。

    指针只是其中一个块的大小:

    int

    +----------+ | *tmp | +----------+ | XXXX | +----------+ | XXXX | +----------+ 是谁知道什么。

    当您尝试在XXXX上查找这些字段作为普通结构时会发生什么?你得到那些tmp内容(因为它们相对于XXXX在内存中的位置,这些字段的位置)。

    现在,如果您的堆栈是以正确的 方式设置的,那么您可能会遇到这样的行为,哦,我不知道......除了标题和报尾之外总是会删除所有内容列表。

    用C调试很有趣。