Variablenwerte in Datei speichern



  • Little Programmer schrieb:

    Oder übersehe ich da gerade den Trick dahinter, wie man damit doch alles mögliche speichern kann?

    Casten, memcpy usw.



  • Hab das jetzt mal getestet, aber gibt es eine Möglichkeit, ein komplettes Objekt auf einmal zu casten? Jede Membervariable eines Objekts erst zu zerpflücken und beim auslesen wieder zusammenzufügen ist ziemlich umständlich. Doch weder mit const_cast <char*> (&Objekt), noch mit char(Objekt) konnte mein Kompiler etwas anfangen. Gibt es da eine direkte Möglichkeit?



  • http://www.cppreference.com/wiki/keywords/reinterpret_cast
    Objekte so in ne Datei schreiben geht aber nur, wenn diese selber keine Objekte enthalten



  • Danke. Und nochmal ne Frage, ich versuch mich gerade an normalen int, double usw. Variablen. Aber bei double bin ich auf ein Problem gestoßen. Eine double-Variable ist größer als eine char, das heißt, wenn ich mit:

    konfiguration.put(char(7563.5725));
    //oder auch nur den int-Wert:
    konfiguration.put(char(7563));
    

    speichere, dann erhalte ich im ersten Fall egal ob ich es als int oder als double auslese 127 und im zweiten -117 als Wert. Wie kann ich also eine double oder eine große int über soviele char-Stellen wie nötig speichern und auslesen?



  • invalid reinterpret_cast from type `Test' to type `std::string'|

    Erhalte ich, egal in was ich mit reinterpret_cast konvertieren will.

    string Text = reinterpret_cast<string> (Objekt);
    konfiguration.write(Text.c_str(), Text.length);
    


  • Du mußt den reinterpret_cast auf 'char *' direkt beim ersten Parameter durchführen, z.B.

    double d = 42.14;
    
    konfiguration.write(reinterpret_cast<char *>(&d), sizeof(d)); // wichtig: der Adreßoperator & !!!
    

    Analog dann für andere einfache Datentypen (statt double).



  • std::string kannst du so nicht speicher



  • Das binäre Speichern von Daten kann je nach Plattform, etc. zu Problemen führen. Warum nimmst du nicht eine ganz "normale" Konfigurationsdatei und speicherst deine Strings als Text? Damit sparst du dir eine menge Ärger 🙂



  • Ich will ja eine Möglichkeit haben, z.B. bei einem komplexen programm, in dem viele Objekte existieren ein Speicherabbild aller objekte zu erstellen. Wenn ich nun mit Memberfunktionen jedes Objekt in seine Einzelteile zerlege und wieder zusammensetze, kann sich da leicht ein Fehler unterschmuggeln. Mir wäre es lieb gewesen, wenn ich direkt den Speicherbereich eines Objekts in einer Datei kopieren kann. Na gut, dann muss es halt mit zerpflücken gehen. Ich versuch das jetzt nochmal mit dem reinterpret_cast.



  • Hm, ich denke mal in eine Richtung funktionierts jetzt, allerdings kann ich das nicht sicher sagen, da ich die Datei nicht mehr auslesen kann:

    #include <iostream>
    #include <fstream>
    
    using namespace std;
    
    void Speichern()
    {
        std::ofstream konfiguration;
        konfiguration.open("blubb.dat", ios::out);
        konfiguration.put(char(9));
        double d = 7563.5725;
        konfiguration.write(reinterpret_cast<char *>(&d), sizeof(d));
        //konfiguration.put(char(7563.5725));
        if(!konfiguration)
            cout << "Konnte nicht speichern.\n";
    }
    
    void Laden()
    {
        int Toastbrot = 0;
        double Brot = 0;
        char Temp = 0;
        char TempArray[100] = {0};
        std::fstream konfiguration("blubb.dat");
    
        if(!konfiguration)
        {
            cout << "Konnte nicht laden.\n";
        } else {
    
        konfiguration.get(Temp);
        Toastbrot = int (Temp);
        cout << "\n" << Toastbrot << endl;
    
        double d = 7563.5725; //Nur damit Länge bestimmen kann
        //konfiguration.seekg (1, ios::beg);
        konfiguration.read(TempArray, sizeof(d));
        Brot = reinterpret_cast<double>(TempArray)
        //Brot = atof(TempArray);
        cout << "\n" << Brot << endl;
        }
    
    }
    
    int main()
    {
        Speichern();
        Laden();
        system("PAUSE");
        return 0;
    }
    

    Die Rückumwandlung in eine double ist so nicht zulässig, aber mit atof erhalte ich "0" als Wert. Irgendwie hab ich das Ganze noch nicht ganz durchschaut. Kann mir jemand weiterhelfen?



  • Little Programmer schrieb:

    Ich will ja eine Möglichkeit haben, z.B. bei einem komplexen programm, in dem viele Objekte existieren ein Speicherabbild aller objekte zu erstellen.

    Dazu müsstest du ne andere Sprache nehmen, z.B. Python oder Java.

    Little Programmer schrieb:

    Die Rückumwandlung in eine double ist so nicht zulässig, aber mit atof erhalte ich "0" als Wert. Irgendwie hab ich das Ganze noch nicht ganz durchschaut. Kann mir jemand weiterhelfen?

    Ja, schau dir mal an wie Daten binär gespeichert werden, dann verstehst du vielleicht auch, was du da speicherst.

    http://de.wikipedia.org/wiki/Dualsystem
    http://de.wikipedia.org/wiki/Integer_(Datentyp)
    http://de.wikipedia.org/wiki/IEEE_754

    double a=342.5231;
    	char* bla=reinterpret_cast<char*>(&a);
    
    	double b=*(reinterpret_cast<double*>(bla));
    




  • Hallo LittleProgrammer,

    vergiß das char-Array!

    Auch beim Lesen einfach:

    double d; 
    
    konfiguration.read(reinterpret_cast<char *>(&d), sizeof(d)); // wichtig: der Adreßoperator & !!!
    
    cout << d << endl;
    

    Genau wie beim Schreiben -)



  • @ NightCoder, wieso weiße ich der double einen Zeiger auf eine double zu?

    double b=*(reinterpret_cast<double*>(bla));
    

    und @ Th69, wenn ich das richtig sehe, dann lese ich die Datei doch in die double aus und caste die dann in in einen charakter. ist das nicht falsch herum?

    konfiguration.read(reinterpret_cast<char *>(&d), sizeof(d));
    

    Die beiden Sachen sind mir absolut unklar. Ich würde mir das so denken, ka, wieso es nicht so ist:

    double* b=*(reinterpret_cast<double*>(bla));
    //bzw.
    double b=*(reinterpret_cast<double>(bla));
    
    //und Th69s Code käm ich so gar nicht auf die Idee zu schreiben.
    

    Wo liegt denn immernoch mein Denkfehler?



  • Nein, probiere es einfach mal aus.
    Dann erkennst du evtl. auch, was du bzgl. des Castens anscheinend noch nicht ganz verstanden hast...

    Der Parameter "(const) char *" bedeutet nur, daß die Funktion einen Zeiger auf eine beliebige Bytefolge erwartet (nicht, daß es sich um ein char-Array handeln muß!).


Anmelden zum Antworten