1

次の連結リスト宣言では、

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

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


void destroy (list *l)
{
    if (l)
    {
        destroy (l->next);
        free (l);
    }
}

次のメインが機能するのはなぜですか

int main()
{
    list *test;
    list *ptr1, *ptr2;
    int i;
    test = malloc (sizeof (list));
    test->val = 0;
    ptr2 = test;
    for (i = 1; i <= 10; i++)
    {
        ptr1 = (list *) malloc (sizeof (list));
        ptr1->val = i;
        ptr2->next = ptr1;
        ptr2 = ptr1;
    }
    ptr1 = test;
    while (ptr1)
    {
        printf ("%d\n", ptr1->val);
        ptr1 = ptr1->next ;
    }
    destroy (test);
    return 0;
}

これはリストを作成しませんが(ノードは1つしか作成しません)?

int main()
{
    list *test;
    list *ptr;
    int i;
    test = malloc (sizeof (list));
    test->val = 0;
    ptr = test->next;
    for (i = 1; i <= 10; i++)
    {
        ptr = (list *) malloc (sizeof (list));
        ptr->val = i;
        ptr = ptr->next;
    }
    ptr = test;
    while (ptr)
    {
        printf ("%d\n", ptr->val);
        ptr = ptr->next ;
    }
    destroy (test);
    return 0;
}

彼らは同じロジックを使用していませんか?

4

3 に答える 3

3

コード

ptr = test->next;
for (i = 1; i <= 10; i++)
{
    ptr = (list *) malloc (sizeof (list));
    ptr->val = i;
    ptr = ptr->next;
}

のコピーを取得することから始めますが、それ自体test->nextに何も割り当てませんtest->next。したがって、から始まるリストtestには 1 つの項目しかありません。さらに悪いことに、そのアイテムには初期化されていないnextポインターがあるため、リストを反復しようとするコードはほぼ確実にクラッシュします。

他の回答で示唆されているように、このパターンは、新しく割り当てられたノードごとに繰り返されます。

あなたのコメントへの回答として、2 番目の関数を機能させる最善の方法は、最初の (動作する) バージョンのようにすることです。わかりやすくするために変数の名前を変更しました

list *head;
list *next, *curr;
int i;
head = malloc (sizeof(*head));
head->val = 0;
curr= head;
for (i = 1; i <= 10; i++)
{
    next = malloc (sizeof(*next));
    next->val = i;
    curr->next = next;
    curr= next;
}
curr= head;
于 2013-06-03T12:53:03.663 に答える
1

2回目のメイン中

ptr = test->next;

メモリを割り当てずに test->next にアクセスしようとしています。次のようにコードを変更して、2番目のメインが機能するようにすることができます

test = malloc (sizeof (list));
    test->val = 0;
    test->next = (list *) malloc (sizeof (list));
    ptr = test->next;
    for (i = 1; i <= 10; i++)
    {
        ptr->val = i;
    ptr->next = (list *) malloc (sizeof (list));
        ptr = ptr->next;
    }
于 2013-06-03T12:54:05.847 に答える
1

動作する最初の例でptr2は、以前に作成されたノードをリストに保持しているように見えるため、これを書き換えることができます

last_created_node = test;
for (i = 1; i <= 10; i++)
{
    // create new node
    new_node = (list *) malloc (sizeof (list));
    new_node ->val = i;
    // chain newly created node onto list so far
    // make last created node point to new node
    last_created_node->next = new_node ;
    // last created node is now new node
    last_created_node = new_node ;
}
// terminate the list
last_created_node->next = 0;

与えられた 2 番目のコード サンプルでは、​​新しいノードをチェーンにリンクすることに相当するものはありません。また、他の人がコメントしているように、ユニット化されたメモリにも問題があります。上記のサンプルの最後の行に示されているように、終了条件を追加するとよいでしょう。

于 2013-06-03T13:02:13.317 に答える