在遍历链表时发生了分段错误

3
我正在学习链表,我试图创建一个函数,遍历链表并打印每个值。然而,在 while 循环结束时,当我经过最后一个节点时,我遇到了分段错误。我认为通过将条件从(temp!= NULL)更改为(temp->next!= NULL),可以消除分段错误,但是我仍然遇到了错误。我需要一些帮助。我提供了打印函数,其中出现错误,但如果需要,我也可以提供完整的代码。
void printList(node_t *head){
    node_t *temp = head;

    if (temp != NULL) {
        while (temp->next != NULL) {
            int i = temp->value;
            printf("%d\n", i);
            temp = temp->next;
            
        }
    }
}

添加了更多的代码。

#include <stdio.h>
#include <stdlib.h>

struct node{
    int value;
    struct node *next;
};

typedef struct node node_t;

void printList(node_t *head){
    node_t *temp = head;

    if (temp != NULL) {
        while (temp->next != NULL) {
            int i = temp->value;
            printf("%d\n", i);
            temp = temp->next;

        }
    }

}

node_t *create_new_node(int value){
    node_t *next_pointer = malloc(sizeof(node_t));
    next_pointer->value = value;
    next_pointer->next = NULL;
    return next_pointer;
}

node_t *insert_at_head(node_t **head, node_t *new_node){
    new_node->next = *head;
    *head = new_node;
    return new_node;
}

int main(){
    node_t *tmp, *head;

    for(int i= 0; i<25; i++){
        tmp = create_new_node(i);
        insert_at_head(&head, tmp);
    }
    
    printList(head);
    
    return 0;
}

1
你的逻辑可以简化。记住,如果条件为假,while循环将不会执行。 - stark
@avvocato 提供一个最小完整的程序来展示问题。 - Vlad from Moscow
1
使用该程序逻辑,您将会错过最后一个元素。但是我不明白除非列表的创建本身就有问题,否则为什么会出现段错误。通常情况下,最后一个元素的下一个指针可能会指向无处。这是典型的初学者错误。您需要编辑并展示给我们一个最小可复现代码以获取更多信息。 - Jabberwocky
@Yunnosch 谢谢你的建议,我在 main 函数开始时将 *head 初始化为 NULL,现在它可以工作了,但我不太明白为什么。 - avvocato
@Jabberwocky 我喜欢用衣架来做这个。https://stackoverflow.com/questions/59097696/tricks-to-analyse-pointer-and-pointer-to-pointer-structures-in-c/59097858#59097858 - Yunnosch
显示剩余7条评论
2个回答

3
程序的问题是您没有将指针初始化为头节点。
node_t *tmp, *head;

作为头节点被添加的结果,最后一个节点的数据成员next的值变得不确定。
你需要编写。
node_t *tmp, *head = NULL;

函数printList可以如下所示:
void printList( const node_t *head )
{
    for ( ; head != NULL; head = head->next )
    {
        printf( "%d\n", head->value );
    }
}

同时,函数create_new_node应该按照以下方式进行定义

node_t * create_new_node( int value )
{
    node_t *next_pointer = malloc(sizeof(node_t));
    if ( next_pointer != NULL )
    {
        next_pointer->value = value;
        next_pointer->next = NULL;
    }

    return next_pointer;
}

2
初始化头部:
node_t *tmp, *head=NULL;

这样,最后一个next的定义很清晰,并且可以防止访问不确定的位置。
然后我得到了一个漂亮的反向输出(减去了最后插入的第一个元素0;请参见Jabberwocky的评论)。
例如,在这里https://www.tutorialspoint.com/compile_c_online.php 否则,你会做这个:
head->OhNo
head->1->OhNo
head->2->1->OhNo
....
当输出函数到达/之前到达指向不确定位置的“OhNo”时,这将使您的输出函数出错。
使用init是这样的:
head->NULL
head->1->NULL
head->2->1->NULL
...
后者与您的输出函数一起清洁工作。

你忘了提到 printList 缺少第一个元素。 - Jabberwocky

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接