C中的Trie:指针检测为空。导致内存泄漏
我正在学习哈佛大学的在线计算机科学MOOC(),对于其中一个习题集,你必须将字典加载到某种数据结构中(我选择了Trie),然后使用所述数据结构检查信息。我正在编写加载字典的函数,我遇到了一些重大问题。我的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
#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;
现在来看看肉:
代码在检测到空节点时创建一个新节点。但是,它不会将指向新节点的指针存储在父节点中。因此,父节点中的指针将始终为空。对于这个问题集,规范说我们不必担心大写字母。谢谢你的挑剔