2

基本的に、私はハフマンテーブルを次のように持っています

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 と関係があります。助言がありますか?ビットと値を保存するより良い方法があれば、私が聞きたいです。

4

3 に答える 3

4

自分で行うことも、ブーストを使用して行うこともできます: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)をお勧めします。これには、データを透過的に圧縮できる圧縮ストリームも含まれています。

于 2008-12-09T01:43:39.917 に答える
3

この方法でバイナリ値をディスクにシリアル化することはできません。インメモリ表現は、単に連続したメモリブロックではなく、たとえそうであったとしても、ブロックのアドレスに相対的なポインタが含まれている可能性があります。

マップを繰り返し処理し、各アイテムを個別にシリアル化する必要があります。次に、それらを元に戻すには、ディスクからアイテムを1つずつ読み取り、マップに再挿入して、マップを再構築します。

于 2008-12-09T01:38:16.887 に答える
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;
}
于 2008-12-09T01:34:59.373 に答える