使用fgets将文件中的行读入二进制搜索树

时间:2017-10-21 00:24:36

标签: c string pointers data-structures binary-search-tree

目前我试图将我文件中的每个单独行存储到一个字符串中,然后将其存储在二叉搜索树中,但是会出现问题。出于某种原因,当我打印我的BST时,只输出最后一行,而不是第一行。下面是我的代码。

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


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

struct node *newNode(char* item)
{
    struct node* temp = (struct node*)malloc(sizeof(struct node));
    temp->key = item;
    temp->left = NULL;
    temp->right = NULL;
    temp->count = 1;
    return temp;
};

void printInorder(struct node* root)
{
    if(root != NULL)
    {
        printInorder(root->left);
        printf("%s \n", root->key);
        printInorder(root->right);
    }
}

struct node* insert(struct node* node, char* key)
{
    if(node == NULL)//When tree is empty
        return newNode(key);
    if(strcmp(key, node->key) < 0)
        node->left = insert(node->left, key);
    if(strcmp(key, node->key) > 0)
        node->right = insert(node->right, key);

    return node;

};


int main()
{

    struct node *root = NULL;


    int i = 0;
    char str[100];
    FILE* fp;
    fp = fopen("textFile.txt", "r");
    if ((fp = fopen("textFile.txt","r")) == NULL)
    {
        printf("Could not open textFile.txt\n");
        exit(1);
    }

    while(fgets(str, 100, fp) != NULL)
    {
        ++i;
        root = insert(root, str);
        printf("%3d: %s", i, str);

    }


    printf("bst printed\n");
    printInorder(root);

    return 0;
}

textFile.txt包含

bob is working.
david is a new hire.
alice is bob's boss.
charles doesn't like bob.

当打印出bst时,输出的唯一一行是最后一行 查尔斯不喜欢鲍勃。

真的很感激任何帮助。

1 个答案:

答案 0 :(得分:3)

请注意,使用newNode创建节点时,会存储传递给它的指针的副本,而不是指向的字符串的副本。这意味着每次向树中插入值时,它都会在main中存储指向str缓冲区的指针。换句话说,在您第一次插入后,事情看起来像这样:

 +------------+
 |  BST Node  |                            str
 +------------+            +---+---+---+---+---+...+---+
 |    key     | ---------> | b | o | b |   | i |   | 0 |
 +------------+            +---+---+---+---+---+...+---+

当你读到文件的下一行时,你用这行的内容覆盖str,所以图片看起来像这样:

 +------------+
 |  BST Node  |                            str
 +------------+            +---+---+---+---+---+...+---+
 |    key     | ---------> | d | a | v | i | d |   | 0 |
 +------------+            +---+---+---+---+---+...+---+

请注意,即使您从未插入该值,您的BST现在就像包含“david是新员工”一样。因此,当您尝试将“david is a new hire”插入BST时,没有任何反应。

接下来的几次读取会发生同样的事情,直到最后你读到文件的最后一行,当事情看起来像这样:

 +------------+
 |  BST Node  |                            str
 +------------+            +---+---+---+---+---+...+---+
 |    key     | ---------> | c | h | a | r | l |   | 0 |
 +------------+            +---+---+---+---+---+...+---+

这就是为什么你最后只看到关于查理的这一行--BST正在指引您到缓冲区的单个共享副本。

要解决此问题,请使BST存储传入其中的字符串的副本,或者在将字符串存储到树中之前复制字符串。例如,您可能需要newNode函数调用strdup来获取自己要存储的字符串副本:

struct node *newNode(char* item)
{
    struct node* temp = (struct node*)malloc(sizeof(struct node));
    temp->key = strdup(item); // <--- here!
    /* TODO: Error-handling! */
    temp->left = NULL;
    temp->right = NULL;
    temp->count = 1;
    return temp;
};

这应该可以解决您的问题。只要确保在完成后取消分配所有内容!