0
typedef struct list
{
    struct list * next;
    int val;
}*list_t;    

list_t add(list_t l,int e)
{
    list_t head;

    if(l == NULL)
    {
        l = malloc(sizeof(list_t));
        l->val = e;
        l->next = NULL;
        return l;
    }       

    head = l;

    while(l != NULL)
        l=l->next;

    l = malloc(sizeof(list_t));

    l->val = e;

    l->next = NULL;

    return head;
}

示例驱动程序:

int main()
{
    list_t ints=NULL;
    int i;

    for(i=0;i<156;i+=2)
        ints = add(ints,i);

    while(ints->next != NULL)
    {   
        printf("%d\n",ints->val);
        ints=ints->next;
    }

    system("pause");
    return 0;
}

程序可以工作,但是“添加”函数会倒回列表,因此永远不会实现 main 循环的主体。这让我很惊讶,因为我认为我一直在将列表作为值传递!你能解释一下这个现象吗?

4

3 回答 3

2

问题不在于 add 函数倒回列表,而在于它根本不起作用:您的代码中没有任何地方声明列表的前一个末端应该链接到新添加的元素。

我稍微修改了一下:

typedef struct list
{
    struct list * next;
    int val;
} list_t;    

list_t *add(list_t *l,int e)
{
    list_t *head;

    if(l == NULL)
    {
        l = malloc(sizeof(list_t));
        l->val = e;
        l->next = NULL;
        return l;
    }       

    head = l;

    while(l->next != NULL)
        l=l->next;

    l->next = malloc(sizeof(list_t));

    l=l->next;

    l->val = e;

    l->next = NULL;

    return head;
}

int main()
{
    list_t *ints=NULL;
    int i;

    for(i=0;i<156;i+=2)
        ints = add(ints,i);

    while(ints->next != NULL)
    {   
        printf("%d\n",ints->val);
        ints=ints->next;
    }

    return 0;
}

代码现在按预期工作。

请记住,这ladd函数中的局部变量。l如果不允许以某种方式离开函数的范围(就像你在返回它时所做的那样,在第一个 if 内),对它所做的任何更改都将丢失。使用 the或运算符对变量l指向的更改将对有权访问该变量的任何人有效。*->

我建议您开始阅读调试技术。它们因您的环境而异,可以从gdb 等神秘的命令行工具到成熟的图形对象浏览器等。通过这种方式,您将能够逐步查看发生的情况并监控内存更改并检查变量中实际存储的内容。

编辑:修复了评论中的指针问题。内存分配现在提供整个结构变量,并且不再隐式使用指针。

于 2013-01-16T18:34:06.543 回答
2

避免特殊情况。add() 函数只能做一件事:分配一个列表节点并将其指针值分配给链中恰好为空的第一个节点。NULL 节点在链的头部、中间或尾部没有区别。(当然空节点不能存在于列表的中间。它们可以存在于列表的头部,但是列表将是空的)找到第一个 NULL 并将新节点放在那里。

struct list *add(struct list *lp, int e)
{
    struct list **pp;

    for (pp= &lp; *pp; pp = &(*pp)->next) {;}

    *pp = malloc(sizeof **pp);
    (*pp)->val = e;
    (*pp)->next = NULL;

    return lp;
}
于 2013-01-16T18:39:54.223 回答
1
l = malloc(sizeof(list_t));

分配一个指向结构的指针,而不是结构本身。例如,在 64 位机器上,malloced 大小是 8,但它应该是 16。

当你随后说

l->val = ..
l->next = ..

只有上帝知道你写信到哪里..

去搜索一些链表的示例代码,并阅读它,我的意思是在调试器中。

于 2013-01-16T18:44:05.387 回答