Benutzerdefinierte Funktionen und Prozeduren
Mit benutzerdefinierten Funktionen und Prozeduren lassen sich
Programme wesentlich besser strukturieren als mit den klassischen
BASIC-Anweisungen GOSUB und RETURN.
Benutzerdefinierte Funktionen liefern einen Wert zurück
und werden genauso aufgerufen wie die BASIC-Funktionen.
Prozeduren dagegen liefern keinen Wert zurück
und werden deshalb wie BASIC-Anweisungen behandelt.
Struktur des BASIC-Programms
Benutzerdefinierte Funktionen und Prozeduren werden nach
dem Hauptprogramm implementiert, d.h.,
die erste FUNCTION-
bzw. SUB-Anweisung
beendet das Hauptprogramm.
Ab hier dürfen außer Kommentare nur noch Implementierungen
von benutzerdefinierten Funktionen und Prozeduren folgen.
Mit dem Begriff Hauptprogramm ist der erste Teil
des BASIC-Programms gemeint, bei dem die Programmausführung beginnt.
Aufruf
Benutzerdefinierte Funktionen und Prozeduren werden anhand ihres
Namens aufgerufen.
Dieser Name darf kein reserviertes Schlüsselwort sein.
Damit der Compiler bei der Verwendung eines Funktions-
oder Prozedurnamens diesen nicht als Variable interpretiert,
muss eine benutzerdefinierte Funktion oder Prozedur bei ihrem Aufruf
dem BASIC-Compiler bereits bekannt sein.
Das ist der Fall, wenn sie weiter oben im BASIC-Programm
implementiert wurde.
Ist das nicht möglich (z.B. bei Aufruf im Hauptprogramm
oder bei Rekursion), muss die Funktion bzw. Prozedur dem Compiler
vorher mit der DECARE-Anweisung
bekanntgemacht werden.
Lokale Variablen
Eine Besonderheit von benutzerdefinierten Funktionen und Prozeduren ist,
dass sie lokale Variablen deklarieren und verwenden können
(siehe Anweisung LOCAL).
Diese Variablen werden bei jedem Aufruf der Funktion bzw. Prozedur
neu angelegt und sind nur innerhalb dieser Funktion bzw. Prozedur sichtbar.
Das gilt auch für Rekursionen, d.h., wenn sich eine Funktion
oder Prozedur selbst aufruft, hat sie in jeder Aufrufebene separate
lokale Variablen.
Allerdings muss in dem Fall der Stack-Bereich ausreichend groß
gewählt werden, da die lokalen Variablen auf dem Stack angelegt werden.
Innerhalb einer benutzerdefinierten Funktion oder Prozedur
müssen die lokalen Variablen zuerst angelegt werden,
d.h., alle LOCAL-Anweisungen
müssen unmittelbar hinter der
FUNCTION- bzw.
SUB-Anweisung folgen.
Nur Kommentare sind dazwischen noch erlaubt.
Der JKCEMU-BASIC-Compiler unterstützt keine lokalen Feldvariablen,
d.h., bei LOCAL können
nur einfache Variablen angegeben werden.
Innerhalb einer benutzerdefinierten Funktion oder Prozedur
sind sowohl die lokalen als auch die globalen,
d.h. die im Hauptprogramm verwendeten, Variablen sichtbar.
Hat allerdings eine lokale Variable den gleichen Namen wie eine globale,
wird die globale verdeckt und ist somit nicht mehr sichtbar.
Argumente
Benutzerdefinierte Funktionen und Prozeduren können
Argumente haben.
Diese werden bei der Deklaration und Implementierung hinter dem
Funktions- bzw. Prozedurnamen in Form einer in runden Klammern
und mit Komma getrennten Liste von Argumentnamen angegeben.
Aus den Argumentnamen leitet sich auch der Datentyp ab
(Integer oder String, je nachdem, ob der Argumentname
auf ein $-Zeichen endet).
Innerhalb einer Funktion bzw. Prozedur sind die Argumente
als lokale Variablen implementiert,
d.h., ihnen kann auch ein Wert zugewiesen werden.
Der einzige Unterschied zwischen diesen "Argumentvariablen"
und mit LOCAL
deklarierten Variablen besteht darin,
dass Argumentvariablen beim Aufruf der Funktion bzw. Prozedur
von "außen" initialisiert werden.
Rückgabewert
Benutzerdefinierte Funktionen liefern einen Wert zurück.
Der Typ des Rückgabewertes hängt vom Funktionsnamen ab.
Endet dieser mit einem $-Zeichen,
wird eine Zeichenkette zurückgegeben, anderenfalls ein Integer-Wert.
Der gewünschte Rückgabewert ist syntaktisch
einer Variable zuzuweisen, die den gleichen Namen hat wie die Funktion.
Mehrfache Zuweisungen sind möglich.
In dem Fall ist die letzte Zuweisung relevant.
Ein Rücklesen des zugewiesenen Rückgabewerts ist aber
in der Funktion nicht möglich.
Programmbeispiel
Das Beispiel zeigt die Programmierung einer benutzerdefinierten
Funktion mit lokalen Variablen.
Als weitere Besonderheit wird bei den DATA- und RESTORE-Anweisungen
eine Marke verwendet.
'Eingabe einer Zahl und Ausgabe als roemische Zahl
'Hauptprogramm
DECLARE FUNCTION roemische_zahl$(z)
DO
INPUT "Zahl: ";Z
IF Z>0 THEN
PRINT "Roemische Zahl: ";roemische_zahl$(Z)
ELSEIF Z=0 THEN
PRINT "Ende"
EXIT
ELSE
PRINT "Keine negative Zahl!"
ENDIF
LOOP
END
'Zuordnung Dezimalzahl zu roemischer Zahl
roem_map:
DATA 1000,"M",900,"CM",500,"D",400,"CD"
DATA 100,"C",90,"XC",50,"L",40,"XL"
DATA 10,"X",9,"IX",5,"V",4,"IV",1,"I"
'Implementierung der benutzerdefinierten Funktion
FUNCTION roemische_zahl$(z)
LOCAL n,t$,rv$
rv$=""
RESTORE roem_map
WHILE z>0
READ n,t$
WHILE z>=n
z=z-n
rv$=rv$+t$
WEND
WEND
roemische_zahl$=rv$:'Rueckgabewert zuweisen
END FUNCTION