2008-12-09 3 views
2

в основном, я получил свой Хаффман таблицуC++ код Хаффмана Заголовок

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

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

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

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)); 

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

ответ

4

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

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), который включает в себя поток сжатия, который также может сжимать ваши данные.

2

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

Вот как можно сериализовать 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; 
} 
3

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

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

Смежные вопросы