Question

fondamentalement, j'ai ma table de Huffman comme

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

Où string est le motif de bits et char est la valeur représentée par ce motif. Le problème est de savoir comment enregistrer cet en-tête dans mon fichier compressé afin de pouvoir reconstruire la même carte lorsque je souhaite le décoder.

Essayer de le stocker en tant que binaire:

size_t mapLen = ciMap.size();
outFile.write(reinterpret_cast<char*>(&mapLen), sizeof(size_t));
outFile.write(reinterpret_cast<char*>(&ciMap), sizeof(ciMap));

Et construire plus tard avec:

inFile.read(reinterpret_cast<char*>(&mapLen), sizeof(size_t));
inFile.read(reinterpret_cast<char*>(&ciMap), sizeof(mapLen));

Ne fonctionne pas, je reçois une erreur d'initialisation de chaîne ... quelque chose à voir avec NULL. Aucune suggestion? Si vous avez un meilleur moyen de stocker les bits et les valeurs que je voudrais entendre.

Était-ce utile?

La solution

Vous pouvez le faire vous-même, ou avec un boost: http://www.boost.org/doc/libs/1_37_0/libs/serialization/doc/index.html . Ce que vous essayez actuellement, c’est d’afficher la carte comme un type de données ordinaire, ce qui signifie essentiellement qu’il s’agit d’un type de données C. Mais ce n'est pas le cas, donc il ne parvient pas à enregistrer / charger. La sérialisation boost le fait correctement. Jetez un coup d'oeil. Si vous ne voulez pas l'utiliser, vous pouvez faire quelque chose comme ceci:

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

Notez que ce qui précède nécessite quelques modifications si les caractères stockés peuvent également être des espaces. Pour cette raison, il est probablement préférable de convertir d'abord en int avant d'écrire, puis de lire en tant qu'int lors du chargement. En fait, je recommande d’améliorer la sérialisation et les iostreams ( http : //www.boost.org/doc/libs/1_37_0/libs/iostreams/doc/index.html ), qui inclut un flux de compression qui peut également compresser vos données de manière transparente.

Autres conseils

Vous ne pouvez pas simplement sérialiser les valeurs binaires sur le disque de cette manière. La représentation en mémoire n'est pas simplement un bloc de mémoire contigu, et même si c'était le cas, elle contiendra probablement des pointeurs relatifs à l'adresse du bloc.

Vous devez parcourir la carte et sérialiser chaque élément individuellement. Ensuite, pour les ramener, reconstruisez la carte en lisant un à un les éléments du disque et en les réinsérant dans la carte.

Excellente question. Le problème ici est que les conteneurs par défaut ne prennent pas en charge la sérialisation - vous devez l'écrire vous-même, c'est pénible, mais c'est possible.

Voici comment vous pouvez sérialiser un std::map en un format textuel. Vous pouvez l'adapter pour écrire dans le format binaire dont vous avez besoin. Il suffit de remplacer l'opérateur << par reads et 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;
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top