2016-12-01 5 views
0

ノードを追加した後にリンクリストを印刷しようとしています。私は、リストにリンク済みリスト無限ループC

Node **nodeArray; 
    nodeArray = malloc(10 * sizeof(Node *)); 

    int i; 
    for (i = 0; i < 10; i++) { 
     nodeArray[i] = malloc(sizeof(Node));  
    } 

    if (userChoice == 'a') 
     add(&nodeArray, setNumber); 

void add(Node ***nodeArray, int setNumber) { 
     char userString[5]; 
     printf("Please enter some data: "); 
     scanf("%s", userString); 

     Node *head = *nodeArray[setNumber];  /* head pointer to first element of array (dummy) */ 
     Node *newNode = malloc(sizeof(Node)); /* new node to be added to array */ 

     strncpy(newNode->data, userString, sizeof(newNode->data)); /* copies string entered by the user to data field of new node */ 
     newNode->next = NULL; /* initializes next field of new node to NULL */ 

     Node *tmp = head; /* pointer to head of list */ 

     while (!tmp->next) { 
      tmp->next = newNode; /* inserts new node into array */ 
      tmp = newNode;  /* points head to newly added node */ 
     } 

     tmp = head;  /* points tmp back to head of list */ 

     printf("List is: "); 
     while (tmp->next) { 
      printf("%s", (tmp->data)); 
      tmp = tmp->next; 
     } 
} 

を開始するためにダミー・ノードを持っている。しかし、私は印刷するとき、私は新しく追加したノードのデータフィールドをプリントアウトし、無限ループを取得します。リンクされたリストにひどい... ....私は間違って何をしていますか? newNodeとnewNodeにnewNode->次のポイントへ

while (!tmp->next) { 
    tmp->next = newNode; /* inserts new node into array */ 
    tmp = newNode;  /* points head to newly added node */ 
} 

ヘッドポイント:

+2

を[MCVE]を入力してください。物語のように伝える必要はありません。 MCVEを提示するのは、ブロックの説明だけでなく、そのような簡単なコードを自分のためだけに読むことができるからです。また、1つのブロックにすべてが含まれているので、必要に応じて誰でも簡単にコピーできます。 – kaylum

+0

'nodeArray'とは何ですか? 'Node * head = * Node [setNumber];という意味ですか? '? – Sanich

+0

編集の詳細を参照してください。 – namarino

答えて

1
while (tmp->next) { 
    tmp->next = newNode; /* inserts new node into array */ 
    tmp = newNode;  /* points head to newly added node */ 
} 

を使用すると、次のノードにrefrenceを失って、すぐ隣のヘッドにnewNodeを追加しています。たとえば、次のようなリストがあります:

[1]->[2]->[3] 

をそして、あなたはそのリストに新しい要素をプッシュする:[4]、あなたがあなたのプッシュ機能(上記のスニペット)を実行したときに起こることです:

tmp = head; // tmp = [1] 
while(tmp->next) { 
    tmp->next = newNode; // [1]->next = [4] 
    tmp = newNode; // tmp = [4] 
} 

次回は '(tmp-> next)'と評価されます:[4] - > nextと評価され、NULLになり、ループが解除されます。あなたのリストには、次のようになります。あなたは、もはやそれを参照ポインティングを持っていないので、

[1]->[4] 

他の要素は、あなたが後でそれらを解放することができなくなりますので、これはメモリリークと呼ばれ、失われます。

あなたのプッシュ機能をこのように記述することができます。

tmp = head; 
while(tmp->next) 
    tmp = tmp->next; 
tmp->next = newNode // Adds new node to the tail of the linked list 
+0

申し訳ありませんが、もう少し詳しく説明できますか? – namarino

+1

@ナナリノもちろん。これはあなたのスニペットで起こっていることです:例えば、あなたはこのリスト[1] - > [2] - > [3]を持っており、あなたは[4]を追加します。あなたはtmp = [1]を設定しています。あなたのループが最初に実行されるとき、あなたはtmp-> next = newNodeを設定します。、[1] - > next = [4]、その後にtmp = newNode、iを設定します。すなわち、tmp = [4]である。だから、次にループするときには、あなたが期待しているように、[4] - > [next]ではなく[next]で評価されます。プッシュ後の最終リストは[1] - > [4]、[2] - > [3]は永遠に失われます。 – k3oy

+0

それはたくさんの意味があります。私が言ったところで私が行ったように私のヘッドポインタへのポインタを作ることは良い考えですか?Node * head = * nodeArray [setNumber]; \t、次にNode * tmp = head;または私はちょうど頭と直接作業する必要がありますか? – namarino

1

これはこの後です。

これは問題です。 実際、newNodeの挿入は問題です。あなたはそれを変更する必要があります。

+0

newNode->次にnewNodeをポイントするのはいつですか?このように初期化されておらず、このループは頭が何を指しているかだけを変更するように見えます。 –

1

新しいノードを配列の終わり(別名プッシュ)に追加しようとしているとします。 ので、この方法を試してください。このスニペットで

Node tmp=head; /* pointer to the head of list */ 
while (tmp->next) tmp=tmp->next; /* step from Node to Node till the last one */ 
tmp->next=newNode; /* tell that last one to point to the new Node you created */ 
1

あなたはこの線で黒丸リンクリストを作った:ので、この後、実際にあなたが `tmp->はnewNode->next = newNodeを取得

while (!tmp->next) { 
    tmp->next = newNode; /* inserts new node into array */ 
    tmp = newNode;   /* points head to newly added node */ 
} 

次= tmp。

ので、代わりにこのあなたがこれを行う必要があります。

while (tmp->next) { 
    tmp = tmp->next; //Find the last node 
} 
tmp->next = newNode; //Inserts new node into the end of the array 
+0

tmpは頭部へのポインタです。ノード*ヘッド= *ノード配列[setNumber];ノード* tmp =ヘッド; – namarino

+0

@namarino編集してください – Sanich