2013-04-10 71 views
0

我已經看到一些關於如何打印鏈表的其他文章,但沒有一篇對我有幫助,因此我決定發佈自己的代碼。這是問題:在C程序中打印鏈表

我能夠添加一個名字和年齡完全正常,但第二個我添加另一個名稱和年齡它覆蓋了前一個。

所以,如果我輸入:

馬特和21,然後查爾斯和34也只會輸出查爾斯和34 我如何得到它輸出的一切嗎? 非常感謝您的幫助! :)

這裏是我的代碼:

#include<stdlib.h> 
#include<stdio.h> 
#include<malloc.h> 
#include<conio.h> 
#include<string.h> 
#include<ctype.h> 
#define pause system ("pause") 

// prototype variables 
struct node * initnode(char*, int); 
void printnode(struct node*); 

struct node{ 
    char name[20]; 
    int age; 
    struct node *next; 
}; 

struct node *head = (struct node*) NULL; 
struct node *end = (struct node*) NULL; 

struct node* initnode(char *name, int age){ 
    struct node *ptr; 
    ptr = (struct node*) calloc(3, sizeof(struct node)); 
    if(ptr == NULL) 
     return (struct node*) NULL; 
    else { 
     strcpy(ptr->name, name); 
     ptr->age = age; 
     return ptr; 
    } 
} 

void printnode(struct node *ptr) { 
    printf("Name -> %s\n", ptr->name); 
    printf("Age -> %d\n", ptr->age); 
} 


main() { 
    char name[20]; 
    int age, choice = 1; 
    struct node *ptr; 
    while(choice != 3){ 
     system("cls"); 
     printf("1. Add a name\n"); 
     printf("2. List nodes\n"); 
     printf("3. Exit"); 
     printf("\nEnter Menu Selection: "); 
     scanf("%d", &choice); 
     switch(choice) { 
     case 1: printf("\nEnter a name: "); 
      scanf("%s", name); 
      printf("Enter age: "); 
      scanf("%d", &age); 
      ptr = initnode(name, age); 
      break; 
     case 2: if(ptr == NULL) { 
       printf("Name %s not found\n", name); 
      } else 
       printnode(ptr); 
      pause; 
      break; 
     case 3: exit(3); 
     default: printf("Invalid Entry"); 
     }// end of switch 


    }// end of main 

} 

哦,我知道了一些「#包括的」可能不是很有用。我一直在添加和刪除代碼。

+4

它看起來不像你正在建造鏈表。例如,「head」和「end」從未被引用。 – 2013-04-10 17:02:50

+1

呵呵,你不需要在C程序中輸入'malloc'的返回值。除此之外,什麼是所有的'NULL'的轉換? – 2013-04-10 17:03:47

+0

你的鑄造是正確的,你不需要在C編程中明確施放,完好無損它**可能**會導致錯誤一段時間......但這也是**不是你的答案** – 2013-04-10 17:07:35

回答

1

雖然您已經定義了headend指針,它們會生成鏈表,但實際上並沒有使用這些指針來存儲新信息。在創建新節點並將其存儲在ptr變量中之後,實際上並未將其存儲在列表中。

我建議添加另一種方法,addnode,它將這個新創建的節點添加到headend指針定義的鏈接列表中。

void addnode(struct node *ptr) { 
    if (end == NULL) { 
     head = ptr; 
     end = ptr; 
    } 
    else { 
     end = end->next = ptr; 
    } 
} 

大體上,我們檢查是否有任何項目已經在列表中;如果不是,列表的開始和結束都將由同一個節點表示:列表中唯一的一個!否則,我們讓當前節點之後的節點成爲要添加的節點,然後將我們的全局指針指向當前最後一個節點。

這使我們能夠維護一個多於一個節點的鏈(列表中的條目)。然後,我們必須在打印整個列表時,從第一個節點(head)到最後一個節點。我們可以用一個簡單的循環做到這一點:而不是簡單地對臨時ptr變量我們main()保持通話printnode(),我們寫:

struct node *current = head; 
while (current != end) { 
    printnode(current); 
    current = current->next; 
} 
+0

我得到「addnode」將是一個新功能,但它會去哪裏? – 2013-04-10 18:09:20

+0

如果你聲明一個原型,它可以在文件頂層的任何地方(即不在任何其他函數中);否則它必須在主要功能之前。 – 2013-04-10 18:26:46

+0

但是,當你在main中調用它時,函數調用是否會在我的情況1下面出現:「ptr = initnode(name,age);」還是會進入案例2? – 2013-04-10 18:52:03

1

只是remamrk:

ptr = (struct node*) calloc(3, sizeof(struct node)); 

是錯誤的,因爲你是分配3 * sizeof(struct node),它應該是

ptr = (struct node*) calloc(1, sizeof(struct node)); 

您的代碼缺少很多東西。您沒有將您創建的節點鏈接到任何鏈接列表。在整個代碼中,您沒有使用next。你必須更多地關注這段代碼。

問題不僅來自鏈接列表的打印。問題來自如何創建鏈表

我可以建議你一個鏈接列表的模板,可以幫助開發這樣的程序。這個模板中包含的功能和宏湯治療鏈表像

  • 增加鏈表的頭
  • 尾部
  • 從鏈表中刪除加入鏈表...

你可以從這裏獲得鏈表模板(list.h)link

以下link包含一個如何使用它的例子

請參閱本款在上面的鏈接

用很少的修改(刪除名單的硬件預取 項目),我們還可以使用這個列表中我們的應用程序。該文件的可用版本 可在此處下載。

0

此行這裏:

ptr = initnode(name, age); 

就是爲什麼你總是覆蓋名/年齡,因爲你聲明的局部節點稱爲ptr和每次添加一個值時您覆蓋與該節點下一個節點。

在你的節點結構中看到struct node *next;元素?您需要點說來,纔能有1個多節點創建的下一個節點,有點像:

ptr->next = initnode(name, age); 

,當涉及到鏈表有第一個節點的特殊情況下,你的第一個節點ptr是空的,所以當你的列表的長度爲0,則需要設置ptrinit_node(),你需要設置ptrnext元素接下來的時間,然後你需要更新PTR,以便它是當前節點:

ptr = ptr->next; 

當然,這樣做會導致你「鬆開」開始列表中。這就是你的head進來的地方。當你開始時,如果你初始化headptr,那麼永遠不要動腦筋,你會永遠記住你的列表開始的位置。

你也有一個變量:

struct node *end = (struct node*) NULL; 

你必須不斷更新與每一位除了以始終指向最後一個元素添加...如果你的關心。正常情況下,endlasttail指針是如果你打算建立一個雙鏈表。

0

我能夠在一個姓名和年齡完全沒有增加,但第二個I 以另一個名稱添加並且其時間覆蓋前一個。

您的代碼不會覆蓋前一個節點,它會用新節點替換它並泄漏之前的節點。 (泄漏是你分配的一塊內存,然後丟失了任何指針,所以你永遠不能釋放它。)下面是創建一個新的節點行:

ptr = initnode(name, age); 

如果ptr是指針到列表中的第一個節點,你應該添加新節點列表的末尾,而不是將其分配給ptr