Array in Methode dynamisch allokieren



  • Habe schon diverse Artikel darüber gelesen, wie man arrays als parameter übergeben und auch zurückgeben kann, aber noch nichts gefunden, was mir helfen würde...

    meine Klasse:

    class STICKMAN
    {
    	private:
    		...
    		POINT DoesntMove[1]; // Punkte Array
    		...
    		void CalcDoesntMove(int height); // DoesntMove soll hier allokiert werden
    
    	public:
    		void SetColor(COLORREF color);
    		void GetColor(COLORREF& gColor);
    		void ManInit(HWND hwnd, int posX, int posY, int heigth);
    		void DrawDoesntMove(int posX, int PosY);
    };
    

    Wie der Klassenname schon sagt, möchte ich ein Strichmännchen zeichnen.
    In CalcDoesntMove sollen die Punkte errechnet und in ein Array gespeichert werden. In DoesntMove[].x wird die Anzahl Elemnte des Arrays gespeichert.
    Die in dem Array gespeicherten Punkte sollen später in DrawDoesntMove gezeichnet werden.

    CalcDoesntMove:

    void STICKMAN::CalcDoesntMove(int height)
    {
    	int zaehler = 1;
    	...
    	zaehler++;
    	POINT* DoesntMove = new POINT[zaehler];
    	DoesntMove[zaehler-1].x = x;
    	DoesntMove[zaehler-1].y = y;
    	...
    }
    
    void STICKMAN::DrawDoesntMove(int posX, int posY)
    {
    	HDC hdc = GetDC(hwnd);
    	for (int i = 0; i <= DoesntMove[0].x; i++)
    	{
    		SetPixel(hdc, posX+DoesntMove[i].x, posY+DoesntMove[i].y, color);
    	}
    	ReleaseDC(hwnd, hdc);
    }
    

    So wie ich das zu diesem Zeitpunkt beurteile, liegt mein Fehler/Problem darin, dass der Speicher der in der Methode allokiert wird, nach Ende der Methode wieder freigegeben wird...
    Ich weiss wirklich nicht weiter, bin seit tagen am ausprobieren.
    Ich bin noch Schüler und programmiere nur hobbymässig, wäre darum sehr dankbar für hilfe... wäre auch froh, wenn ihr mich auf unschöne Dinge in meinem Code hinweisen würdet, man soll schliesslich aus seinen Fehlern lernen 😃



  • Was willst du machen? Das erstellte Array an die andere Funktion übergeben?



  • das array ist ja eine Variable der Klasse STICKMAN...

    in der Methode CalcDoesntMove sollen die Elemnte des Arrays definiert werden, so das später die Methode DrawDoesntMove darauf zugreifen kann..

    mit den anderen Variablen wie z.B. COLORREF color klappt das ganz gut (ist auch unter private deklariert, hab der übersichtwegen die anderen Variablen rausgelöscht...)
    Nur mit dem Array klappt es nicht



  • Konkrete Fehlermeldungen und ALLE relevanten Codestellen wären hilfreich.

    Der Schleifenkopf

    for (int i = 0; i <= DoesntMove[0].x; i++)
    

    erscheint mir für eine Array mit nur einem Element auch etwas merkwürdig.

    Weiterhin solltest Du Dir vielleicht mal std::vector als Alternative zu den ollen C-Arrays ansehen.



  • es handelt sich um einen Run-Time-Error, weil ich in der for schleife auf ein Elementzugreifen will, das nicht existiert.
    Das Array soll ja nicht nur ein Element haben, es wird mit einem Element initialisiert, soll dann aber in der Methode CalcDoesntMove weitere Elemente erhalten, und dass ist genau das, was nicht funktioniert...

    wollte es eigentlich ohne vektoren machen, hab keinerlei Erfahrung mit Vektoren, aber vielleicht werde ich sie mir jetzt trotzdem mal ansehen...



  • Argus Magnus schrieb:

    das array ist ja eine Variable der Klasse STICKMAN...

    void STICKMAN::CalcDoesntMove(int height)
    {
    	int zaehler = 1;
    	...
    	zaehler++;
    	POINT* DoesntMove = new POINT[zaehler]; //Hier machst du ein neues und weist es einem lokalen Pointer zu und nicht dem der Klasse
    	DoesntMove[zaehler-1].x = x;
    	DoesntMove[zaehler-1].y = y;
    	...
    }
    

    PS
    Es gibt auch std::vector



  • Naja, wenn Du ein Array in der Form...

    POINT DoesntMove[1];
    

    ...anlegst, dann ist das Ding in seiner Größe statisch, d.h. Du kannst nichts mehr an der Größe ändern.
    Du musst Deine Arrays in der richtigen Größe anlegen, bevor Du auf seine Elemente zugreifst, sonst kommt es zu den von Dir beschriebenen Schutzverletzungen.
    Wenn Du finale Größe Deines Arrays erst zur Laufzeit bekannt ist, musst Du es dynamisch mit new allokieren...

    //Deklarationsteil Deiner Klasse
        POINT* DoesntMovePtr;
    
    //z.B. im Konstruktor
        DoesntMovePtr = new POINT[NumberOfElements];
        //evtl. je nach Fall besser in der Initialisierungsliste
    

    Und nicht vergessen, den Speicher im Destruktor wieder frei zu geben:

    delete[] DoesntMovePtr ;
    

    Das sind nur Ausschnitte. Wenns sicher sein soll, solltest Du den Speicher über RAII-Mechanismen (Wikipedia nachgucken ;)) allokieren bzw. auto_ptr benutzen, falls möglich.

    Auf den Punkt gebracht:
    Dein POINT DoesntMove[1] hat wird immer und ewig nur EIN POINT-Element haben.



  • danke erst mal

    es gibt jetzt zwar keinen Error mehr, aber es passiert auch nicht das, was ich möchte...

    hier mal der komplette Code:

    game.h:

    #ifndef GAME_H
    #define GAME_H
    
    double wurzel(int i, double zahl);
    void GeradenGleichung(int x1, int y1, int x2, int y2, float& m, float& c);
    
    class STICKMAN
    {
    	private:
    		COLORREF color;
    		HWND hwnd;
    		int posX;
    		int posY;
    		int heigth;
    		POINT* DoesntMove;
    		void CalcDoesntMove(int height);
    
    	public:
    		void SetColor(COLORREF color);
    		void GetColor(COLORREF& gColor);
    		void ManInit(HWND hwnd, int posX, int posY, int heigth);
    		void DrawDoesntMove(int posX, int PosY);
    		void ManDelete();
    };
    
    #endif
    

    game.cpp:

    #include <windows.h>
    
    #include "game.h"
    
    double wurzel(int i, double zahl)
    {
    	double x = 2;
    	double y = 0;
    	double a;
    	int z = i-1;
    	int e = 0;
    
    	while (e < 20 && x != y)
    	{
    		a = x;
    		for (int j = 1; j < z; j++)
    			a = a*a;
    		y = zahl/a;
    		x = (z*x+y)/i;
    		e++;
    	}
    	return x;
    }
    
    void GeradenGleichung(int x1, int y1, int x2, int y2, float& m, float& c)
    {
    	m = (y1-y2)/(x1-x2);
    	c = y1-(m*x1);
    }
    
    void STICKMAN::CalcDoesntMove(int height)
    {
    	int zaehler = 1;
    	double e;
    	int radius = height/6;
    	int px = 0;
    	int py = 0;
    	int mx = px+radius;
    	int my = py+radius;
    	float m1, m2, c1, c2;
    	/********************** HEAD **********************/
    	for (int y = my-radius; y <= my+radius; y++)
    	{
    		for (int x = mx-radius; x <= mx+radius; x++)
    		{
    			e = wurzel(2,((mx-x)*(mx-x)+(my-y)*(my-y)));
    			if ((int)(e+0.5) < radius)
    			{
    				zaehler++;
    				DoesntMove = new POINT[zaehler];
    				DoesntMove[zaehler-1].x = x;
    				DoesntMove[zaehler-1].y = y;
    				for (int z = 1; z < zaehler-1; z++)
    				{
    					if (DoesntMove[z].x == x && DoesntMove[z].y == y)
    					{
    						zaehler--;
    					}
    				}
    			}
    		}
    	}
    	/**************************************************/
    	/********************** BODY **********************/
    	for (int y = py+2*radius; y <= py+4*radius; y++)
    	{
    		for (int x = px+radius*9/10; x <= px+radius*12/10; x++)
    		{
    			zaehler++;
    			POINT* DoesntMove = new POINT[zaehler];
    			DoesntMove[zaehler-1].x = x;
    			DoesntMove[zaehler-1].y = y;
    			for (int z = 1; z < zaehler-1; z++)
    			{
    				if (DoesntMove[z].x == x && DoesntMove[z].y == y)
    				{
    					zaehler--;
    				}
    			}
    		}
    	}
    	/**************************************************/
    	/********************** LLEG **********************/
    	GeradenGleichung(px+radius*9/10, py+radius*4, px+radius*6/10, py+radius*5, m1, c1);
    	GeradenGleichung(px+radius*11/10, py+radius*4, px+radius*8/10, py+radius*5, m2, c2);
    	for (int y = py+4*radius; y <= py+5*radius; y++)
    	{
    		for (int x = px+radius/2; x <= px+radius*12/10; x++)
    		{
    			if (y >= m1*x+c1 && y <= m2*x+c2)
    			{
    				zaehler++;
    				POINT* DoesntMove = new POINT[zaehler];
    				DoesntMove[zaehler-1].x = x;
    				DoesntMove[zaehler-1].y = y;
    				for (int z = 1; z < zaehler-1; z++)
    				{
    					if (DoesntMove[z].x == x && DoesntMove[z].y == y)
    					{
    						zaehler--;
    					}
    				}
    			}
    		}
    	}
    	for (int y = py+5*radius; y <= py+height; y++)
    	{
    		for (int x = px+radius*6/10; x <= px+radius*7/10; x++)
    		{
    			zaehler++;
    			POINT* DoesntMove = new POINT[zaehler];
    			DoesntMove[zaehler-1].x = x;
    			DoesntMove[zaehler-1].y = y;
    			for (int z = 1; z < zaehler-1; z++)
    			{
    				if (DoesntMove[z].x == x && DoesntMove[z].y == y)
    				{
    					zaehler--;
    				}
    			}
    		}
    	}
    	/**************************************************/
    	/********************** RLEG **********************/
    	GeradenGleichung(px+radius*10/10, py+radius*4, px+radius*13/10, py+radius*5, m1, c1);
    	GeradenGleichung(px+radius*12/10, py+radius*4, px+radius*15/10, py+radius*5, m2, c2);
    	for (int y = py+4*radius; y <= py+5*radius; y++)
    	{
    		for (int x = px+radius*9/10; x <= px+radius*1.6; x++)
    		{
    			if (y <= m1*x+c1 && y >= m2*x+c2)
    			{
    				zaehler++;
    				POINT* DoesntMove = new POINT[zaehler];
    				DoesntMove[zaehler-1].x = x;
    				DoesntMove[zaehler-1].y = y;
    				for (int z = 1; z < zaehler-1; z++)
    				{
    					if (DoesntMove[z].x == x && DoesntMove[z].y == y)
    					{
    						zaehler--;
    					}
    				}
    			}
    		}
    	}
    	for (int y = py+5*radius; y <= py+height; y++)
    	{
    		for (int x = px+radius*14/10; x <= px+radius*15/10; x++)
    		{
    			zaehler++;
    			POINT* DoesntMove = new POINT[zaehler];
    			DoesntMove[zaehler-1].x = x;
    			DoesntMove[zaehler-1].y = y;
    			for (int z = 1; z < zaehler-1; z++)
    			{
    				if (DoesntMove[z].x == x && DoesntMove[z].y == y)
    				{
    					zaehler--;
    				}
    			}
    			DoesntMove[0].x = zaehler-1;
    		}
    	}
    	/**************************************************/
    }
    
    void STICKMAN::SetColor(COLORREF color)
    {
    	this->color = color;
    }
    
    void STICKMAN::GetColor(COLORREF& gColor)
    {
    	gColor = color;
    }
    
    void STICKMAN::ManInit(HWND hwnd, int posX, int posY, int height)
    {
    	this->hwnd = hwnd;
    	this->posX = posX;
    	this->posY = posY;
    	this->heigth = heigth;
    
    	/************************* Stickman zeichnen ***********************/
    	CalcDoesntMove(height);
    	DrawDoesntMove(posX, posY);
    	/*******************************************************************/
    }
    
    void STICKMAN::DrawDoesntMove(int posX, int posY)
    {
    	HDC hdc = GetDC(hwnd);
    	for (int i = 0; i <= DoesntMove[0].x; i++)
    	{
    		SetPixel(hdc, posX+DoesntMove[i].x, posY+DoesntMove[i].y, color);
    	}
    	ReleaseDC(hwnd, hdc);
    }
    
    void STICKMAN::ManDelete()
    {
    	delete[] DoesntMove;
    }
    

    main.cpp:

    ...
    case WM_PAINT:
    	hdc = BeginPaint(fenster, &ps);
    	player.ManInit(fenster, 5, 5, 200);
    	EndPaint(fenster, &ps);
    	player.ManDelete();
    	return 0;
    ...
    

    Noch einmal: ich möchte, das der Inhalt und die Anzahl Elemnte vom DoesntMove-Array erst in der Methode CalcDoesntMove festgelegt wird

    :: edit ::

    und mit "es passiert nicht das was ich möchte" meine ich, dass gar nichts (jedenfalls nichts, das ich bemerken würde) passiert, es erscheint einfach ein weisses fenster...



  • Na, dann ist es jetzt Zeit für dich mal debuggen zu lernen.



  • solche Beiträge helfen mir ungemein weiter... ich hätte das Problem gar nicht erst gepostet, wenn ich nicht längst schon alle lösungsansätze die mir einfielen getestet hätte...

    :: edit ::

    jetzt fallen mir wie schuppen von den Augen...

    kann es sein das ich den Array nur einmal allokieren kann (wäre eigentlich logisch...)?

    :: edit 2 ::

    ok, danke an alle, hat geklappt



  • Argus Magnus schrieb:

    kann es sein das ich den Array nur einmal allokieren kann (wäre eigentlich logisch...)?

    Ein Array hat - wie auch immer angelegt - eine feste Größe. Falls du etwas haben willst das dynamisch zur Laufzeit in der Größe änderbar ist, sind die schon vorher erwähnten STL-Container (std::vector, std::list, std::map...) mit Sicherheit besser geeignet.

    cu André


Anmelden zum Antworten