当参数不为NULL时,递归函数传递NULL指针

时间:2011-11-06 10:59:18

标签: c pointers recursion reference binary-tree

下面的程序旨在使用strcmp函数在二进制搜索树中按字母顺序存储单词。该程序详细说明的问题是在函数的最后部分函数的递归调用中没有传递指针。

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为该单词创建新的存储空间时,该位置不是NULL。

更新:使用双指针的新脚本:

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);
        }

我遇到了分段错误,我不知道为什么。

2 个答案:

答案 0 :(得分:3)

问题是* nod已修改但未返回:更改

void enter_recursively(NOD *nod, char *word)

通过

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

以便返回合法指针。在函数内部,使用* nod代替点头,这是正确的方法。

当您仅将NOD *传递给该函数时,分配的内存未正确存储。就像你想在函数内修改一个int值一样,你传递它的地址,而不是值。

此外,在使用它们之前,请先验证null指针。你可以获得一个核心。

最终的代码接缝如下:

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);
    }

答案 1 :(得分: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 */
}