Types in Variablen, Parametern und Funktionen nutzen

Übersicht BlitzBasic FAQ und Tutorials

Neue Antwort erstellen

 

Sirrus

Betreff: Types in Variablen, Parametern und Funktionen nutzen

BeitragMi, Okt 28, 2015 6:24
Antworten mit Zitat
Benutzer-Profile anzeigen
Ein Hinweis vorweg: Ich schreibe das Tutorial auf deutsch, darum verwende ich in Texten die deutschen Worte "Funktion" und "Lokal", in Syntax-Definitionen und Programmbeispielen jedoch die englischen Keywords "Function" und "Local"

Verwendete Form bei Definitionen
{Wert} In geschweiften Klammern eingeschlossener Text darf nicht eingegeben werden. Was statt dessen verwendet werden soll, ist jeweils nach den Definitionen erklärt.
Fett Was Fett geschrieben ist, muss genau so wie es in der Definition steht, auch im Progamm verwendet werden (außer wenn es in Eckigen Klammern steht)
[] Eckige Klammern (die nicht Fett sind) bezeichnen Bereiche, die nicht unbedingt eingegeben werden müssen, aber eigegeben werden können. (Fette eckige Klammern dagegen werden für Blitzarrays gebraucht)

Einleitung:
Bei einigen Mitgliedern scheint es hier Unklarheiten zu geben, wie man Types in Variablen, Parametern und Funktionen verwendet, darum schreibe ich dazu einmal ein Tutorial. Insbesondere möchte ich dabei auf die Verwendung von Types in Funktionen eingehen, denn die eher umständliche Handhabung mit Handle/Object ist wohl in den meisten Fällen völlig überflüssig.

Zum besseren Verständnis erst einmal einige Syntax-Definitionen:
Syntax von Variablen
[{Gültigkeit}] {Variablenname}[{Datentyp}][[{Dimension}]| = {Startwert}][,{weitere Variablen}]

Syntax von Funktionsparametern
{Parametername}[{Datentyp}][[{Dimension}]|= {Vorgabewert}][,{weitere Parameter}]

Syntax von Funktions-Definitionen
Function {Funktionsname}[{Rückgabe-Datentyp}]([{Parameterliste}])
[Local] {Variablenname}[{Datentyp}][[{Dimension}]|= {Startwert}][,{weitere Variablen}]
{Programm}
End Function

Syntax von Funktions-Aufrufen
{Funktionsname}[{Rückgabe-Datentyp}][(| ][{Werte anstelle der Parameter}][)]

Erklärungen zu den Definitionen:
Zunächst einmal ist vielleicht jemandem aufgefallen, daß bei der "Syntax von Funktions-Aufrufen" die runden Klammern nicht Fett dargestellt, sondern in eckige Klammern eingeschlossen sind. Das soll nicht bedeuten, daß man bei Funktions-Aufrufen die runden Kammern immer weglassen kann, sondern man kann sie nur dann weglassen, wenn die Funktion keinen Rückgabewert gibt, oder man den Rückgabewert nicht benötigt. In dem Fall muss zwischen dem Funktionsnamen und dem ersten Parameter ein Leerzeichen anstelle der öffnenden runden Klammer stehen und die schließende runde Klammer kann weggelassen werden. Verwendet man jedoch den Rückgabewert, müssen beide runden Klammern verwendet werden. (es ist nämlich möglich, eine Variable mit dem gleichen Namen, wie dem Funktionsnamen zu erstellen, die auch noch einen abweichenden Datentyp haben kann. Ein Aufruf ohne Klammern gibt den Wert der Variablen, ein Aufruf mit Klammern jedoch den Rückgabewert der Funktion zurück)

{Gültigkeit}:
Es gibt nur zwei Gültigkeitsbereiche, die mit dem entsprechenden Keyword bestimmt werden:
Local definierte Variablen sind nur dort gültig, wo sie Definiert werden. Also im Hauptprogramm definierte lokale Variablen können nur dort, aber nicht in Funktionen genutzt werden, während in einer Funktion definierte lokale Variablen nur innerhalb der Funktion gültig sind.
Global definiere Variablen sind überall gültig, im Hauptprogramm und in allen Funktionen, jedoch können in Funktionen keine globalen Variablen definiert werden.
Wenn keine Gültigkeit angegeben wird, ist eine Variable immer Lokal, sie muss dann aber entweder als Blitzarray definiert, oder/und mit Startwert(en) initialisiert werden.

    * Namen von Funktionen und Types sind immer Global
    * Nur Variablen (und Blitzarrays) im Hauptprogramm können mit Global in Funktionen verfügbar gemacht werden
    * Funktionsparameter und Variablendefinitionen in Funktionen sind immer Lokal. Es gibt zwar die Möglichkeit, den Namen einer globalen Variable in einer Funktionsdefinition anzugeben, jedoch erstellt man dadurch nur eine lokale Variable mit dem gleichen Namen in der Funktion und kann dadurch nicht mehr aus der Funktion auf die globale Variable zugreifen. (das gleiche gilt für in der Funktion erstellte lokale Variablen)


{Startwert} / {Vorgabewert}:
Mit = werden Variablen mit einem Startwert initialisiert, bei Parametern wird jedoch ein Vorgabewert festgelegt. Das ist ein Unterschied, weil bei Variablendefinitionen der Name der Variablen immer angegeben werden muss. Bei Parametern hingegen wird in der Funktionsdefinition ein Vorgabewert vür einen optionalen Parameter bestimmt, der beim Funktionsaufruf weggelassen werden kann. In dem Fall wird beim Funktionsaufruf der Parameter mit dem Vorgabewert initialisiert. (optionale Parameter müssen jedoch am Ende einer Parameterliste stehen)

{Datentyp}:
Der Datentyp kommt in den vier Syntaxdefinitionen vor und kann auch jeweils in jeder Form verwendet werden. Dabei wird eine feste Verbindung hergestellt, die innerhalb des Gültigkeitsbereichs nicht mehr gelöst/geändert werden kann. Wenn keine explizite Definition von Variablen vorgenommen wird, werden Variablen bei ihrer ersten Verwendung definiert. (Parameter und Funktionen müssen jedoch immer definiert werden)

% = integer (Vorgabe)
Legt für eine Variable, einen Parameter oder den Rückgabetyp einer Funktion fest, daß nur ganze Zahlen verwendet werden können. (Wenn kein Datentyp angegeben wird, wird integer Festgelegt) Wenn kein Wert in der Definition bestimmt wird, beträgt der Wert 0
# = float
Legt für eine Variable, einen Parameter oder den Rückgabetyp einer Funktion fest, daß nur Fließkommazahlen verwendet werden können. Wenn kein Wert in der Definition bestimmt wird, beträgt der Wert 0.0
$ = string
Legt für eine Variable, einen Parameter oder den Rückgabetyp einer Funktion fest, daß nur Zeichenketten verwendet werden können. Wenn kein Wert in der Definition bestimmt wird, beträgt der Wert ""
.<Typename> = typezeiger
Legt für eine Variable, einen Parameter oder den Rückgabetyp einer Funktion fest, daß nur Typezeiger für den angegebenen Type verwendet werden können. Wenn kein Wert in der Definition bestimmt wird, beträgt der Wert Null

Ein Hinweis noch zum Rückgabewert von Funktionen: Es ist (soweit mir bekannt) nicht möglich in einer Funktion auf den Rückgagewert zuzugreifen, außer das man den Datentyp bestimmt und mit Return {Variablenname} einen Wert zuweist.

Einige Beispiele:
BlitzBasic: [AUSKLAPPEN]
Global A=6
Testfunction A
Print "Wert von A außerhalb der Function: "+A
WaitKey
Function Testfunction(A)
A=4
Print "Wert von A innerhalb der Function: "+A
End Function
Es wird eine globale Variable erstellt und an eine Funktion übergeben. Da aber Parameter immer lokal sind, wird in der Funktion die lokale Variable auf 4 gesetzt und mit Funktionsende gelöscht, die globale Variable wird nicht verändert. Darum sollte man für Parameter niemals die Namen von globalen Variablen verwenden.BlitzBasic: [AUSKLAPPEN]
Global A#[5]
Testfunction
WaitKey
Function Testfunction()
Local A#[3], N%
For N=0 To 5
A[N]=N
Next
End Function
Man könnte glauben, daß in der Funktion in der For-Schleife nach dem Schreiben der Blitzarray-Elemente 0-3 in das lokale Array, die Elemente 4+5 in das globale Blitzarray erfolgen, das ist jedoch nicht so. Nachdem ein lokales Blitzarray erstellt wurde, erfolgt bei Überschreitung der Arraygrenze keine Überprüfung, ob in ein globales Array geschrieben werden kann. Das Progamm bricht also bei N=4 mit der Fehlermeldung "Blitz array index out of bounds" ab.
BlitzBasic: [AUSKLAPPEN]
Global Test.Testtype[5]
Type Testtype
Field A%
End Type
Testfunction 5
WaitKey
Function Testfunction(A)
Test[A]=New Testtype
Test[A]\A=A
If A>0 Then Testfunction A-1
End Function
Erst wird ein globales Blitzarray mit Typezeigern erstellt, dann wird das Array mit einer Funktion rekursiv mit Zeigern auf neue Types gefüllt. Das funktioniert einwandfrei, man darf nur bei rekursiven Funktionen die Abbruchbedingung nicht vergessen, denn sonst läuft das Programm bis zum Speicherplatzmangel.
Auf jedes Type-Element könnte man jetzt direkt mit einem Index über das Blitzarray zugreifen.

Wenn da jemand weitere Beispiele braucht, läßt sich das noch eränzen. Es wird aber sicher noch mehr Tutorials von mir geben.

Ein sinnvolles Programm zum Abschluß:
Nach diesem Tutorial sollten eigentlich zu dem folgenden Programm keine Fragen mehr kommen. Es ist nur ein einfaches Type (das sich aber jeder nach Belieben ergänzen kann) mit einigen Funktionen, die den Zugriff auf Type-Elemente (und Felder) über einen Index ermöglicht.
BlitzBasic: [AUSKLAPPEN]
Type Testtype
Field A#
End Type
;Der Rückgabewert von Handle wird nicht benötigt,aber ein fortlaufender
;Integerwert wird für neue Elemente erst beim Aufruf von Handle erstellt.
;Beim Aufruf der Funktion braucht der Datentyp nicht angegeben werden,
;da der (globale) Funktionsname fest mit dem Datentyp verbunden ist.
Function Element_Erstellen.Testtype(Anzahl=1)
Local E.Testtype,H%
If Anzahl>0 Then E=New Testtype:H=Handle(E) Else Return Null
If Anzahl=1 Then Return E
Element_Erstellen Anzahl-1
End Function
;Solange kein "Insert" oder "Delete" verwendet wird, gibt das Handle
;des letzten Elements die Anzahl der Elemente zurück.
Function Element_Anzahl%()
Return Handle(Last Testtype)
End Function
;Da Handle nach jedem New aufgerufen wurde, sind die Handles fortlaufend
;nummeriert und man kann man mit Object über die Angabe eines Index
;direkt ein bestimmtes Element ansprechen, ohne die Liste mit Each
;durchlaufen zu müssen.
;Blitzarrays oder Dimfelder brechen das Programm mit einer Fehlermeldung ab,
;wenn ein Element ausserhalb der Dimensionen angesprochen wird. Bei dieser
;Liste erfolgt jedoch kein Programmabbruch, wenn man den Rückgabewert auf Null
;testet, bevor man auf den Inhalt zugreift.
Function Element_Auswaehlen.Testtype(Index%)
Return Object.Testtype(Index)
End Function
;Man kann jetzt Testtype um beliebige Felder erweitern und anstelle der
;Funktion "Element_Auswaehlen.Testtype" für jedes Feld zwei Funktionen
;schreiben, um den Inhalt der Felder direkt über Angabe des Index zu lesen
;oder zu schreiben. Dabei muss man aber auf den richtigen Datentyp bei den
;Definitionen der Funktionen achten. Aber das sollte nach diesem Tutorial
;kein Problem mehr sein....
Function Feld_A_Auslesen#(Index%)
Local E.Testtype
E=Object.Testtype(Index)
If E=Null Return 0.0 Else Return E\A
End Function
;Schreiben gibt den vorherigen Wert (zur Kontrolle) zurück
Function Feld_A_Schreiben#(Index%,NeuerWert#)
Local E.Testtype,AlterWert#
E=Object.Testtype(Index)
If E=Null Return 0.0
AlterWert=E\A
E\A=NeuerWert
Return AlterWert
End Function
;zu beachten ist nur noch, das Blitzarrays und Dimfelder mit Element 0 beginnen,
;diese Liste jedoch erst mit 1. Aber auch ein Zugriff auf Element 0 erzeugt keine
;Fehlermeldung, sondern gibt nur einen Default-Wert zurück. Daher kann sich jeder
;seine eigene Fehlerbehandlung schreiben.
Nachtrag: In den Funktionen "Element_Anzahl" und "Element_Auswaethlen" werden die Befehle Handle und Object verwendet. Laut Hilfe sind das undokumentierte Befehle, sollten diese Befehle wieder offiziell entfernt werden, wären Programmcodes zu allen zukünftigen Updates nicht mehr kompatibel und müssten umgeschrieben werden. Die Anwendung erfolgt daher auf eigenes Risiko. (Auf bereits compilierte Programme hat ein mögliches Entfernen von Handle und Object jedoch keinen Einfluß)

Neue Antwort erstellen


Übersicht BlitzBasic FAQ und Tutorials

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group