Loading data to construct a ternary tree not working properly(C)

Viewed 42

I have build a structure of a ternary tree and also some functions to do basic operations with it. One of them is reading word by word from a file and construct the tree! The problem is probably in function read_words. When i insert manually the data works fine but when i try to do it from a File it just makes the tree with contents from the last data input.

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



typedef struct a{ 
    char * word ;
    int occurs;
    struct a * left;
    struct a * same;
    struct a * right; } Node; 
    
typedef Node * Node_ptr ;
typedef Node * TriTree ;

void inorder(TriTree x) {
    if(x==NULL) return;
    inorder(x->left);
    printf("%s(%d)--" , x->word, x->occurs);
    inorder(x->same);
    inorder(x->right);
    return;}

void strlower(char * lower){
    for (char *p = lower; *p; ++p) *p = tolower(*p);
    // printf("%s\n",lower);
};
// 1
Node_ptr create(char * word){
    Node_ptr tmp_ptr;
    tmp_ptr = (Node_ptr)malloc(sizeof(Node));
    tmp_ptr-> word = word;
    tmp_ptr-> occurs = 1;
    tmp_ptr-> left = NULL;
    tmp_ptr-> same = NULL;
    tmp_ptr-> right = NULL;
    return tmp_ptr;
}
TriTree insert(TriTree x, Node_ptr node_ptr){
    if(x==NULL){
        // printf("%s\n","Empty Tree!");
        x = node_ptr;
        return x;
    }

    int ret;
    strlower(x->word);
    strlower(node_ptr->word);
    ret = strcmp(x->word,node_ptr->word);
    if(ret < 0) {
    //   printf("str1 is less than str2");
      x->right = insert(x->right,node_ptr);
    } else if(ret > 0) {
    //   printf("str2 is less than str1");
      x->left = insert(x->left,node_ptr);
    } else {
    //   printf("str1 is equal to str2");
      x->same = insert(x->same,node_ptr);
    }
    return x;
} ;


TriTree read_words (FILE *f,TriTree x) {
    char c[1024];

    while (fscanf(f, " %1023s", c) == 1) {
        Node_ptr tmp; 
        // printf("%s\n",c);
        tmp = create(c);
        printf("%s\n",tmp->word);
        x = insert(x,tmp);
        //free(tmp);
    }
    fclose(f);

    return x;
}


int main()
{
    TriTree x;
    x = NULL;
   
    FILE * fp = fopen("input.txt", "r");
        
    x = read_words(fp,x);
    inorder(x);
    return 0;
}
input:
hello bye ask life BYE Hello night HeLLO

desired output:
ask bye BYE hello Hello HeLLo life night

my output:
hello hello hello hello hello hello hello hello
1 Answers

Within the function create

Node_ptr create(char * word){
    Node_ptr tmp_ptr;
    tmp_ptr = (Node_ptr)malloc(sizeof(Node));
    tmp_ptr-> word = word;
   //...

you are assigning the pointer word used as a parameter to the data member tmp_ptr->word.

But you are passing the same pointer in each call of create from the function read_words

TriTree read_words (FILE *f,TriTree x) {
    char c[1024];

    while (fscanf(f, " %1023s", c) == 1) {
        Node_ptr tmp; 
        // printf("%s\n",c);
        tmp = create(c);
              ^^^^^^^^^

that is the pointer to the first element of the local array

    char c[1024];

that moreover will not be alive after exiting the function.

You need to create dynamically a string with the copy of the passed string in the function create.

Related