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

Issues to load a dictionary in a tree structure and unload it - C programming

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

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

#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;
}

所以在我的 headers 语句中,我将我的指针声明为 NULL,并让所有子函数(全局变量)都可以访问它们。之后,在 LOAD 的顶部,我将节点的内存大小分配给我的指针根。我尝试了很多方法来对此进行编码,但共享的方法似乎是最合乎逻辑的。

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

在这种情况下,如果能继续调试,我们将不胜感激,因为这不是我唯一的问题!

这是我在尝试 运行 拼写器时遇到的主要错误,主函数调用加载:

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 (REVISED) 代码:

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);
    }
}

如果需要更多的东西来帮助我,尽管问,我会添加。感谢您的光临。

您的加载函数看起来没问题。在你的卸载函数中,你必须首先下降所有节点,然后释放底部节点,然后再向上一层等等:

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);
}