Ändern einer Variablen eines Structs eines Vectors



  • Developer_X schrieb:

    @__-- :

    object_speed = int

    ist zwar nicht der fehler, aber sollte das nicht ein Sint16 sein 😕



  • Developer_X schrieb:

    Sehr geehrtes Forum, ich habe eine Frage:

    Wie kann ich eine Variable ändern, die in einem Struct ist, und dieses Struct in einem Vector?

    Wenn ich das so mache, geht es nicht, wieso?

    Der Wert wird nicht verändert :

    vector<Objekt>::iterator it;
    	for(it=objects.begin(); it<objects.end(); it++)
    	{
    	    it->rect.x += object_speed;
    	}
    

    doch, wird verändert.



  • Wenn ich das mit Cout ausgeben lasse wird das nicht verändert, egal, dann lass ich es halt sein, ich habe doch hilfe bekommen, weil das Problem ist hier nur stark vereinfacht dargestellt,

    trotzdem danke euch allen!



  • Developer_X schrieb:

    Wenn ich das mit Cout ausgeben lasse wird das nicht verändert, egal, dann lass ich es halt sein, ich habe doch hilfe bekommen, weil das Problem ist hier nur stark vereinfacht dargestellt,

    trotzdem danke euch allen!

    Soll das heißen es geht jetzt? Wo war der Fehler?



  • Dann zeig mal den Original-Code her.
    Membervariablen von Structs in einem vector zu verändern geht nämlich wirklich wunderbar, und genau so wie du im ersten Beitrag geschrieben hast.
    Das Problem wird also wo anders liegen.



  • Es geht jetzt leider nicht, ich hatte gedacht der Fehler wär dort, mein Code ist ziemlich lang, wollt ihr ihn wirklich sehen?

    Über 600 Zeilen, ich habe echt die Hoffnung verloren, ging alles wunderbar, doch jetzt wo ich mit den vectoren arbeiten muss geht gar nichts mehr, ich zeig euch mal den Code, ihr könnt ihr runterladen, ist ne .hpp und ne .cpp datei.

    Wenn ihr mir helfen könntet, wäre das natürlich sehr freundlich
    Es dauert bestimmt nicht lange mir zu helfen, da das Problem nur in der Methode : drawObjekt(..) zu sein scheint,beim Aufruf,
    vielleicht wisst ihr ja was ich da machen kann,

    www.gamehighscores.kilu.de/Game.zip

    m.f.G. Developer_X



  • void Game::moveObjects(vector<Objekt*> objects,bool b)
    

    Referenz übergeben, nicht alles kopieren. Gilt für ziemlich alle Methoden.



  • Ich danke dir vielmalst!

    Es klappt jetzt, ich habe wieder neuen Mut gefunden, ich arbeite an diesem kleinen Spiel schon 30Stunden und war echt traurig als es an einem so kleinen Teil hing, danke dir!



  • Mhh ... Frosch hüpft von unten nach oben, muss Autos ausweichen? Kenn ich als Frosch hüpft über flößende Stämme um auf das andere Ufer zu kommen 🙂 war ein tolles Spiel.

    Was mir so auffiel:

    Für sowas fände ich sprechende Namen schöner:

    struct Options
    	{
    		// Control
    		bool useGMPD;
    		int mlf;
    		int mrt;
    		int mup;
    		int mdn;
    		int kps;
    		int gps;
    		// Sound
    		int ms_vlm;
    		int so_vlm;
    		//Grafik
    		bool antialising;
    		int bpp;
    	}options;
    

    remadeObjects(.) sollte vielleicht remakeObjects heissen?

    Sowas

    music = NULL;
    	jump = NULL;
    	collect = NULL;
    	frogPut = NULL;
    	splash = NULL;
    	crash = NULL;
    
    	imageCollection = NULL;
    
    	object_speed = 5;
    	points = 0;
    	life = 5;
    	timeMS = 0;
    	level = 1;
    

    gehört eigenlich in die Initialisierungsliste des Konstructors, zB so:

    Game::Game() :	
    	game_paused(false), 
    	textColor(SDL_Color(0,255,255)),  // <-- weiss nicht obs den Contructor gibt, schau nach :) 
    	music(NULL), // statt NULL besser 0 oder nullptr
    	jump(NULL),
    	collect(NULL),
    	frogPut(NULL),
    	splash(NULL),
    	crash(NULL),
    	imageCollection(NULL),
    	object_speed(5),
    	points(0),
    	life(5),
    	timeMS(0),
    	level(1)
    { 
            // ...
    }
    
    void Game::drawObjects(vector<Objekt*> objects,bool b) // warum b, warum nicht move_right;
    {
    	vector<Objekt*>::iterator it;
    	int zahl = 0; // wofür ?!?
    
    	for (it=objects.begin(); it<objects.end(); it++)
    	{ /*
    		if(b)
    			drawObject(it,true);
    		else
    			drawObject(it,false);
              */
                    drawObject(it,b); // warum testest du das und stopfst das selbe wieder rein? Magst du viele Code-Zeilen? 
    		zahl++;
    	}
    }
    

    guck mal was für nen Vector du übergibst, was für einen iterator du darauf losläßt und überleg dir mal was mit den erase'ten Pointern auf Objekt geschieht ... werden die Freigegeben oder produzieren die Memoryleaks?

    void Game::remadeObjects(vector<Objekt*> objects,bool b,bool c) // warum b, warum c warum keine Namen die was aussagen?
    
    {
    	if(b)
    	{
    		vector<Objekt>::iterator it;
    
    		Objekt newObject; // das hier wird HIER nicht gebraucht -> so spät machen wie möglich
    		int rand_number;
    
    		for (it=objects.begin(); it<objects.end(); it++)
    		{
    			if(it->rect.x+it->rect.w>=gameRect.x+gameRect.w)
    			{
    				objects.erase(it);
    
    				srand((unsigned)time(0));  // mhh ... das wird bei jedem Aufruf der remadeObjects() methode neu initialisiert (mit der aktuellen Zeit)  - das gehört EINMAL in den Konstruktor, nirgends sonst hin
    				rand_number = (rand()%8);  // ok, du erzeugst ne nummer zwischen 0 und (inkl.) 7
    				while(rand_number>4)       // Häh? du willst nur nummern kleiner gleich 4?  
    				{
    					srand((unsigned)time(0)); // schonwieder initialisiert ... s.o.
    					rand_number = (rand()%8); // ok, wieder ne Zahl [0..7] solange bis was <=4 rauskommt ... warum nicht gleich rand()%5 ?
    				}
    
    // SNIPP
    				srand((unsigned)time(0)); // s.o.
    				rand_number = (rand()%8); // s.o.
    				while(rand_number!=1&&rand_number!=2&&rand_number!=3&&rand_number!=4)
    				{
    					srand((unsigned)time(0)); // s.o.
    					rand_number = (rand()%8); // du willst 1-4 nicht? mach rand_number = rand()%5; if (rand_number != 0) rand_number+=4;
    				}
    // SNIPP
                                    newObject.rect.y = gameRect.y+gameRect.h-carAright.h*1; // warum * 1 ?
    

    DAS hier sollte dir zu denken geben: - noch klappt es, wenn du da mehr machst kanns krachen ...

    http://www.cplusplus.com/reference/stl/vector/erase/ schrieb:

    vector::erase

    public member function

    iterator erase ( iterator position );
    iterator erase ( iterator first, iterator last );

    Erase elements
    Removes from the vector container either a single element (position) or a range of elements ([first,last)).

    This effectively reduces the vector size by the number of elements removed, calling each element's destructor before.

    Because vectors keep an array format, erasing on positions other than the vector end also moves all the elements after the segment erased to their new positions, which may not be a method as efficient as erasing in other kinds of sequence containers (deque, list).

    This invalidates all iterator and references to elements after position or first.

    Ich bin mir nicht sicher was die SDL kann, aber Images zu spiegeln sollte doch drin sein? Das würde deine Sprites halbieren wenn du statt "statischen" Bildern einfach "gemirrorte" Bilder nutzt. Die carAleft + carAright würde zu sowas: carA und applySurface bräuchte noch ein bool mirrored - damit sparst du die Hälfte der clipping rectangles und dein sourcebild wird auch halbiert -> ansonsten wäre das vielleicht auch gut (ge-structed) aus einer Datei einlesbar.

    Du könntest bei Wikipedia auch mal nach "const correctness" suchen und Übergabe "per Value" und "per Refefence".

    Sowas hier: void Game::drawObjects(vector<Objekt*> objects, bool b); kopiert den übergebenen vector. Besser wäre sowas void Game::drawObjects(vector<Objekt*> & objects, bool b); dann wird der Vector selbst weitergereicht. Noch besser wäre
    void Game::drawObjects(const vector<Objekt*> & objects,bool b); wenn du sicherstellen willst das der Vector zwar weitergereicht statt kopiert, dann aber nicht geändert werden darf.



  • Developer_X schrieb:

    Es geht jetzt leider nicht, ich hatte gedacht der Fehler wär dort, mein Code ist ziemlich lang, wollt ihr ihn wirklich sehen?

    Nein. Es ist Deine Aufgabe -- als Hilfesuchender -- das Problem zu isolieren und ein kurzes, kleines Programm zu zeigen, was sich kompilieren lassen sollte und den "Laufzeit-Fehler" reproduziert. Dazu gehört auch die Beschreibung des erwarteten Verhaltens und dem tatsächlichen Verhalten. Als jemand, der C++ nicht versteht, bist Du auch nicht in der Lage, Codezeilen nach ihrer Relevanz bzgl des Problems zu selektieren. Daher ---> vollständigen aber kurzen Code!

    Anhand der Zeile, die hier von Deinem Code zitiert wurde, kann man aber schon erahnen, wo bei Dir die Missverständnisse liegen. Das, was man von Hilfesuchenden erwartet, hätte in Deinem Fall so aussehen müssen:

    Mein Problem: Dieses Programm verhält sich nicht so, wie ich es gedacht hätte. Ich erwarte, dass das Programm 2 ausgibt, weil in der Funktion foo ein zweites Element dem Vektor hinzugefügt wird. Stattdessen gibt es 1 aus. Warum?

    Hier gibt es ein kompilierbares kleines Beispiel zu sehen, eine Beschreibung der erwarteten Ausgabe und dem, was das Program tatsächlich ausgibt. Du solltest beim nächsten mal versuchen, selbst soweit zu kommen.

    Nun. Warum verhält sich das Programm so? Warum denn nicht? vector<int> ist hier nicht anders als int oder double. In allen Fällen werden lokale Kopien erzeugt. Die Funktion arbeitet auf der lokalen Kopie und Änderungen an dieser Kopie sind nach außen nicht sichbar. Parameterübergabe an Funktionen kommt einer sogenannten "Kopierinitialisierung" gleich. Genauso sind hier

    vector<int> x;
    x.push_back(23);
    vector<int> y = x; // <-- auch eine "Kopierinitialisierung"
    y[0] = 42;
    cout << x[0];
    

    x und y zwei verschiedene vector<int>-Objekte. Die Unterscheidung zwischen "Werttyp" und "Referenztyp" wie es in anderen Sprachen der Fall ist (zB Java und C#) gibt es hier nicht. Wenn Du Indirektion willst, musst Du das explizit sagen.

    So, jetzt habe ich wieder viel mehr geschrieben als ich das eigentlich wollte. Ich hoffe, dass wenigstens klar ist, dass Du beim Stellen von Fragen mehr Arbeit investieren musst. Wenn Du nir ein paar irrelevante Codefetzen zeigst und sagst "geht nicht!" brauchst Du Dich nicht wundern, wenn Dir keiner hilft.



  • mehr reineditiert ...



  • Danke hilfsbereiter, ich werde das dann in Zukunft so machen, ich muss mich in C++ erstmal etwas eingewöhnen, auch wenn ich es schon ein halbes jahr neben Java mache^^, doch mal im Ernst, jetzt programmiere ich nur noch mit C++ weil ich mich daran gewöhnen will. Danke für deine Tipps!

    Danke padreigh für deine Code verbesserungen, das mit den initialisierungslisten werde ich dann in der Zukunft so handhaben.
    Ach und nein, die SDL stellt leider keine solche Methode, zum Spiegeln
    bereit, als ich Games mit Java gemacht habe, habe ich das so auch
    gehandhabt. Ich werde in Zukunft wohl eher nicht mehr mit der SDL arbeiten, da sie wirklich sehr begrenzt in ihrer Funktionalität ist, und immer so viele Librarys extra einzubinden, ist auch ziemlich nervig. Ich wurde auf die SFML gebracht, die versuch ich mal aus. Es ging mir bei diesem Spiel auch eher darum bisschen mein Wissen zu festigen.
    Ach und ja, das soll Frogger werden^^

    Danke euch allen für eure Hilfe, sie hat mir wirklich stark weitergeholfen.
    M.f.G. Developer_X



  • [quote="Developer_X"]

    vector<Objekt>::iterator it;
    	for(it=objects.begin(); it<objects.end(); it++)
    	{
    	    it->rect.x += object_speed;
    	}
    

    Ist es nicht gefährlich, Iteratoren in der Schleife mit '<' zu vergleichen?

    Freilich, bei einem Vektor liegen die alle hintereinander, so daß es funktioniert, aber wenn Du mal auf die Idee kommst, den Vektor durch ein Set oder eine Liste zu ersetzen, würde ich nicht darauf wetten, daß die alle kleiner als objects.end() sind. Den Fehler findet man dann sehr schwer.

    lg



  • OK, danke sehr, ich werde das auch ändern,



  • padreigh schrieb:

    Mhh ... Frosch hüpft von unten nach oben, muss Autos ausweichen? Kenn ich als Frosch hüpft über flößende Stämme um auf das andere Ufer zu kommen 🙂 war ein tolles Spiel.

    Naja eigentlich war es erst Autos in der unteren Bildschirmhälfte und dann Baumstämme in der oberen.



  • NA schrieb:

    Ist es nicht gefährlich, Iteratoren in der Schleife mit '<' zu vergleichen?

    Nein. Gefährlich ist das nicht. Aber es funktioniert nur bei sogenannten "Random Access"-Iteratoren.

    NA schrieb:

    Freilich, bei einem Vektor liegen die alle hintereinander, so daß es funktioniert,

    Ob die Objekte alle hintereinander im Speicher liegen oder nicht ist irrelevant. std::deque bietet auch Random-Access-Iteratoren und die Elemente liegen nicht alle hintereinander im Speicher.


Anmelden zum Antworten