Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

marfi

Treue Seele

  • »marfi« ist der Autor dieses Themas

Beiträge: 100

Wohnort: Schwerte

  • Private Nachricht senden

1

25.07.2010, 17:58

Rekursive Funktion komplett unterbrechen

Hallo Leute,

ich habe ein Problem mit meiner Funktion. Ich trage in einem Quadtree in jedem leaf einen pointer ein. Diesen möchte ich wieder abfragen. Mit einer Funktion die den pointer zurückgibt hat es nicht funktioniert. Wenn ich den NULL pointer aber übergebe, wird er beim zweiten Aufruf der Funktion vom Stack wieder mit dem NULL pointer überschrieben. Obwohl im ersten Aufruf schon die gesuchte Adresse eingetragen wurde.

Kann mit da jemand einen Tip geben? Ich bin mit meinem Latein am Ende. Jedenfalls heute :)

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
void CM3DQuadTree::GetData(SNode* pRoot, int nPointX, int nPointY, CTileData* pDataOut) 
{ 
if(!pRoot) 
return; 
if((nPointX >= pRoot->X1)&&(nPointX <=pRoot->X2)&&(nPointY >=pRoot->Y1)&&(nPointY <= pRoot->Y2)) 
{ 
if(pRoot->TYPE == LEAF) 
{ 
pDataOut = pRoot->pData;return; 
} 

} 

GetData(pRoot->pTopLeftChild,nPointX,nPointY,pDataOut); 
GetData(pRoot->pTopRightChild,nPointX,nPointY,pDataOut); 
GetData(pRoot->pBottomLeftChild,nPointX,nPointY,pDataOut); 
GetData(pRoot->pBottomRightChild,nPointX,nPointY,pDataOut); 
}

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

2

25.07.2010, 18:12

Du solltest Dir den Unterschied zwischen "Übergabe eines Pointers" und "Call by Reference" nochmal ansehen, denn was Du offensichtlich machen willst ist einen Pointer oder Wert als Call by Refenrence zu übergeben, Du übergibst aber einfach nur einen Pointer. Und wenn Du den lokal überschreibst, dann ändert der sich rein gar nicht nach dem Rücksprung.

Insgesamt erschließt sich mir aber auch nicht, warum Du über ALLE Blätter wanderst, wenn Du doch nur einen Wert zurück bekommen willst.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

marfi

Treue Seele

  • »marfi« ist der Autor dieses Themas

Beiträge: 100

Wohnort: Schwerte

  • Private Nachricht senden

3

25.07.2010, 18:20

Eigentlich war ich den Meinung, dass ich pointer genauso wie Referenzen dauerhaft überschreiben kann. Jedenfalls ist das bei Inhalten von pointern so. Bei "leeren" pointern bin ich mir gerade nicht sicher. Ich muss doch alle quads durchlaufen um das zu finden, welches mit den übergebenen Koordinaten übereinstimmt. Ich möchte ja die Daten eines bestimmten Quads haben.

Ich könnte es ja mal mit einer Referenz auf einen Integer probieren, um mir den pointer zu holen. ... Irgendwie bin ich gerade verwirrt. ;)

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

4

25.07.2010, 18:28

Du kannst das überschreiben, worauf der Pointer zeigt, nicht den Pointer selber, der ja ein Parameter und somit eine lokale Variable darstellt. Also überschreiben kannst Du ihn schon, er hat aber beim Rücksprung wieder den alten Wert.

Und trotzdem: Selbst wenn Du einen gefunden passenden hast, so hast Du keine Abbruchbedingung für die nachfolgenden Rekursionen in die anderen Äste angegeben und würdest wunderschön weitersuchen, in allen Ästen, auch wenn die Suche keinen weiteren Erfolg mehr bringen dürfte.

PS:
Beschäftige Dich lieber noch mal mit Parametern von Funktionen, Pointern und Referenzen, bevor Du Dich an Quad-Trees heranwagst...
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

BurningWave

Alter Hase

Beiträge: 1 106

Wohnort: Filderstadt/Konstanz

Beruf: Student

  • Private Nachricht senden

5

25.07.2010, 21:06

Wie wärs mit Exceptions?

6

25.07.2010, 21:15

Für diesen Anwendungsfall fehl am Platz. Da reicht eine ordentliche Abbruchbedingungen.
Mach beim letzten if mal ne else Verzweigung und häng da das GetData dran, dann wird nicht immer der gesamte Baum durchlaufen.

Die Sache mitm Zeiger wurd ja schon erklärt ;)

Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von »Genion« (25.07.2010, 21:23)


marfi

Treue Seele

  • »marfi« ist der Autor dieses Themas

Beiträge: 100

Wohnort: Schwerte

  • Private Nachricht senden

7

26.07.2010, 19:51

Vielen Dank für eure geistige Unterstützung!

@BlueCobold: So schlimm sieht es mit meinen Programmierkünsten auch wieder nicht aus. Den Umgang mit Zeigern und Referenzen bin ich gewohnt, aber ich habe nicht daran gedacht, dass ein Zeiger eigentlich nur eine Variable mit der Adresse als Inhalt ist. Nicht die Adresse selbst, wie bei der Referenz. Normalerweise benutze ich Zeiger nicht auf diese Art. Ansonsten funktioniert mein Quadtree nun so, wie ich es mir vorstelle. Aber danke für den Hinweis ;) Manchmal braucht man einen leichten Schlag auf den Hinterkopf :)

Hier nun die funktionsfähige Funktion.

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
 void CM3DQuadTree::GetData(SNode* pRoot, int nPointX, int nPointY, CTileData*& pDataOut) 
{ 
if((!pRoot)||(pDataOut)) 
return; 
if((nPointX >= pRoot->X1)&&(nPointX <=pRoot->X2)&&(nPointY >=pRoot->Y1)&&(nPointY <= pRoot->Y2)) 
{ 
if(pRoot->TYPE == LEAF) 
{ 
pDataOut = pRoot->pData; 
return; 
} 
} 
else 
return; 

if(!pDataOut) 
GetData(pRoot->pTopLeftChild,nPointX,nPointY,pDataOut); 
if(!pDataOut) 
GetData(pRoot->pTopRightChild,nPointX,nPointY,pDataOut) ; 
if(!pDataOut) 
GetData(pRoot->pBottomLeftChild,nPointX,nPointY,pDataOut); 
if(!pDataOut) 
GetData(pRoot->pBottomRightChild,nPointX,nPointY,pDataOut); 



}

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

8

26.07.2010, 19:53

Ich denke nicht, dass der Code jetzt korrekt ist. Meiner Meinung nach ist da ein return zu viel, welches bewirkt, dass Du kein Ergebnis bekommst.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

daG

Treue Seele

Beiträge: 130

Wohnort: Hamburg

  • Private Nachricht senden

9

26.07.2010, 20:10

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
 void CM3DQuadTree::GetData(SNode* pRoot, int nPointX, int nPointY, CTileData*& pDataOut) 
{ 
if((!pRoot)||(pDataOut)) 
return; 
if((nPointX >= pRoot->X1)&&(nPointX <=pRoot->X2)&&(nPointY >=pRoot->Y1)&&(nPointY <= pRoot->Y2)) 
{ 
if(pRoot->TYPE == LEAF) 
{ 
pDataOut = pRoot->pData; 
return; 
} 
} 
else 
return; 

if(!pDataOut) 
GetData(pRoot->pTopLeftChild,nPointX,nPointY,pDataOut); 
if(!pDataOut) 
GetData(pRoot->pTopRightChild,nPointX,nPointY,pDataOut) ; 
if(!pDataOut) 
GetData(pRoot->pBottomLeftChild,nPointX,nPointY,pDataOut); 
if(!pDataOut) 
GetData(pRoot->pBottomRightChild,nPointX,nPointY,pDataOut); 



}
Ich würde mal behaupten, dass ist das beste Beispiel warum man nicht immer auf die {} verzichten sollte nur weil es möglich ist ^^

Und Einrückung hat auch ihren Sinn, aber die ist wahrscheinlich beim Posten hier verloren gegangen (hoffe ich doch :D)

marfi

Treue Seele

  • »marfi« ist der Autor dieses Themas

Beiträge: 100

Wohnort: Schwerte

  • Private Nachricht senden

10

26.07.2010, 20:19

Die Formatierung ist beim posten leider verloren gegangen. :/ Hab es schon etwas zurechtgerückt.

Also eigentlich funktioniert der Code, was ja noch lange nicht bedeutet das er korrekt ist :D

Das erste return ist für pRoot == NULL oder pData gefunden.

Das zweite return ist wieder für pData gefunden

und das dritte return falls die Koordianten nicht mehr im Quad liegen, dass sollen die kleineren auch nicht mehr durchsucht werden.

Durch die Rekursion ist dieses if(!pDataOut) vor jedem Aufruf nötig, da bei return ja nur zum vorherigen Funktionsaufruf gesprungen wird. Danach will er ja da weiter machen, wo er aufgehört hat.

Werbeanzeige