将项目插入树

时间:2016-01-11 11:15:10

标签: c

我是C编程新手,我正在编写一个带树的程序。用户提供字符串输入,程序将这些字符串拆分为单词并将这些单词插入树中。当其中一个单词等于" eoi"时,程序停止。当我给出第一个输入时,正确打印v->项(实际上这是root->项)。但是当我给出第二个输入时,v->项有错误的值(它不再是root->项值,而是新输入的值)。

这是我的代码:

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

typedef struct treeNode TreeNode;

typedef struct treeNode {
  char* item;
  TreeNode *left;
  TreeNode *right;
  int freq;

  int rank; 
} TreeNode;

TreeNode* insertItem(TreeNode *root, char* x);

int main(int argc, char** argv) {

    TreeNode *root = NULL;

    char str[100];

    printf("Enter input text : ");
    gets(str);
    printf("Input : %s\n", str);  
    char *tok;
    tok = strtok(str, " ");
    int i,j;
    i = j = 1;

    while((strcmp(tok, "eoi") != 0))
    {           
        printf("%d %s\n", i, tok);          
        i++;
        root = insertItem(root, tok);
        tok = strtok (NULL, " ");       
        while(tok != NULL)
        {
            if(strcmp(tok, "eoi") != 0)
            {
                printf("%d %s\n", i, tok);
                i++;
                root = insertItem(root, tok);
            } 
            else
            {
                j = 0;
                break;
            }  
            tok = strtok (NULL, " ");
        }
        if(j == 0)
        {
            break;
        }
        gets(str);
        printf("Input : %s\n", str);  
        tok = strtok(str, " ");
        i = 1;      
    }   


    return (EXIT_SUCCESS);
}

TreeNode* insertItem(TreeNode *root, char* x) {  

   TreeNode *tmp;
   TreeNode *v = root;  
   TreeNode *pv = NULL; 
   while (v != NULL) {  
      pv = v; 
      printf("v->item : %s\n",v->item);
      if (strcmp(x, v->item) < 0) v=v->left;
      else if (strcmp(x, v->item) > 0) v=v->right;
           else { 
                  printf("%s already exists.\n", x);
                  tmp->freq++;
          return root;
           }   
   }

   tmp = (TreeNode *)malloc((strlen(x) + 1) * sizeof(TreeNode));
   tmp->item=x; tmp->left=tmp->right=NULL;
   tmp->freq = 1;
   if (root != NULL) { 
      if (strcmp(x, pv->item) < 0) pv->left=tmp;
         else pv->right=tmp;
   } else root=tmp;
   printf("root->item: %s", root->item);
   return root; 
}

例如,在开始时使用输入:one two 现在v-&gt;项目是一个 然后输入输入:five six v-&gt;项目是五,但我应该是一个 程序崩溃了。

有人可以帮我解决吗?

3 个答案:

答案 0 :(得分:1)

问题是char str[100];中缓冲区main()的重用,以及tmp中未初始化指针insertItem()的取消引用:

main()中,gets()(您绝对永远不应该使用)使用第一个输入填充char str[100] - 缓冲区,然后将缓冲区标记为-place,所以str现在包含

"one\0two\0[garbage]"

您将令牌插入树中,这样可以正常工作,因为两个字符串比较不相等。但是,当您读取下一个输入时,缓冲区将被重用。标记化后,str包含

"five\0six\0[garbage]"

现有树节点中的指针指向此缓冲区! Particaluarly,第一个树节点的char *item指向"five\0",因此strcmp()比较相等,正如我的评论中所指出的那样,tmp取消引用insertItem() tmp = (TreeNode *)malloc((strlen(x) + 1) * sizeof(TreeNode));在初始化之前。

可能实际上并不想在insertItem()中分配tmp = malloc(sizeof(*tmp)); // == sizeof(TreeNode) tmp->item = strdup(x); // or tmp->item = malloc(strlen(x)+1); strcpy(tmp->item, x); ,而是

def create
  @contry = Contry.find(params[:contry_id])
  @state = @contry.states.create(state_params)
  redirect_to state_path(@state)
end

private
def state_params
  params.require(:state).permit(:name) 
end

答案 1 :(得分:1)

确切的问题在于insertItem(),因为没有内存分配给item。你可以做到

tmp = malloc(sizeof(TreeNode);
tmp->item = malloc(strlen(x)+1);
strcpy(tmp->item,x);

可以在http://ideone.com/nomnJ4看到正在运行的代码。此外,我使用gets避免了scanf的所有并发症,因为您需要及时阅读一个单词。

答案 2 :(得分:1)

检查以下修订后的代码。在行上评论了4个变化:

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

typedef struct treeNode TreeNode;

typedef struct treeNode {
    char item[100];     // change-1
    TreeNode *left;
    TreeNode *right;
    int freq;

    int rank;
} TreeNode;

TreeNode* insertItem(TreeNode *root, char* x);

int main(int argc, char** argv) {

    TreeNode *root = NULL;

    char str[100];

    printf("Enter input text : ");
    gets(str);
    //printf("Input : %s\n", str);
    char *tok;
    tok = strtok(str, " ");
    int i,j;
    i = j = 1;

    while((strcmp(tok, "eoi") != 0))
    {
        printf("%d %s\n", i, tok);
        i++;
        root = insertItem(root, tok);
        tok = strtok (NULL, " ");
        while(tok != NULL)
        {
            if(strcmp(tok, "eoi") != 0)
            {
                printf("\n%d %s\n", i, tok);
                i++;
                root = insertItem(root, tok);
            }
            else
            {
                j = 0;
                break;
            }
            tok = strtok (NULL, " ");
        }
        if(j == 0)
        {
            break;
        }
        printf("\nEnter input text : ");    // change-3: added
        gets(str);
        printf("Input : %s\n", str);
        tok = strtok(str, " ");
        i = 1;
    }


    return (EXIT_SUCCESS);
}

TreeNode* insertItem(TreeNode *root, char* x) {

    TreeNode *tmp;
    TreeNode *v = root;
    TreeNode *pv = NULL;
    while (v != NULL) {
        pv = v;
        printf("v->item : %s\n",v->item);

        if (strcmp(x, v->item) < 0)
            v=v->left;
        else if (strcmp(x, v->item) > 0)
            v=v->right;
        else {
            printf("%s already exists.\n", x);
            v->freq++;  // change-2
            return root;
        }
    }

    tmp = (TreeNode *)malloc((strlen(x) + 1) * sizeof(TreeNode)); // change-4
    strcpy(tmp->item,x); tmp->left=tmp->right=NULL;
    tmp->freq = 1;
    if (root != NULL) {
        if (strcmp(x, pv->item) < 0) pv->left=tmp;
        else pv->right=tmp;
    } else root=tmp;
    printf("root->item: %s", root->item);
    return root; 
}

输出:

Enter input text : 1 2 3
1 1
root->item: 1
2 2
v->item : 1
root->item: 1
3 3
v->item : 1
v->item : 2
root->item: 1
Enter input text : 3 4 5
1 3
v->item : 1
v->item : 2
v->item : 3
3 already exists.
----root->item: 1
2 4
v->item : 1
v->item : 2
v->item : 3
root->item: 1
3 5
v->item : 1
v->item : 2
v->item : 3
v->item : 4
root->item: 1
Enter input text : eoi