C 实现搜索功能后的二叉树分割错误

C 实现搜索功能后的二叉树分割错误,c,segmentation-fault,structure,binary-tree,C,Segmentation Fault,Structure,Binary Tree,我正试图写一个程序,将做以下事情 -read a file from std in -read each line, and add each line to a binary tree *if name is already in binary tree,dont add the name to the tree again but update its count of repititions -print out the binary tree 正在读取的文件看起来像 dylan bo

我正试图写一个程序,将做以下事情

-read a file from std in
-read each line, and add each line to a binary tree
 *if name is already in binary tree,dont add the name to the tree again but update its count of repititions
-print out the binary tree
正在读取的文件看起来像

dylan
bob
dylan
randall
randall
所以当我打印出二叉树时,我希望它打印出来

bob 1
dylan 2
randall 2
我能够成功地打印出姓名,而不用担心重复。我已经注释掉了那些把我的程序弄得一团糟的代码块,这些代码块与我的搜索函数交互,我在事后添加了搜索函数来处理重复。该代码构建了一个二叉树,每个“左”是一个由4部分组成的结构,即名称、计数以及指向左、右child的指针

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct node {
    char* name;
    int count;
    struct node* left;
    struct node* right;
};

struct node* addNode(char* string);
void insert(struct node *root, char* stringgg);
void preorder(struct node *root);
int search(struct node* leaf,char* string2find);

int main()
{
    char buffer[20];
    struct node *root = NULL;

    while( fgets(buffer, sizeof(buffer), stdin) != NULL )
    {
        if(root == NULL)
            root = addNode(buffer);
        else

            insert(root,buffer);

    }
    preorder(root);

}

struct node* addNode(char* string)
{
    struct node *temp = malloc(sizeof(struct node));
    temp->name = malloc(strlen(string) + 1);
    strcpy(temp->name,string);

    temp->left = NULL;
    temp->right = NULL;
    return temp;
}

void insert(struct node *root, char* stringgg)
{
   /* int flag = 5;
    flag = search(root,stringgg);
    if(flag == 1)
        return; */

    if(strcmp(stringgg,root->name) < 0)
    {
        if(root->left == NULL)
            root->left = addNode(stringgg);
        else
            insert(root->left, stringgg);
    }
    else
    {
        if(root->right == NULL)
            root->right = addNode(stringgg);
        else
            insert(root->right,stringgg);
    }
}

/*int search(struct node* leaf,char* string2find)
{
    if(strcmp(string2find,leaf->name) == 0)
    {
        leaf->count = leaf->count + 1;
        return 1;
    }
    else if(strcmp(string2find,leaf->name) < 0)
    {
        return search(leaf->left,string2find);
    }
    else
    {
        return search(leaf->right,string2find);
    }
    return 0;

} */

void preorder(struct node *root)
{
    if(root == NULL)
        return;
    printf("%s",root->name);
    preorder(root->left);
    preorder(root->right);

}
#包括
#包括
#包括
结构节点{
字符*名称;
整数计数;
结构节点*左;
结构节点*右;
};
结构节点*添加节点(字符*字符串);
void insert(结构节点*root,字符*stringgg);
无效预订单(结构节点*根);
int搜索(结构节点*leaf,char*string2find);
int main()
{
字符缓冲区[20];
结构节点*root=NULL;
while(fgets(buffer,sizeof(buffer),stdin)!=NULL)
{
if(root==NULL)
root=addNode(缓冲区);
其他的
插入(根、缓冲区);
}
前序(根);
}
结构节点*添加节点(字符*字符串)
{
结构节点*temp=malloc(sizeof(结构节点));
temp->name=malloc(strlen(string)+1);
strcpy(临时->名称,字符串);
temp->left=NULL;
temp->right=NULL;
返回温度;
}
空插入(结构节点*根,字符*字符串)
{
/*int标志=5;
标志=搜索(根,stringgg);
如果(标志==1)
返回*/
if(strcmp(stringgg,root->name)<0)
{
如果(根->左==NULL)
root->left=addNode(stringgg);
其他的
插入(根->左,stringgg);
}
其他的
{
如果(根->右==NULL)
root->right=addNode(stringgg);
其他的
插入(根->右,stringgg);
}
}
/*int搜索(结构节点*leaf,char*string2find)
{
if(strcmp(string2find,leaf->name)==0)
{
叶->计数=叶->计数+1;
返回1;
}
else if(strcmp(string2find,leaf->name)<0)
{
返回搜索(叶->左,string2find);
}
其他的
{
返回搜索(叶->右,string2find);
}
返回0;
} */
无效预订单(结构节点*根)
{
if(root==NULL)
回来
printf(“%s”,根->名称);
预订单(根->左);
预订单(根->右);
}
上面的代码打印出所有名称,即使树中已经有名称。我希望有人能指出我的搜索功能错误,这样在打印时就不会导致分割错误。可能的原因可能是我不恰当地使用了return函数,在这个函数中,我试图返回main if flag==1,这意味着找到了匹配项,所以不要添加节点。但如果flag不等于1,则找不到匹配项,因此继续添加节点。

在main

while( fgets(buffer, sizeof(buffer), stdin) != NULL ){
    char *p = strchr(buffer, '\n');
    if(p) *p=0;//remove '\n'
在addNode

temp->count = 1;//initialize counter
return temp;
插入时

void insert(struct node *root, char* stringgg){
    int cmp_stat = strcmp(stringgg,root->name);

    if(cmp_stat == 0)
        root->count++;
    else if(cmp_stat < 0) {
        if(root->left == NULL)
            root->left = addNode(stringgg);
        else
            insert(root->left, stringgg);
    } else {
        if(root->right == NULL)
            root->right = addNode(stringgg);
        else
            insert(root->right,stringgg);
    }
}

错误在于搜索空树中的第一个项目-您调用

    search(root, stringgg)
但是
root
NULL
,所以在
search()
中调用

    strcmp(string2find, leaf->name)
使用
leaf==NULL
时,程序崩溃

解决方法:在更新树之前不要搜索,而是通过搜索来更新它

struct node* update(struct node* nd, const char* str)
{
    int cmp;

    // (sub)tree is empty? - create a new node with cnt==1
    if(nd == NULL)
        return CreateNode(str);

    // test if the node found
    cmp = strcmp(str, nd->name);

    if(cmp == 0)          // YES
        nd->count ++;     // update the counter
    else if(cmp < 0)      // NO - search in a subtree
        nd->left  = update(nd->left,  str);
    else
        nd->right = update(nd->right, str);

    return nd;            // return the updated subtree
}

实际上,
root
值在第一次调用时只会更改一次,并且所有后续赋值都不会更改其值。但是,这会使代码更具可读性。

首先解决这个问题:在
else
之后和
insert(根,缓冲区)之前有一个不必要的新行main()
函数中的code>。确保它是一个可编译的代码。尽管与当前的问题没有多大关系,但我想指出,
intmain()
不一定是
C
intmain(void)
是!如何退出
fgets
循环?在友好的本地调试器下运行时发生了什么事?@wedapasi:standard(ISO/IEC 9899:2011)在§5.1.2.2.1程序启动中说:[
main
]应使用
int
的返回类型定义,并且不带参数:
int main(void){/*…*/}
…或同等产品。尽管我总是编写
intmain(void)
(因为我使用GCC选项进行编译,例如
-Wstrict原型
-Wold样式定义
),但编写
intmain()
并没有错,因为这是一个没有参数的函数。作为其他函数的声明,
int otherfunc()是错误的;它表示“没有关于参数的信息”,应该是
int otherfunc(void)
struct node* update(struct node* nd, const char* str)
{
    int cmp;

    // (sub)tree is empty? - create a new node with cnt==1
    if(nd == NULL)
        return CreateNode(str);

    // test if the node found
    cmp = strcmp(str, nd->name);

    if(cmp == 0)          // YES
        nd->count ++;     // update the counter
    else if(cmp < 0)      // NO - search in a subtree
        nd->left  = update(nd->left,  str);
    else
        nd->right = update(nd->right, str);

    return nd;            // return the updated subtree
}
    root = update(root, buffer);