Intestazione del codice Huffman C ++
-
20-08-2019 - |
Domanda
sostanzialmente, ho il mio tavolo Huffman come
std::map<std::string, char> ciMap;
Dove stringa è il modello di bit e char è il valore rappresentato da detto modello. Il problema è come posso memorizzarlo come intestazione del mio file compresso in modo da poter ricostruire la stessa mappa quando voglio decodificarlo?
Prova di memorizzarlo come binario:
size_t mapLen = ciMap.size();
outFile.write(reinterpret_cast<char*>(&mapLen), sizeof(size_t));
outFile.write(reinterpret_cast<char*>(&ciMap), sizeof(ciMap));
E poi costruendo con:
inFile.read(reinterpret_cast<char*>(&mapLen), sizeof(size_t));
inFile.read(reinterpret_cast<char*>(&ciMap), sizeof(mapLen));
Non funziona, ricevo un errore di inizializzazione della stringa ... qualcosa a che fare con NULL. Eventuali suggerimenti? Se hai un modo migliore di memorizzare bit e valori, mi piacerebbe sentire.
Soluzione
Puoi farlo da solo o puoi farlo con boost: http://www.boost.org/doc/libs/1_37_0/libs/serialization/doc/index.html . Quello che provi attualmente è solo visualizzare la mappa come un semplice tipo di dati vecchio, il che significa essenzialmente che è un tipo di dati C. Ma non lo è, quindi non riesce a salvare / caricare. aumentare la serializzazione lo fa correttamente. Date un'occhiata a questo. Se non vuoi usarlo, puoi fare qualcosa del genere:
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));
Si noti che quanto sopra necessita di alcune modifiche se i caratteri memorizzati potrebbero essere anche spazi bianchi. Per questo motivo, è probabilmente il migliore da convertire dapprima in un int prima di scrivere e poi leggere come int durante il caricamento. In realtà, raccomando di aumentare la serializzazione e aumentare iostreams ( http : //www.boost.org/doc/libs/1_37_0/libs/iostreams/doc/index.html ), che include un flusso di compressione in grado di comprimere in modo trasparente anche i tuoi dati.
Altri suggerimenti
Non puoi semplicemente serializzare i valori binari su disco in questo modo. La rappresentazione in memoria non è semplicemente un blocco contiguo di memoria, e anche se lo fosse probabilmente conterrà puntatori relativi all'indirizzo del blocco.
È necessario scorrere l'iter sulla mappa e serializzare ciascun elemento singolarmente. Quindi per riportarli indietro ricostruisci la mappa leggendo gli elementi dal disco uno per uno e reinserendoli nella mappa.
Ottima domanda. Il problema qui è che i contenitori predefiniti non supportano la serializzazione: devi scriverlo tu stesso, è una seccatura, ma è possibile.
Ecco come è possibile serializzare un std::map
in un formato testuale. Puoi adattarlo per scrivere in qualsiasi formato binario di cui hai bisogno. Sostituisci l'operatore <<
con reads
e 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;
}