Хеширование с++

#include <iostream>
#include <string>
#include <list>
#include <vector>
#include <iterator>
using namespace std;

vector< list<string>*> hash_table;

void hash_(string word) {
    int sum = 0;
    int num = 0;
    hash_table.resize(10);
    char numbers1[] = { '0','А', 'Б', 'В', 'Г', 'Д', 'Е', 'Ё', 'Ж', 'З', 'И', 'К', 'Л', 'М', 'Н', 'О', 'П', 'Р', 'С', 'Т', 'У', 'Ф', 'Х', 'Ц', 'Ч', 'Ш', 'Щ', 'Ъ', 'Ы', 'Ь', 'Э', 'Ю', 'Я' };
    char numbers2[] = { '0','а', 'б', 'в', 'г', 'д', 'е', 'ё', 'ж', 'з', 'и', 'к', 'л', 'м', 'н', 'о', 'п', 'р', 'с', 'т', 'у', 'ф', 'х', 'ц', 'ч', 'ш', 'щ', 'ъ', 'ы', 'ь', 'э', 'ю', 'я' };

        for (int k = 0; k < word.size(); k++) {
            for (int m = 0; m < sizeof(numbers1); m++) {
                if (word[k] == numbers1[m]) {
                    sum += m;
                    num++;
                }
            }
            for (int t = 0; t < sizeof(numbers2); t++) {
                if (word[k] == numbers2[t]) {
                    sum += t;
                    num++;
                }
            }

        }
        sum = sum % 10;

        list<string> list1;
        list1.push_front(word);
        list<string>* ptr = &list1;
        hash_table[sum] = ptr;
        cout << "Слово " << num << " : " << sum << endl;
        sum = 0;
    }
int getHash(string word) {
    int sum = 0;
    int num = 0;
    char numbers1[] = { '0','А', 'Б', 'В', 'Г', 'Д', 'Е', 'Ё', 'Ж', 'З', 'И', 'К', 'Л', 'М', 'Н', 'О', 'П', 'Р', 'С', 'Т', 'У', 'Ф', 'Х', 'Ц', 'Ч', 'Ш', 'Щ', 'Ъ', 'Ы', 'Ь', 'Э', 'Ю', 'Я' };
    char numbers2[] = { '0','а', 'б', 'в', 'г', 'д', 'е', 'ё', 'ж', 'з', 'и', 'к', 'л', 'м', 'н', 'о', 'п', 'р', 'с', 'т', 'у', 'ф', 'х', 'ц', 'ч', 'ш', 'щ', 'ъ', 'ы', 'ь', 'э', 'ю', 'я' };

    for (int k = 0; k < word.size(); k++) {
        for (int m = 0; m < sizeof(numbers1); m++) {
            if (word[k] == numbers1[m]) {
                sum += m;
                num++;
            }
        }
        for (int t = 0; t < sizeof(numbers2); t++) {
            if (word[k] == numbers2[t]) {
                sum += t;
                num++;
            }
        }

    }
    sum = sum % 10;
    return sum;
}

void string_find(string word) {
   int num = getHash(word);
   cout<< *hash_table[num]->begin();
}
    int main() 
    {
        setlocale(LC_ALL, "Russian");
        cout << "Задание 1: " << endl;
        vector<string> words = { "Ноутбук","Компьютер","Телефон","Планшет","Приставка","Умные часы","Наушники" };
        //hash1(words, 7, listwords);
        for (int i = 0; i < 7; i++) {
            hash_(words[i]);
        }
       string_find(words[0]);
        cout << endl << "Задание 2: " << endl;
      
        return 0;
    }
    

Сделал функцию хеширования,которая берет сумму номеров букв в алфавите и берет остаток от деления на 10(да функция очень плохая,но по заданию так надо). Вообщем я слова заношу в разные списки.И указатели на списки храню в массиве.Но в функции поиска слова,я не могу получить слово из списка. Вылазит исключение: нарушение доступа для чтения. _Mycont было 0xDDDDDDDD.Что не так?


Ответы (1 шт):

Автор решения: DmitryK

Проблема в том, что вы присваиваете указатель на локальный объект, который тут же при выходе из функции уничтожается. И у вас сохраненный указатель указывает в никуда.

list<string> list1; // создается локальный объект

list<string>* ptr = &list1;
hash_table[sum] = ptr; // сохраняется указатель на него
}  // в конце функции локальный list1 уничтожается, и теперь сохраненный указатель указывает в никуда

И при обращении по указателю на несуществующий объект происходит ошибка.
Поскольку вы работаете с контейнерами, нет смысла хранить указатели. Храните сразу списки:

vector< list<string> > hash_table(10); // поскольку максимум будет 10 строк
                          // и кстати необязательно использовать `list<string>`, можно использовать `vector<string>`

И тогда использование будет

hash_table[sum].push_back(word);

Несколько замечаний:

  • уже есть функция int getHash(string word) {}, зачем дублирование кода в _hash() ?
  • Поскольку в getHash() массивы одинаковые, то достаточно 1 цикла внутри цикла по слову
for (int m = 0; m < sizeof(numbers1); m++) 
   if (word[k] == numbers1[m] || word[k] == numbers2[m]) 
      sum += m;
  • m в этом цикле должна начинаться с 1, т.к. нулевой элемент это ноль, а не буква
  • вывод списка в поток неправильный. cout<< *hash_table[num]->begin(); вы выводите значение итератора, в данный момент указывающего на начало списка, что абсолютно бессмысленное действие. Нужно в цикле пройти по списку и вывести каждый элемент:
for(auto item : hash_table[num])
   cout << item << "\t";
→ Ссылка