【问题标题】:Looping through recursive list in C循环遍历C中的递归列表
【发布时间】:2023-12-24 16:56:01
【问题描述】:

我刚开始使用 C,我认为整个指针/malloc/free 让我发疯。我试图定义一个简单的线性递归数据结构并循环遍历它,打印我循环遍历的每个元素。 (代码如下)。

但是,当我尝试移动到下一个元素以“插入”新元素时,我得到了 Segmentation Fault: 11

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

 typedef struct number_list {
     int num;
     struct number_list *next_num;
 } numlist;

 int main() {
     numlist *cur, *pointer;
     numlist *NewList=NULL;

     cur = NewList;

     cur = malloc(sizeof(numlist));
     cur->num=5; // this operation is never reached too
     cur = cur->next_num // Must I malloc? 
     printf("Reached."); // Is never reached.
     cur->num=9;

     pointer=NewList;

     while (pointer!=NULL) {
         printf("%d", pointer->num);
         pointer=pointer->next_num;
     }
     return 0;
 }

此外,我在另一个更大的程序中有一个 while 循环,它的功能与这里的这个 while 循环完全一样,除了“填充”递归结构。因此,我实际上不需要创建任何新元素,只需运行并打印出每个元素。但是,在循环打印最后一个元素的那一刻,它再次崩溃,并出现 Segmentation Fault: 11。我猜这很可能是因为我试图做pointer = pointer-&gt;next_num。无论如何,我如何正确地在 C 上正确运行这样的数据结构?

【问题讨论】:

    标签: c recursive-datastructures


    【解决方案1】:

    您有一些概念性问题。首先你要知道指针和它所指向的内存的区别;

    int a1 = 0;
    int a2 = 0;
    int *b = &a1;
    *b = 3;
    // now a1 = 3, a2 = 0
    b = &a2;
    *b = 2;
    // now a1 = 3, a2 = 2
    

    这意味着在这两行中:

    cur = NewList;
    cur = malloc(sizeof(numlist));
    

    第二个完全取代了第一个赋值。

    现在这一行:

    cur = cur->next_num;
    

    next_num 尚未设置,因此 cur 设置为垃圾内存(malloc 不会将内存归零,因此它甚至不是 NULL)。你应该做的是;

    cur->next_num = malloc( sizeof( numlist ) );
    cur = cur->next_num;
    cur->next_num = NULL; // explicitly NULL-cap, because of issue mentioned above.
    

    最后,NewList 最后仍然是 NULL。你应该在你的第一个 malloc 行之后使用NewList = cur;

    在实际代码中,您会将大部分内容放入可重用的函数中,但对于学习这些修复程序就足够了。

    打印您提到的最后一个元素后的崩溃也可能是由于 NULLing 问题。据我所知,您的 while 循环本身很好。

    【讨论】:

    • 是的,谢谢你的解释,肯定清除了很多东西!
    【解决方案2】:

    你没有为NewList分配内存。

    cur = NewList;
    cur = malloc(sizeof(numlist));
    

    一定是:

    NewList= malloc(sizeof(numlist));
    cur = NewList;
    

    是的,您必须为每个元素分配内存。

    【讨论】:

    • 好的,我在 cur-&gt;num = 5cur-&gt;num = 9 之前为 NewList 和 cur = malloc(sizeof(numlist)); 分配了内存,所以它现在看起来像这样 `cur = malloc(sizeof(numlist));当前->数字=5; cur = malloc(sizeof(numlist)); cur = cur->next_num;当前->数字=9; ` 不幸的是仍然产生分段错误:11。我试图通过将printf 放在代码的不同部分来测试它,它似乎甚至无法运行main() 的第一行。不过它编译得很好。
    【解决方案3】:
    #include <stdio.h>
    #include <stdlib.h>
    
    typedef struct number_list {
        int num;
        struct number_list *next_num;
    } numlist;
    
    numlist *NewList(int value){
        numlist *newp;
    
        newp = malloc(sizeof(numlist));
        if(newp){
            newp->num = value;
            newp->next_num = NULL;//initialize!
        }
        return newp;
    }
    
    int main() {
        numlist *cur, *pointer;
        numlist *newList=NULL;
    
        cur = NewList(5);
        newList = NewList(9);
    
        newList->next_num = cur;
        cur = newList;
    
        pointer=cur;
    
        while (pointer!=NULL) {
            printf("%d ", pointer->num);
            pointer=pointer->next_num;
        }
        return 0;
    }
    

    【讨论】: