【问题标题】:Adding words to a trie将单词添加到 trie
【发布时间】:2019-11-08 19:49:03
【问题描述】:

我正在创建一个 trie,但在编译时遇到了问题。

我得到的警告是: "从 'currNode->dict' 读取无效数据:可读大小为 '104' 字节,但可以读取 '388' 字节。"

#pragma once
#include <iostream>
#include <fstream>
#include <string>
using namespace std;

const int SIZE = 26;

struct Node {
bool isWord;
Node* dict[SIZE];
};

class Dictionary
{
public:
Dictionary();
Dictionary(string file);
void addWord(string word);

private:
Node *root;
int numWords;
};

Dictionary::Dictionary()
{
numWords = 0;
root = new Node;

for (int i = 0; i < SIZE; i++)
    root->dict[i] = nullptr;
}

Dictionary::Dictionary(string file)
{
numWords = 0;
root = new Node;

for (int i = 0; i < SIZE; i++)
    root->dict[i] = nullptr;

ifstream inFile;
string word;

inFile.open(file);

while (inFile >> word) {
    addWord(word);
    numWords++;
}
}

void Dictionary::addWord(string word)
{
int len = word.length(); // size of word
char letter;
int pos;

Node *currNode = root;

for (int i = 0; i < len; i++) {
    letter = word[i]; // takes character at position i
    pos = letter - 'a'; // finds the position of the character in the array (0 through 25)
                        // with 'a' being 0 and 'z' being 25

    if (!currNode->dict[pos]) {
        currNode->dict[pos] = new Node;

        currNode->isWord = false;
    }
    currNode = currNode->dict[pos];
}
currNode->isWord = true;
}

这可能是什么原因造成的?我很确定我没有尝试访问无效内存。也许这是我设置节点和类的方式?

【问题讨论】:

  • 我很确定我没有试图访问无效内存 -- 请发帖minimal reproducible example。我们不知道这些代码在何处、何时或如何发挥作用。
  • docs.microsoft.com/en-us/visualstudio/code-quality/… 是这个错误/警告吗?你也能指定你在什么林得到这个吗?
  • pos = letter - 'a'; -- 如果pos 结果是负数怎么办?或者一般来说,如果pos 在您这样做时无效怎么办:currNode-&gt;dict[pos]
  • 对于这个作业,我只添加了小写的单词。根据ASCII,'a'之后的所有字母都是一个更高的整数,所以我相信你不会得到负数。
  • @ThrmsNPrfs -- 我只添加小写单词 -- 这并不意味着您只是假设该字符是有效的。如果不是呢?我看不到包含所有小写数据的main 程序。教训是永远不要编写一个如此开放的程序,以便发生错误。

标签: c++ trie


【解决方案1】:

一个错误是您未能将Node 初始化为默认值。在您的 Dictionary 默认构造函数中,您的代码确实应该成为 Node 应该做的事情的一部分:

root = new Node ;
for (int i = 0; i < SIZE; i++)
    root->dict[i] = nullptr;

这应该是Node 的工作,而不是Dictionary 的工作。

相反,你有这个:

struct Node {
    bool isWord;
    Node* dict[SIZE];
};

所以每次你这样做:

if (!currNode->dict[pos]) {
    currNode->dict[pos] = new Node;

您正在创建一个未初始化的 Node 对象。整个Node::dict 数组包含未初始化的指针,您稍后会尝试访问这些指针。

最简单的解决方案是将Node 对象初始化为零。

if (!currNode->dict[pos]) {
    currNode->dict[pos] = new Node(); // <-- Note the parentheses

这将自动将dict 指针设置为nullptr


另一种方法是确保使用默认值创建Node 对象:

   #include <algorithm>

   struct Node {
        bool isWord;
        Node* dict[SIZE];
        Node() : isWord(false) { std::fill_n(dict, SIZE, nullptr); }
    };

这样,即使new Node; 也会创建已初始化的节点。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-25
    • 1970-01-01
    相关资源
    最近更新 更多