Maps in Datei abspeichern



  • Hallo zusammen,
    ich hatte versucht, eine Map in eine Datei abzuspeichern.
    Leider hat dieser Versuch folgende Compilermeldung ausgegeben:

    1>------ Erstellen gestartet: Projekt: Adressbuch, Konfiguration: Debug Win32 ------
    1> int main ().cpp
    1>d:\meine projekte\visual c++\adressbuch\adressbuch\int main ().cpp(66): error C2664: 'std::basic_ostream<_Elem,_Traits>::write': Konvertierung des Parameters 1 von 'std::map<_Kty,_Ty> *' in 'const char *' nicht möglich
    1> with
    1> [
    1> _Elem=char,
    1> _Traits=std::char_traits<char>
    1> ]
    1> and
    1> [
    1> _Kty=std::string,
    1> _Ty=int
    1> ]
    1> Die Typen, auf die verwiesen wird, sind nicht verknüpft; die Konvertierung erfordert einen reinterpret_cast-Operator oder eine Typumwandlung im C- oder Funktionsformat.
    ========== Erstellen: 0 erfolgreich, Fehler bei 1, 0 aktuell, 0 übersprungen ==========

    der betroffene Quelltextausschnitt sieht wie folg aus:

    Output.open ("adressbuch.db", ios::binary);
    				Output.write (&adressen_map, sizeof (adressen_map));
    				Output.close();
    

  • Mod

    Oje, da ist ja alles falsch. Vergiss deinen Ansatz komplett.

    Also die Grundidee wäre es, die einzelnen Mapelemente zu serialisieren und abzuspeichern. Ich sehe du hast ints als Schlüssel und strings als Werte. Die ints kannste einfach als Zeichen ausgeben, bei den Strings ist das ein bisschen komplizierter. Falls da nur "normaler" Text drin steht, kannst du sie auch einfach ausgeben und hinterher einfach den Rest der Zeile hinter dem Schlüssel einlesen. Falls da auch Sonderzeichen in den Strings sein können, dann wäre es vielleicht eine gute Idee, die Zeichenkette erst in base64 o.Ä. konvertieren, dass macht das ganze etwas einfacher.

    Und dann iterierst du über die ganze Map und gibst jedes einzelne Element aus.



  • Erstens: Wie der Compiler dir mitteilen willst, kann man die meisten Zeigertypen nicht implizit ineinander umwandeln. Dazu benötigt man schon einen expliziten Cast.

    Zweitens: Selbst wenn du das durch den Compiler quetschen kannst, macht es nicht das was du erwartest. write() schreibt nur die Innereien des übergebenen Objekts, bei einer map<> sind das vermutlich ein paar Zeiger und int-Werte. Die eigentlichen Nutzdaten liegen auf dem Heap und werden nicht angefasst.
    Um den map<>-Inhalt abspeichern zu können, mußt du einmal komplett durch iterieren und jedes Schlüssel/Wert-Paar einzeln schreiben.

    (btw, std::string kannst du auch nicht einfach per write() schreiben)



  • hallo,
    wenn ich die Map komplett iteriere und abspeichere, kann ich dann nicht ein Problem bekommen, wenn ich diese Daten aus der Datei auslesen möchte?
    Ich meine, ich speichere doch in der Map strings ab und als Wert dazu ints. Wie kann ich denn auf Basis von Strings iterieren?



  • Zweistein97 schrieb:

    Wie kann ich denn auf Basis von Strings iterieren?

    So wie bei jedem anderen Typ? Was soll an Strings speziell sein?

    Der Iterator gibt dereferenziert ein std::pair mit Key und Value zurück. Die kannt du ganz normal auslesen...



  • also in etwa so:

    typedef std::map<std::string,int>::const_iterator MCI;
    
    for(MCI itr = adressen_map.begin(); itr != adressen_map.end(); itr++)
    {
        output << itr->first << '\t' << itr->second << '\n';
    }
    

  • Mod

    Hyde++ schrieb:

    also in etwa so:

    typedef std::string::const_iterator SCI;
    
    for(SCI itr = adressen_map.begin(); itr != adressen_map.end(); itr++)
    {
        output << itr->first << '\t' << itr->second << '\n';
    }
    

    😕
    Du meinst wohl eher einen map-Iterator.



  • ohhh, ja klar! peinlich!



  • Ausserdem könntest du dir unnötige Kopien sparen, indem du ++itr statt itr++ schreibst. Manche Leute speichern sich sogar den end() -Iterator, wenn er konstant bleibt 🙂

    (Wird beides kaum etwas ausmachen, aber ist gut zu wissen in Situationen, wo der Iterationsoverhead ins Gewicht fällt)



  • Hyde++ schrieb:

    also in etwa so:

    typedef std::map<std::string,int>::const_iterator MCI;
    
    for(MCI itr = adressen_map.begin(); itr != adressen_map.end(); itr++)
    {
        output << itr->first << '\t' << itr->second << '\n';
    }
    

    gut! Danke für den Beispielquelltext 😉
    Nur arbeitest du mit zeilenumbrüchen innerhalt einer Datei.
    Als eher unerfahrener Programmierer würde ich gern wissen, wie man etwas ausliest.
    habt ihr hier eine Ahnung?



  • Zweistein97 schrieb:

    Als eher unerfahrener Programmierer würde ich gern wissen, wie man etwas ausliest.
    habt ihr hier eine Ahnung?

    mit getline() bzw. Stream-Operator die beiden Werte lesen und dann per insert() in die map<> einfügen.



  • Vielleicht könnte dir dieser Thread helfen, in dem ich ein ähnliches Problem hatte:

    http://www.c-plusplus.net/forum/291145



  • CStoll schrieb:

    Zweistein97 schrieb:

    Als eher unerfahrener Programmierer würde ich gern wissen, wie man etwas ausliest.
    habt ihr hier eine Ahnung?

    mit getline() bzw. Stream-Operator die beiden Werte lesen und dann per insert() in die map<> einfügen.

    Es fände es echt gut, wenn du mir ein Codebeispiel geben würdest. Beim Googlen bin ich darauf gestoßen (Um ehrlich zu sein, war das das einzige womit ich etwas anfangen konnte):

    http://www.willemer.de/informatik/cpp/iostream.htm

    Die Erklärung auf dieser Seite ist aber zu kurz für mich, damit ich es verstehe... 😞


  • Mod

    Ach nun komm. Die ersten Treffer bei jeder einigermaßen gut gestellten Google-Anfrage dürften diese sein:
    http://www.cplusplus.com/reference/string/getline/
    http://www.cplusplus.com/reference/iostream/istream/operator>>/

    Außerdem sollte das in so ziemlich jedem Lehrbuch zu C++ schätzungsweise auf Seite 2 stehen.

    Und was willst du noch mehr? Der Link sind 4 sehr große Bildschirmseiten. Du erwartest doch nicht, dass hier jemand noch mehr Erklärung als das liefert?



  • zu beachten ist, das diese Seiten auf Englisch sind, und ich es im Englischen als 13 Jähriger noch nicht so weit bin....


Anmelden zum Antworten