(Erledigt) Sowas wie ByRef als Funktionsrückgabe

Previous topic - Next topic

Markus

Sowas brauche ich damit nicht jedes mal eine neue Struktur erzeugt wird.
Vieleicht geht sowas auch schon und ich weiß es noch nicht.

Code (glbasic) Select

FUNCTION >>>ByRef<<< FindPlayer AS TPlayer:Nr

FOREACH P IN Players[]
IF P.Nr=Nr THEN RETURN P
NEXT

ENDFUNCTION


Tatsache ist das ich hier den echten Inhalt vom Array bekomme
Code (glbasic) Select

LOCAL P AS TPlayer
FOREACH P IN Players[]
P.Draw()
IF P.Nr=1 THEN P.Update() //das geht
NEXT


Plan B geht nicht  (das Byref ist bei PR wohl schon automatisch bei)
Code (glbasic) Select

FUNCTION FindPlayer:Nr, PR AS TPlayer

FOREACH PR IN Players[]
IF PR.Nr=Nr 
BREAK
ENDIF
NEXT

ENDFUNCTION


Sowas macht eine Kopie
Code (glbasic) Select

FUNCTION FindPlayer:Nr, PR AS TPlayer

FOREACH P IN Players[]
IF P.Nr=Nr 
PR=P
BREAK
ENDIF
NEXT

ENDFUNCTION




backslider

Geht nicht
Code (glbasic) Select

FUNCTION FindPlayer: Nr, BYREF p AS TPlayer
    FOREACH P IN Players[]
        IF P.Nr=Nr THEN p = P
    NEXT
ENDFUNCTION

?

Quentin

Meinst du sowas, dass die Funktion den Typen zurückliefert? Doch das geht schon. musst nur die Funktion entsprechend deklarieren:

Code (glbasic) Select

TYPE TPlayer
text$
ENDTYPE

GLOBAL players[] AS TPlayer
DIM players[3]

players[0].text$ = "Erster"
players[1].text$ = "Zweiter"
players[2].text$ = "Dritter"

LOCAL test AS TPlayer

test = get_player("Zweiter")
STDOUT test.text$
KEYWAIT


FUNCTION get_player AS TPlayer: text$
FOREACH p IN players[]
IF p.text$ = text$
RETURN p
ENDIF
NEXT
ENDFUNCTION

backslider

Dein Beispiel hat er doch als erste Funktion genannt, nur das er da irgendwie nen BYREF haben will.  :P

Kitty Hello

Byref geht nicht. Aber Du kannst ja byref als argument übergeben.
Wenn Du BYREF returnen willst - worauf soll der Rückgabewert zeigen!?

backslider

QuoteByref geht nicht. Aber Du kannst ja byref als argument übergeben.
Damit meinst Du doch meine Idee, oder nicht?

Kitty Hello

ja. genau.
...warum red ich überhaupt...

kanonet

Lenovo Thinkpad T430u: Intel i5-3317U, 8GB DDR3, NVidia GeForce 620M, Micron RealSSD C400 @Win7 x64

Markus

#8
byref bei einem Parameter mit Struktur gibt mir ein Syntax Error.
ich gehe aber davon aus das der Parameter eh schon als Pointer übergeben wird weil das nur ein paar Bytes sind und so üblich ist.
Oben mein Beispiel ging aber nicht wie ich das erwartet hatte.

Bei A=B habt ihr mir erklärt das dort die Struktur B nach A kopiert wird,ich will aber B haben original :-)

@Quentin
ich möchte keine kopie als Rückgabe

@Kitty Hello
ich will quasi Pointer tauschen bzw. weiter geben und Variable A durch B ersetzen vom gleichem Typ.
Das was im Array ist möchte ich mit einer Funktion raus suchen ohne eine kopie zu erstellen, dann mit .MachIrgendwas() ändern.
Ansonsten muß ich bei einer Kopie das ja auch wieder zurück kopieren in mein Array.
Und wenn man mit kopien arbeitet dann haben andere Funktionen wieder nicht das aktuelle.
Kopien kosten zu dem unnötig Zeit.

Was zum experimentieren:
Code (glbasic) Select


TYPE TPlayer
Nr
Name$
x
y
Money

FUNCTION Draw:
SETPIXEL self.x,self.y,RGB(255,255,255)
ENDFUNCTION

FUNCTION Position: x,y
self.x=x
self.y=y
ENDFUNCTION

FUNCTION Update:

//<- 203 Cursors
//-> 205
//^  200
//V  208
//o   28 RETURN

LOCAL Name$=self.Name$ //for debug

IF KEY(205)
IF self.x<800 THEN self.x=self.x+1
ENDIF

ENDFUNCTION

ENDTYPE

GLOBAL Players[] AS TPlayer

ALLOWESCAPE TRUE

MainLoop()
END

FUNCTION MainLoop:

LOCAL A AS TPlayer
A.Nr=1
A.Name$="Markus"
A.Position(100,300)

LOCAL B AS TPlayer
B.Nr=2
B.Name$="Computer"
B.Position(800-100,300)

DIMPUSH Players[],A
DIMPUSH Players[],B

REPEAT

LOCAL P AS TPlayer
FOREACH P IN Players[]
P.Draw()
//IF P.Nr=1 THEN P.Update() //das geht
NEXT
FindPlayer(1,P)
P.Update() //das nicht weil das wohl eine Kopie der Struktur ist
//ReplacePlayer(1,P) //Workaround

SHOWSCREEN

UNTIL FALSE

ENDFUNCTION

// P als BYREF gibt Syntax Error
FUNCTION FindPlayer: Nr, P AS TPlayer
    FOREACH P IN Players[]
        IF P.Nr=Nr
        BREAK
        ENDIF
    NEXT
ENDFUNCTION


Kitty Hello

Keine Chance. Das Array ist ein echtes Array, keine Liste mit Pointern. Was in's Array soll, muss reinkopiert werden.
Bevor jetzt das Geheule über Geschwindigkeit losgeht, bitte erst ein konkretes Projekt machen und prüfen ob's wirklich "langsam" ist. Die GLB Arrays sind nämlich oft viel schneller als so linked-list Kram.

Markus

@Kitty Hello
Ich will doch direkt im Array arbeiten und hier mit dem Beispiel geht es ja auch.
Dieses P ist doch ein Block der im Speicher (Array) steht, den möchte ich auch bearbeiten.
Ich bekomme aber das P nicht aus einer Funktion zurück ohne das es als Kopie angelegt wird.
Wie ich das verstehe ist das P in dem Beispiel unten ein Pointer auf einen Speicherbereich wo die Struktur in echt ist oder ?
Wenn ich bei Update() mit self.xy=x einen Wert zuweise ist das wieder im Array darum gehe ich davon aus das P ein Ausschnitt vom Array ist.
LOCAL P AS TPlayer
FOREACH P IN Players[]
   P.Draw()
   IF P.Nr=1 THEN P.Update() //das geht
NEXT

Schranz0r

I <3 DGArray's :D

PC:
AMD Ryzen 7 3800X 16@4.5GHz, 16GB Corsair Vengeance LPX DDR4-3200 RAM, ASUS Dual GeForce RTX™ 3060 OC Edition 12GB GDDR6, Windows 11 Pro 64Bit, MSi Tomahawk B350 Mainboard

Quentin

Quote from: Markus on 2012-Apr-24
@Quentin
ich möchte keine kopie als Rückgabe

ja sorry, hatte ich übersehen, hattest du ja schon probiert.

Was dein "P" hier angeht:
lt. Hilfe
"Man muss "ref" nicht als LOCAL definieren. Das passiert automatisch. Jedoch ist "ref" nach dem zugehörigem "NEXT" nicht mehr gültig."

Das beantwortet wohl, warum du nach der FOREACH-Schleife nicht mehr auf dein P zugreifen kannst. Und wenn du unbedingt direkt mit dem Array arbeiten willst, ohne irgendwelche Kopieraktionen, wieso arbeitest du dann nicht mit einem Index.

Anstatt FOREACH einfache FOR-Schleife:
Code (glbasic) Select

FOR i = 0 TO LEN(Players[]) - 1
    Players[i].draw()
NEXT

// damit kannst du dann auch außerhalb der Schleife gezielt über den Index zugreifen
// und deine gezeigte FindPlayer-Funktion wäre überflüssig

Players[5].update()



Schranz0r

Quote from: Quentin on 2012-Apr-24
Und wenn du unbedingt direkt mit dem Array arbeiten willst, ohne irgendwelche Kopieraktionen, wieso arbeitest du dann nicht mit einem Index.

Richtig, mach es nach dem GLB-Way, oder nutze einfach INLINE...
Ist ja das coole an GLB das du mixen kannst :)
I <3 DGArray's :D

PC:
AMD Ryzen 7 3800X 16@4.5GHz, 16GB Corsair Vengeance LPX DDR4-3200 RAM, ASUS Dual GeForce RTX™ 3060 OC Edition 12GB GDDR6, Windows 11 Pro 64Bit, MSi Tomahawk B350 Mainboard

Markus

@Quentin
ich wollte auch nicht nach der Schleife das P noch benutzen.
Das sieht jetzt nur in dem Beispiel so aus weil ich Experimente mache.
In der Funktion das P nach Außen geben .
Ich habe aber Explizite Deklaration an,warum nacht dann das ForEach
selber was ? Aber ich sehe grad dank dir wie das ForEach gemacht ist.
Da wird tatsächlich am Anfang und Ende alles kopiert, das muß ich ja dann
wohl auch so machen :-)

@Schranz0r
ihr habt mich grad auf die Idee gebracht das Array als Byref zu übergeben :-)

@Kitty Hello
hab dank Quentin ein Beispiel gefunden was das ForEach eigentlich macht.