2017-10-19 41 views
1

我試圖插入一個節點到鏈表的末尾,並且所有的工作都像奇蹟般,但是,當它涉及到最後一個元素時,它會打印出null。有問題必須在else塊,我在想,當我尋找的最後一個項目可能指向NULL而不是有next作爲NULL鏈接列表,一個元素會丟失

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


#define HOW_MANY 7 
char *names[HOW_MANY]= {"Simon", "Suzie", "Alfred", "Chip", "John", "Tim", 
       "Harriet"}; 
int ages[HOW_MANY]= {22, 24, 106, 6, 18, 32, 24}; 

struct person { 
    int age; 
    char *name; 
    struct person *next; 
}; 


struct person* insert_end(struct person *ptr, char *name, int age) 
{ 
    //The new location for the new person 
    struct person* newPer = malloc(sizeof(struct person)); 
    if (newPer == NULL) { 
     printf("something went wrong allocating the memory\n"); 
     exit(1); 
    } 

    newPer -> name = name; 
    newPer -> age = age; 
    //Make its next points previous element 
    if (ptr->next == NULL) { 
    newPer -> next = ptr; 


    return newPer; 
    } 
    else { 
    struct person *tmp = ptr; 
    while(tmp -> next != NULL){ 
     tmp = tmp -> next; 

    } 
    printf("%s", tmp -> name); 
    tmp -> next = newPer; 


    //if(strcmp("Harriet",name)==0) 
    return ptr; 
    } 
    //return the new address so that it becomes the new HEAD of the linked list 
    return newPer; 
} 


int main(int argc, char **argv) 
{ 
    //This is the head of the list 
    struct person *HEAD = NULL; 
    HEAD = malloc(sizeof(struct person)); 
    if (HEAD == NULL) { 
     printf("something went wrong allocating the memory"); 
     exit(1); 
    } 


    int i; 
    //insert a new person and make HEAD points to it, so that HEADS 
    //will be pointing to the last element added to the linked list. 
    for (i = 0; i < HOW_MANY; i++){ 
     HEAD = insert_end (HEAD, names[i], ages[i]); 
    } 

    struct person* tmp = HEAD; 
    //We can use the member name(pointer) as the condition, if we did then extra 
    //unwanted elements added to the linked list by accident won't be printed 
    while (tmp != NULL){ 
    if (tmp -> next != NULL) 
     printf("The name is %s, the age is %d years\n", tmp->name, tmp->age); 

    //store the pointer in a tmp so than we can access the next pointer then 
    //free tmp 
    struct person* prevtmp = tmp; 
    tmp = tmp -> next; 
    free(prevtmp); 
    } 
} 

輸出是

The name is Simon, the age is 22 years 
The name is (null), the age is 0 years 
The name is Suzie, the age is 24 years 
The name is Alfred, the age is 106 years 
The name is Chip, the age is 6 years 
The name is John, the age is 18 years 
The name is Tim, the age is 32 years 
+0

這段代碼甚至應該在最後一位做什麼?只是列出清單? –

+0

你的第一個分配元素('main'的頂部)永遠不會獲得'name'。 –

+0

最後一點只是將所有內容都打印出來 – Zed

回答

1
元素

只需將if (tmp -> next != NULL)更改爲if (tmp != NULL)即可。你忘了列表中的最後一個節點沒有「下一個」節點。

+0

這似乎工作,但它也打印空行。所以如果我有一個指向結構的指針而沒有初始化結構,那麼這不意味着它的成員是NULL? – Zed

+0

@Zed否,它不會,你也需要將其初始化爲NULL,正如其他人指出的那樣。 – mnistic

1

確保newPer->next設置爲NULL

newPer -> name = name; 
    newPer -> age = age; 
    newPer -> next = NULL; 

與您的定點相同HEAD

HEAD = malloc(sizeof(struct person)); 
    if (HEAD == NULL) { 
     printf("something went wrong allocating the memory"); 
     exit(1); 
    } 
    HEAD->name = "HEAD"; 
    HEAD->age = -1; 
    HEAD->next = NULL; 
+0

與主功能中的HEAD相同。 – EdmCoff

+0

@Zed可以考慮讓'Simon'開頭,然後在1 – Bl4ckb0ne

+0

開始你的填充循環這不就意味着我有一個不同的根,而不是有根作爲一個有效的結構,但它指向一個NULL指針? – Zed

0

您初始化*HEAD作爲NULL,但你永遠不填充一個人該地址,這樣NULL被推至年底,並在那裏停留。試試在你的函數的頂部添加此:

if (*ptr == NULL){ 
    newPer = ptr 
} 
else { 
    struct person* newPer = malloc(sizeof(struct person)); 
    if (newPer == NULL) { 
     printf("something went wrong allocating the memory\n"); 
     exit(1); 
    } 
} 

您可能需要改變一對夫婦的其他條件,但這個想法是,你需要檢查是否newPer是列表中的第一項,以及怎麼改你處理這種情況。

+0

由於NULL被認爲是一個指針值,我不允許將一個結構與一個指針進行比較 – Zed

+0

@Zed,上例中的newPer是一個指針,您可以隨時將NULL與任何指針進行比較。 – jwdonahue

0

首先,未初始化的列表頭應始終爲NULL。插入函數應該檢測到這一點,並簡單地返回正確初始化的第一個節點。之後,您可以根據您的邏輯p->next是否爲NULL。你幾乎不得不重寫好一段代碼才能正確使用它。對於'insert_end'應該總是返回它交給它的頭指針,'insert_front'應該總是返回新的節點,因爲它總是新的頭部。

+0

我認爲我的頭部爲NULL,我不明白函數應該檢測到的第二部分。對於返回指針,我做了你所說的。你能澄清第二部分嗎? – Zed

+0

在'main'中,通過調用'malloc'初始化第一個節點。所有列表管理都應在列表管理功能中完成。這就是所謂的分離問題。在你的情況下,'main'只是你的列表實現(作業分配?)的測試驅動程序,它不應該參與列表管理,除了保持頭指針,其他函數返回給它。 – jwdonahue