PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Arrays an Sub oder Function übergeben



darwin.nuernberg
15.01.2006, 12:50
Hallo Bascomler,

ich versuche verzweifelt nach einem Weg,
wie ich ein Zahlenarray an eine Sub oder Function übergeben kann.

(In anderen Basic Dialekten geht es so oder ähnlich, nur Bascom ist da wieder etwas anders)

Egal was ich mache, immer wieder andere Probleme.

Ist das nicht möglich oder übersehe ich da was.

Keine genaue Dokumataion in der Hilfe


Ich verwende das Bascaom 1.11.8.1


' Àrray Demo
'
'

$regfile = "m32def.dat"
Baud = 19200

Dim B_ar_werte(5) As Byte
Dim X As Byte

Declare Sub Arrayanzeigen(b_array(5) As Byte)



For X = 1 To 5 ' einfache Schleife
B_ar_werte(x) = X ' Dem Array Werte Zuweisen
Next X


Print "Von Mainroutine aus :" ' Zum Beweis dass es hier funktioniert
For X = 1 To 5 ' einfache Schleife
Print "Folgender Wert ist in B_ar_werte(";
Print X;
Print ") enthalten :";
Print B_ar_werte(x) ' Inhalt des Arrays anzeigen.
Print
Next X

Call Arrayanzeigen(b_ar_werte(5)) ' Sub aufrufen und Array übergeben




Do ' nur damit der Simulator weiter läuft
nop
Loop

End 'end program

' --------------------------------------------------------------------------

Sub Arrayanzeigen(b_array(5) As Byte)
Local Y As Byte

Print "Von Suboutine aus :"

For Y = 1 To 5 ' einfache Schleife
Print "Folgender Wert ist in B_ar_werte(";
Print Y;
Print ") enthalten :";
Print B_array(y) ' Inhalt des Arrays anzeigen.
' Beim Compilieren kommt (nur in der SUB) Numeric parameter expected ???
Print
Next Y


End Sub

' --------------------------------------------------------------------------

End

Ich habe die Sub auch schon mit BYVAL (Sub Arrayanzeigen(Byval b_array(5) As Byte)) deklariert dann geht es auch nicht.
Kann mir jemand helfen?

linux_80
15.01.2006, 13:05
Hallo,

wenn man das so schreibt:
Call Arrayanzeigen(b_ar_werte(5))

wird doch nur dieser eine Wert übergeben, Array wert Nr. 5

kann man da nicht nur den Namen angeben
Call Arrayanzeigen(b_ar_werte)
hab ich aber nicht probiert, ob das Bascom kapiert.

Evtl. geht es aber wenn man den ersten Wert des Arrays ByRef übergibt, und dann selber weiterzählt !?

tobimc
15.01.2006, 13:13
Hi!

Du hast das Array oben mit Dim als Global definiert (!= private)
Also kannst du auch in den Subs drauf zugreifen.

Wenn du es weitergeben würdest, bräuchtest du den doppelten Speicher.
(schau mal nach deinem Stack.... Frame usw...)

VLG Tobi

PicNick
15.01.2006, 14:08
@Darwin: Du kannst das auch so machen


dim tabelle[juchuu] as byte
dim addresse as word

declare sub anzeigen(addr as word)

Aufruf:
addresse = varptr (tabelle(xx))
call anzeigen(addresse)
............

sub anzeigen(addr as word)
Local Y As Byte
Local D As Byte

Print "Von Suboutine aus :"
For Y = 1 To 5 ' einfache Schleife
Print "Folgender Wert ist in B_ar_werte(";
Print Y;
Print ") enthalten :";
D = INP(addr)
Print D ' Inhalt des Arrays anzeigen.
Print
incr addr
Next Y
End Sub


Die Ecke mit VARPTR ist notwendig, weil sich Bascom aus formalen Gründen weigert.

Es ist nicht notwendig, byref hinzuschreiben, das nimmt er eh' an.

darwin.nuernberg
15.01.2006, 15:07
Dankeschöööön:

Ich hab ein bischen tüfteln müssen,
die eckigen Klammern waren falsch,
aber soweit geht es jetzt:


Dim Tabelle(5) As Byte
Dim Addresse As Word
Dim X As Byte

Declare Sub Array_anzeigen(addr As Word)


Aufruf:
Addresse = Varptr(tabelle(1))



For X = 1 To 5
Tabelle(x) = X * 11
Print "Schreibe Werte in Tabelle(";
Print X;
Print ") = ";
Print Tabelle(x)
Next X
Call Array_anzeigen(addresse)
Do
nop
Loop

End 'end program

' ............

Sub Array_anzeigen(addr As Word)
Local Y As Byte
Local D As Byte

Print "Von Suboutine aus :"
For Y = 1 To 5 ' einfache Schleife
Print "Folgender Wert ist in B_ar_werte(";
Print Y;
Print ") enthalten :";
D = INP(addr)
Print D ' Inhalt des Arrays anzeigen.
Incr Addr
Next Y
End Sub


Soweit so gut.

Ist möchte jetzt aber noch mehr.
(kaum gibt man ihm den kleinen Finger...)


Ist es möglich herauszufinden wie groß das Array dimensioniert wurde (ein- und/oder mehrdimensional) also z.B. (5) oder (2 , 5)?

Dann könnte man ohne große Probleme verschiedene Tabellen mit der gleichen Routine bearbeiten ohne Gefahr in ein "out of range" zu laufen.


Print "Dimension = " ; Tabelle(0) geht auch nicht. (eindimensional)

Dies wäre ein extra Bonbon.

PicNick
15.01.2006, 15:37
*brabbel* Eckig tut mir leid, das is eine C-Krankheit

So einen Wert wie "sizeof(aaa)" hab ich bei Bascom noch nicht finden können. aaaaber:
da du ja nicht weißt, (in der sub) welches anfangselement du als param kriegst, würde die gesamtlänge gar nix nutzen. (ich) würde einfach eine Topadresse mitschicken


declare sub func (adr as word, top as word)

dim tabelle(trallala) as byte
dim tabtop as word
tabtop = varptr(tabtop) ' das ändert sich eigentlich nie

dim tabaddr as word
tabaddr = varptr(tabelle(xx)) ' je nach aufruf
call func ( tabaddr, tabtop)
.....
sub func (adr as word, top as word)
local xx as byte
while adr < top
xx = INP(adr)
print xx
incr adr
wend

Im Grunde funzt das auch bei mehrdimensionale Tabellen, da ja meist nur eine Dimension ungewiss ist. Aber man kann immer auch
anfang = varptr(erstes Byte)
endr = varptr(letzes Byte)
übergeben.

Anm: "Out of range" kannst du nur beim kompilieren kriegen, wenn du feste Zahlen verwendest. Zur Runtime liest er auch aus dem Nirwana, wenn's darauf ankommt und du einen Fehler hast.

darwin.nuernberg
15.01.2006, 17:28
*brabbel* Eckig tut mir leid, das is eine C-Krankheit
Der Compiler hat da aber nicht gemeckert *zustimmbrabbel*




Du meinst also jedem Aray so eine Art Header mit zu speichern?

Ja das ginge schon, nur (vielleicht) wenn mal der Speicher knapp wird
(Keine Ahnung wann es soweit ist) wäre eine Solche Funktion nicht schlecht um ein paar bytes zu sparen.


PS: Ein Problem gibt es noch, habe ich aber gelöst.

Du hattest in deinem Beispiel in der Sub den Adresspointer direkt incremmentiert. Irgendwie hat sich das weitergeschlichen und eine Folgende Sub mit gleichen aber localen Variablennamen hat das mitgekriegt (Ist dann evtl. byref der Standard?).

Lieber solche Dinge explizit angeben, als dann lange suchen müssen.

Ich habe jetzt eine zusätzliche Locale Variable (Pointer) der ich dann die Basisadresse zuweise und den Index aufaddiere.

Dann braucht man byval auf jedenfall wenn man mit mehr als nur einem Parameter arbeitet. Sonst meckert der Compiler.

Warum ist das so, mit nuer einem Parameter geht's doch auch?

Für diejenigen welche es interresriert hier nochmal ein neuer Code.

'

$regfile "m32def.dat"
'
Dim Tabelle(5) As Byte
Dim W_addr As Word
Dim X As Byte

Declare Sub Array_anzeigen(wptr As Word )
Declare Sub Array_aendern(byval Wptr As Word , Byval Modifikator As Byte )




W_addr = Varptr(tabelle(1))


Print "Hauptprogramm: Schreibe Werte in Tabelle an Adresse :";
Print W_addr

For X = 1 To 5
Tabelle(x) = X * 11
Print Tabelle(x) ;
Print " ";
Next X
Print

Print
Print "Aufruf Unterprogramm mit Parameter :";
W_addr = Varptr(tabelle(1))
Print W_addr
Call Array_anzeigen(w_addr)
Call Array_aendern(w_addr , 100)
Call Array_anzeigen(w_addr)

Do
Wait 1

Loop

End 'end program

' ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----

Sub Array_anzeigen(wptr As Word )
Local Bx As Byte
Local Bd As Byte
Local Pointer As Word


Print
Print "Unterprogramm Array_anzeigen"
Print "----------------------------"

Print "Übergebende Adresse = ";
Print Wptr
Print


For Bx = 0 To 4 ' einfache Schleife
Pointer = Wptr + Bx

Print "Wert an Adresse ";
Print Pointer;
Print " enthält :";
Print Inp(pointer ) ' Inhalt des Arrays anzeigen.
Next Bx
Return
End Sub

End 'end program
' ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----

Sub Array_aendern(byval Wptr As Word , Byval Modifikator As Byte )
Local Bx As Byte
Local Bd As Byte
Local Pointer As Word


Print
Print "Unterprogramm Array_anzeigen"
Print "----------------------------"

Print "Übergebende Adresse = ";
Print Wptr
Print


For Bx = 0 To 4 ' einfache Schleife
Pointer = Wptr + Bx
Bd = Inp(pointer ) ' Inhalt des Arrays anzeigen.
Bd = Bd + Modifikator
Out Pointer , Bd
Next Bx
Return
End Sub

End 'end program
' ----

PicNick
15.01.2006, 17:46
Du sprichst da ein paar Sachen an, denen man nachgehen sollte.
byval adr.: klaro, wenn du den gleichen Parameter mehrfach verwendest, brauchst du eine kopie je sub
Ein parameter, den du mit einem Const belegst, MUSS natürlich byval sein.
sonst sollte es da keine Einschränkung geben.
Daten deskriptor: Bei Bascom ist eine besondere Flexibilität zu Runtime meist nicht notwendig, dimensions können sich ja nicht einfach ändern
Du selbst könntest gut und gerne den Tabellen Index selbst als parameter handeln, da ja die Tabelle global ist. Das wär auch mehr Bascom-style.


const tab_len = 242
dim tabelle(tab_len) as byte

call func (index )


func (byval index as byte)
while index <= tab_len
...
wend


Man muß halt immer entscheiden: elegante Sprach-Schweinerei oder nicht so elegant, aber sprachenrein.
Was red' ich, das weißt du ja