2016-12-01 43 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; 
     } 
} 

但是当我打印,我得到一个无限循环打印出新加入的节点的数据字段。可怕的链接列表....我做错了什么?

+2

请提供[MCVE。不需要像故事那样讲它。只需介绍MCVE,因为我们可以在没有块解释的情况下为自己读取这样简单的代码。而且所有功能都在一个模块中,因此如果需要,任何人都可以更容易地进行复制。 – 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] 

你想一个新的元素推入该名单:

tmp = head; // tmp = [1] 
while(tmp->next) { 
    tmp->next = newNode; // [1]->next = [4] 
    tmp = newNode; // tmp = [4] 
} 
:[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

@namarino当然。这就是你的代码片段中发生的事情:例如你有这个列表[1] - > [2] - > [3],并且你将添加[4]。所以你正在设置tmp = [1]。在第一次执行循环时,您将设置tmp-> next = newNode,即,[1] - > next = [4],然后设置tmp = newNode,i。即,tmp = [4]。所以下一次循环时,它会评估[4] - >下一个,而不是[2] - >下一个。推后的最终列表将是[1] - > [4],[2] - > [3]永远丢失。 – k3oy

+0

这很有道理。创建一个指向我的头指针的指针是个好主意,就像我在那里做的那样Node * head = * nodeArray [setNumber]; \t然后Node * tmp = head;或者我应该直接与头部一起工作? – namarino

1

这是因为在此之后:

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

头指向newNode和newNode-> next指向newNode。

这就是问题所在。 其实插入一个newNode是一个问题。你将不得不改变它。

+0

什么时候newNode-> next指向newNode?它不是以这种方式初始化的,而且这个循环似乎只改变头指向的地方。 –

1

我假设你正试图将新的节点添加到你的数组的末尾(又名push)。 所以试试这个:

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

你让这个线的闭合循环链接列表:

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

后,这实际上让您获得newNode->next = newNode这是'TMP-> next = 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是一个指向头部的指针。 Node * head = * nodeArray [setNumber];然后Node * tmp = head; – namarino

+0

@namarino请参阅编辑 – Sanich