C++ ハフマン コード ヘッダー
-
20-08-2019 - |
質問
基本的に、ハフマンテーブルは次のようになります
std::map<std::string, char> ciMap;
ここで、string はビット パターン、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と関係があります。助言がありますか?ビットと値を保存するより良い方法がある場合は、聞きたいです。
解決
自分で行うことも、ブーストを使用して行うこともできます。 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 として読み取ることがおそらく最善です。実際には、シリアル化を強化し、iostream を強化することをお勧めします (http://www.boost.org/doc/libs/1_37_0/libs/iostreams/doc/index.html)、これにはデータを透過的に圧縮できる圧縮ストリームが含まれています。
他のヒント
あなたは、このようにディスクにバイナリ値をシリアル化することはできません。メモリ表現で単にメモリの連続ブロックではなく、それがあった場合でも、それはおそらくブロックのアドレスに関連しているのポインタが含まれています。
あなたはマップを反復し、個別に各項目をシリアライズする必要があります。そしてあることで、ディスク1オフの項目を読んで、マップにそれらを再挿入することで、マップを再構築バックあなたの中にそれらをもたらすために。
グレート質問です。ここでの問題は、デフォルトのコンテナがシリアル化をサポートしていないということです - あなたはそれを自分で記述する必要があり、それは苦痛だが、それが可能だ。
。ここでは、テキスト形式に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;
}