0

I have ran into an issue with my Hashing program I keep getting a String Subscript out of Range error but it does not tell me what line it is causing it on. I would like to know what is causing this error and preventing me from being able to output my file correctly.

Image below showing my error.

https://i.stack.imgur.com/s77mp.png

Here are my files to compile the program:

Client.cpp:

#include <iostream>
#include <fstream>
#include <cassert>
#include "HashedDictionary.h"

using namespace std;

struct FamousPerson {
    string id;
    char taxStatus;
    string lastname;
    string firstname;
    int age;
    string street;
    string zip;
};

void readOnePerson(istream& infile, FamousPerson& readMe);


// the insertion operator overload is just here so that the HashedDictionary
// display function can use it to print FamousPerson objects.
ostream& operator<<(ostream& out, const FamousPerson& printMe);


int main() {
    HashedDictionary<string, FamousPerson> h;
    FamousPerson tempPerson;
    ifstream infile("famous.txt");
    assert(infile);

    readOnePerson(infile, tempPerson);
    while (infile) {
        h.add(tempPerson.lastname, tempPerson);
        cout << tempPerson << endl;
        readOnePerson(infile, tempPerson);
    }

    h.display();
}





ostream& operator<<(ostream& out, const FamousPerson& printMe) {
    out << printMe.id << " ";
    out << printMe.taxStatus << " ";
    out << printMe.lastname << " ";
    out << printMe.firstname << " ";
    out << printMe.age << " ";
    out << printMe.street << " ";
    out << printMe.zip;
    return out;
}


void readOnePerson(istream& infile, FamousPerson& readMe) {
    infile >> readMe.id;
    infile >> readMe.taxStatus;
    infile >> readMe.lastname;
    infile >> readMe.firstname;
    infile >> readMe.age;
    infile >> readMe.street;
    infile >> readMe.zip;
}

HashedEntry.h:

#ifndef _HASHED_ENTRY
#define _HASHED_ENTRY

#include "Entry.h"

template<class KeyType, class ItemType>
class HashedEntry : public Entry<KeyType, ItemType>
{
private:
   HashedEntry<KeyType, ItemType>* nextPtr;

public:
    HashedEntry()
    {
        nextPtr = nullptr;
    }
   HashedEntry(ItemType newEntry, KeyType itemKey):Entry<KeyType,ItemType>(newEntry, itemKey)
   {
       nextPtr = nullptr;
       //nextPtr->setItem(newEntry);
       //nextPtr->setKey(itemKey);
   }
   HashedEntry(ItemType newEntry, KeyType itemKey, HashedEntry<KeyType, ItemType>* nextEntryPtr) :Entry<KeyType, ItemType>(newEntry, itemKey)
   {
       //nextPtr->setItem(newEntry);
       //nextPtr->setKey(itemKey);
       nextPtr = nextEntryPtr;
   }
   void setNext(HashedEntry<KeyType, ItemType>* nextEntryPtr)
   {
       HashedEntry<KeyType, ItemType>* newEntry = nextPtr;
       HashedEntry<KeyType, ItemType>* endEntry = nextEntryPtr;
       /*
       while (endEntry->nextPtr != nullptr)
       {
           endEntry = endEntry->nextPtr;
       }
       endEntry->nextPtr = nextEntryPtr;
       endEntry = nullptr;*/
       nextPtr = nextEntryPtr;
   }
   HashedEntry<KeyType, ItemType>* getNext() const
   {
       return nextPtr;
   }
}; // end HashedEntry

//#include "HashedEntry.cpp"
#endif

HashedDictionary.h:

    #include <string>
    #include <cstdlib>
    #include<iostream>

    #include "DictionaryInterface.h"
    #include "HashedEntry.h"

    #ifndef _HASHED_DICTIONARY
    #define _HASHED_DICTIONARY

    using namespace std;


    template< class KeyType, class ItemType>
    class HashedDictionary : public DictionaryInterface<KeyType, ItemType>
    {
    private:
        HashedEntry<KeyType, ItemType>** hashTable;
        int itemCount; // Count of dictionary entries
        int hashTableSize; // Table size must be prime
        static const int DEFAULT_SIZE = 101;
    public:

        int hFunction(const KeyType& x) const
        {
            int num = Hrule(x) % hashTableSize;
            return num;
        }

        int Hrule(const KeyType& ph) const
        {
            int numForm = 0;
            for (int i = 0; i < ph.length(); i++)
            {
                numForm = numForm * 128 + ph[i];
            }

            return numForm;
        }

        HashedDictionary()
        {
            itemCount = 0;
            hashTableSize = DEFAULT_SIZE;
            hashTable = new HashedEntry<KeyType, ItemType> * [DEFAULT_SIZE];
        }

        HashedDictionary(int newHTableSize)
        {
            hashTableSize = newHTableSize;
            itemCount = 0;
            hashTable = new HashedEntry<KeyType, ItemType> * [newHTableSize];
        }

        bool isEmpty() const
        {
            return itemCount == 0;
        }

        int getNumberOfItems() const
        {
            return itemCount;
        }


        bool add(const KeyType& searchKey, const ItemType& newItem)
        {
            // Create entry to add to dictionary
            HashedEntry<KeyType, ItemType>* entryToAddPtr =
                new HashedEntry<KeyType, ItemType>(newItem, searchKey);

            // Compute the hashed index into the array
            int itemHashIndex = getHashIndex(searchKey);

            // Add the entry to the chain at itemHashIndex
            if (hashTable[itemHashIndex] == nullptr)
            {
                hashTable[itemHashIndex] = entryToAddPtr;
            }
            else
            {
                entryToAddPtr->setNext(hashTable[itemHashIndex]);
                hashTable[itemHashIndex] = entryToAddPtr;
            }

            return true;
        }



        bool remove(const KeyType& searchKey)
        {
            bool itemFound = false;

            // Compute the hashed index into the array
            int itemHashIndex = getHashIndex(searchKey);
            if (hashTable[itemHashIndex] != nullptr)
            {
                // Special case - first node has target
                if (searchKey == hashTable[itemHashIndex]->getKey())
                {
                    HashedEntry<KeyType, ItemType>* entryToRemovePtr =
                        hashTable[itemHashIndex];
                    hashTable[itemHashIndex] = hashTable[itemHashIndex]->getNext();
                    delete entryToRemovePtr;
                    entryToRemovePtr = nullptr; // For safety
                    itemFound = true;
                }
                else // Search the rest of the chain
                {
                    HashedEntry<KeyType, ItemType>* prevPtr = hashTable[itemHashIndex];
                    HashedEntry<KeyType, ItemType>* curPtr = prevPtr->getNext();
                    while ((curPtr != nullptr) && !itemFound)
                    {
                        // Found item in chain so remove that node
                        if (searchKey == curPtr->getKey())
                        {
                            prevPtr->setNext(curPtr->getNext());
                            delete curPtr;
                            curPtr = nullptr; // For safety
                            itemFound = true;
                        }
                        else // Look at next entry in chain
                        {
                            prevPtr = curPtr;
                            curPtr = curPtr->getNext();
                        }
                    }
                }
            }

            return itemFound;
        }


        void clear()
        {
            for (int i = 0; i < hashTableSize; i++)
            {
                while (hashTable[i] != nullptr)
                {
                    HashedEntry<KeyType,ItemType>* delPtr = hashTable[i];
                    hashTable[i] = hashTable[i]->getNext();
                    delete delPtr;
                    delPtr= nullptr;
                }
            }
            itemCount = 0;
        }

        ItemType getItem(const KeyType& itemKey) const
        {
            assert(contains(itemKey));
            int itemHashIndex = getHashIndex(itemKey);
            HashedEntry<KeyType,ItemType>* chainPtr = hashTable[itemHashIndex];
            while((chainPtr != nullptr) && itemKey != chainPtr->getKey())
            {
                chainPtr = chainPtr->getNext();
            }
            if (chainPtr == nullptr)
            {
                return chainPtr->getItem();
            }
        }

        bool contains(const KeyType& searchKey) const
        {
            int ItemHashIndex = getHashIndex(searchKey);
            HashedEntry<KeyType, ItemType>* chainPtr = hashTable[ItemHashIndex];
            while ((chainPtr != nullptr) && (searchKey != chainPtr->getKey()))
            {
                chainPtr = chainPtr->getNext();
            }
            return (chainPtr != nullptr);
        }


        int getHashIndex(const KeyType& itemKey) const
        {
            int key = 0;
            int i = 0;
            while (isalpha(searchKey[i]))
            {
                key += searchKey[i];
                i++;
            }
            return key % hashTableSize;
        }

        void display()
        {
            int i = 0;
            while (i < hashTableSize)
            {
                if (hashTable[i] != nullptr)
                {
                    HashedEntry<KeyType, ItemType>* nextEntry = hashTable[i];

                    while (nextEntry != nullptr)
                    {
                        cout << nextEntry->getItem() << " ";
                        nextEntry = nextEntry->getNext();
                    }

                    cout << endl;
                    nextEntry = nullptr;
                    delete nextEntry;
                }
                i++;
            }
        }
    };


    #endif 

Entry.h:

#ifndef _ENTRY
#define _ENTRY

template <class KeyType, class ItemType>
class Entry
{
private:
   ItemType item;
   KeyType searchKey;

protected:
    void setKey(const KeyType& itemKey)
    {
        searchKey = itemKey;
   }

public:
    Entry()
    {
        item = ItemType();
        searchKey = KeyType();
    }
   Entry(ItemType newEntry, KeyType itemKey)
   {
       item = newEntry;
       searchKey = itemKey;
   }
   ItemType getItem() const
   {
       return item;
   }
   KeyType getKey() const
   {
       return searchKey;
   }
   void setItem(const ItemType& newEntry)
   {
       item = newEntry;
   }
}; // end Entry

//#include "Entry.cpp"
#endif

DictionaryInterface.h:

#ifndef _DICTIONARY_INTERFACE
#define _DICTIONARY_INTERFACE


template<class KeyType, class ItemType>
class DictionaryInterface 
{
public:   


   /** Sees whether this dictionary is empty.
    @return True if the dictionary is empty;
       otherwise returns false. */
   virtual bool isEmpty() const = 0;

   /** Gets the number of items in this dictionary.
    @return The number of items in the dictionary. */
   virtual int getNumberOfItems() const = 0;

   /** Inserts an item into this dictionary according to the item’s search key.
    @pre  The search key of the new item differs from all search
       keys presently in the dictionary.
    @post  If the insertion is successful, newItem is in its
       proper position within the dictionary.
    @param searchKey  The search key associated with the item to be inserted.
    @param newItem  The item to add to the dictionary.
    @return  True if item was successfully added, or false if not. */
   virtual bool add(const KeyType& searchKey, const ItemType& newItem) = 0;

   /** Removes an item with the given search key from this dictionary.
    @post  If the item whose search key equals searchKey existed in the dictionary, 
       the item was removed.
    @param searchKey  The search key of the item to be removed.
    @return  True if the item was successfully removed, or false if not. */
   virtual bool remove(const KeyType& searchKey) = 0;

   /** Removes all entries from this dictionary. */
   virtual void clear() = 0;

   /** Retrieves an item with a given search key from a dictionary.
    @post  If the retrieval is successful, the item is returned.
    @param searchKey  The search key of the item to be retrieved.
    @return  The item associated with the search key.
    @throw  NotFoundException if the item does not exist. */
   virtual ItemType getItem(const KeyType& searchKey) const = 0;

   /** Sees whether this dictionary contains an item with a given
       search key.
    @post  The dictionary is unchanged.
    @param searchKey  The search key of the item to be retrieved.
    @return  True if an item with the given search key exists in the dictionary. */
   virtual bool contains(const KeyType& searchKey) const = 0;

   /** Traverses this dictionary and calls a given client function once for each item.
    @post  The given function’s action occurs once for each item in the
       dictionary and possibly alters the item.
    @param visit A client function. */
   //virtual void traverse(void visit(ItemType&)) const = 0;
}; // end DictionaryInterface

#endif
sbgib
  • 5,580
  • 3
  • 19
  • 26

1 Answers1

0
  1. When you launch the program run the debugger.
  2. When that error dialog comes up click Retry. That will drop you into the debugger showing the code in the standard library that caught the error. But that's not really what you are interested in.
  3. Click Debug → Windows → Call Stack in visual studio. This will show a list of which functions are currently being run and have called other functions. Your code will be on this stack.
  4. Click the line showing your code and the debugger will display your code where the problem occurred. This will also change the debugging context to that function.
  5. You can then use the Debug → Windows → Locals to see what the variables are holding at that point.

This is an important debugging technique, you'll need it a lot and will soon have it memorized.

double-beep
  • 5,031
  • 17
  • 33
  • 41
Jeff Spencer
  • 507
  • 2
  • 11