【问题标题】:Pset5 implementation of Load using trie使用 trie 实现 Load 的 Pset5
【发布时间】:2018-03-25 07:07:12
【问题描述】:

我在 pset5 中遇到了一些问题,我实际上不知道如何开始调试,我已经看了几遍课程,但我没有任何进展..

当我运行 speller.c 时,它给了我一个段错误,我运行了调试器,它在 For 循环的开头崩溃了,下面是我的代码:

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

#include "dictionary.h"
// default dictionary
#define DICTIONARY "dictionaries/large"

//created the struct node
typedef struct node
{
    bool is_word;
    struct node * paths[27];
}
node;

int letter = 0;
char * word = NULL;

/**
 * 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)
{
//opens dictionary for reading
FILE *fp = fopen(DICTIONARY, "r");
if (fp == NULL)
{
    return false;
    unload();
}

//creates the root of the trie
node *root = malloc(sizeof(node));
root -> is_word = false;

node * trav = root;

char * word = NULL;

//start reading the file
while (fscanf(fp, "%s", word) != EOF)
{
    for (int i = 0; i < strlen(word); i++)
    {
        //assing wich path to take
        char c = fgetc(fp);
        if (isupper(c))
        {
            letter = tolower (c);
            letter = letter -'a';
        }
        else if (isalpha(c))
        {
            letter = c;
            letter = letter -'a';
        }
        else if (c == '\'')
        {
            letter = 26;
        }
        else if (c == '\0')
        {
            trav -> is_word = true;
        }
        if (trav -> paths[letter] == NULL)
        {
            node *new_node = malloc(sizeof(node));
            if (new_node == NULL)
            {
                return false;
               unload();
            }
            //point to new node
            trav -> paths[letter] = new_node;
        }
        else
        {
            trav = trav -> paths[letter];
        }
    }

}
if (fscanf(fp, "%s", word) == EOF)
{
    fclose(fp);
    return true;
}
return false;
}

/**
 * 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;
}

我也不知道如何将 new_node 指向下一个新节点,以及是否必须为它们指定不同的名称。例如,我要存储单词“foo”,所以我读取名为 trav 的节点,转到 path[5](f 字母),检查它是否已经打开,如果没有(如果它是 NULL)我创建了一个名为 new_node 的节点并将 trav -> paths[5] 指向它,而不是我应该将 trav 更新为新节点,所以我将它指向它自己的 path[letter]?

【问题讨论】:

  • 与您的问题无关,但您知道return立即返回?在return 之后的同一作用域内的任何代码都不会被执行,这就是所谓的死代码。在load 函数中,如果您无法打开文件,则会出现这样的死代码
  • 至于你的问题,word 传递给fscanf 时指向哪里? fscanf 不会为你分配内存。
  • 对不起,我已经更新了代码指向词,只是忘了在这里发帖:char * word = NULL;
  • 是的,word 是一个空指针。而fscanf 并没有(不能真的)为该指针分配内存来指向。那么当fscanf 想要取消引用word 以写入它读取的字符时会发生什么?您不能取消引用空指针,它会导致 undefined behavior。我建议您将 word 定义为 array
  • 谢谢!有效!! =)

标签: c trie cs50


【解决方案1】:

word 是一个NULL 指针。而fscanf 并没有(不能真的)为该指针分配内存。那么当fscanf 想要取消引用word 以写入它读取的字符时会发生什么?您不能取消引用 NULL 指针,它会导致未定义的行为。我建议您将 word 定义为数组。

注意:答案来自 cmets

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-05-25
    • 2017-06-08
    • 2023-03-27
    • 1970-01-01
    • 1970-01-01
    • 2017-01-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多