哈希表打印出默认值,但将项目添加到地址边界错误时

Posted

技术标签:

【中文标题】哈希表打印出默认值,但将项目添加到地址边界错误时【英文标题】:Hash table prints out default values but when items are added results into Address Boundary Error 【发布时间】:2021-10-19 05:18:39 【问题描述】:

尝试创建一个以名称为键,其值为饮料的哈希表,当调用 printTable() 而不添加项目(即注释掉以下代码 sn-p)时,它会打印出添加的图像而没有任何地址边界错误:

h.addItem("Paul", "Locha");
h.addItem("Kim", "Iced Mocha");
h.addItem("Emma", "Strawberry Smoothy");
h.addItem("Annie", "Hot Chocolate");
h.addItem("Sarah", "Passion Tea");
h.addItem("Pepper", "Caramel Mocha");
h.addItem("Mike", "Chai Tea");
h.addItem("Steve", "Apple Cider");
h.addItem("Bill", "Root Bear");
h.addItem("Marie", "Skinny Latte");

具有给定默认值的输出图像

但是当通过解析 csv 或直接调用 addItem() 的类成员函数添加项目时,程序会呈现如下错误:

➜  Hash Table ./hashTableWithStruct.o
fish: Job 1, './hashTableWithStruct.o' terminated by signal SIGSEGV (Address boundary error) 

错误代码如下:

hashTableWithStruct.cpp

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

class Hash

private:
    static const int tableSize = 10;

    struct item
    
        string name;
        string drink;
        item *next;
    ;

    item *hashTable[tableSize];

public:
    Hash()
    
        for (int i = 0; i < tableSize; i++)
        
            hashTable[i] = new item;
            hashTable[i]->name = "empty";
            hashTable[i]->drink = "empty";
            hashTable[i]->next = NULL;
        
    

    int hashFunct(string key)
    
        int hashed = 0;
        for (int i = 0; key[i] != '\0'; i++)
        
            hashed += (int)key[i];
        
        return (hashed % tableSize); //returns the BUCKET value
    

    void addItem(string name, string drink)
    
        int BUCKET = hashFunct(name);
        //if the value at BUCKET hasn't been written yet,
        //override the default empty ones
        if (hashTable[BUCKET]->name == "empty")
        
            hashTable[BUCKET]->name = name;
            hashTable[BUCKET]->drink = drink;
        
        //otherwise, make a linked list starting from BUCKET
        else
        
            item *ptr = hashTable[BUCKET];

            item *n = new item;
            n->name = name;
            n->drink = drink;
            n->next = NULL;

            //the linked list might contain many nodes,
            //hence travel to last node and reassign the last node to be this new item
            while (ptr != NULL)
                ptr = ptr->next;
            ptr->next = n;
        
        return;
    

    int numOfItemsInBucket(int BUCKET)
    
        int count = 0;
        if (hashTable[BUCKET]->name == "empty")
            return count;
        else
        
            count++;
            item *ptr = hashTable[BUCKET];
            while (ptr->next != NULL)
            
                count++;
                ptr = ptr->next;
            
        
        return count;
    

    void printTable()
    
        int num; //holds number of elements(items) in each bucket
        for (int i = 0; i < tableSize; i++)
        
            num = numOfItemsInBucket(i);
            cout << "-----------------------------\n"
                 << "Table[" << i << "]" << endl
                 << hashTable[i]->name << endl
                 << hashTable[i]->drink << endl
                 << "# of items in bucket " << i << " : " << num << endl;
            cout << "-----------------------------\n";
        
    
;

int main(int argc, char const *argv[])

    Hash h;
    /* string filename = "datasetForHashTable.csv";
    ifstream myCSV(filename.c_str());
    if (!myCSV.is_open())
    
        cout<<"Failed to open file"<<endl;
        return 0;
    
    string name, drink;
    while (myCSV.peek()!=EOF)
         
        getline(myCSV, name, ',');
        getline(myCSV, drink, '\n');
        h.addItem(name, drink);
    
    myCSV.close(); */

    h.addItem("Paul", "Locha");
    h.addItem("Kim", "Iced Mocha");
    h.addItem("Emma", "Strawberry Smoothy");
    h.addItem("Annie", "Hot Chocolate");
    h.addItem("Sarah", "Passion Tea");
    h.addItem("Pepper", "Caramel Mocha");
    h.addItem("Mike", "Chai Tea");
    h.addItem("Steve", "Apple Cider");
    h.addItem("Bill", "Root Bear");
    h.addItem("Marie", "Skinny Latte"); 

    h.printTable();
    return 0;

基本上,无法理解为什么表格不会打印名称和饮料,因为在没有它的情况下打印表格时它工作得很好。 请帮忙,从 2 天开始就试图解决这个问题。

【问题讨论】:

【参考方案1】:

在这个while循环之后

        while (ptr != NULL)
            ptr = ptr->next;

指针ptr 等于nullptr。所以下一条语句

        ptr->next = n;

由于取消引用空指针而调用未定义的行为。

看来你的意思

        while (ptr->next != NULL)
            ptr = ptr->next;

        ptr->next = n;

【讨论】:

以上是关于哈希表打印出默认值,但将项目添加到地址边界错误时的主要内容,如果未能解决你的问题,请参考以下文章

Python算法哈希存储哈希表散列表原理

哈希表(hash table)基础概念

哈希表详解

Java学习:Object类

哈希表类Hashtable

Freemarker“字符串到哈希转换”?