-2

I am coding a dictionary Trie as an assigment, C++ . I keep getting an error when inserting certain letters in words, especially 'l' and 't' if they are not the first letter.

This is the error

Unhandled exception at 0x00EC5392 in A4Tries.exe: 0xC0000005: Access violation reading location 0x000032EC.

The problem is the InsertTrie function. It breaks on the following line

if (!current->branch[newkey[i] - 'a'])

Im so confused as the code works for loads of test words and then inputs like 'sdfl' or 'sfd', 'ffdf' break the program . If anyone can spot the problem I would be very grateful. Thanks.

const int LETTERS = 26;
typedef char Key[MAXLENGTH];
struct Trienode
{
    Trienode *branch[LETTERS];
    EntryType *ref;
};



class TrieType
{
public:
    TrieType();
    ~TrieType();
    TrieType(TrieType &originalTree);
    void operator=(TrieType & originalTree);
    void MakeEmpty();
    void InsertTrie(Key newkey, EntryType *newentry);
    EntryType *  TrieSearch(Key target);
    bool DeleteTrie(Key delkey);
    void PrintTrie();


private:
    Trienode * root;
};

TrieType::TrieType()
{
    root = NULL;

}


TrieType::~TrieType()
{


}
TrieType::TrieType(TrieType &originalTree)
{

}

EntryType * TrieType::TrieSearch(Key target)
{
    int i;
    Trienode * current = root;
    for (i = 0; i < MAXLENGTH && current; i++)
        if (target[i] == '\0')
            break;
        else
            current =
            current->branch[target[i] - 'a'];
    if (!current)
        return NULL;
    else
        if (!current->ref)
            return NULL;

    return current->ref;
}


Trienode *CreateNode()
{
    int ch;
    Trienode *newnode = new Trienode;
    for (ch = 0; ch < LETTERS; ch++)
        newnode->branch[ch] = NULL;

    newnode->ref = NULL;

    return newnode;
}

void TrieType::InsertTrie(Key newkey, EntryType *newentry)
{
    int i;
    Trienode *current;
    if (!root)
        root = CreateNode();
    current = root;
    for (i = 0; i < MAXLENGTH; i++)
        if (newkey[i] == '\0')
            break;
        else
        {
            if (!current->branch[newkey[i] - 'a'])
                current->branch[newkey[i] - 'a'] = CreateNode();
            current = current->branch[newkey[i] - 'a'];
        }
    if (current->ref != NULL)
        cout << "\nTried to insert a duplicate key." << endl;
    else
        current->ref = newentry;

}



    const int MAXLENGTH = 10;
class EntryType
{
public:
    EntryType();
    EntryType(char * key);
    EntryType(EntryType & entry);
    ~EntryType();
    bool operator== (const EntryType& item) const;
    bool operator!= (const EntryType& item) const;
    void EntryKey(char word[]);
    void PrintWord();

private:
    char entryKey[MAXLENGTH];
};


EntryType::EntryType()
{

}
EntryType::~EntryType()
{

}

void EntryType::EntryKey(char word[])
{
    for (int i = 0; i < 10; i++)
    {
        entryKey[i] = word[i];
    }
}

void EntryType::PrintWord()
{
    cout << entryKey << endl;
}

In the Main

void insert(TrieType & trie)
{
    Key word;
    cout << "Please enter the word you would like to enter: " << endl;
    cin >> word;

    EntryType* newEntry = new EntryType;
    newEntry->EntryKey(word);


    trie.InsertTrie(word, newEntry);


}
  • You really would have to post a complete example. – Mats Petersson Dec 31 '15 at 16:58
  • The failing code seems to assume that `newkey[i]` is a lower case letter. So I searched your full posted code to find any reason to believe or disbelieve that possibilities other than lower case letters were filtered out earlier. Whatever parts of your code should have done that weren't even included in what you posted. – JSF Dec 31 '15 at 17:12

1 Answers1

0

This is why professional programmers uses asserts

    {
        if (!current->branch[newkey[i] - 'a'])
            current->branch[newkey[i] - 'a'] = CreateNode();
        current = current->branch[newkey[i] - 'a'];
    }

When newkey[i] is not a lower case letter, the above code sets current equal to garbage, then the next time through the loop uses current and seg faults.

Some other part of the code should be responsible for making sure you only have lower case letters by the time you get here. But since that is not obvious to anyone debugging this part of the code, there should be an assert.

    {
        assert( newkey[i]>='a' && newkey[i]<='z' );
        if (!current->branch[newkey[i] - 'a'])
            current->branch[newkey[i] - 'a'] = CreateNode();
        current = current->branch[newkey[i] - 'a'];
    }

Then you can run a debug build of the program and either find out the failure was caused by that code elsewhere that permitted characters other than lower case letters to reach here, or you can see that isn't an issue and focus better on finding some less likely defect.

JSF
  • 5,281
  • 1
  • 13
  • 20