Ошибка сегментации и странный вывод в функции удаления в двусвязном списке

Здесь мой код показывает ошибку сегментации в функции delete_node, которая удаляет узел с заданным номером из двусвязного списка. Он показывает ошибку сегментации, если я удаляю первый элемент или последний элемент. Если я попытаюсь удалить промежуточные элементы, он просто заменит его значение на «0». Также скажите, почему закомментированная команда в функции printlist показывает ошибку сегментации, когда я ее раскомментирую.

#include<stdio.h>
#include<stdlib.h>
struct node 
{
int data;
struct node *prev;
struct node *next;

};

struct node *first=NULL;

struct node *insertatbeg(struct node* list,int number)
{
struct node *new_node=malloc(sizeof(struct node));
new_node->data=number;
new_node->next=list;
new_node->prev=NULL;

return new_node;
}

struct node *insertatend(struct node* list,int number)
{
    struct node* new_node;
    struct node *curr=list;
    new_node=malloc(sizeof(struct node));
    new_node->data=number;

    if(list==NULL)
    {
    new_node->next=list;
    new_node->prev=NULL;
    return new_node ;    
    }
    else
    {
    while(curr->next!=NULL)
    {
        curr=curr->next;
    }
    curr->next=new_node;
    new_node->next=NULL;
    new_node->prev=curr;
return list;
    }

}
///Till here no error for sure
////////////////////////////////////////////////////////
void printlist(struct node *list)
{
int i=0;
struct node *p;
for(p=list;p!=NULL;p=p->next)
{
//printf("\nCurr=%d Prev=%d Next=%d\n",p->data,(p->prev)->data,(p->next)->data);//uncomment this & Error(Segmentation Fault comes)
printf("%d->",p->data);

++i;
}
printf("NULL\n");
printf("size=%d\n",i);
}
////////////////////////////////////////////
struct node *delete_node(struct node *list, int number)
{
struct node *curr,*previous;
for(curr=list,previous=NULL;curr!=NULL && curr->data!=number; previous=curr,curr=curr->next, (curr->next)->prev=previous)
;

if(curr==NULL)
{
printf("Sorry..Could not find the element..!!!\n");
return list;    
}

if(curr->prev==NULL)
{
(curr->next)->prev=NULL;
free(curr);
return list;
}

if(curr->next==NULL)
{
(curr->prev)->next=NULL;
free(curr);
return list;
}

else
{
(curr->prev)->next=curr->next;
(curr->next)->prev=curr->prev;
free(curr);
return list;
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////   
}

int main()
{

first=insertatbeg(first,3);
first=insertatend(first,2);
first=insertatbeg(first,1);
//Till here output is fine and is 1->3->2

printlist(first);

//first=delete_node(first,1);

//first=delete_node(first,2);
first=delete_node(first,3);
printlist(first);

return 0;
}

person Akshit    schedule 09.06.2013    source источник
comment
p->next и p->prev могут быть NULL.   -  person BLUEPIXY    schedule 09.06.2013


Ответы (2)


Значения указателя могут быть NULL. Вы должны добавить проверки в код для этого случая.

if(pointer != NULL)
{
    // execute the code
}
person user2448027    schedule 09.06.2013

Также скажите, почему закомментированная команда в списке печати функции показывает ошибку сегментации, когда я ее раскомментирую.

Для первого и последнего элемента списка элементы prev и next будут нулевыми,
что приведет к ошибкам сегментации, поскольку вы пытаетесь получить доступ к недопустимой памяти.

Поскольку у вас есть двойной связанный список, вам не нужно поддерживать два указателя,
вы можете удалить более просто, как это:

struct node *delete_node(struct node *list, int number) 
{
    struct node *c;
    for (c = list; c != NULL && c->data != number; c = c->next)
        ;
    if (c == NULL) return list;             //if node not found

    if (c->next == NULL && c->prev == NULL) //if the only element in
            return NULL;                    //list has to be deleted

    if (c->prev != NULL)                    
        c->prev->next = c->next;
    else list = c->next;                    //if first element is to be deleted

    if (c->next != NULL)
        c->next->prev = c->prev;
    return list;
}
person mohit    schedule 09.06.2013
comment
Как может c!=number так же, как c!=NULL, если это не c-›data!=number - person Akshit; 09.06.2013
comment
Исправленный ответ. c будет NULL в конце цикла. - person mohit; 09.06.2013
comment
Ваше решение неверно. Он работает только для удаления элементов в конце, а не для тех, что в начале и между ними. - person Akshit; 09.06.2013
comment
На самом деле я не проверял это и был совершенно сбит с толку тем, что вы хотели вернуть. Теперь надеюсь, должно работать нормально. - person mohit; 09.06.2013