2011-11-06 101 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

如果不是使用指向指针的指针,而是将指针存储的地址复制到另一个指针,并使用全新指针指向的值,该指针指向的地址已被复制? (当我尝试) –