2011-11-06 120 views
1

以下程序旨在使用strcmp函數按字母順序在二進制搜索樹中存儲單詞。程序中詳述的問題是,函數的最後一部分函數的遞歸調用中沒有傳遞指針。遞歸函數在參數不爲NULL時傳遞NULL指針

typedef struct NodT{ 
    char word[30]; 
    struct NodT *left, *right; 
} NOD; 

void reset_field(NOD *nod){ 
    int i; 
    for(i=0; i<30; i++){ 
     nod->word[i]='\0'; 
    } 
} 

void enter_recursively(NOD *nod, char *word){ 
    if(nod==NULL){ 
     nod= (NOD *) malloc(sizeof(NOD)); 
     nod->left=NULL; 
     nod->right=NULL; 
     reset_field(nod); 
     strcpy(nod->word, word); 
     return; 
    } 

    if(nod->word[0]=='\0'){ 
     strcpy(nod->word, word); 
     return; 
    } 

    if(strcmp(nod->word, word)==0) return; 

    if(strcmp(nod->word, word)<0){ 
     enter_recursively(nod->right, word);//the problem seems to be here 
     printf("right\n"); 
    } 
    else{ 
     enter_recursively(nod->left, word);//...and here 
     printf("left\n"); 
    } 
    //the NULL pointer is being sent over, which is peculiar 
} 

的事情是,當我通過從結構的指針(左,右)的遞歸函數中的if-else條件,它需要對另一側上的NULL值,其中當不可這樣做的原因是,在分配第一個單詞之後,第二個單詞在右側或左側,取決於strcmp,在malloc用於爲單詞創建新存儲空間時進行分配。

更新:使用雙指針的新的腳本:

typedef struct NodT{ 
    int key; 
    char word[30]; 
    struct NodT *left, *right; 
} NOD; 

void enter_recursively(NOD **nod, char *word){ 
     printf("N: %p\n", nod); 
    printf("NL: %p\n", (**nod).left); 
    printf("NR: %p\n", (**nod).right); 
     if(nod==NULL){ 
      nod=malloc(sizeof(NOD));   
      (**nod).left=NULL; 
      (**nod).right=NULL; 
      strcpy((**nod).word, word); 
      return; 
     } 
     if((**nod).word[0]=='\0'){ 
      strcpy((**nod).word, word); 
      return; 
     } 

    if(strcmp((**nod).word, word)==0) return; 

     if(strcmp((**nod).word, word)<0){ 
      enter_recursively((**nod).right, word); 
     } 
     else{ 
      enter_recursively((**nod).left, word); 
     } 

我得到分段錯誤,我不知道爲什麼。

+0

把檢查'點頭== NULL'(或只是'nod' :)之前你曾經試圖訪問其內容。你可能只是傾銷你的堆棧訪問。 –

+2

請在您的編譯器中啓用警告,您使用'return;'在無效函數中使用,這是沒有意義的。同樣,你的拳頭'NULL'檢查將永遠不會匹配,如果'nod'在函數入口處爲null,則會在此之前進行段錯誤檢測。 – Mat

+0

哦對不起,我已經重新編輯了。取得了回報;現在有意義 –

回答

3

的問題是,*點頭修改但不退換:更改

void enter_recursively(NOD *nod, char *word) 

通過

void enter_recursively(NOD **nod, char *word) 

爲了返回合法指針。在函數內部,用*點頭代替點頭,這是正確的方法。

當您只將NOD *傳遞給函數時,分配的內存沒有正確存儲。就像當你想修改一個函數內的一個int值時,你傳遞它的地址,而不是值。

此外,在使用它們之前總是驗證空指針。你可以獲得一個核心。

最終代碼的接縫,如:

void enter_recursively(NOD **nod, char *word){ 
    if (*nod==NULL){ 
     *nod=malloc(sizeof(NOD));   
     (*nod)->left=NULL; 
     (*nod)->right=NULL; 
     strcpy((*nod)->word, word); 
     return; 
    } 
    if((*nod)->word[0]=='\0'){ 
     strcpy((*nod)->word, word); 
     return; 
    } 

    if(strcmp((*nod)->word, word)==0) return; 

    if(strcmp((*nod)->word, word)<0){ 
     enter_recursively(&(*nod)->right, word); 
    } 
    else{ 
     enter_recursively(&(*nod)->left, word); 
    } 
+0

我用NOD *點頭鏈接列表的問題,並返回指針非常好。有什麼不同?你能向我解釋爲什麼雙指針會更好嗎? –

+0

查看我的回答版本 –

+0

噢,如果這是爲BST創建節點的最簡單的形式...它非常複雜。有誰知道一個更簡單的方法來製作一個簡單的BSTree? –

0

您的enter_recursively()函數會分配一個節點,甚至可能會分配給它,但無法將其傳回給調用者。找到一種方法來返回對調用者有用的東西。

更新: 的完整性:這是從孩子送回給其父傳達信息的其他方式:(通過返回值)

NOD * enter_recursively(NOD *ptr, char *word){ 
    int rc; 

    if (ptr==NULL){ 
     ptr = malloc(sizeof *ptr); 
     ptr->left = NULL; 
     ptr->right = NULL; 
     strcpy(ptr->word, word); 
     return ptr; 
    } 

    rc = strcmp(ptr->word, word); 
    if (rc==0) return ptr; 

    if (rc < 0){ 
     ptr->right = enter_recursively(ptr->right, word); 
     fprintf(stderr, "right\n"); 
    } 
    else { 
     ptr->left = enter_recursively(ptr->left, word); 
     fprintf(stderr, "left\n"); 
    } 
    return ptr; /* not reached */ 
} 
+0

我已經重新編輯了,刪除了函數中的指針*右和*,並且添加了nod-> left和nod->右遞歸調用,這是我在第一個原始程序中使用的,也沒有工作。我會嘗試Tio Pepe在其他答案中提出的雙指針。 –

+0

基本上,有兩種方法可以將信息從函數傳回給調用者。顯而易見的方法是使用返回值。另一種方法是使用指針參數(在這種情況下指向指針的指針,因爲要交流的是指針)使用全局變量的第三種方法是可行的,但不可取。 – wildplasser

+0

如果不是使用指向指針的指針,而是將指針存儲的地址複製到另一個指針,並使用全新指針指向的值,該指針指向的地址已被複制? (當我嘗試) –