从链接列表中删除项目时出现分段错误

时间:2014-06-25 19:25:19

标签: c linked-list segmentation-fault singly-linked-list

我尝试创建程序,您输入' + word'它会添加单词,当您输入' -word'它取消了链接列表中的单词。

插入单词对我来说很好,但删除它会导致分段错误。我不确定故障在哪里。另外,有没有一种方法可以让您了解分段错误的位置?

void
remove_from_list(struct linked_list *list, char *data)
{
    struct node *current_node = list->head;
    struct node *previous_node = NULL;

    while (current_node != NULL) {
        if (current_node->data == data) {
            break;
        }
        previous_node = current_node;
        current_node = current_node->next;
    }
    if (previous_node == NULL) {
        list->head = list->head->next;
    } else {
        previous_node->next = current_node->next;
    }
    free(current_node);
    if (list->tail == current_node)
        list->tail = previous_node;
}

int
main(void)
{
    struct linked_list list = { .head = NULL, .tail = NULL };
    char word[50];

    do {
        printf("Enter string: ");
        fgets(word, 50, stdin);
        if (word[0] == '+')
            add_to_list(&list, word);
        else if (word[0] == '-')
            remove_from_list(&list, word);
    } while (word[0] != '\n');

    print_list_rec(&list);
    free_list(&list);
    return 0;
}

5 个答案:

答案 0 :(得分:1)

循环到链接列表的末尾,然后继续在此处取消引用NULL指针

} else {
    previous_node->next = current_node->next;
}

这是因为您的比较并未实际比较数据;

 if (current_node->data == data) {

你永远不会从if语句中得到真实的结果。

如果要比较字符串,请使用strcmp()。

答案 1 :(得分:1)

您遇到seg错误的主要原因是您在尝试删除时没有处理列表中没有数据的情况。

if (previous_node == NULL) { 
    list->head = list->head->next;
} else { // ------------------------- If at the end of the list you go in here
    previous_node->next = current_node->next;
}

current_nodeNull,因此current_node->next会出现错误。

您到列表末尾的原因是因为您没有正确比较字符串的数据。使用strcmp()之类的@this建议进行正确比较。但是你应该处理列表中没有数据的情况。


您可以在while循环和first if语句之间添加一个检查,这将处理一个空列表和不在列表中的数据 -

if(current_node == NULL) // Empty list or wasn't found
    return;

另一个注意事项:

在检查是否是尾巴之前,你释放current_node。颠倒这个顺序。

if (list->tail == current_node)
    list->tail = previous_node;
free(current_node);

答案 2 :(得分:0)

除了其他人所说的,如果列表为空,此代码将导致分段:

if (previous_node == NULL) {
    list->head = list->head->next;
}

答案 3 :(得分:0)

如果没有插入功能的代码,很难说出错了,因为删除的步骤会很好。但是,插入可能会出现问题,因为这样做不起作用。

但是您的代码中存在问题,如果您尝试删除不存在的节点,您仍将最终删除最后一个节点。您需要在while循环中断时设置一个标志,然后仅在flag为true时删除该节点。

答案 4 :(得分:0)

该功能应该采用以下方式

void
remove_from_list( struct linked_list *list, char *data )
{
    struct node *current_node = list->head;
    struct node *previous_node = NULL;

    while ( current_node != NULL && strcmp( current_node->data, data ) != 0 ) 
    {
        previous_node = current_node;
        current_node = current_node->next;
    }

    if ( current_node != NULL ) 
    {
        if ( previous_node != NULL ) 
            previous_node->next = current_node->next;
        else
            head = head->next; 

        if ( list->tail == current_node )
            list->tail = previous_node;

        free( current_node->data );
        free( current_node );
    }
}

此外,我会存储字符串而不会引导+或 - 。在这种情况下,main中的if语句看起来像

    if ( word[0] == '+' )
        add_to_list( &list, word + 1 );
    else if ( word[0] == '-' )
        remove_from_list( &list, word + 1 );

否则,您永远不会找到添加了加号的字符串,以便将其从列表中删除。