C-堆栈分配链表

C-堆栈分配链表,c,linked-list,C,Linked List,下面代码的目标是让用户输入一些整数,将这些整数存储在INT\u NODE类型的堆栈分配节点中,然后将所有这些节点链接在一起。最后,我希望遍历列表并在每个节点上打印出元素(仅在下面代码中的前5个)。然而,当我输入一些数字时,程序会打印出我输入的第一个数字,然后我输入的最后一个数字会重复4次。例如,如果我输入84 5 12 7 1 22 31[enter],然后在下一行的开头按Ctrl+D,在这个Mac上模拟EOF,我会得到以下输出:84 31。我不明白它为什么这样做 我知道我可以使用malloc(

下面代码的目标是让用户输入一些整数,将这些整数存储在
INT\u NODE
类型的堆栈分配节点中,然后将所有这些节点链接在一起。最后,我希望遍历列表并在每个节点上打印出元素(仅在下面代码中的前5个)。然而,当我输入一些数字时,程序会打印出我输入的第一个数字,然后我输入的最后一个数字会重复4次。例如,如果我输入
84 5 12 7 1 22 31[enter]
,然后在下一行的开头按
Ctrl+D
,在这个Mac上模拟EOF,我会得到以下输出:<代码>84 31。我不明白它为什么这样做

我知道我可以使用
malloc()
在堆上分配节点,我已经编写了一个函数来实现这一点。我只是想知道是否可以使用运行时堆栈来完成它

在下面的代码中,
INT\u节点
类型在
“SortingAlgs.h”
标题中定义如下:

typedef struct INT_NODE {
    int element;
    struct INT_NODE *next;
} INT_NODE;

#包括
#包括
#包括“SortingAlgs.h”
内部主(空){
INT_节点头={-9999999};
int-num;
INT_NODE*pccurrentnode=&head;
如果(扫描频率(“%d”,&num)!=EOF){
head.element=num;
while(scanf(“%d”,&num)!=EOF){
INT_NODE newNode;
newNode.element=num;
newNode.next=NULL;
pCurrentNode->next=&newNode;
PCcurrentNode=PCcurrentNode->next;
}
} 
int i;
对于(pccurrentnode=&head,i=0;i<5;
pCurrentNode=pCurrentNode->next,i++)
printf(“%d”,pCurrentNode->element);
printf(“\n”);
返回0;
}

要使用运行时堆栈执行此操作,可以使用以下选项之一:

  • 通过
    alloca
    分配运行时。这很简单:基本上只需将
    malloc
    替换为
    alloca
    (不要试图将
    alloca
    包装到另一个函数中)。但是,
    alloca
    不是标准函数
  • 递归函数,其中每个级别的递归将承载单个列表节点(或固定数量的列表节点)。这有一些严重的限制,但从技术上讲,它满足了在堆栈上分配所有节点的要求
  • 预先分配固定数量的节点作为本地数组,并希望它足以满足您的列表。。。但我相信这不是你的意思
  • 就这样。你现在所拥有的是不可行的,只会导致未定义的行为。您的列表基本上“包含”了生存期已经结束的
    INT\u NODE
    对象。实际上,您通常会一次又一次地重用同一内存位置,从而有效地将单个节点链接到自身

    下面是一个例子,如果一个实现按照递归方法将整个列表保持在“堆栈上”。当然,只有当所有递归调用都处于“活动”状态时,列表才会存在。这限制了这项技术的适用性,但也有它的用途

    #include <stdlib.h>
    #include <stdio.h>
    
    typedef struct INT_NODE 
    {
      int element;
      struct INT_NODE *next;
    } INT_NODE;
    
    void print_list(const INT_NODE *head)
    {
      for (const INT_NODE *current = head; current != NULL; current = current->next)
        printf("%d  ", current->element);
      printf("\n");
    }
    
    void build_list(INT_NODE *head, INT_NODE *last)
    {
      INT_NODE new = { 0 };
    
      if (scanf("%d", &new.element) != 1)
      {
        print_list(head);
        return;
      }
    
      if (head == NULL)
        head = &new;
      else
        last->next = &new;
    
      build_list(head, &new);
    }
    
    int main(void) 
    {
      build_list(NULL, NULL);
    }
    
    #包括
    #包括
    类型定义结构内部节点
    {
    int元素;
    结构INT_节点*下一步;
    }INT_节点;
    无效打印列表(常量内部节点*头)
    {
    for(常数INT_节点*当前=头部;当前!=NULL;当前=当前->下一步)
    printf(“%d”,当前->元素);
    printf(“\n”);
    }
    无效生成列表(内部节点*头部,内部节点*最后)
    {
    INT_NODE new={0};
    if(scanf(“%d”,&new.element)!=1)
    {
    打印列表(标题);
    返回;
    }
    if(head==NULL)
    head=&new;
    其他的
    最后->下一步=&new;
    构建列表(标题和新建);
    }
    内部主(空)
    {
    构建列表(空,空);
    }
    

    我认为原因在于变量的范围。 输入5,程序在堆栈上分配内存,但它将被返回。 输入12,分配相同的内存,然后返回。 最后,头下一个指针是同一个内存,下一个指针是同一个内存本身


    您可以输出5个以上。也许你会得到8431

    谁将为此分配足够的内存?要使用运行时堆栈进行分配,您需要1)通过
    alloca
    进行非标准运行时分配,或者2)递归函数,其中每一级递归将承载一个列表节点。就这样。你现在所拥有的是不可行的,只会导致未定义的行为。当然,您可以简单地预先分配固定数量的节点作为本地数组,并希望它足以满足您的列表。。。但我相信这不是你的意思:这在范围外无效。每次while循环中,您都在创建和销毁yr节点。必须在heapNote上执行此操作,您的打印循环停止的唯一原因是因为
    i<5
    术语。对于一个真正的链表,您将一直运行,直到到达一个下一个指针为空的节点(最常见的情况)。如果你试着这样做,你很可能会得到“永远”产生的
    31
    (直到你感到无聊并杀死你的程序)。这是你麻烦的征兆。请在确定的情况下发布答案。哦,不,我要打绿色复选标记的答案不见了(
    #include <stdlib.h>
    #include <stdio.h>
    
    typedef struct INT_NODE 
    {
      int element;
      struct INT_NODE *next;
    } INT_NODE;
    
    void print_list(const INT_NODE *head)
    {
      for (const INT_NODE *current = head; current != NULL; current = current->next)
        printf("%d  ", current->element);
      printf("\n");
    }
    
    void build_list(INT_NODE *head, INT_NODE *last)
    {
      INT_NODE new = { 0 };
    
      if (scanf("%d", &new.element) != 1)
      {
        print_list(head);
        return;
      }
    
      if (head == NULL)
        head = &new;
      else
        last->next = &new;
    
      build_list(head, &new);
    }
    
    int main(void) 
    {
      build_list(NULL, NULL);
    }