Mehrere Instanzen einer Klasse abspeichern



  • @Kellerautomat
    XML ist weder kompliziert noch unleserlich, und Binärformate sind in den meisten Fällen keine sinnvolle Alternative.
    Binärformate sind schlecht erweiterbar, daher schlecht wartbar und grundsätzlich total unleserlich.

    Das einzige was mMn. gegen XML spricht ist dass XML in C++ etwas fummelig zu verwenden ist.



  • Mich nervt bei XML besonders der Overhead. Das bläht eine ansonsten recht kleine Datei doch sehr auf.


  • Mod

    Braunstein schrieb:

    Mich nervt bei XML besonders der Overhead. Das bläht eine ansonsten recht kleine Datei doch sehr auf.

    Man muss ja auch nicht zwangsläufig gleich zu XML greifen. Bei sehr vielen Anwendungen reichen Formate wie "Alle Zahlen nacheinander", "Ein String pro Zeile" oder auch das gute alte CSV. Hier im Thread ist das Problem, dass uns fast überhaupt gar nichts über die Daten und die Anwendung bekannt ist, das läuft dann bei den Antworten eben auf allerallgemeinste Formate hinaus.



  • sulky schrieb:

    aber in der ausgabefunktion folgt eine Fehlermeldung auf

    is>>e.a>>e.s;>>e.next;
    

    wieso das?

    Wie soll dir jemand die Frage beantworten, wenn du noch nicht einmal die Fehlermeldung nennst und wann du sie bekommst?
    Im Zweifelsfall hast du die Zeile tatsächlich so geschrieben und ein ; zuviel.



  • Sorry aber deine Lösung ist für mich ein Hack.

    Blödsinn, das ist die Standardlösung für Array-Serialisierungen.

    Wer garantiert dass das Format sauber dokumentiert wird, s.d. in 5 Jahren, wenn jemand den Code wieder anfasst, das Datenformat auch ohne Probleme versteht.

    Wovon redest du?

    Was spricht dagegen in solchen Fällen die Klassendefinitionen ins XML Format zu wandeln. Ist lesbarer als deine Lösung und eindeutiger definiert.

    Lol, das ist jetzt nicht dein ernst, oder? 👎 😮



  • Hallo zusammen, vielen Dank für eure Hilfe.
    Auch wenn ich nicht alles bis ins detail verstehen konnte.

    Hier nochmals meine Klasse. Neu will ich (auf Rat aus diesem Forum) den Zeiger auf die nächste Instanz nicht mehr mit abspeichern, da nach einem Computerneustart die Instanz wohl kaum mehr an der gleichen Stelle befinden
    wird.

    class element
    {
    public:
    int a;
    string s;
    element*next;
    
    friend ostream& operator<<(std::ostream& os, element const& e)
        {
            os<<e.a<<e.s;
    
    		// Die ganzen Member von e in os reinschreiben
             return os; // Referenz auf Stream zurückgeben -> damit os << a << b << c möglich wird
        }
    
    friend istream& operator>>(std::istream& is, element& e)
        {
             is>>e.a>>e.s;
             return is; // ~ zurückgeben -> damit is >> a >> b >> c möglich wird.
        }
    };
    

    und hier das Testprogram, welches auch funktioniert:

    int _tmain(int argc, _TCHAR* argv[])
    {
    element m;
    m.a=7;
    m.s="hallo";
    
    std::ofstream os("Bla.txt");
    os << m; 
    os.close();
    
    std::ifstream stream("Bla.txt");
    element k;
    stream >> k;
    
    cout<<k.a<<"   "<<k.s<<endl;
    }
    

    Nun möchte ich ja aber nicht eine Instanz abspeichern, sondern mehrere:
    Dazu erweitere ich mein Testprogram wie folgt:

    int _tmain(int argc, _TCHAR* argv[])
    {
    element m;
    m.a=7;
    m.s="hallo";
    
    element n;
    n.a=5;
    n.s.hello;
    
    std::ofstream os("Bla.txt");
    os << m; 
    
    //hier stehe ich an. Jetzt möchte ich n doch auch noch in die selbe    
    //datei speichern
    
    os.close();
    
    std::ifstream stream("Bla.txt");
    element k;
    element l; //nun brauche ich ein zweites Element, welches n ersetzt 
    stream >> k;
    
    stream >> l; //ob dies so richtig ist, bin ich mir überhaut nicht sicher.
    
    cout<<k.a<<"   "<<k.s<<endl;
    
    cout<<l.a<<"   "<<l.s<<endl; //und auch hier der Test, ob l und n identisch sind
    }
    

    nun sind folgende Probleme noch ungelöst:

    1. Wie schreibe ich ein zweites Element in dieselbe datei?
    2. Funkioniert das lesen des zeiten Elementes auf diese Weise?
    3. (Bereits in diesem Forumsbeitrag erwähnt) Wie passe ich den String an, damit
    nicht aus "Hallo Welt" ein "Hallo" wird.



  • 1. Genau wie beim ersten Element auch:

    Datei << Element1; 
    Datei << Element2;
    

    2. Das funktioniert also genau andersrum:

    Element Element1;
    Element Element2;
    
    Datei >> Element1; 
    Datei >> Element2;
    

    3. Speicher den std::string z.B. als eigene Zeile und lies ihn mit std::getline wieder aus.



  • hallo jjjjj
    VIelen Dank für deine Antwort.
    Leider funktioniert es noch nicht.

    Hier nochmals das angepasste Program:
    Die Klasse ist unverändert.

    int _tmain(int argc, _TCHAR* argv[])
    {
    element m,n;
    m.a=7;
    m.s="hallo";
    
    n.a=5;
    n.s="hello";
    
    std::ofstream os("Bla.txt");
    os << m;
    os<< n;
    os.close();
    
    std::ifstream stream("Bla.txt");
    element k,l;
    stream >> k;
    stream >>l;
    
    cout<<k.a<<"   "<<k.s<<endl;
    cout<<l.a<<"   "<<l.s<<endl;
    }
    

    Konsolenausgabe:
    7 hallo5hello
    -895993460

    Erst dachte ich, es läge daran, dass ich den String noch nicht so eingelesen habe, wie du es empfohlen hast und das Program deshalb nicht erkennt wo der string zu ende ist. Dann habe ich aber sämtliche Strings entfernt und einen Test gemacht. Hat aber nicht funktioniert.
    Was läuft da noch schief?



  • Probier mal:

    os << m << std::endl;
    os << n << std::endl;
    

    Ansonsten zeig nochmal den aktuellen Code (insbesondere die Operatoren >> und << in der Klasse)



  • Fantastisch! Jetzt klappts.

    Aber ich schreibe den String immer noch nicht als zeile in die datei. Kann dies späternoch zu problemen führen?



  • sulky schrieb:

    Fantastisch! Jetzt klappts.

    Aber ich schreibe den String immer noch nicht als zeile in die datei. Kann dies späternoch zu problemen führen?

    Durch das std::endl tust du das indirekt. Denn std::endl schreibt auch eine Leerzeile in die Datei.

    Ich habe dir in deinem anderen Thread dazu noch ausführlicher geantwortet. Am besten experimentierst du damit ein wenig rum und schaust dir auch mal die Datei Bla.txt an. Das sollte Klarheit schaffen.



  • Wieso ist mir das noch nicht aufgefallen?

    Einerseits können chars und ints unterschiedlich gross sein

    Nein, die Größe von char, signed char und unsigned char ist vom Standard deutlich festgelegt: Genau ein Byte.



  • Sone schrieb:

    Wieso ist mir das noch nicht aufgefallen?

    Einerseits können chars und ints unterschiedlich gross sein

    Nein, die Größe von char, signed char und unsigned char ist vom Standard deutlich festgelegt: Genau ein Byte.

    Quizfrage:

    Programm A speichert 60 Bytes in eine Datei.
    Programm B liest die gesamte Datei, findet aber nur 40 Bytes vor.
    Kann das sein?



  • reinterpreter schrieb:

    Sone schrieb:

    Wieso ist mir das noch nicht aufgefallen?

    Einerseits können chars und ints unterschiedlich gross sein

    Nein, die Größe von char, signed char und unsigned char ist vom Standard deutlich festgelegt: Genau ein Byte.

    Quizfrage:

    Programm A speichert 60 Bytes in eine Datei.
    Programm B liest die gesamte Datei, findet aber nur 40 Bytes vor.
    Kann das sein?

    Nein. Wenn Programm A 60 chars in die Datei schreibt, dann findet Programm B auch 60 vor.



  • Sone schrieb:

    reinterpreter schrieb:

    Sone schrieb:

    Wieso ist mir das noch nicht aufgefallen?

    Einerseits können chars und ints unterschiedlich gross sein

    Nein, die Größe von char, signed char und unsigned char ist vom Standard deutlich festgelegt: Genau ein Byte.

    Quizfrage:

    Programm A speichert 60 Bytes in eine Datei.
    Programm B liest die gesamte Datei, findet aber nur 40 Bytes vor.
    Kann das sein?

    Nein. Wenn Programm A 60 chars in die Datei schreibt, dann findet Programm B auch 60 vor.

    Doch. Da nicht festgelegt ist, aus wie vielen Bits ein Byte besteht. Bei Programm A sind es 8 Bits, bei Programm B 12 Bits.

    C++11-Standard § 1.7/1 schrieb:

    The fundamental storage unit in the C++ memory model is the byte. A byte is at least large enough to contain
    any member of the basic execution character set (2.3) and the eight-bit code units of the Unicode UTF-8
    encoding form and is composed of a contiguous sequence of bits, the number of which is implementation-
    defined. The least significant bit is called the low-order bit; the most significant bit is called the high-order
    bit. The memory available to a C++ program consists of one or more sequences of contiguous bytes. Every
    byte has a unique address.

    Wobei anzumerken ist, dass es höchst ungewöhnlich ist, dass an dieser Stelle ein Fehler passiert, aber es ist durchaus denkbar.



  • Ein 12-Bit-Byte Programm kann nicht auf einem 8-Bit-Byte File zugreifen. Weil ein 8-Bit-Byte File nur auf einer 8-Bit-Byte Plattform existieren, bzw. genutzt werden kann. Und diese kann keine 12-Bit-Byte Programme ausführen. (Denk mal darüber nach, wie grundlegend das eigentlich ist, worüber wir gerade schreiben)

    Edit: Ach, der Standard kennt ja keine Dateisysteme. Dann muss ich es direkter Formulieren. (Für alle, die den Text gelesen haben bevor er editiert wurde)


  • Mod

    Sone, es ist einfach falsch.

    (Aber realistisch ist die Annahme von 8-Bit chars natürlich schon. Man muss ganz schön suchen, um ein Gegenbeispiel zu finden)



  • SeppJ schrieb:

    Sone, es ist einfach falsch.

    Aber war dann mein Argument jetzt nicht richtig oder wie darf ich mir das merken..?


  • Mod

    Sone schrieb:

    SeppJ schrieb:

    Sone, es ist einfach falsch.

    Aber war dann mein Argument jetzt nicht richtig oder wie darf ich mir das merken..?

    Welches Argument genau meinst du? Ich möchte jetzt nicht den ganzen Thread durchlesen. Die Größe von char ist nicht festgelegt, das Padding ist nicht festgelegt, die Byteorder ist nicht festgelegt, usw. Eigentlich alles was ich Kellerautomat schon erklärt habe, warum ein direkt geschriebenes Binärformat so unportabel ist.



  • Sone schrieb:

    SeppJ schrieb:

    Sone, es ist einfach falsch.

    Aber war dann mein Argument jetzt nicht richtig oder wie darf ich mir das merken..?

    Wenn du deine letzte Auslassung meinst:

    Sone schrieb:

    Ein 12-Bit-Byte Programm kann nicht auf einem 8-Bit-Byte File zugreifen. Weil ein 8-Bit-Byte File nur auf einer 8-Bit-Byte Plattform existieren, bzw. genutzt werden kann.

    Quatsch.

    Sone schrieb:

    Und diese kann keine 12-Bit-Byte Programme ausführen.

    Irrelevant.

    Sone schrieb:

    (Denk mal darüber nach, [...]

    daß ein 12-bittiger char auf Platform A super in einen 16/32-bittigen int auf Platform B passt.

    Sone schrieb:

    Ach, der Standard kennt ja keine Dateisysteme.

    Jo. Wurscht.

    Sone schrieb:

    Dann muss ich es direkter Formulieren. (Für alle, die den Text gelesen haben bevor er editiert wurde)

    Vorher noch mehr Mist?


Anmelden zum Antworten