Arrayübergabe in Prozeduren

Anfängerfragen zum Programmieren mit PureBasic.
Raberopi
Beiträge: 3
Registriert: 10.04.2005 17:22

Arrayübergabe in Prozeduren

Beitrag von Raberopi »

Hi,
wie übergebe ich am einfachsten Arrays in Prozeduren, ohne shared bzw. global - Anweisungen bemühen zu müssen.

Beispiel :

Im Hauptprogramm habe ich die ARRAYs
a(100),b(20),c(1000)
und möchte mit Hilfe einer Prozedure statistische Maßzahlen berechnen.
z.B. arithmet. Mittel . Als Parameter will ich die Länge des Vektors und den Vektor selbst übergeben.
In Visual Basic und Powerbasic no problem, wie geht es in Purebasic. Oder sehe ich den Wald vor Bäumen nicht?
Beste Grüße
Raberopi
Benutzeravatar
Captn. Jinguji
Beiträge: 397
Registriert: 07.06.2005 19:47
Computerausstattung: PB 4.73x64, i7, WIN 10x64, ATI NVidia RTX 2070
Wohnort: Witten

Arrays an Procs übergeben

Beitrag von Captn. Jinguji »

Hi, Raberopi.

Die gute Nachricht ist: Du musst da gar nix besonderes machen.
Die "schlechte" Nachricht ist: Selbst wenn Du wolltest, KÖNNTEST Du gar keine lokalen Arrays erzeugen.

Ich zitier' mal die Hilfe:
Arrays in PureBasic sind immer global verfügbar. Dies bedeutet, dass auf sie auch aus Prozeduren heraus zugegriffen werden kann, ohne die Befehle Global oder Shared aufrufen zu müssen.

Hoffe, das hilft.
Gruss
Jinguji
Ist das Kunst hier, oder kann das weg ?
Benutzeravatar
Eric
Beiträge: 303
Registriert: 05.09.2004 09:50
Wohnort: Göttingen

Beitrag von Eric »

Du kannst ja die Adresse auf das Array übergeben.

Als Ersatz für nicht zu komplexe (eindimensionale) lokale Arrays kannst du ja mit AllocateMemory() Speicher reservieren und dann mit Peek und Poke drauf zugreifen. Darfst nur nicht vergessen, den Speicher wieder freizugeben
/:->

So zum Beispiel: (ist kein elegantes Beispiel)

Code: Alles auswählen

Procedure a(b.l)

mem=AllocateMemory(101)      ;Speicher für lokales Array reservieren

For x=0 To 100              ;Das übergebene Array in das lokale kopieren
PokeB(mem+x,PeekB(b+x))
Next

For x=0 To 100
PokeB(mem+x,PeekB(mem+x)+1)  ;alle Elemente um eins Erhöhen
Next

For x=0 To 100
PokeB(b+x,PeekB(mem+x))      ;alle Elemente in das übergebene Array zurückkopieren
Next

FreeMemory(mem)              ;lokales Array löschen

EndProcedure

Dim b.b(100)
a(@b(0))

For x=0 To 100
Debug b(x)
Next
Benutzeravatar
Froggerprogger
Badmin
Beiträge: 855
Registriert: 08.09.2004 20:02

Beitrag von Froggerprogger »

Es geht auch so:
(Ich kann den Code hier nicht testen, da hier kein Purebasic ist, aber sowas in der Art sollte funktionieren)

Code: Alles auswählen

Dim A.l(10)
Dim *myLocalArray.l(0)

Procedure DoSomething (*a.l)
  *myLocalArray() = *a
  Debug *myLocalArray(1)
  *myLocalArray(2) = 2
EndProcedure

A(1) = 1;
DoSomething(A())
Debug A(2)
[edit]Klammer nachträglich gesetzt[/edit]
Zuletzt geändert von Froggerprogger am 13.06.2005 18:53, insgesamt 1-mal geändert.
!UD2
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8809
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Beitrag von NicTheQuick »

@FroggerProgger:
So einfach geht das leider nicht. :wink:

@Raberopi:
Aber vielleicht ist das ein Ansatz, der dir gefällt:

Code: Alles auswählen

Dim A.l(10) ; Structure: LONG

Procedure DoSomething (*a)
  Debug "inProc"
  Debug PeekL(*a + SizeOf(LONG) * 0)  ;0 für Element an Position 0
  Debug PeekL(*a + SizeOf(LONG) * 1)  ;1 für Element an Position 1
  
  PokeL(*a + SizeOf(LONG) * 2, 3) ;2 für Element an Position 2
EndProcedure 

A(0) = 10
A(1) = 1
DoSomething(@A()) 
Debug "outProc"
Debug A(2) 
Benutzeravatar
remi_meier
Beiträge: 1078
Registriert: 29.08.2004 20:11
Wohnort: Schweiz

Beitrag von remi_meier »

@Nic: Stimmt, bei Froggerprogger fehlte ne Klammer... :wink:

Code: Alles auswählen

Dim A.l(10) 
Dim *myLocalArray.l(0) 

Procedure DoSomething (*a.l) 
  *myLocalArray() = *a 
  Debug *myLocalArray(1) 
  *myLocalArray(2) = 3
EndProcedure 

A(1) = 1; 
DoSomething(A()) 
Debug A(2)
Raberopi
Beiträge: 3
Registriert: 10.04.2005 17:22

Vielen Dank für die Antworten

Beitrag von Raberopi »

Ich möchte mich recht herzlich für die Antworten bedanken, obwohl ich die PEEK & POKE Methode schon kannte (Habe ich in OPL (PSION Serie 5) angewendet; irgendwie sind PureBasic und OPL verwandt). Ich dachte, ich hätte was übersehen und es ginge einfacher.
Wahrscheinlich ist es am besten - wenn die Prozedur nicht zeitkritisch ist - , man schreibt über PEEK den Array in ein Protected Array, führt die gewünschten Operationen durch und POKEd dann die Ergebnissse zurück.
Gruß
Raberopi
Benutzeravatar
Froggerprogger
Badmin
Beiträge: 855
Registriert: 08.09.2004 20:02

Beitrag von Froggerprogger »

Warum nicht direkt ? Die Methode, die ich meinte, und die remi korrigiert hat unterscheidet sich von 'echten' als Parametern übergebenen Arrays doch nur dadurch, dass eine Zeilen mehr am Anfang der Prozedur steht.
Die ganzen * sind ebenfalls nicht notwendig, falls die verwirren sollten.
So kann man innerhalb der Prozedur ganz normal auf das Array zugreifen, und alle Änderungen werden direkt auf dem orignalen Array durchgeführt.

Hier nochmal ein etwas umfangreicheres Beispiel:

Code: Alles auswählen

Dim A.l(10)
A(1) = 111
A(2) = 222
A(3) = 333
A(4) = 444

Dim localArray.l(0) ; kann temporär in Prozeduren für Arrays mit LONG-daten genutzt werden
                    ; die Größe wird dabei automatisch mit übernommen

Procedure DoSomething (array.l)
  ; setze Arrayname localArray() auf das an 'array' übergebene
  localArray() = array

  ;Ab jetzt kann mit localArray(xxx) direkt auf das übergebene Array A() zugegriffen werden
  
  Debug "Innerhalb der Prozedur"
  Debug localArray(1)
  Debug localArray(2)
  Debug localArray(3)
  Debug localArray(4)
  
  ; ... auch können Daten darin verändert werden
  
  localArray(1) = -111
  localArray(2) = -222
  localArray(3) = -333
  localArray(4) = -444
EndProcedure

DoSomething(A())

; ... was sich im Array direkt niederschlägt
Debug "Nach der Prozedur"
Debug A(1) 
Debug A(2) 
Debug A(3) 
Debug A(4) 
!UD2
Benutzeravatar
zigapeda
Beiträge: 1753
Registriert: 06.03.2005 17:22
Wohnort: Kaufbeuren
Kontaktdaten:

Beitrag von zigapeda »

was habt ihr den immer mit den localen arrays?
Ich zitire nochmal aus der PB Hilfe (hat vorhin schon mal jemand gemacht):
Arrays in PureBasic sind immer global verfügbar. Dies bedeutet, dass auf sie auch aus Prozeduren heraus zugegriffen werden kann, ohne die Befehle Global oder Shared aufrufen zu müssen.
Stimmt das nicht oder was?
kluger Mann + kluge Frau = Romanze | dummer Mann + dumme Frau = Schwangerschaft
kluger Mann + dumme Frau = Affäre | dummer Mann + kluge Frau = Shopping <)
Benutzeravatar
Froggerprogger
Badmin
Beiträge: 855
Registriert: 08.09.2004 20:02

Beitrag von Froggerprogger »

Ja, Arrays sind global.
Trotzdem wünscht man sich oftmals, dass man an Prozeduren ein beliebiges Array übergeben kann, um eine Operation darauf durchzuführen, ohne dass man zu diesem Zeitpunkt den Namen des Arrays benötigt.

Das kann man entweder umständlich durch einen Pointer auf das Array und anschließendem Peeken/Poken machen, oder aber bequemer, indem man sozusagen ein 'pseudo-lokales' Array als Hilfe nutzt.

Das in obigem Code bezeichnete 'localArray()' ist natürlich in Wahrheit ebenfalls ein globales, und wird zu Beginn mit Größe 0 initialisiert.
Innerhalb der Prozedur aber wird es auf den Anfang des an die Prozedur übergebenen Arrays gesetzt, so dass der Programmierer innerhalb der Prozedur einen bequemen Zugriff - ohne Peek/Poke - auf das übergebene Array hat. Dieselbe Prozedur könnte nun auch auf andere Arrays angewendet werden, ohne dass man die Prozedur umschreiben müßte, um sie an die anderen Arraynamen anzupassen.
!UD2
Antworten