Objekte auf dem Heap sichern



  • Toa schrieb:

    Kann es vielleicht daran liegen das ich der FUnktion die sachen so übergeben hab :

    void cWorld::status_save(sPlayer *wPlayer) <-- also das der SternOperator falsch ist ?

    ja. du uebergibst einen zeiger.
    mach es per referenz oder du musst den zeiger dereferenzieren.

    Meep Meep



  • eine dereferenzierung würde dann so ausehen sPlayer&*wPlayer; oder ? .. ach man so kurz vor dem Ziel xD



  • ne so wPlayer->money. Besser wäre es aber wenn du keinen zeiger sondern eine referenz übergen würdest. also status_save(sPlayer& wPlayer). Beim Aufrufen der funktion dann ohne & übergeben.



  • Hab jetzt zwar keine Compile errors mehr aber es geht immer noch net *heul* ich verzeifel noch xD

    Meine Klasse :

    class sPlayer
    {
          public:
           std::string name;
           std::string HeroTyp;
           int health;
           int mana;
           int maxdmg;
           int mindmg;
           int defence;
           int level;
           int xp;
           float geld;
    };
    

    Die Klasse in der die Funktionen Deffiniert sind :

    class cWorld
    {
          public:
    
                   // Kirche - save /Delete Account / SpielZeit anzeige
                 void Kirche(sPlayer *wPlayer);
                 void LoadPlayer();
    
                 void status_save(sPlayer& wPlayer);
    
    };
    

    die FUnktion in der ich die Kirche aufrufe in der man Saven kann :

    void cWorld::Greenvillage(sPlayer *wPlayer)
    {
    
         string eingabe;
         // Auswahl
         system("cls");
         getline(20); colorcout('1',"Wohin moechten Sie?"); getline(20);
         cout
              << "-Kirche\n";
         newline(1); // hehe :P
    
         cin >> eingabe;
    
    ..... Bla Bla ..: 
    
         else if(eingabe == "-Kirche" ||eingabe == "-Kirche" ||eingabe == "kirche" ||eingabe == "Kirche")
             Kirche(wPlayer); //Kirche - speichern - löschen - spielzeit
         {
    
    }
    

    DIe Kirche an SIch in der man speichern kann:

    void cWorld::Kirche(sPlayer *wPlayer)     //Kirche - speichern - löschen - spielzeit
    {
        char menue;
    
    	cout << "(s)pielstand speichern\n";
    	cout << "(a)ccounts löschen";
    	cout << "(g)esamte Spielzeit anzeigen";
    	cout << "____________________\n";
    	cout << "Bitte w\204hlen:\n";
    	cin >> menue;
    	cout << "\a";
    	switch (menue)
    	{
    		case ('s'):
    			{
    				cWorld save;
                    save.status_save(*wPlayer);  // das ist nur WIchtig !!!!
    			}break;
    		case ('a'):
    			{
    				cout << "loeschen";
    			}break;
    		case ('g'):
    			{
    				cout << "spielzeit";  //Muss noch gemacht werden !
    
    			}break;
    
    	}
    	}
    

    Das Saven:

    void cWorld::status_save(sPlayer& wPlayer)
    {
    
       cout << "Waehle einen Accountnamen:" << flush;  // unter welchem namen soll es gespeichert werden
       string file_name;
       cin >> file_name;
       CreateDirectory("Saves", NULL);   //legt ordner save an
       file_name.insert(0, "Saves\\");
       if (file_name.substr(file_name.length() - 4) != ".sav")  //Hängt an den namen ein Sav
       file_name += ".sav";
    
       ofstream nfout(file_name.c_str(), ios::binary );   //Den inhalt des files kann ein Mensch nicht lesen, i.e. binary, not text format.
       nfout.write(wPlayer.name.c_str(), wPlayer.name.size() + 1);
       nfout.write(wPlayer.HeroTyp.c_str(), wPlayer.HeroTyp.size() + 1);   //liest strings ein
       nfout.write(reinterpret_cast<const char*>(&(wPlayer.health)), sizeof(wPlayer.health));   //liest alles einzeln ein
       nfout.write(reinterpret_cast<const char*>(&(wPlayer.mana)), sizeof(wPlayer.mana));
       nfout.write(reinterpret_cast<const char*>(&(wPlayer.maxdmg)), sizeof(wPlayer.maxdmg));
       nfout.write(reinterpret_cast<const char*>(&(wPlayer.mindmg)), sizeof(wPlayer.mindmg));
       nfout.write(reinterpret_cast<const char*>(&(wPlayer.defence)), sizeof(wPlayer.defence));
       nfout.write(reinterpret_cast<const char*>(&(wPlayer.level)), sizeof(wPlayer.level));
       nfout.write(reinterpret_cast<const char*>(&(wPlayer.xp)), sizeof(wPlayer.xp));
       nfout.write(reinterpret_cast<const char*>(&(wPlayer.geld)), sizeof(wPlayer.geld));
       nfout.close();  //schließt den Stream
       system("cls");
       cout << "Dein Account wurde  unter '" << file_name << "' gespeichert ...\n\n" ;
       system("pause");
    
    }
    

    Und Später dann das laden und ausgeben :

    void cWorld::LoadPlayer()
    {
        sPlayer  wPlayer;
    
       string dateiname;
    
        DIR *dirHandle;   // --- > liestet das verzeichniss Save auf
        struct dirent * dirEntry;
    
        dirHandle = opendir("Saves\\");
        if (dirHandle) {
        while (0 != (dirEntry = readdir(dirHandle))) {
        puts(dirEntry->d_name);
        }
        closedir(dirHandle);
        }
        cout << "Gib den Namen deines Saves ein, den du laden willst:";
        cin >> dateiname;
        dateiname += ".sav";    // wenn man namen ohne sav eingibt hängt das save dran
        system("Cls");
        cout << "Load '" << dateiname << "' ...\n";
        dateiname.insert(0, "Saves\\");
    
        ifstream nfin (dateiname.c_str(), ios::binary);
    
        nfin.read(reinterpret_cast< char*>(&(wPlayer.name)), sizeof(wPlayer.name));
        nfin.read(reinterpret_cast< char*>(&(wPlayer.HeroTyp)), sizeof(wPlayer.HeroTyp));
        nfin.read(reinterpret_cast< char*>(&(wPlayer.health)), sizeof(wPlayer.health));   //liest alles einzeln ein
        nfin.read(reinterpret_cast< char*>(&(wPlayer.mana)), sizeof(wPlayer.mana));
        nfin.read(reinterpret_cast< char*>(&(wPlayer.maxdmg)), sizeof(wPlayer.maxdmg));
        nfin.read(reinterpret_cast< char*>(&(wPlayer.mindmg)), sizeof(wPlayer.mindmg));
        nfin.read(reinterpret_cast< char*>(&(wPlayer.defence)), sizeof(wPlayer.defence));
        nfin.read(reinterpret_cast< char*>(&(wPlayer.level)), sizeof(wPlayer.level));
        nfin.read(reinterpret_cast< char*>(&(wPlayer.xp)), sizeof(wPlayer.xp));
        nfin.read(reinterpret_cast< char*>(&(wPlayer.geld)), sizeof(wPlayer.geld));
        nfin.close();  //schließt den STream
    
        cout << "Account as read from binary file " <<dateiname <<endl;
        system("pause");
        cout << wPlayer.name << endl;
        system("pause");
        cout << wPlayer.HeroTyp << endl;
        system("pause");
        cout << wPlayer.health << endl;
        system("pause");
        cout << wPlayer.mana << endl;
        system("pause");
        cout << wPlayer.maxdmg << endl;
        system("pause");
        cout << wPlayer.mindmg << endl;
        system("pause");
        cout << wPlayer.defence << endl;
        system("pause");
        cout << wPlayer.xp << endl;
        system("pause");
        cout << wPlayer.geld << endl;
        system("pause");
    
    }
    

    ...SO jetzt hab ich echt alles gepostet , ich bin am rande der verzeiflung ..Seit Stunden und Tagen verusche ich es einzubaun und es geht einfach nicht

    MFG TOa



  • Hallo zusammen,

    bietet boost nicht Mittel zur Serialisierung?

    Grüße Martin



  • http://www.boost.org/libs/serialization/doc/index.html

    sollte man da einfach mal einsetzen



  • nfin.read(reinterpret_cast< char*>(&(wPlayer.name)), sizeof(wPlayer.name));
    

    So geht das nicht. Man kann nicht einfach einen std::string* nach char* casten.

    Mach's z.B. so:

    std::vector<char> buf(1024);
    nfin.read(&(buf[0]), buf.size());
    wPlayer.name.assign(buf.begin(), buf.end());
    

    Damit würden allerdings nur Strings bis 1024 Zeichen eingelesen werden können, außerdem hab ich's jetzt nicht getestet.



  • Am besten schreibst du vor jeden String noch einmal die Länge des strings. Denn mein Beispiel würde jetzt nur mit Strings gehen, die immer 1024 Zeichen lang sind.



  • bitte keine tipps mehr über unsichere cast-orgien - gerade anfänger haben damit arge probleme

    das boost zeug sollte wesentlich praktischer und einfacher zu verwenden sein



  • das problem beim einlesen seiner strings ist, das er nicht weiß wie lange sie sind. also koennte man beim speichern der strings noch die laenge mitgeben. dann hat man schon ein problem weniger.

    inline void WriteStringToStream(std::ostream &out, const std::string &str)
    {
       std::size_t len = str.size();
       out.write(reinterpret_cast<const char*>(&len), sizeof(len));
       out.write(str.c_str(), len); // '\0' brauchen wir nicht mehr, weil wir die laenge speichern
    }
    

    zum auslesen kann man dann folgendes machen:

    void ReadStringFromStream(std::istream &in, std::string &str)
    {
       std::size_t len;
       in.read(reinterpret_cast<char*>(&len), sizeof(len));
       char *buffer = new char[len];
       in.read(buffer, len);
       str.assign(buffer, len);
       delete[] buffer;
    }
    


  • schaut euch ma die ausgabe an :

    http://www.imagehack.eu/uploads/b7f20d91fe.jpg

    die ersten beiden Sachen stimmen noch ich hieß Ujih und mein Typ war Warrior aber die Zahlen dann nicht mehr .. also die sTrings werden richtig gespeichert und ausgegeben nur die zahlen haben Probleme 😕 ... wisst ihr warum ? die Lösung ist so nahe ^^

    PS :

    sieht jetzt so aus :

    ifstream nfin (dateiname.c_str(), ios::binary);
        vector<char> buf(1024);
        nfin.read(&(buf[0]), buf.size());
        wPlayer.name.assign(buf.begin(), buf.end());
        nfin.read(reinterpret_cast< char*>(&(wPlayer.HeroTyp)), sizeof(wPlayer.HeroTyp));
        nfin.read(reinterpret_cast< char*>(&(wPlayer.health)), sizeof(wPlayer.health));   //liest alles einzeln ein
        nfin.read(reinterpret_cast< char*>(&(wPlayer.mana)), sizeof(wPlayer.mana));
        nfin.read(reinterpret_cast< char*>(&(wPlayer.maxdmg)), sizeof(wPlayer.maxdmg));
        nfin.read(reinterpret_cast< char*>(&(wPlayer.mindmg)), sizeof(wPlayer.mindmg));
        nfin.read(reinterpret_cast< char*>(&(wPlayer.defence)), sizeof(wPlayer.defence));
        nfin.read(reinterpret_cast< char*>(&(wPlayer.level)), sizeof(wPlayer.level));
        nfin.read(reinterpret_cast< char*>(&(wPlayer.xp)), sizeof(wPlayer.xp));
        nfin.read(reinterpret_cast< char*>(&(wPlayer.geld)), sizeof(wPlayer.geld));
        nfin.close();  //schließt den STream
    
        cout << "Account as read from binary file " <<dateiname <<endl;
        system("pause");
        cout << wPlayer.name << endl;
        system("pause");
        cout << wPlayer.HeroTyp << endl;
        system("pause");
        cout << wPlayer.health << endl;
        system("pause");
        cout << wPlayer.mana << endl;
        system("pause");
        cout << wPlayer.maxdmg << endl;
        system("pause");
        cout << wPlayer.mindmg << endl;
        system("pause");
        cout << wPlayer.defence << endl;
        system("pause");
        cout << wPlayer.xp << endl;
        system("pause");
        cout << wPlayer.geld << endl;
        system("pause");
    

    und noch eine Frage warum muss ich den HeroTyp denn nicht auch so wie name umschreiben und er wird trotzdem richtig ausgegeben also bzw eingelesen ...



  • Du musst noch die Größe des Strings mitspeichern. Hier mal ein Minimalbeispiel:

    #include <iostream>
    #include <fstream>
    #include <vector>
    
    void SaveString(std::ofstream& fout, const std::string& str)
    {
    	int size = str.size();
    	fout.write(reinterpret_cast<const char*>(&size), sizeof(size));S
    	fout.write(str.c_str(), size);
    }
    
    std::string LoadString(std::ifstream& fin)
    {
    	int size;
    	fin.read(reinterpret_cast<char*>(&size), sizeof(size));
    	std::vector<char> buf(size);
    	fin.read(&buf[0], size);
    	std::string temp(buf.begin(), buf.end()); // oder mit .assign(...)
    	return temp;
    }
    
    int main()
    {
    	std::ofstream fout("test.txt");
    	SaveString(fout, "Hallo Welt!");
    	SaveString(fout, "Test!");
    	fout.close();
    	std::ifstream fin("test.txt");
    	std::cout << LoadString(fin) << std::endl;
    	std::cout << LoadString(fin) << std::endl;
    }
    


  • Öhm warum denn ? die Beiden Strings werden doch richtig einglesen nur die FLoat und integer Variablen der Klasse nicht ! 😕 ..

    meinst du dann so ?

    int size = wPlayer.size();
    nfout.write(reinterpret_cast<const char*>(&size), sizeof(size));S

    ne oder das kann net sein man muss ja irgendwo die namen der strings reinbringen aber das mit den Strings klappt ja nur wie gesagt die Interger und FLoat Variablen der Klasse sPlayer machen Probleme , sieht man ja auch auf dem Bild ..der Name und der Typ wird richtig ausgegeebn aber die Zahlen nicht die dahinter FOlgen und dann noch eine andere Frage : Ich hab doch Binary als Typ angegeben aber man kann den Namen und den Typ einfach so in der txt lesen .

    http://www.imagehack.eu/uploads/9f63fa90e2.jpg



  • Toa schrieb:

    die Beiden Strings werden doch richtig einglesen nur die FLoat und integer Variablen der Klasse nicht !

    Eigentlich wird nichts richtig gelesen. Der erste String ist 1024 Zeichen lang, mein erstes Beispiel war ziemlich schlecht. Deswegen siehst du auch noch den zweiten. Du musst die Länge irgendwie speichern, schau dir den Code von Meep Meep und mir mal an.



  • Aber es ist doch logisch das man den Zweiten auch sieht weil der ja auch ausgeeben wird .. aber ich glaube ich verstehe was du meinst wenn man nur den ersten ausgegeben h#tte , würde der zweite auch ausgegeben werden weil er mitgesavt wurde ! .. okay haste ne IDee wegen den Integer Vars und den FLoat warum die net richtig gespeichert und ausgegeebn werden ?? .. und wegen dem Lesen der txt

    Kannst du mir für die beiden Strings das mit dem Länge saven mal machen ? damit ichs seh wies geht ? ...

    bei saves sind es die beiden:

    nfout.write(wPlayer.name.c_str(), wPlayer.name.size() + 1);
       nfout.write(wPlayer.HeroTyp.c_str(), wPlayer.HeroTyp.size() + 1);
    

    und bei load hab ich das

    ector<char> buf(1024);
        nfin.read(&(buf[0]), buf.size());
        wPlayer.name.assign(buf.begin(), buf.end());
        nfin.read(reinterpret_cast< char*>(&(wPlayer.HeroTyp)), sizeof(wPlayer.HeroTyp));
    


  • gibt es eigentlich einen gund dafür das das boost zeug immer noch aktiv ignoriert wird ? (weil die cast orgien sind _____schlimm______)



  • Öhm *nachschau* ..jetzt hab ich das eine schon fast soweit nur noch das mit der char länge und den Integer und FLoat Variablen das die gehen und dann hätt ichs xD
    *nach oben deut*



  • Toa schrieb:

    Aber es ist doch logisch das man den Zweiten auch sieht weil der ja auch ausgeeben wird .. aber ich glaube ich verstehe was du meinst wenn man nur den ersten ausgegeben h#tte , würde der zweite auch ausgegeben werden weil er mitgesavt wurde ! .. okay haste ne IDee wegen den Integer Vars und den FLoat warum die net richtig gespeichert und ausgegeebn werden ?? .. und wegen dem Lesen der txt

    Kannst du mir für die beiden Strings das mit dem Länge saven mal machen ? damit ichs seh wies geht ? ...

    bei saves sind es die beiden:

    nfout.write(wPlayer.name.c_str(), wPlayer.name.size() + 1);
       nfout.write(wPlayer.HeroTyp.c_str(), wPlayer.HeroTyp.size() + 1);
    

    und bei load hab ich das

    ector<char> buf(1024);
        nfin.read(&(buf[0]), buf.size());
        wPlayer.name.assign(buf.begin(), buf.end());
        nfin.read(reinterpret_cast< char*>(&(wPlayer.HeroTyp)), sizeof(wPlayer.HeroTyp));
    

    ne, das ist ja immer noch nicht so wie wir meinten. Probier mal folgendes: Kopier dir einfach meine SaveString und LoadString funktion in dein Projekt und dann machste:

    SaveString(mfout, wPlayer.name);
    SaveString(mfout, wPlayer.HeroTyp);
    

    und beim Laden:

    wPlayer.name = LoadString(mfin);
    wPlayer.HeroTyp = LoadString(mfin);
    

    Achja: HeroTyp ist ein wenig komisch denn eigentlich heißt es ja type oder Held.
    Und nochwas: mit [ cpp ] wird's schön bunt 😛



  • Ohh haa jetzt mekkert er aber :

    wPlayer.name = LoadString(nfin);
    

    ---> invalid conversion from void to HISTANCE_*

    wPlayer.name = LoadString(nfin);
    

    --->too few arguments to function int lOadStringA(HISTANCE_,UNIT CHAR int

    void SaveString(std::ofstream& fout, const std::string& str)
    

    --->void saveString (SDT::ofstream& COnst Std::string&) used Prior to declaration

    und warum werden die integer und Float variablen immmer noch falsch gespeichert weil er gibt ja so komische zeichen aus 😕 und warum kann man den Namen und Typ in der txt file trotz binary lesen ?



  • Toa schrieb:

    Ohh haa jetzt mekkert er aber :

    wPlayer.name = LoadString(nfin);
    

    ---> invalid conversion from void to HISTANCE_*

    wPlayer.name = LoadString(nfin);
    

    --->too few arguments to function int lOadStringA(HISTANCE_,UNIT CHAR int

    void SaveString(std::ofstream& fout, const std::string& str)
    

    --->void saveString (SDT::ofstream& COnst Std::string&) used Prior to declaration

    WTF? Ich tippe mal auf WinAPI mit ihren dummen Makros, nenn die Funktion um in z.B. MyLoadString und MySaveString.

    und warum werden die integer und Float variablen immmer noch falsch gespeichert weil er gibt ja so komische zeichen aus 😕

    Müsste mit dem String-Speichern zusammenhängen

    und warum kann man den Namen und Typ in der txt file trotz binary lesen ?

    txt-Files sind sowas wie binär files von strings. Sie sind also fast das gleiche wie wenn du Binärdateien nur mit strings beschreibst.


Anmelden zum Antworten