Сохранение STL map в файл.
От: _Lestat_ Россия  
Дата: 13.10.06 11:14
Оценка: :))) :)))
Я реализую алгоритм сжатия Хаффмана. Таблица перекодировки символов у меня хранится в
map<char, string> Codes;

Мне нужно сохранять таблицу перекодировки вместе с сжатым файлом. Я записываю таблицу в файл следующим образом:
fwrite(&Codes, sizeof(Codes), 1, fdOut);

А считываю так:
fread(&Codes, sizeof(Codes), 1, fdIn);


Можно ли так делать? Если нет, то каков правильный варинт.?
Backup not found: (A)bort (R)etry (P)anic
Re: Сохранение STL map в файл.
От: Bell Россия  
Дата: 13.10.06 11:23
Оценка: 4 (1)
Здравствуйте, _Lestat_, Вы писали:

...

_L_>Можно ли так делать?


Естественно нет. Попробуй ради интереса проследить зависимость sizeof(Codes) от количества хранимых в Codes елементов.
Hint: каждый узел — динамический объект. Кроме того, std::string также хранит свое содержимое в динамическом буфере.

_L_>Если нет, то каков правильный варинт.?

Для текстового файла можно так:
ofstream out("map.txt");
out << Codes.size() << '\n';
map<char, string>::iterator b = Codes.begin(), e = Codes.end();
for(; b != e; ++b)
   out << b->first << '\t' << b->second << 'endl';

//дальше твои данные


Для бинарного бедет несколько сложнее — нужно будет вручную организовать звпись строк.
Любите книгу — источник знаний (с) М.Горький
Re: Сохранение STL map в файл.
От: Greg Zubankov СССР  
Дата: 13.10.06 11:25
Оценка:
Здравствуйте, _Lestat_, Вы писали:

_L_>Можно ли так делать? Если нет, то каков правильный варинт.?


Нет, так делать нельзя. Подобный вариант сохранения подходит только для POD типов.
Елементы std::map хранятся в куче, и не попадут в файл.

Воспользуйся библиотеками сериализации. К примеру Boost.Serialization.
Re: Сохранение STL map в файл.
От: np9mi7 Россия  
Дата: 13.10.06 11:26
Оценка:
Здравствуйте, _Lestat_, Вы писали:

_L_>Можно ли так делать? Если нет, то каков правильный варинт.?


Так делать нельзя, потому как std::map и std::basic_string не POD типы и работают с динамической памятью. Ты просто сохраняешь состояние объекта, так как он есть в памяти. Объект агрегирует в себя указатели, не факт (вообще это мало вероятно), что эти указатели будут валидны при попытке загрузить этот объект обратно;

Писать свой способ сериализации. По этому поводу можно почитать http://rsdn.ru/article/xml/xmlcpp.xml
Автор(ы): Андрей Мартынов
Дата: 30.11.2003
В статье рассмотрен декларативный подход к решению задачи чтения/записи XML-файлов из программ на классическом C++. Метод основан на построении специальной структуры статических данных — метаданных типов.
и http://rsdn.ru/article/files/Classes/Serialization2.xml;

Тебе необходимо поддержать простую структуру:

...
<Key> <Value>
<Key> <Value>
<Key> <Value>
...

, а это не так сложно;
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
"В любое мгновение принятия решения, лучшее, что вы можете сделать, это принять правильное решение; следующим лучшим вариантом будет принять неправильное решение, худший вариант – не принимать решения совсем" (c) Теодор Рузвельт.
Re: Сохранение STL map в файл.
От: sch  
Дата: 13.10.06 11:34
Оценка: 1 (1) +2
_L_>Можно ли так делать? Если нет, то каков правильный варинт.?

Правильный вариант -- не использовать ассоциативное хранилище там где оно не нужно.

// таблица
string table[MAX_CHAR];

// получить строку по символу ch
char ch;
string &rule = table[unsigned(ch)];


Получится даже быстрее, потому что не нужен поиск по сбалансированному бинарному дереву, который в твоем случае требует log2(256) = 8 итераций не самого быстрого цикла,
Re: Сохранение STL map в файл.
От: Greg Zubankov СССР  
Дата: 13.10.06 12:07
Оценка:
Здравствуйте, _Lestat_, Вы писали:

_L_>Можно ли так делать? Если нет, то каков правильный варинт.?


Вот работающий кусок кода, который может сериализовать твой map в текстовую строку, и десериализовать строку в map.

#include <map>
#include <string>
#include <sstream>
#include <iostream>
#include <iterator>
#include <vector>
#include <cassert>

namespace std
{

  std::ostream& operator<<(std::ostream& ostr, std::pair<char, std::string> const& pr)
  {
    ostr << pr.first << ' ' << pr.second.size() << ' ' << pr.second << ' ';
    return ostr;
  }

  std::istream& operator>>(std::istream& istr, std::pair<char, std::string>& pr)
  {
    std::size_t sz;
    istr >> pr.first >> sz;
    if(!istr)
      return istr;
    std::vector<char> tmp(sz);  // vector испульзуется из-за того, string не дает contiguous гарантии 
    istr.read(&tmp[0], 1);      // пропуск пробела перед строкой
    istr.read(&tmp[0], sz);
    pr.second.assign(tmp.begin(), tmp.end());
    return istr;
  }

}

int main()
{
  std::map<char, std::string> mymap;
  mymap['a'] = "greg";
  mymap['d'] = "test string";

  typedef std::pair<char, std::string> mypair;

  std::stringstream oss;
  std::copy(mymap.begin(), mymap.end(), std::ostream_iterator<mypair>(oss));
  std::cout << oss.str();

  std::map<char, std::string> mymap1;
  std::copy(std::istream_iterator<mypair>(oss), std::istream_iterator<mypair>(), std::inserter(mymap1, mymap1.begin()));

  assert(mymap1 == mymap);
}
Re: Сохранение STL map в файл.
От: Аноним  
Дата: 13.10.06 14:11
Оценка:
Здравствуйте, _Lestat_, Вы писали:

_L_>Можно ли так делать?


Да, синтаксис такое позволяет, но результат будет не тот, который ты ожидаешь
Re[2]: Сохранение STL map в файл.
От: Roman Odaisky Украина  
Дата: 13.10.06 15:34
Оценка:
Здравствуйте, sch, Вы писали:

sch>Правильный вариант -- не использовать ассоциативное хранилище там где оно не нужно.


И в самом деле, интересно: по стандарту можно реализовывать std::map<char, X> как X[256]? И, если можно, кто-то так делает?
До последнего не верил в пирамиду Лебедева.
Re: Сохранение STL map в файл.
От: _Lestat_ Россия  
Дата: 14.10.06 05:31
Оценка:
Я ожидал, что мой вариант неправильный, т.к. map — это динамический класс.

В итоге я сделал просто. Формат файла получился такой: количество_элементов_в_контейнере, char, длина string, сам string, char, длина string, сам string, и т.д.

Спасибо за ответы.
Backup not found: (A)bort (R)etry (P)anic
Re[2]: Сохранение STL map в файл.
От: siv Украина  
Дата: 14.10.06 10:29
Оценка: +1
> ... подходит только для POD типов.
В теории верно, на практике чревато Ибо на стороне писателя и
читателя может быть разное выравнивание...
Posted via RSDN NNTP Server 2.0
Re[2]: Сохранение STL map в файл.
От: Greg Zubankov СССР  
Дата: 14.10.06 10:37
Оценка:
Здравствуйте, _Lestat_, Вы писали:

_L_>В итоге я сделал просто. Формат файла получился такой: количество_элементов_в_контейнере, char, длина string, сам string, char, длина string, сам string, и т.д.


В ранее предложенном мною варианте количество элементов контейнера не используется. Взгляни.
Re[3]: Сохранение STL map в файл.
От: johny5 Новая Зеландия
Дата: 15.10.06 11:03
Оценка:
siv>читателя может быть разное выравнивание...

.. и разные размеры базовых типов, и разные ENDIAN...
Re: Сохранение STL map в файл.
От: Rakafon Украина http://rakafon.blogspot.com/
Дата: 20.08.09 14:34
Оценка:
Здравствуйте, _Lestat_, Вы писали:
_L_>Можно ли так делать? Если нет, то каков правильный варинт.?

БугагагГ!!! Долго ржал!!!

ИМХО, boost::serialization тебе поможет ...

... и ещё раз БуГаГаГГГ!!!
"Дайте мне возможность выпускать и контролировать деньги в государстве и – мне нет дела до того, кто пишет его законы." (c) Мейер Ансельм Ротшильд , банкир.
Re[3]: Сохранение STL map в файл.
От: Rakafon Украина http://rakafon.blogspot.com/
Дата: 20.08.09 14:36
Оценка:
Здравствуйте, siv, Вы писали:
siv>В теории верно, на практике чревато Ибо на стороне писателя и
siv>читателя может быть разное выравнивание...

... мне кажется с тех пор как придумади механизм засериализовать всё что угодно в строку и оттуда же это всё десериализовать, бинарное перепехивание POD объектов стало экзотическим извратом!
"Дайте мне возможность выпускать и контролировать деньги в государстве и – мне нет дела до того, кто пишет его законы." (c) Мейер Ансельм Ротшильд , банкир.
Re[2]: Сохранение STL map в файл.
От: ant_katcin Россия  
Дата: 20.08.09 17:06
Оценка: +1 :))
R>БугагагГ!!! Долго ржал!!!

Да, действительно долго... с 2006 года все ещё успокоится не можешь
... << RSDN@Home 1.2.0 alpha 4 rev. 1181>>
Re[3]: Сохранение STL map в файл.
От: Кодт Россия  
Дата: 24.08.09 13:25
Оценка:
Здравствуйте, Roman Odaisky, Вы писали:

RO>И в самом деле, интересно: по стандарту можно реализовывать std::map<char, X> как X[256]? И, если можно, кто-то так делает?


Нельзя.

Элемент мапа (value_type) — это pair<const Key, Value>.
Синтезировать его в итераторе (как это делается у vector<bool>) нельзя, т.к. ссылки и указатели на элементы не должны инвалидироваться при разрушении итератора.
Плюс ещё нужно где-то хранить признаки присутствия. То есть,
— pair<bool, storage<value_type>>[256]
— (value_type*)[256]
— storage<value_type>[256] + bool[256]
где storage<T> — выделенная, но не инициализированная память под объект типа T.

Далее встаёт вопрос о sizeof(map<char,Value>) — значит, массив должен быть динамическим.

Ну и самое главное — этот подход годится только для map<char,Value,Pred,Alloc> у которых
— Alloc способен создавать массив, а не только мелкие объекты (узлы дерева)
— Pred — это less<char> либо greater<char>, либо ещё какие-то порядки, для которых известна проекция на числовую ось, т.е. Pred(c1,c2) == Index(c1)<Index(c2)
(для less<char> Index(c) = (unsigned char)c, а для greater — соответственно, (unsigned char)(-c)).

Так что проще не заморачиваться со специализацией, а делать правильный контейнер "по мотивам".
... << RSDN@Home 1.2.0 alpha 4 rev. 1237>>
Перекуём баги на фичи!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.