链表只打印最后添加的成员。可能是什么错误?

Linked list only prints out the last added member. What could be the mistake?

我在使用单向链表时遇到问题。我正在尝试将元素添加到函数内部的列表末尾(我猜这是 FIFO 排列)(不是从主函数中一个一个地传递元素)所以我的想法是保存头指针的位置并创建每次我添加一个元素时都会改变位置的另一个指针。

问题是,当我添加一个新元素时,头指针的值也会发生变化,我不确定为什么,因为我唯一一次改变头指针的任何东西是在我将第一个元素添加到名单。然后创建了我分配给头指针的“当前”指针,并从那时起使用它来添加所有其他元素,但是当我尝试在 while 循环的每次迭代中打印头指针值时,它打印了最后输入的值(我想分配给“当前”的值,而不是头)。

当我尝试打印出整个列表时,它只会反复打印出最后一个元素。

这是我编写的代码:

typedef struct node NODE;
typedef struct node* PNODE;


struct node {
    int info;
    PNODE next;
};


void addToEnd(PNODE *head) {
    PNODE newN = malloc(sizeof(NODE));
    
    int num = 0;
    printf("Type in the numbers. The loop ends when you type in -1.\n");
    scanf("%d", &num);
    getchar();
    newN->info = num;
    newN->next = NULL;
    (*head) = newN;
    PNODE current = *head;
    while(1) {
        scanf("%d", &num);
        getchar();
        if (num == -1) {
            break;
        }

        newN->info = num;
        newN->next = NULL;

            
        if (current->next == NULL) {
            current->next = newN;
            current = current->next;
        }
            
        
    }


    current = (*head);

    while (current != NULL) {
        printf("%d ", current->info);
        current = current->next;
    }
}


main() {
    PNODE head = NULL;
    addToEnd(&head);
    
}

The problem is that the head pointer's value also changes when I add a new element and I'm not sure why, because the only time I changed anything in regards to the head pointer is when I added the first element to the list.

我认为“头节点的值”是指 (*head)->info(与 *head 相对)。

的确,你只给*head赋值一次,但是你多次更新(*head)->info的值,结果是*headnewN, 和 current 都具有相同的(指针)值。观察:

    (*head) = newN;
    PNODE current = *head;

... *head赋值为newNcurrent赋值为*head;现在这些都一样了。那么...

        newN->info = num;
        newN->next = NULL;

... currentnewN*head 仍然相同,所以这设置了 infonext 成员它们都指向的节点。然后,因为current == newN,我们知道刚刚设置为NULLcurrent->next == newN->next,所以一直执行:

        if (current->next == NULL) {
            current->next = newN;
            current = current->next;

此外,因为currentnewN(和*head)仍然相等,所以current->next = newN等同于current->next = current,当然,之后也就是说,current = current->next 不会更改 current 的值或使其不等于 *headnewN。这三个在整个输入循环中始终保持不变。

在那之后,当然...

    current = (*head);

...仍然使三个指针彼此相等。如果在输入循环期间至少输入了一个数字,那么我们还有 current->next == current,因此打印循环将一遍又一遍地打印最后输入的值,直到您终止程序。

简而言之,这几乎都是错误的。

如果您想将元素添加到列表中,以便每个元素都附加在末尾,那么一种合理的处理方法是:

  1. 准备
    1. 创建一个虚拟 NODE 并将 *phead 指定为其 next 指针的值。 (正常声明一个NODE即可,这个不需要动态分配。)
    2. 初始化 current 以指向虚拟节点 (current = &dummy)。
    3. 使用循环前进current指向列表中的最后一个节点(如果列表最初为空,它将继续指向dummy)。
  2. 输入
    1. 尝试读取一个值。如果出现 none,则跳出循环;否则...
    2. 分配一个新的NODE
    3. 将新读取的值赋给新节点。
    4. 更新 current->next 以指向新节点。
    5. 更新 current 以指向新节点。 (不要在第 4 步之前执行此操作!)
    6. 返回 INPUT.1。
  3. 完成
    1. 循环终止后,current指向最后添加的节点。将 current->next 设置为 NULL 以标记列表的结尾。
    2. 设置*head = dummy->next。如果列表最初为空并且至少添加了一个值,那么这将分配 *head 指向头节点。否则,它只会将 *head 的原始值复制回其中(参见步骤 PREPARATION.1)。