Заголовок кода Хаффмана C++

в основном, у меня есть таблица Хаффмана как

std::map<std::string, char> ciMap;

Где строка - это битовый шаблон, а char - значение, представленное указанным шаблоном. Проблема в том, как сохранить это как заголовок моего сжатого файла, чтобы я мог снова построить ту же карту, когда захочу ее декодировать?

Попытка сохранить его как двоичный:

size_t mapLen = ciMap.size();
outFile.write(reinterpret_cast<char*>(&mapLen), sizeof(size_t));
outFile.write(reinterpret_cast<char*>(&ciMap), sizeof(ciMap));

А позже построение с:

inFile.read(reinterpret_cast<char*>(&mapLen), sizeof(size_t));
inFile.read(reinterpret_cast<char*>(&ciMap), sizeof(mapLen));

Не работает, я получаю ошибку инициализации строки ... что-то связано с NULL. Какие-либо предложения? Если у вас есть лучший способ хранения битов и значений, я хотел бы услышать.

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
0
3 042
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Отличный вопрос. Проблема здесь в том, что контейнеры по умолчанию не поддерживают сериализацию - вы должны написать это самостоятельно, это больно, но возможно.

Вот как можно преобразовать std::map в текстовый формат. Вы можете адаптировать его для записи в любой нужный вам двоичный формат. Просто замените оператор << на reads и writes.

template<typename K, typename V>
std::ostream &operator << (std::ostream &out, const std::map<K,V> &map) {
    out << "map " << map.size() << "\n";
    for (typename std::map<K,V>::const_iterator i = map.begin(); i != map.end(); ++i) {
        out << (*i).first << "\n" << (*i).second << "\n";
    }
    return out;
}

template<typename K, typename V>
std::istream &operator >> (std::istream &in, std::map<K,V> &map) {
    std::string mapkeyword;
    size_t num;
    in >> mapkeyword >> num;
    for (size_t i = 0; i < num; ++i) {
        K key; V value;
        in >> key >> value;
        map[key] = value;
    }
    return in;
}

Вы не можете просто сериализовать двоичные значения на диск таким образом. Представление в памяти - это не просто непрерывный блок памяти, и даже если бы это было так, оно, скорее всего, будет содержать указатели, относящиеся к адресу блока.

Вам нужно перебирать карту и сериализовать каждый элемент индивидуально. Затем, чтобы вернуть их, вы реконструируете карту, считывая элементы с диска один за другим и повторно вставляя их в карту.

Ответ принят как подходящий

Вы можете сделать это сами, а можете сделать это с помощью boost: http://www.boost.org/doc/libs/1_37_0/libs/serialization/doc/index.html. В настоящее время вы пытаетесь просто просматривать карту как обычный старый тип данных, что, по сути, означает, что это тип данных C. Но это не так, поэтому не удается сохранить / загрузить. Boost сериализация делает это правильно. Посмотри на это. Если вы не хотите его использовать, вы можете сделать что-то вроде этого:

typedef std::map<std::string, char> my_map;
my_map ciMap;

// saving
std::ofstream stream("file.txt");
for(my_map::const_iterator it = ciMap.begin(); it != ciMap.end(); ++it) {
    stream << it->first << " " << it->second << std::endl;
}

// loading
char c;
std::string bits;
std::ifstream stream("file.txt");
while(stream >> bits >> c)
    ciMap.insert(std::make_pair(bits, c));

Обратите внимание, что приведенное выше требует некоторых изменений, если сохраненные символы также могут быть пробельными символами. Из-за этого, вероятно, лучше сначала преобразовать в int перед записью, а затем читать как int при загрузке. На самом деле, я рекомендую повысить сериализацию и увеличить iostreams (http://www.boost.org/doc/libs/1_37_0/libs/iostreams/doc/index.html), который включает поток сжатия, который также может прозрачно сжимать ваши данные.

Другие вопросы по теме