在树结构中加载字典并卸载它的问题 - C编程

时间:2015-11-14 12:37:33

标签: c pointers dictionary tree cs50

我还在尝试调试我的加载函数,哪个应该加载一个字典文件。我一次又一次地重写我的代码,但没有结果......我知道我们需要有特定的问题,但现在我只有很多问题。所以,我会按照我认为的错误来源。我认为我没有正确地初始化我的两个指针,通过初始化,我的意思是分配内存并为它们定义一个特定类型的值。

在那里,我如何定义和初始化我的节点和指针的结构:

#include "dictionary.h"
#define NB_NODES 27

// define global structure and pointers
typedef struct node
{
    bool is_word;
    struct node* children[NB_NODES];
} node;

// initialize pointers and variables
node* root = NULL;
node* current = NULL;
int word_counter = 0;

现在,我实现了LOAD:

bool load(const char* dictionary)
{
// open dictionary file
FILE* inptr = fopen(dictionary, "r");

if (inptr == NULL)
{
    printf("fail to open dictionary\n");
    return false;
}

// initialize tools
root = malloc(sizeof(node));
word_counter = 0;
int index = 0;
current = root;

// looks for word until end reached
for (int c = fgetc(inptr); c != EOF; c = fgetc(inptr))
{
    // looking words one by one
    if (c != '\n')
    {
        if (c == '\'')
        {
            index = 26;

            if (current->children[index] == NULL)
            {
                current->children[index] = calloc(1, sizeof(node));

                // test
                if (current->children[index] == NULL)
                {
                    printf("error with apostrophe");
                    return 1;
                }

            }
        }

        else
        {
            index = c - 'a';

            if (current->children[index] == NULL)
            {
                current->children[index] = calloc(1, sizeof(node));

                // test
                if (current->children[index] == NULL)
                {
                    printf("error with characters");
                    return 1;
                }
            }
        }

        // update current pointer to the next node
        current = current->children[index];
    }

    else if (c == '\n')
    {
        // new word found
        if (current->is_word == false)
        {
            current->is_word = true;
            word_counter++;
            current = root;
        }

        // duplicate word
        else
        {
            current = root;
        }
    }

    // character not found
    else 
    {
        printf("character not found");
        return 2;
    }
}

fclose(inptr);
return true;
}

所以在我的头文件中,我声明我的指针等于NULL,并让所有子函数(全局变量)都可以访问它们。之后,在LOAD的顶部,我将节点的内存大小分配给指针根目录。我已经尝试了很多方法来编写代码,但是共享的方法似乎是最符合逻辑的。

我也怀疑在找到完整单词后重新初始化根指针的方式。可能是这样做,我做的方式,我"失去"刚刚找到这个词的轨迹?

在这种情况下,我们非常感谢帮助继续调试,因为这不是我唯一的问题!

这是我在尝试运行speller时遇到的主要错误,主函数调用load:

jharvard@appliance (~/Dropbox/pset5): ./speller                  ~cs50/pset5/dictionaries/small/austinpowers.txt
Could not open /home/cs50/pset5/dictionaries/small/austinpowers.txt.
*** Error in `./speller': double free or corruption (!prev): 0x094302d8 ***
Aborted (core dumped)
jharvard@appliance (~/Dropbox/pset5): 

我还在gdb中启动了拼写错误并得到了这个错误:

jharvard@appliance (~/Dropbox/pset5): gdb ./speller
Reading symbols from ./speller...done.
(gdb) run ~cs50/pset5/dictionaries/small/austinpowers.txt
Starting program: /home/jharvard/Dropbox/pset5/speller     ~cs50/pset5/dictionaries/small/austinpowers.txt
Could not open /home/cs50/pset5/dictionaries/small/austinpowers.txt.
*** Error in `/home/jharvard/Dropbox/pset5/speller': double free or     corruption (!prev): 0x0804c2d8 ***

Program received signal SIGABRT, Aborted.
0xb7fdd428 in __kernel_vsyscall ()
(gdb) 

奇怪的是,当我在gdb中一步一步地前进时,我可以通过我的加载循环而不会收到失败......

我的代码是UNLOAD(已修订):

bool unload(void)
{
// recursive_free prototype
void recursive_free (node* node_to_free);

    recursive_free(root);

    if (root == NULL)
    {
        return true;
    }

    else return false;
}


void recursive_free (node* node_to_free)
{
    for (int i = 0; i < NB_NODES; i++)
    {
        // node created to assign memory to free if children found
        node* temp;

        // if children found
        if (node_to_free->children[i])
        {
            temp = node_to_free;
            node_to_free = node_to_free->children[i];
            free(temp);
            recursive_free(node_to_free);
        }

        else free(node_to_free);
    }
}

如果需要更多东西来帮助我,请问,我会补充。谢谢你的时代。

1 个答案:

答案 0 :(得分:0)

您的加载功能看起来不错。在卸载函数中,您必须首先下降所有节点,然后释放底部节点,然后再升级一级等等:

void recursive_free (node* node_to_free)
{
    for (int i = 0; i < NB_NODES; i++)
    {
        // if children found
        if (node_to_free->children[i])
        {
            recursive_free(node_to_free->children[i]);
        }
    }
    free(node_to_free);
}