2014-03-27 188 views
0

我正在編寫遞歸打印鏈接在一起的節點的字符的代碼。這些節點被鏈接在一起創建一個「映射」(簡單地說就是從結構到其他節點的指針)。該結構實現如下:什麼導致分段錯誤?

typedef struct Node *node_ptr; 

struct Node{ 
    char ch; 
    node_ptr firstPtr; 
    node_ptr secondPtr; 
    node_ptr thirdPtr; 
}; 

現在,我需要打印出如何x節點的步驟方式。我從存儲在int變量中的控制檯獲取該值,並將其傳遞給函數。我也傳遞一個指向Node的指針。該功能實際上打印出正確的輸出,但是出現了兩個小錯誤。

例如,我有一個節點我叫「A」。 「A」的ch字段爲'A',並且我的每個節點ch字段都將是我稱爲指向節點的指針以使其變得簡單。一個簡單的例子我想是這樣的:

節點A:

ch -> 'A'; 
    A->firstPtr = B; 
    A->seondPtr = NULL; 
    A->thirdPtr = NULL; 

節點B:

ch = 'B'. 
B->firstPtr = A; 
B->secondPtr = C; 
B->thirdPtr = F; 

所以,如果我用戶輸入A和距離遠離爲2,它應該打印出來:B,C,F。

我寫的遞歸函數是這樣做的,但也打印出A.這很可能是因爲B也指向A並且它也打印出來,但我認爲我處理那種情況和它仍然如此。另外,它在程序結束時給出了分段錯誤,我不知道爲什麼。下面是遞歸函數:

void print_levels(int dist, node_ptr aNode){ 
if(dist == 0){ 
// if int is zero, do nothing we are done. 
} 
else{ 
    /* 
    if there is pointer (doesn't point to NULL) and if the Node it's pointing 
    to does not have the same "ch" as the current Node. 
    */ 
    if(aNode->firstPtr && !(aNode->firstPtr->ch == aNode->ch)){ 
     printf("%c\n", aNode->firstPtr->ch); 
    } 
    if(aNode->secondPtr && !(aNode->secondPtr->ch == aNode->ch)){ 
     printf("%c\n", aNode->secondPtr->ch); 
    } 
    if(aNode->thirdPtr && !(aNode->thirdPtr->ch == aNode->ch)){ 
     printf("%c\n", aNode->thirdPtr->ch); 
    } 
    print_levels(dist-1, aNode->firstPtr); 
    print_levels(dist-1, aNode->secondPtr); 
    print_levels(dist-1, aNode->thirdPtr);  
} 
} 

我所問的是爲什麼它在我給了有關的例子,它也打印出和爲什麼這導致段錯誤?我對C相對陌生,並且非常感謝所有的幫助和洞察力。

+2

你有沒有malloc'ed你的指針 - 'firstPtr','第二'等? – brokenfoot

+0

調試器告訴你什麼。它至少會告訴你什麼是你正在死亡的行 – pm100

+1

當print_level的第二個參數是NULL時,它正在出現分段錯誤,因爲遞歸調用最終將成爲print_levels(dist-1,NULL-> secondPtr) '和'print_levels(dist-1,NULL-> thirdPtr)'。 – alvits

回答

1

您致電:

print_levels(dist-1, aNode->firstPtr); 
print_levels(dist-1, aNode->secondPtr); 
print_levels(dist-1, aNode->thirdPtr); 

您應該每個如果aNode->firstPtr前檢查等爲NULL:

if (aNode->firstPtr != NULL) 
    print_levels(dist-1, aNode->firstPtr); 
if (aNode->secondPtr != NULL) 
    print_levels(dist-1, aNode->secondPtr); 
if (aNode->thirdPtr != NULL) 
    print_levels(dist-1, aNode->thirdPtr); 

還是在print_levels檢查aNode爲NULL,就回到:

void print_levels(int dist, node_ptr aNode){ 
    if (dist == 0 || aNode == NULL){ 
+0

添加這兩個東西(這當然是不必要的),並沒有改變任何東西 – user3268401

+0

這不是沒有必要的,你測試它們在執行printf之前是否爲NULL,但是在遞歸調用之前不是這樣,在這種情況下會出現分段錯誤。如果你知道當然有必要做什麼,那就做你應該做的事吧,再見。 – CMoi

1

1)打印出來的原因是,一旦你遞歸y電話print_levels()aNode指的是當前節點而不是前一個節點。因爲圖中存在循環,所以A被打印:一旦aNode是B,aNode->是'B',因此aNode->firstPtr->ch是'A'並且因爲它不等於'B'而被打印。如果您想要避免打印初始節點,您可以將其他字符傳遞給print_levels函數並檢查它是否相等。

2)分段錯誤是一個運行時錯誤,如果沒有看到所有的代碼,這個錯誤就會更加困難。我建議你在調試器(例如gdb)中運行代碼,找出錯誤發生的位置(堆棧跟蹤)。正如註釋中所指出的,確保所有變量在使用前都被初始化。特別要確保aNode不是NULL(aNode && aNode->firstPtr && !(aNode->firstPtr->ch == aNode->ch)),否則訪問aNode->firstPtr是未定義的行爲。

0

我認爲你的鏈表中有循環,並導致分段錯誤。 A指向B並且B再次指向A等等。你應該實現一些東西來避免循環。