2017-08-12 123 views
2

我想用一個鏈表來編寫一個簡單的字典,但是我在調​​用顯示函數後不斷丟失數據。C數組鏈接列表,將數組鏈接列表分配給另一個

這裏是我的結構定義

typedef struct node{ 
    int elem; 
    struct node *next; 
}*L; 

typedef L Dictionary[10]; 

這是我的顯示

void display(Dictionary A) 
{ 
    int i; 
    for(i=0;i<10;i++){ 
     printf("A[%d]: ",i); 
     while(A[i]!=NULL){ 
      printf("%d\t",A[i]->elem); 
      A[i] = A[i]->next; 
     } 
     printf("\n"); 
    } 
} 

對此的解決方案是一個臨時變量。

我試圖

Dictionary tempStruct 
for(i=0;i<10;i++){ 
    tempStruct[i] = A[i]; 
} 

和它的作品。但是有沒有其他方法可以分配比這個更有效的鏈表?

tempStruct = A; 

並沒有真正的工作,我得到incompatible types node** to Dictionary{*node[10]}

回答

2

您可以在顯示功能改變循環到這一點:

for(i=0;i<10;i++){ 
    printf("A[%d]: ",i); 
    L tmp = A[i]; 
    while(tmp!=NULL){ 
     printf("%d\t",tmp->elem); 
     tmp = tmp->next; 
    } 
    printf("\n"); 
} 

沒有必要對整個陣列複製,簡單通過鏈接列表導航的臨時指針就足夠了。

旁註:對於數組的副本,你試圖分配tempStruct = A;。有兩個原因不起作用:

  • 在你的函數中,A沒有數組類型。 C不支持將數組傳遞給函數。當一個函數有一個數組類型的參數時,它會自動調整爲一個指針類型,而不是傳遞一個數組,而是傳遞一個指向數組第一個元素的指針。這種效果通常表示爲陣列衰減爲指針,這就是您的消息incompatible types node** to Dictionary{*node[10]}的原因。

  • 即使A數組類型,但它仍然是行不通的,因爲C不允許分配到一個數組。這有點令人驚訝,因爲同樣的事情可以用於struct。我想不出在C中不允許分配數組的原因,你應該記住你不能。當然,你可以做手工,如果你不希望每一個元素分配,你可以使用函數memcpy(),在string.h聲明:

    int foo[5]; 
    int bar[5] = {1, 2, 3, 4, 5}; 
    
    // instead of foo = bar; 
    memcpy(foo, bar, sizeof foo); 
    

無關你的問題,但是我很難理解這段代碼。你的typedef是可讀性災難性的。 永遠不會將指針隱藏在typedef之後 - 爲了理解處理指針的代碼,重要的是指針是明顯的。數組類型的typedef至少也是有問題的。我建議以下代碼:

typedef struct node { 
    int elem; 
    struct node *next; 
} node; 
// not strictly necessary, but IMHO, if you want to typedef a struct type, 
// it's the least confusing option to name it the same as the struct tag. 

#define DICTSIZE 10 

void display(node **a) // variable names are often lowercase by convention 
{ 
    // to cope with ANY possible size, you need size_t, int might be too small 
    // include stddef.h or stdlib.h to use it. Of course, with 10 elements, 
    // int is enough. 
    for (size_t i = 0; i < DICTSIZE; ++i) { 
     printf("a[%zu]: ", i); 
     node *tmp = a[i]; 

     // now it's obvious tmp is a pointer, so no need to explicitly 
     // write the != NULL ... (any pointer that's not NULL evaluates true) 
     while (tmp) { 
      printf("%d\t", tmp->elem); 
      tmp = tmp->next; 
     } 
     printf("\n"); 
    } 
} 

同樣要注意一些額外的空間大大提高了代碼(因此,使用它們)的可讀性。


我會考慮原來的顯示功能,因爲它修改它所顯示出來。這不是顯示數據的功能的預期行爲。如果你想進一步改進你的代碼,你應該使用const來明確該函數不應該修改它接收到的內容,所以編譯器可以捕獲錯誤。在上面的例子中,display簽名應該更好的是這樣的:

void display(const node *const *a) 

第一const將使任何struct node不變,第二const(星號)之後,使你的指針數組一成不變英寸有了這個,你也必須寫

const node *tmp = a[i]; 

因爲你不能指定一個const指針指向非const指針。

+1

良好的聲音螺母和螺栓編程建議。 –

0

在你的顯示功能中,你用A[i] = A[i]->next;修改字典數組的條目,這樣就會破壞數據結構並丟失數據。

你應該使用一個局部變量來枚舉每個列表:

void display(Dictionary A) { 
    struct node *n; 
    int i; 
    for (i = 0; i < 10; i++) { 
     printf("A[%d]:", i); 
     for (n = A[i]; n; n = n->next) { 
      printf(" %d", n->elem); 
     } 
     printf("\n"); 
    } 
} 

隱藏指針和數組類型定義的背後,是一個壞主意,它會導致混亂的代碼爲讀者和程序員都。你應該只是typedef struct node node;並使用顯式指針和數組。