1

这是我在开始时添加节点的代码。

void screate(ll *node)
{
  ll *newNode=(ll *)malloc(sizeof(ll));
  printf("Enter number :\t");
  scanf("%d",&newNode->data);
  if(newNode->data != NULL)
  {
    newNode->next=node;
    node= newNode;
    screate(node);
  }
  else
  {
    free(newNode);
    newNode=NULL;
  }
}

即使我在这里找到了相同的代码,我也无法弄清楚为什么我得到错误的输出。

这是当前节点

56->78->77->NULL

但是,当我尝试在开始时添加新节点时,我仍然得到相同的输出,即56->78->77->NULL. 需要帮忙 !!

更新

void show(ll *node){
while(node->next != NULL)
 {
  printf("%d->",node->data);
  node=node->next;
 }
printf("NULL");
}
4

4 回答 4

4

您分配给nodewhich 只是函数的一个参数。由于它是按值传递的,因此不会更新调用函数持有的版本。

您需要传递一个指向它的指针(即ll **node)并将您的代码更改为分配给*node,并更改调用者以&在参数之前添加 a 以获取其地址。

void screate(ll **node)
{
  ll *newNode=malloc(sizeof(ll));
  printf("Enter number :\t");
  scanf("%d",&newNode->data);
  if(newNode->data != NULL)
  {
    newNode->next=*node;
    *node= newNode;
    screate(node);
  }
  else
  {
    free(newNode);
  }
}

如果将指向某事物的指针传递给函数,它可以更改某事物,但不能更改指针本身。因此,自然的结论是使某物本身成为指针——即指向指针的指针。

原则上,您可以根据需要尽可能深地使用此指针链接,但实际上您通常只需要“指向事物的指针”之外的任何东西。

其他几点。尽量避免变量名lll因为小写 L 很容易与许多字体中的数字 1(和大写 I)混淆。此外,您再次使用递归调用screate()作为循环可能会更有效while。一些编译器会发现它是尾递归的,并且无论如何都会优化为循环,但我从不喜欢依赖这种东西,因为一开始就很清楚使用循环。

于 2013-01-20T09:33:11.713 回答
3
newNode->next=node;
node = newNode;

问题是node = newNode只更改本地副本,node这意味着调用者看不到更改。对于调用者来说,就好像您从未调用过该函数,node仍然指向它之前指向的任何位置。

您可能想通过 all **node并更改*node或其他内容。

于 2013-01-20T09:31:08.310 回答
1

您应该将带有参数的签名更改为指向链表指针的指针

void screate(ll **node);

而你的函数中对应的指针变化一定是这样的

newNode->next=*node;
*node= newNode;
screate(&node);
于 2013-01-20T09:39:54.710 回答
0

我建议更改您的 screate 函数,使其返回一个struct ll *. 返回值将对应于您的新头节点。

if(newNode->data != NULL)不是从 scanf 检测输入故障的明智方法。事实上,那行代码是不明智的。NULL 被标识为空指针集的成员。newNode->data 是一个 int,而不是一个指针。将其与 0 进行比较会更有意义。[这里][1] 是标准化的 scanf 参考。仔细阅读并回答以下问题,你就会知道如何区分scanf的成功与失败:

int x, y;
int z = scanf("%d%d", &x, &y);
int c = getchar();
  1. 如果我通过标准输入发送“abcd{enter}”,z 会是什么?
  2. 如果我通过标准输入发送“abcd{enter}”,c 会是什么?
  3. 如果我通过标准输入发送 EOF 信号,scanf 会返回什么?
  4. 如果 z 成功读取并将值放入两个变量 x 和 y 中,z 将是哪个值?
于 2013-01-20T12:21:35.490 回答