C中的Trie:指针检测为空。导致内存泄漏

C中的Trie:指针检测为空。导致内存泄漏,c,pointers,memory-leaks,trie,C,Pointers,Memory Leaks,Trie,我正在学习哈佛大学的在线计算机科学MOOC(),对于其中一个习题集,你必须将字典加载到某种数据结构中(我选择了Trie),然后使用所述数据结构检查信息。我正在编写加载字典的函数,我遇到了一些重大问题。我的trie尽管尝试检测空指针,但仍在分配内存 这是我的密码: #include <stdbool.h> #include <stdio.h> #include <stdlib.h> #include "dictionary.h" #include <cty

我正在学习哈佛大学的在线计算机科学MOOC(),对于其中一个习题集,你必须将字典加载到某种数据结构中(我选择了Trie),然后使用所述数据结构检查信息。我正在编写加载字典的函数,我遇到了一些重大问题。我的trie尽管尝试检测空指针,但仍在分配内存

这是我的密码:

#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include "dictionary.h"
#include <ctype.h>
//Defines the trie data structure which is used to store the words
struct trieNode{
    char letter;
    bool wordComp;
    bool isRoot;
    struct trieNode* childNodes[27];
 }trie;
 //The trie that will be used for the rest of the program
 struct trieNode root;
/**
* Returns true if word is in dictionary else false.
*/
bool check(const char* word)
{
    // TODO
    return false;
}

/**
 * Loads dictionary into memory.  Returns true if successful else false.
 */
bool load(const char* dictionary)
{
    //Counts to see whether the word was just an \n or it was really a word
    int cLettCount = 0;
    //counts the number of total words used
    int tWordCount = 0;
    //basic setup stuff
    root.isRoot = true;
    //Pointer to the current node (current node starts as root node).
    struct trieNode* currNode = &root;
    FILE* dic = fopen(dictionary, "r");
    char currChar = 1;
    //main loop (Goes till end of file)
    while(currChar != EOF){
        //resets letter count
        cLettCount = 0;
        //resets currNode to the root node
        currNode = &root;
        currChar = 1;
        //Loop gathers current word and pushes the letters to the trie
        for(int j = 0;  currChar != '\n'; j++){
            currChar = fgetc(dic);
            //Makes sure we're not at the end of a word or at EOF
            if(currChar == '\n'|| currChar == EOF)
            {
                break;
            }
            //Makes sure we only get alpha chars
            else if(!isalpha(currChar) && currChar != 39)
            {
                printf("Nonalpha char %c detected. Quiting...\n", currChar);
                return false;
            }
            //Meat and bones. Adds letters onto the trie
            else
            {
                bool isNull = false;
                if(currChar == 39){
                    currNode = currNode->childNodes[26];
                    if(currNode->childNodes[26] == NULL)
                    {
                        isNull = true;
                    }
                }
                else
                {
                //Finds the node that corrosponds with the letter
                    if(currNode->childNodes[currChar - 97] == NULL)
                    {
                        isNull = true;
                    }
                    currNode = currNode->childNodes[currChar - 97];
                }
                if(isNull)
                {
                     currNode = malloc (sizeof (trie));
                     currNode->isRoot = false;
                     currNode->letter = currChar;
                     currNode-> wordComp = false;
                     printf("Node created for: %c\n", currNode->letter);
                }else if(!isNull){
                    printf("Node not created\n");
                }
            }
        }
        if(currChar == EOF){
                break;
        }
        else if(currChar == '\n'){
            currNode -> wordComp = true;
            tWordCount++;
            printf("\n");
        }
    }
    return true;
}

/**
 * Returns number of words in dictionary if loaded else 0 if not yet loaded.
 */
unsigned int size(void)
{
    // TODO
    return 0;
}

/**
 * Unloads dictionary from memory.  Returns true if successful else false.
 */
bool unload(void)
{
    // TODO
    return false;
}
#包括
#包括
#包括
#包括“dictionary.h”
#包括
//定义用于存储单词的trie数据结构
结构三节点{
字符字母;
bool-wordComp;
bool-isRoot;
结构三节点*子节点[27];
}特里亚;
//将用于程序其余部分的trie
结构三极根;
/**
*如果单词在字典中,则返回true,否则返回false。
*/
布尔检查(常量字符*单词)
{
//待办事项
返回false;
}
/**
*将字典加载到内存中。如果成功,则返回true;否则返回false。
*/
布尔加载(常量字符*字典)
{
//计数以查看该单词是否只是一个单词\n或它是否真的是一个单词
int cLettCount=0;
//统计使用的总字数
int-tWordCount=0;
//基本设置资料
root.isRoot=true;
//指向当前节点的指针(当前节点以根节点开始)。
结构三节点*currNode=&root;
文件*dic=fopen(字典,“r”);
char currChar=1;
//主循环(直到文件结束)
while(currChar!=EOF){
//重置字母计数
cLettCount=0;
//将currNode重置为根节点
currNode=&root;
currChar=1;
//循环收集当前单词并将字母推送到trie
对于(int j=0;currChar!='\n';j++){
currChar=fgetc(dic);
//确保我们不在一个词的结尾或EOF
如果(currChar='\n'| | currChar==EOF)
{
打破
}
//确保我们只得到阿尔法字符
如果(!isalpha(currChar)&&currChar!=39),则为else
{
printf(“检测到非LPHA字符%c。正在退出…\n”,currChar);
返回false;
}
//肉和骨头。在trie上添加字母
其他的
{
bool isNull=false;
如果(currChar==39){
currNode=currNode->childNodes[26];
if(currNode->childNodes[26]==NULL)
{
isNull=true;
}
}
其他的
{
//查找与字母对应的节点
if(currNode->childNodes[currChar-97]==NULL)
{
isNull=true;
}
currNode=currNode->childNodes[currChar-97];
}
if(isNull)
{
currNode=malloc(sizeof(trie));
currNode->isRoot=false;
currNode->letter=currChar;
currNode->wordComp=false;
printf(“为%c\n创建的节点”,currNode->letter);
}如果(!isNull),则为else{
printf(“未创建节点”);
}
}
}
如果(currChar==EOF){
打破
}
else if(currChar=='\n'){
currNode->wordComp=true;
tWordCount++;
printf(“\n”);
}
}
返回true;
}
/**
*如果已加载,则返回字典中的字数;如果尚未加载,则返回0。
*/
无符号整数大小(void)
{
//待办事项
返回0;
}
/**
*从内存中卸载字典。如果成功,则返回true;否则返回false。
*/
bool卸载(无效)
{
//待办事项
返回false;
}

Load()
是我的问题所在。

我想我刚刚发现了自己的错误。我正在将curNode设置为新节点,但不是根节点中的指针。

如果你比我快,我需要学会更快地键入:)

首先,有些吹毛求疵:

不要对字符常量使用硬代码编号

 39 should be '\''
 97 should be 'a'
请注意,大写字母将使程序崩溃。将外部输入转换为数组索引后始终进行范围检查,例如

index = currChar - 'a';
if ( index < 0 || index > 25 )
   return false;
index=currChar-'a';
如果(指数<0 | |指数>25)
返回false;
现在来看看肉:


代码在检测到空节点时创建一个新节点。但是,它不会将指向新节点的指针存储在父节点中。因此,父节点中的指针将始终为空。

对于这个问题集,规范说我们不必担心大写字母。谢谢你的挑剔