Search code examples
cbinary-treebinary-search-treepointer-to-pointer

I am trying to load words from a text file into a binary search tree


I am trying to load words from a text file into a binary search tree.

Each line of the file contains one word.

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

typedef struct node node;
struct node {
    node *left, *right;
    char *key;
};

node *newnode(char *key)
{
    node *n = malloc(sizeof(node));
    n->key = malloc(sizeof(key));
    strcpy(n->key, key);
    n->right = n->left = NULL;
    return n;
}

node *insirtNode(node *root, char *key)
{
    if (!root)
        return newnode(key);
    if (strcmp(key, root->key) < 0)
        root->left = insirtNode(root->left, key);
    else if (strcmp(key, root->key) > 0)
        root->right = insirtNode(root->right, key);
    return root;
}

void readFromFileToTree(const char *fname, node **root)
{ 
    // read each line
    FILE *s = fopen(fname, "r");
    if (!s) {
        printf("101");
        exit(0);
    }
    char *t = NULL;
    do {
        char temp[100];
        t = fgets(temp, 40, s); // printf("%s ",temp); to check what words are being insirting and whats not
        *root = (node *)insirtNode(*root, temp);
    } while (t);
    fclose(s);
}

int main()
{
    node *root = NULL;
    readFromFileToTree("anas.txt", &root);
    return 0;
}

the code stops before reading every word from the file and returns -1073740940


Solution

  • The memory size allocated for the word in newnode() is incorrect: n->key = malloc(sizeof(key)); allocates the size of a pointer, not the length of the string plus an extra byte for the null terminator.

    You should use strdup() that allocates and copies the string in a single call:

    node *newnode(const char *key) {
        node *n = malloc(sizeof(node));
        n->key = strdup(key);
        n->right = n->left = NULL;
        return n;
    }
    

    Note also these problems:

    • printf("101"); is a cryptic error message. You should use

       fprintf(stderr, "cannot open %s: %s\n", fname, strerror(errno));
      

      and exit with a non-zero status;

    • the loop in readFromFileToTree() is incorrect: you will pass a null pointer to insirtNode() at the end of file. You should use this instead:

        char temp[100];
        while(fgets(temp, sizeof temp, s)) {
            *root = insirtNode(*root, temp);
        }
      

    Here is a modified version:

    #include <errno.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    typedef struct node node;
    struct node {
        node *left, *right;
        char *key;
    };
    
    node *newnode(const char *key) {
        node *n = malloc(sizeof(*n));
        n->right = n->left = NULL;
        n->key = strdup(key);
        return n;
    }
    
    node *insertNode(node *root, const char *key) {
        if (!root)
            return newnode(key);
    
        int cmp = strcmp(key, root->key);
        if (cmp < 0)
            root->left = insertNode(root->left, key);
        else
        if (cmp > 0)
            root->right = insertNode(root->right, key);
        return root;
    }
    
    node *readFromFileToTree(const char *fname) {
        node *root = NULL;
        FILE *fp = fopen(fname, "r");
        if (!fp) {
            fprintf(stderr, "cannot open %s: %s\n", fname, strerror(errno));
            return NULL;
        }
        char temp[100];
        while (fgets(temp, sizeof temp, fp)) {
            root = insertNode(root, temp);
        }
        fclose(fp);
        return root;
    }
    
    void freeTree(node *n) {
        if (n) {
            freeTree(n->left);
            freeTree(n->right);
            free(n);
        }
    }
    
    int main() {
        node *root = readFromFileToTree("anas.txt");
        freeTree(root);
        return 0;
    }