字符串下标超出范围,使用散列 ADT
Posted
技术标签:
【中文标题】字符串下标超出范围,使用散列 ADT【英文标题】:String Subscript out of Range , Using Hashing ADT 【发布时间】:2020-12-11 06:03:28 【问题描述】:我的 Hashing 程序遇到了问题,我不断收到 String Subscript out of Range 错误,但它没有告诉我它是在哪一行引起的。我想知道是什么导致了这个错误并阻止我正确输出我的文件。
下面的图片显示了我的错误。
这是我编译程序的文件:
客户端.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
【问题讨论】:
点击“重试”按钮。 @S.M.它打开了一个我以前从未见过的奇怪语法的“xstring”文件 查看调用堆栈。 @S.M.哦,好吧,它表明调用堆栈在第 183 行的 hashIndex 函数和第 73 行的 add 函数中检测到错误 我假设您的意思是getHashIndex
函数。你为什么不在那里使用密钥的长度?
【参考方案1】:
-
启动程序时运行调试器。
当该错误对话框出现时,单击重试。这将使您进入调试器,显示标准库中捕获错误的代码。但这并不是您真正感兴趣的。
在 Visual Studio 中单击调试 → Windows → 调用堆栈。这将显示当前正在运行的函数以及调用了其他函数的列表。您的代码将在此堆栈中。
单击显示代码的行,调试器将显示出现问题的代码。这也会将调试上下文更改为该函数。
然后您可以使用 Debug → Windows → Locals 来查看此时变量所包含的内容。
这是一项重要的调试技术,您将非常需要它,并且很快就会记住它。
【讨论】:
以上是关于字符串下标超出范围,使用散列 ADT的主要内容,如果未能解决你的问题,请参考以下文章