2017-03-10 61 views
1

我一直有一個很難搞清楚這段代碼:鏈表開頭插入

typedef struct student_grade sg; 

sg *first = NULL; 
sg *renew = NULL; 
sg *temp = NULL; 

int num; 
float g; 
char classname[12], fn[STR_LENS], ln[STR_LENS]; 

printf("Enter the classname (without spaces): "); 
scanf("%11s", classname); 

printf ("Enter the student's name and their grade. Enter 0 0 0 to quit. \n(FirstLast ##.#): "); 



num = scanf("%11s %11s %f", fn, ln, &g); 

while (fn[0] != '0') 
{ 
    if (num == 3) 
    { 
     renew = (sg*) malloc(sizeof(sg)); 

     strncpy(renew->first_name, fn, STR_LENS-1); 
     strncpy(renew->last_name, ln, STR_LENS-1); 
     renew->grade = g; 
     renew->next = first; //next pointer to first 
     first = renew; //assign address of renew to first 
    } 
    else 
    { 
     return 1; 
    } 

    printf("Enter the student's name and their grade.Enter 0 0 0 to quit\n(First Last ##.#): "); 

    num = scanf("%11s %11s %f", fn, ln, &g); 

} 

特別是這部分:

 renew = (sg*) malloc(sizeof(sg)); 

     strncpy(renew->first_name, fn, STR_LENS-1); 
     strncpy(renew->last_name, ln, STR_LENS-1); 
     renew->grade = g; 
     renew->next = first; //next pointer to first 
     first = renew; //assign address of renew to first 

renew被分配結構,指向first指針,它最初是NULL,並且first被指定了與renew相同的地址,然後指向地址renew。在第二次循環之後,同樣的renew顯然被克隆,並且也指向first的地址,然後first的地址被分配與克隆的renew相同的地址。

沒有一個加起來。

回答

0

沒有發生renew的克隆。每次迭代都會分配一塊新的內存(這就是malloc調用的目的),並將指針更改爲引用此新內存。

0

這是一個向鏈表添加新元素的循環。

第一個scanf讀取類名,就是這樣。然後,還有另一種scanf存儲姓,名和等級分爲3個變量,然後while循環開始:

每次代碼malloc新元素的空間分配,然後填充它的3個字段(您沒有顯示struct student_grade的定義,但我們可以推斷出它具有first_name,last_namegrade)字段,方法是將用戶使用scanf插入的數據複製到這些數據中,然後再處理鏈表兩行:我們在開始時插入,這意味着新元素將成爲第一個元素。因此,renew->next = first;確保在我們正在創建的元素之後的元素(它不在列表中!)是當前的第一個(它將成爲下一行的第二個元素),然後與first = renew;程序確保從現在開始,名單將從我們添加的元素開始。

在循環結束時,新的scanf要求提供另一名學生的數據,這些數據與以前一樣存儲在相同的變量中,以便在循環的下一次迭代中將它們複製到結構中,並且它一直持續到用戶插入一個0.

這裏沒有克隆。每次撥打電話malloc時,都會獲得一塊與上一塊不同的新內存塊,其地址暫存在renew中。由於每次都會覆蓋renew,並且您不想丟失它,所以您必須確保它存儲在某處:第一個元素的地址始終存儲在first中,並且每個元素都將指針(next)存儲到下一個元素,這樣就不會丟失地址。每次都不克隆renew;相反,變量總是相同的,但其值(地址)每次都會改變。

0

第二次循環後,同樣的'更新'顯然被克隆...

首先renew未被克隆。一個全新的內存空間被分配給它。

您想將renew添加到列表的開頭。一個不同的指針(first)指向列表的開始。

renew->next = first; - 這條線,你基本上說,「好吧,從這點renew將是第一個項目在我的名單和它的下一個項目將是實際first。基本上renew是我的清單中的第0項。「

first = renew; - 您有指針指向您的列表開頭。您還希望first點指向列表的開始。所以解決方法是將first指針設置爲指向first指針所指向的內存位置。現在,您的指針都會正確指向列表中的第一個項目。

renew基本上用作輔助指針。它有助於將新項目添加到列表中。另一方面,first指針是你列表的重要組成部分。它的工作是指向列表中的第一個元素。