Überschreibe beim Laden wohlmöglich den Stack. Nur wo?



  • Hallo!
    Bin noch ziemlicher Anfänger, progge grade an einem kleinen Konsolenspiel und habe nun ein Problem: Immer, wenn ich den alten Spielstand lade, passiert es irgendwann, dass an einer falschen Stelle gelesen bzw veruscht zu schreiben wird.

    Zudem kommt mir mein Speicher und Lade code auch noch sehr schlecht vor, habe jedoch weder im Netz noch in meinen Büchern eine bessere Lösung gefunden. Da vor der Implementierung der Möchtegern-AI dieser Fehler noch nicht auftrat, könnte ich vermuten, dass der Fehler in Zeile 62-72 bzw 258-267 liegt. Bin mir aber nicht sicher.

    Zu den ganzen Stringstreams: Das muss ja sicherlich nicht sein, oder? Wie kann ich meine Int's und Float's sinnvoll speichern und laden? Mit nur einem Stringstream habe ich immer die wirresten Ergebnise rausbekommen!

    Liebe Grüße,

    fstream f;
        f.open("thevillage/values.dat", ios::out);
    	if(f)
    	{
    		f << wood << endl;
    		f << iron << endl;
    		f << stone << endl;
    		f << food << endl;
    		f << gold << endl;
    		f <<experience << endl;
    		f <<prestige << endl;
    		f <<xWood << endl;
    		f <<xStone << endl;
    		f <<xIron << endl;
    		f <<xGold << endl;
    		f <<xFood << endl;
    		f <<inhabitants << endl;
    		f <<::bWoodmine << endl;
    		f <<::bIronmine << endl;
    		f <<::bStonemine << endl;
    		f <<::bFarm << endl;
    		f <<::bMarketplace << endl;
    		f <<::bKaserne << endl;
    		f <<::bDiplomatie << endl;
    		f <<::fighter << endl;
    		f <<::horsefighter << endl;
    		f <<::swordfighter << endl;
    		f <<::bowfighter << endl;
    		f <<::tTaxes << endl;
    		f <<::insg << endl;
    		f <<::humor << endl;
    		f.close();
    
    		fstream boolsout;
    		boolsout.open("thevillage/bools.dat", ios::out);
    		for (int i = 0; i<20; i++)
    		{
    			if(::const_dialogBools[i] != true)
    			{
    				boolsout << '0';
    			}
    			else
    			{
    				boolsout << '1';
    			}
    		}
    		boolsout << endl;
    
    		boolsout.close();
    
    		fstream buildings;
    		buildings.open("buildings.dat",ios::out);
    		buildings.write((char *)&marketplace, sizeof(class buildings));
    		buildings.write((char *)&ironmine, sizeof(class buildings));
    		buildings.write((char *)&woodmine, sizeof(class buildings));
    		buildings.write((char *)&stonemine, sizeof(class buildings));
    		buildings.write((char *)&farm, sizeof(class buildings));
    		buildings.write((char *)&kaserne, sizeof(class buildings));
    		buildings.close();
    
    		fstream enemys;
    		enemys.open("enemys.dat",ios::out);
    		enemys.write((char *)&::nympth, sizeof(class player));
    		enemys.write((char *)&::isabell, sizeof(class player));
    		enemys.write((char *)&::malark, sizeof(class player));
    		enemys.write((char *)&::tresla, sizeof(class player));
    		enemys.write((char *)&::skott, sizeof(class player));
    		enemys.write((char *)&::gregor, sizeof(class player));
    		enemys.write((char *)&::tammo, sizeof(class player));
    		enemys.write((char *)&::ariana, sizeof(class player));
    		enemys.write((char *)&::finmor, sizeof(class player));
    		enemys.close();
    
    	return true;
    	}
    	else
    		return false;
    
    	::const_dialogBools[5] = true;
    }
    
    bool load()
    {
    	fstream f2;
    	string s;
        f2.open("thevillage/values.dat", ios::in);
    	if(f2)
    	{
    		stringstream ss1;
    		getline(f2,s);
    		ss1 << s;
    		ss1 >> wood;
    		cin.get();
    
    		stringstream ss2;
    		getline(f2,s);
    		ss2 << s;
    		ss2 >> iron;
    
    		stringstream ss3;
    		getline(f2,s);
    		ss3 << s;
    		ss3 >> stone;
    
    		stringstream ss4;
    		getline(f2,s);
    		ss4 << s;
    		ss4 >> food;
    
    		stringstream ss5;
    		getline(f2,s);
    		ss5 << s;
    		ss5 >> gold;
    
    		stringstream ss6;
    		getline(f2,s);
    		ss6 << s;
    		ss6 >> experience;
    
    		stringstream ss7;
    		getline(f2,s);
    		ss7 << s;
    		ss7 >> prestige;
    
    		stringstream ss8;
    		getline(f2,s);
    		ss8 << s;
    		ss8 >> xWood;
    
    		stringstream ss9;
    		getline(f2,s);
    		ss9 << s;
    		ss9 >> xStone;
    
    		stringstream ss10;
    		getline(f2,s);
    		ss10 << s;
    		ss10 >> xIron;
    		cin.get();
    
    		stringstream ss11;
    		getline(f2,s);
    		ss11 << s;
    		ss11 >> xGold;
    
    		stringstream ss12;
    		getline(f2,s);
    		ss12 << s;
    		ss12 >> xFood;
    
    		stringstream ss13;
    		getline(f2,s);
    		ss13 << s;
    		ss13 >> inhabitants;
    
    		stringstream ss14;
    		getline(f2,s);
    		ss14 << s;
    		ss14 >> bWoodmine;
    
    		stringstream ss15;
    		getline(f2,s);
    		ss15 << s;
    		ss15 >> bIronmine;
    
    		stringstream ss16;
    		getline(f2,s);
    		ss16 << s;
    		ss16 >> bStonemine;
    
    		stringstream ss17;
    		getline(f2,s);
    		ss17 << s;
    		ss17 >> bFarm;
    
    		stringstream ss18;
    		getline(f2,s);
    		ss18 << s;
    		ss18 >> bMarketplace;
    
    		stringstream ss19;
    		getline(f2,s);
    		ss19 << s;
    		ss19 >> bKaserne;
    
    		stringstream ss19_1;
    		getline(f2,s);
    		ss19_1 << s;
    		ss19_1>> bDiplomatie;
    
    		stringstream ss20;
    		getline(f2,s);
    		ss20 << s;
    		ss20 >> fighter;
    
    		stringstream ss21;
    		getline(f2,s);
    		ss21 << s;
    		ss21 >> horsefighter;
    
    		stringstream ss22;
    		getline(f2,s);
    		ss22 << s;
    		ss22 >> swordfighter;
    
    		stringstream ss23;
    		getline(f2,s);
    		ss23 << s;
    		ss23 >> bowfighter;
    
    		stringstream ss24;
    		getline(f2,s);
    		ss24 << s;
    		ss24 >> ::tTaxes;
    
    		stringstream ss25;
    		getline(f2,s);
    		ss25 << s;
    		ss25 >> ::insg;
    
    		stringstream ss26;
    		getline(f2,s);
    		ss26 << s;
    		ss26 >> ::humor;
    		f2.close();
    
    		fstream bools;
    		bools.open("thevillage/bools.dat", ios::in);
    		string z;
    		getline(bools,z);
    		for (int i = 0; i<20; i++)
    		{
    
    			if(z.at(i) == '0')
    			{
    				::const_dialogBools[i] = false;
    			}
    			if(z.at(i) == '1')
    			{
    				::const_dialogBools[i] = true;
    			}
    		}
    
    		fstream input;
    		input.open("buildings.dat",ios::in);
    		input.read((char *)&marketplace, sizeof(class buildings));
    		input.read((char *)&ironmine, sizeof(class buildings));
    		input.read((char *)&woodmine, sizeof(class buildings));
    		input.read((char *)&stonemine, sizeof(class buildings));
    		input.read((char *)&farm, sizeof(class buildings));
    		input.read((char *)&kaserne, sizeof(class buildings));
    		input.close();
    
    		fstream enemysout;
    		enemysout.open("enemys.dat",ios::in);
    		enemysout.read((char *)&::nympth, sizeof(class player));
    		enemysout.read((char *)&::isabell, sizeof(class player));
    		enemysout.read((char *)&::malark, sizeof(class player));
    		enemysout.read((char *)&::tresla, sizeof(class player));
    		enemysout.read((char *)&::skott, sizeof(class player));
    		enemysout.read((char *)&::gregor, sizeof(class player));
    		enemysout.read((char *)&::tammo, sizeof(class player));
    		enemysout.read((char *)&::ariana, sizeof(class player));
    		enemysout.read((char *)&::finmor, sizeof(class player));
    		enemysout.close();
    
    		return true;
    
    	}
    
    	else
    		return false;
    }
    

  • Mod

    Wenn du etwas aus einem Stream liest, in einen Stringstream schreibst, dann wieder aus dem Stringstream liest, dann hättest du auch gleich aus dem Stream lesen können. (Nichts für ungut, aber das hier ist ein typischer Fall von "Zahl zu String mal gesehen, aber nicht verstanden")

    Wenn du 40 verschiedene Variablen hast, dann bietet es sich mal an, diese irgendwie sinnvoll in Kategorien (Klassen) zusammenzufassen. Wenn du Klassen hast, dann bietet es sich an, diesen einen Operator<< und >> zu verpassen, der genau diese Klasse schreiben/lesen kann. Die höheren Schreib- und Lesefunktionen benutzen dann diese Operatoren. So erhält man viel kleinere und übersichtlichere Einheiten, in denen man Fehler viel genauer einkreisen kann. Und es geschehen gar nicht erst so viele Fehler: Was wäre zum Beispiel bei deinen writes und reads, wenn eine deiner Klassen kein POD mehr wäre? Bumm! Oder ist vielleicht genau das der Fehler hier? Überhaupt ist so eine Art des Rausschreibens sehr riskant und Fehleranfällig. Was zum Beispiel, wenn zufällig der Wert 13 (oder war es 10?) in den Daten steht und man unter Windows arbeitet? Nochmal Bumm! Denn du hast die Dateien nicht passend geöffnet für Binärdaten.

    Dein Stil ist ziemlich ungewönlich. Wo lernt man denn, sizeof(class foo) zu schreiben anstatt sizeof(foo) ? Oder das viele open und close bei den Dateien anstatt die Konstruktoren und Destruktoren das automatisch machen zu lassen? Und warum fstreams mit expliziten openmodes, anstatt ifstream und ofstream? Das sieht alles so aus, als hätte jemand ein C-Tutorial 1:1 nach C++ übersetzt, ohne zu wissen, was C++ sonst noch so bietet.



  • Mal davon abgesehen das ich den Code sehr unübersichtlich finde:

    fstream f;
        f.open("thevillage/values.dat", ios::out);
        if(f) ...
    

    Ich würde

    f.good()
    

    verwenden. Siehe
    http://www.cplusplus.com/reference/iostream/ios/operatornot/
    http://www.cplusplus.com/reference/iostream/ios/good/
    Ausserdem würde ich std::ofstream verwenden.

    Was ich auch nicht verstehe: bei dieser ersten Datei prüfst Du auf Fehler beim öffnen. Danach öffnest Du innerhalb des "if" Body weitere Dateien die Du nicht prüfst? Wenn schon dann für jede Datei das gleiche tun 😉

    Zu Deiner "load()" Funktion: was sind "wood", "iron" etc. für Datentypen?

    fstream input;
            input.open("buildings.dat",ios::in);
            input.read((char *)&marketplace, sizeof(class buildings));
    

    Auch wenn es erlaubt ist, C-style Casts haben IMO in einem C++ Programm nichts zu suchen:

    input.read(reinterpret_cast<char*>(&marketplace), sizeof(class buildings));
    

    Wobei ich das sowieso sehr problematisch finde, wenn dann die Grösse des tatsächlichen Objektes verwenden:

    input.read(reinterpret_cast<char*>(&marketplace), sizeof(marketplace));
    

    Aber auch das dürfte problematisch sein wenn Du in deiner Klasse "buildings" nicht die exakte Grösse aller Member angibst bzw. nicht weisst was tatsächlich mal drinstehen wird.

    Mal ein Beispiel:

    class Foo {
        std::string m_MemberString;
    };
    
    Foo f;
    std::ifstream inFile("test.txt")
    if (inFile.good()) {
    
        inFile.read(reinterpret_cast<char*>(&f), sizeof(f));
        inFile.close();
    }
    

    Das Problem:

    Foo::m_MemberString
    

    ist ein leerer String,

    sizeof(f)
    

    gibt also auch die Grösse von "f" mit leerem String zurück. Wehe wenn in der Datei "m_MemberString" tatsächlich ein Wort wäre (also kein leerer String). Den liest Du dann nämlich nicht mit.

    Korrigiert mich bitte wenn ich mich irre.

    Edit: SeppJ war schneller 🙂


  • Mod

    @schwudde: Da ist aber etwas falsch an deiner Erklärung über sizeof eines Strings. Mag sein, dass du das richtige meinst, aber sizeof(irgendwas) ist eine Compilezeitkonstante. Das Problem an deinem Beispiel ist, dass die Klasse kein POD-Typ ist und daher auch nicht wie einer behandelt werden darf.

    Deine Meinung zu good() vs operator void* und operator! kann ich nicht nachvollziehen.



  • SeppJ schrieb:

    @schwudde: Da ist aber etwas falsch an deiner Erklärung über sizeof eines Strings. Mag sein, dass du das richtige meinst, aber sizeof(irgendwas) ist eine Compilezeitkonstante. Das Problem an deinem Beispiel ist, dass die Klasse kein POD-Typ ist und daher auch nicht wie einer behandelt werden darf.

    Deine Meinung zu good() vs operator void* und operator! kann ich nicht nachvollziehen.

    Ich habe das als Beispiel genommen weil ja nicht ersichtlich wie die Klasse "buildings" aufgebaut ist. Wenn er da z.B. std::string verwendet ist es ja ebenfalls kein POD-Typ.

    "good()" weil damit auch das "eofbit" geprüft wird. Aber Du hast sicherlich recht, das "eofbit" wird man bei einem output stream sicher nicht gesetzt finden. Davon abgesehen hatte ich ja geschrieben das "ich" das so machen würde (wohl weil ich es eben aus gewohnheit so mache).



  • Das mit den 'In Klassen packen' hab ich schon öfters gehört. Nur ich verstehe das irgendwie nicht. Klassen sind doch nur gut, wenn ich verschiedene Instanzen eines Objektes anlegen will, oder? Und das soll in dem Spiel ja nicht der Fall sein.
    Und dass meine Klasse nicht POD ist, weiß ich nicht. Mit Strings war sie nicht POD (was auch immer das heißen mag) und deswegen habe ich anstattdessen ein char array genommen... Die Werte Wood, Iron, Stone etc sind vom Typ float.

    Hier mal die .h der Klasse player:

    #include <iostream>
    
    class player
    {
    
    private:
    
    	int initNumber;
    	int iStatusToPlayer;
    	int iStatusToAi[12];
    	int prosperty;
    	int forceStrength;
    	int development;
    	int timesTradedWithPlayer;
    	int timesPlayerRejectedOffer; 
    
    	float aiWood,
    		aiStone,
    		aiIron,
    		aiGold,
    		aiFood,
    		aiHumor;
    
    	int aiDefend,
    		aiAttack;
    	int
    		aiInhabitants;
    
    		// True = Verbündet / False = /
    
    public:
    	char *name;
    	bool bStatusToPlayer;		//Enemy or Friend? True = Feind False = Neutral
    	bool bStatusToPlayerAlly;	// Verbündeter?	
    	bool bStatusToAi[9];		// True = Neutral / False = Feind
    	bool bStatusToAiAlly[9];
    
    	player(char* _name)  : name(_name)
    	{
    		this->iStatusToPlayer = 0;
    		this->prosperty = 0;
    		this->forceStrength = 0;
    		this->aiWood = 100;
    		this->aiStone = 100;
    		this->aiIron = 100;
    		this->aiFood = 100;
    		this->aiGold = 100;
    		this->aiHumor = 1.0f;
    		this->aiInhabitants = 100;
    		this->development = 5.000f;
    		this->timesTradedWithPlayer = 0;
    		this->timesPlayerRejectedOffer = 0;
    		this->aiAttack = 300;
    		this->aiDefend = 300;
    
    		for(int i = 0; i<9;i++)
    		{
    			this->bStatusToAi[i] = true;
    			this->bStatusToAiAlly[i] = false;
    		}
    		this->bStatusToPlayer = false;
    		this->bStatusToPlayerAlly = false;
    }
    
    	void calculateDevelopment();
    	void calculateRessources();
    	void calculateStatusToAi();
    	void calculateStatusToPlayer();
    	void calculateForceStrengthAndHumor();
    	void calculateAll();
    
    	void checkEvents();	  // Kontrolliert ob irgendwelche Werte besonders niedrig sind. Wenn ja, löst es Folgen aus 
    
    	void tradeWithPlayer(float &lWood, float &lStone, float &lFood, float &lIron, float &lGold, int luck);
    	void setStatusToPlayer(int i);
    
    	int getAttack();
    	int getDefend();
    	int getAiWood();
    	int getAiIron();
    	int getAiStone();
    	int getAiGold();
    	int getAiFood();
    
    };
    

    Zu den Stringstreams: Ich konvertiere beim schreiben doch die Zahlen in einen String, bzw sie können nur noch als string eingelesen werden. Und dann muss ich diese Zeilen doch über einen stringstream laufen lassen, oder? Anscheinend mache ich einen Gedankenfehler. Aber wo?



  • Die binäre Serialisierung deiner Player-Klasse scheitert an dem rohen char-Zeiger name. Da wird nämlich nur die Adresse gespeichert, nicht der Inhalt.

    EiGelbb schrieb:

    Zu den Stringstreams: Ich konvertiere beim schreiben doch die Zahlen in einen String

    Und der operator>> konvertiert wieder zurück, genau das ist seine Aufgabe. Der Zwischenschritt über den Stringstream ist unnötig.



  • Ok, danke.

    Und wie löse ich das Problemchen? Die Gegner sollten schon einen Namen haben. Und immer einer init-Number über switch(initnumber) aufzurufen wäre ein wenig Overkill, finde ich, oder?
    Mit String geht es ja auch nicht. Deswegen dachte ich, machst du's mit Char... Aber wenn das auch nicht geht 😞

    BTW, kann mir jemand ein weiterführendes C++ Buch empfehlen, wo auch mal die Praxis ein wenig beleuchtet wird? Es ist ja schön und gut zu wissen, was Klassen so machen könnten, wie Templates funktionieren etc. Aber diese reinen Fälle kommen halt nie vor. Hatte bisher C++ für Spieleprogrammierer gelesen (80% des Textes besteht darin, dem Leser zu verdeutlichen, dass das eben gezeigte zu erklären den Rahmen des Buches sprengen würde), und C++ Objektorientiertes Programmieren von Anfang an, was mehr Nachschlagwerk als Lernbuch ist... 😞



  • du brauchst keine char arrays benutzten. du musst dir halt die stream-operatoren überladen. ich glaube dazu gibt es auch artikel hier im forum.

    und das mit dem konvertieren:

    #include <iostream>
    
    int main()
    {
      double d;
      std::cin >> d;
    }
    

    hier liest du auch ein double direkt ein

    vario-500

    Edit: für buchempfehlungen schau mal in signatur von Seppj 😉


  • Mod

    EiGelbb schrieb:

    Hier mal die .h der Klasse player:

    Kein POD.

    Mit Strings war sie nicht POD (was auch immer das heißen mag) und deswegen habe ich anstattdessen ein char array genommen

    Kaputtrepariert. Jetzt ist alles viel schlimmer, da du char-Arrays nicht verstanden hast.

    POD (was auch immer das heißen mag)

    Und was macht man, wenn man etwas nicht versteht?

    Zu den Stringstreams: Ich konvertiere beim schreiben doch die Zahlen in einen String, bzw sie können nur noch als string eingelesen werden. Und dann muss ich diese Zeilen doch über einen stringstream laufen lassen, oder? Anscheinend mache ich einen Gedankenfehler. Aber wo?

    Ich habe die Fehler hervorgehoben.

    BTW, kann mir jemand ein weiterführendes C++ Buch empfehlen, wo auch mal die Praxis ein wenig beleuchtet wird?

    Siehe meine Signatur. Du brauchst aber kein weiterführendes Buch, dir fehlen sämtliche wichtigen Grundlagen.





  • Nachdem ich ja selber in letzter zeit sehr viele Bücher durchgearbeitet hatte um mich mit C++ auseinander zu setzen kann ich bisher nur eines wirklich empfehlen, Englischkenntnisse vorausgesetzt.

    http://www.amazon.de/C-Primer-Plus-Developers-Library/dp/0321776402/ref=sr_1_cc_1?s=aps&ie=UTF8&qid=1331723226&sr=1-1-catcorr

    Online lesbar hier ...

    http://books.google.de/books?id=eC-iLe_iET8C&printsec=frontcover&hl=de&source=gbs_ge_summary_r&cad=0#v=onepage&q&f=false



  • Und wie mache ich das mit dem Überladen der Streams?! Habt ihr vielleicht einen Link wo das erklärt ist? Ich versteh nicht wie man >> oder << überladen kann?! Und vorallem wie man das dann anwendet. Und das mit den stingstreams geht wie ich es mache auch nicht. wenn ich direkt von dem string in die Float bzw Int schreiben will, meckert der Compiler ;_(



  • Von String in einen Integer bzw Float kannst du mit atoi(string/char array) für Integer und atof(string/char array) lösen.

    http://www.cplusplus.com/reference/clibrary/cstdlib/atoi/
    http://www.cplusplus.com/reference/clibrary/cstdlib/atof/

    und hier noch ne kleine URL zu Operatoren

    http://www.gia.rwth-aachen.de/Lehre/Cpp/script/online/node141.html



  • Wenn du eine schnelle Hilfe brauchst, dann:
    http://www.parashift.com/c++-faq-lite/input-output.html#faq-15.8


  • Mod

    EiGelbb schrieb:

    Und wie mache ich das mit dem Überladen der Streams?! Habt ihr vielleicht einen Link wo das erklärt ist? Ich versteh nicht wie man >> oder << überladen kann?! Und vorallem wie man das dann anwendet.

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

    Und das mit den stingstreams geht wie ich es mache auch nicht. wenn ich direkt von dem string in die Float bzw Int schreiben will, meckert der Compiler ;_(

    Was willst du auch mit dem String? Schreib doch einfach in den Stream, ganz ohne Zwischenschritte! Und lesen genau umgekehrt!

    Videonauth schrieb:

    Von String in einen Integer bzw Float kannst du mit atoi(string/char array) für Integer und atof(string/char array) lösen.

    http://www.cplusplus.com/reference/clibrary/cstdlib/atoi/
    http://www.cplusplus.com/reference/clibrary/cstdlib/atof/

    Das halte ich für einen ganz schlechten Ratschlag. Zum einen braucht er hier gar nichts umzuwandeln. Zum anderen, falls er es doch mal brauchen sollte, ist die Methode die er jetzt hat schon ganz ok. Vielleicht mal als Funktion, anstatt 30x den gleichen Code wiederholen. Und als Template.



  • Das mit dem Überladen des << versteh ich zum Teufel komm raus nicht...
    Was soll mir das bringen, wenn ich da &ostream operator<<(ostream &xy, yx); hab?
    Wofür brauche ich da den Rückgabewert, was bewirkt dieses Überladen nun und wie schreibe ich dann?
    Ich krieg gleich ein Herzkasper, da ich nirgendwo im Internet was finde, womit ich es finde. Immer steht nur: Überlade einfach und dann einfach ausgeben.

    Hilfee! Ich versteh das hinten und vorne nicht. :_(


  • Mod

    EiGelbbb schrieb:

    Das mit dem Überladen des << versteh ich zum Teufel komm raus nicht...
    Was soll mir das bringen, wenn ich da &ostream operator<<(ostream &xy, yx); hab?
    Wofür brauche ich da den Rückgabewert, was bewirkt dieses Überladen nun und wie schreibe ich dann?

    #include <iostream>
    #include <string>
    
    using namespace std;
    
    class Datum
    {
      int tag, monat, jahr;
      friend istream& operator>>(istream &in, Datum &datum)
      {
        char point;
        return in >> datum.tag >> point >> datum.monat >> point >> datum.jahr;
      }
    };
    
    class Stueck_Obst
    {
      string sorte;
      Datum ablaufdatum;
      friend istream& operator>>(istream &in, Stueck_Obst &obst)
      {
        return in >> obst.sorte >> obst.ablaufdatum;
      }
    };
    
    int main()
    {
      Stueck_Obst foo;
    
      // Datensätze von der Form
      // Orange 12.34.4567
      // Banane 76.43.2135
      // usw.
    
      // *****************************************
      // Wie du einen Datensatz einlesen würdest:
    
      // Nein. Das kann ich einfach nicht vormachen. Versuchs mal selber.
      // *****************************************
    
      // *****************************************
      // Wie man viel einfacher einen Datensatz einlesen würde:
      cin >> foo;
      // *****************************************
    }
    

    Außerdem nochmal eine frühere Antwort:

    SeppJ schrieb:

    Siehe meine Signatur. Du brauchst aber kein weiterführendes Buch, dir fehlen sämtliche wichtigen Grundlagen.

    Dein früheres Buch war wohl nicht so gut. Der Title kommt mir auch schon verdächtig vor.



  • Ich glaub, ich bin einfach zu dumm um C++ zu lernen... Seit zwei Stunden verusche ich das Überladen zu verstehen, und ihr seit so nett und versucht mir zu helfen, aber bei mir steht da oben immer noch dick 'Bahnhof'.

    Frage 1: was bewirkt das

    char point
    

    da? Und wo ist das definiert? Wie weiß der Compiler jetzt, dass er bei cin >> keine tastatureingabe erwarten soll sondern aus einer Datei lesen soll? Das soll er da doch oder? Ich sehe nicht, so cin gesagt wird, dass er überladen handeln soll. Und wie das mit Outpur geht weiß ich auch immer noch nicht...

    Wenn ich jetzt eine Klasse Player habe:

    ostream& operator<<(std::ostream& os, const player xy) 
     { 
         os << xy.getAiFood(); 
         return os; 
     }
    

    Das würde doch jetzt bewirken, dass ich in den ersten Paramter des Operators, also in ein ostream-Objekt den Wert von xy.getAiFood() schreiben würde. Doch wie rufe ich diese Funktion auf? Irgendwo muss ich doch die Paramter übergeben? Also

    ostream abc("filename.dat");
    <<(abc,xy);
    

    oder wie? Das sieht mehr sehr falsch aus.
    Logischer würde mir

    ostream abc("filename.dat");
    abc << xy;
    

    erscheinen. Doch: Wo wird da dem << gesagt, dass er überladen ist?!
    Und wie lade ich das jetzt wieder? Ich schreibe ja nicht nur einen sondern gleich mehrere in eine Datei. getline kann ich ja nicht sagen. Wer weiß, ob dass Alles in einer Zeile steht.

    Also, meine konkreten Fragen:

    -Woher weiß cin >>, welchen ostream ich meine?! Da steht ja nichts von einem ostream, sondern nur, dass ein Objekt eingelesen werden soll.
    -Wie funktioniert das speichern und lesen mehrerer Elemente.
    -Was bewirkt das char point in deinem Beispiel?
    -WIE FUNKTIONIERT DAS?!

    Mein Problem ist wohl, dass alle Bücher bisher immer nur die Oberflächen erklärt haben.

    "Mit cin >> gibst du Daten ein"... Doch was der Operator >> nun wirklich könnte, was cin eigentlich bedeutet, etc wird nirgends erklärt 😞

    Oder vielleicht bin ich wirklich nur zu dumm um das Alles zu verstehen 😞


  • Mod

    EiGelbbb schrieb:

    Mein Problem ist wohl, dass alle Bücher bisher immer nur die Oberflächen erklärt haben.

    "Mit cin >> gibst du Daten ein"... Doch was der Operator >> nun wirklich könnte, was cin eigentlich bedeutet, etc wird nirgends erklärt 😞

    Oder vielleicht bin ich wirklich nur zu dumm um das Alles zu verstehen 😞

    Deine Bücher machen das vielleicht so. Die Erklärung die du hier als Beispiel gibst ist auch schlecht bis falsch. Du hast auch tatsächlich überhaupt nicht verstanden, was cin bedeutet. Aber das sind viel zu viele, viel zu lange Fragen und die werden auch noch Folgefragen nach sich ziehen. Das kann ich nicht alles beantworten. Daher: Lies ein gutes Grundlagenbuch! Nichts für Spieleprogrammierer, für Dummies, von A bis Z oder in 21 Tagen, sondern ein gutes Buch!


Anmelden zum Antworten