【问题标题】:simple linked list failing to print简单链表打印失败
【发布时间】:2018-05-29 19:02:05
【问题描述】:

我正在学习如何制作一个链表,但它根本无法打印出任何东西,我不知道为什么???请帮忙。我相信这与我的指针有关,但我不知道它是什么。

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

// typedef is used to give a data type a new name
typedef struct node * link ;// link is now type struct node pointer

/*
    typedef allows us to say "link ptr"
    instead of "struct node * ptr"
*/

struct node{
    int item ;// this is the data
    link next ;//same as struct node * next, next is a pointer
};

void printAll(link head); // print a linked list , starting at link head
void addFirst(link ptr, int val ); // add a node with given value to a list
link removeLast(link ptr); // removes and returns the last element in the link

//prints the link
void printAll(link head){
    link ptr = head;
    printf("\nPrinting Linked List:\n");
    while(ptr != NULL){
        printf(" %d ", (*ptr).item);
        ptr = (*ptr).next;// same as ptr->next
    }
    printf("\n");
}

//adds to the head of the link
void addFirst(link ptr, int val ){
    link tmp = malloc(sizeof(struct node));// allocates memory for the node
    tmp->item = val;
    tmp->next = ptr;
    ptr = tmp;
}

// testing
int main(void) {
    link head = NULL;// same as struct node * head, head is a pointer type

    //populating list
    for(int i = 0; i<3; i++){
        addFirst(head, i);
    }

    printAll(head);

    return 0;
}

输出:

打印链表:

进程返回 0 (0x0) 执行时间:0.059 s

按任意键继续

【问题讨论】:

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


【解决方案1】:

这是因为您将一个空指针传递给您的函数,而退出循环的条件是该指针为空,所以没有任何反应。 你的addFirst 函数接受一个指针的值,但它不能修改你在main() 中声明的head。 要修改head,您需要传递一个指向链接的指针,然后您可以取消引用该指针以访问您的head,然后您可以更改它。

void addFirst(link *ptr, int val ){
    link tmp = malloc(sizeof(struct node));// allocates memory for the node
    tmp->item = val;
    tmp->next = *ptr;
    *ptr = tmp;
}

现在您可以更改头指针。只要记住在调用函数时将地址传递给它。 addFirst(&amp;head,i)

【讨论】:

  • 我不明白,虽然我已经通过使用typedef struct node * link ;// link is now type struct node pointer 传递了一个指针变量,为什么我必须再次将它声明为指针?为什么我不能只使用link ptrlink ptr 不是已经是指针类型了吗?
  • @37712 指针指向一个节点,一个包含您的值的结构和下一个节点的指针。然而,将这个指针传递给一个函数,你只传递了那个指针的值,也就是节点的地址。因此,您无权访问您声明的head。您可以访问该指针指向的内容,但不能修改指针本身。您的代码仅修改函数本地的 ptr。因此你的head 保持不变。要更改head,你必须给函数它的地址,并且函数必须有一个指向指针的指针,在这种情况下是链接*
【解决方案2】:

在for循环中

for(int i = 0; i<3; i++){
    addFirst(head, i);
}

你创建了一堆指向NULL的指针。 head 永远不会改变,因为指针本身是“按值”传递的。例如。 head 被复制,并且对 addFirst 中指针本身的所有修改在外部均不可见。

这与int 相同。想象一下void foo(int x);。这个函数对 x 所做的任何事情在外部都是不可见的。

不过更改link ptr指向的内存当然是可见的。

例如这一行什么都不做:

   tmp->next = ptr;
   ptr = tmp;      <=== this line
}

您可以通过多种方式解决此问题。一种是从addFirst 返回新节点,另一种是使link ptr 成为指向指针的指针:link *ptr。因为在这种情况下你想改变指针值(不是指针值):

//link *ptr here a pointer to pointer
void addFirst(link * ptr, int val ){
    link tmp = malloc(sizeof(struct node));// allocates memory for the node
    tmp->item = val;
    tmp->next = *ptr; //<<changed
    *ptr = tmp;    //<<changed
}

不要忘记更新上面的声明。和电话:

void addFirst(link * ptr, int val ); // add a node with given value to a list

...
for(int i = 0; i<3; i++){
    addFirst(&head, i);
}

然后这段代码产生:

Printing Linked List:
 2  1  0

添加: 重要的是要了解使用链表需要使用两种不同类型的数据。

首先是struct node,您使用links 传递此类数据。

第二个是head。这是指向第一个节点的指针。当您想修改头部时,您会发现它不是“节点”。这是另外一回事。这是列表中第一个节点的“名称”。这个名字本身就是一个指向节点的指针。看看head 的内存布局与列表本身有何不同。

head[8 bytes]->node1[16 bytes]->node2[16 bytes]->...->nodek[16 bytes]->NULL;

顺便说一句 - 这里唯一有词法名称的是head。所有节点都没有名称,可通过node-&gt;next 语法访问。

您还可以在这里想象另一个指针link last,它将指向nodek。同样,这将具有与节点本身不同的内存布局。如果你想在一个函数中修改它,你需要将函数指针传递给它(例如指向指针的指针)。

指针和它指向的数据是不同的东西。在您的脑海中,您需要将它们分开。指针类似于intfloat。它“按值”传递给函数。是的link ptr 已经是指针,它允许您更新它指向的数据。但是,指针本身是按值传递的,并且指针的更新(在您的情况下为ptr=tmp)在外部不可见。

(*ptr).next=xxx 当然是可见的,因为数据已更新(不是指针)。这意味着您需要做一个额外的步骤 - 对您的指针进行更改,使其在函数之外可见,例如将指针本身 (head) 转换为另一个指针的数据,例如使用struct node **ptr(这里的第一颗星表示这是指向一个节点的指针,第二颗星将该指针转换为另一个指针的数据。

【讨论】:

  • 我不明白,虽然我已经使用typedef struct node * link ;// link is now type struct node pointer 传递了一个指针变量,为什么我必须再次将它声明为指针?为什么我不能只使用link ptrlink ptr 不是已经是指针类型了吗?
  • 请参阅更新。如果仍然不清楚,请随时提出更多问题
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-15
  • 2012-04-08
  • 2015-01-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多