ASICKurs: "Von Adam und Eva..."(Teil 9)
----------------------------------------
Hallihallo, da sind wir wieder. Entgegen
allen Gerüchten, die ich das letzte Mal
aufgestellt habe, ist der Basickurs
jetzt doch noch einen Teil länger. Wir
haben uns dazu entschlossen, daß es doch
besser ist, wenn dieser Kurs hier kom-
plett abgeschlossen ist, so daß es kei-
ner langwierigen Erklärungen mehr benö-
tigt, wenn wir uns ab nächten Monat an
die Grafik machen werden.
Heute kommen nun noch die ultimativ
letzten Basicbefehle an die Reihe, mit
denen sich auch noch einiges anfangen
läßt...
1.) Die Stringfunktionen :
--------------------------
Wie diese Überschrift schon verrät, bie-
tet uns BASIC V2.0 eine Fülle von Funk-
tionen, mit denen wir auf einfachste Art
und Weise Stringvariablen verändern und
manipulieren können. Was kann man darun-
ter verstehen? Nun, vielleicht ist Ih-
nen ja schon im letzten Teil aufgefal-
len, daß ich dort ein sequentielles File
mit dem Befehl :
OPEN 1,8,2,NA$+",S,W"
zum Schreiben geöffnet hatte. Vielleicht
haben Sie sich gefragt, was dieses "+"-
Zeichen bewirken soll. Nunja, wie wir
dann ja feststellten, diente es dazu,
die beiden Stringketten (zum einen der
String in NA$ und zum anderen das
",S,W") miteinander zu verknüpfen. Stün-
de beispielsweise der String "FILENAME"
in NA$, so hieße das für den OPEN-
Befehl, daß er hier die Gesamtzeichen-
kette "FILENAME,S,W" vor sich hat. Der
notwendige Appendix ist somit direkt an
den veränderbaren oder variablen Text in
NA$ angehängt worden. Genau dies ist
auch als Variablenzuweisung möglich, wie
es das folgende Programm demonstriert :
10 A$="STRINGS KOENNEN "
20 B$="MIT '+' VERKETTET "
30 C$=A$+B$+"WERDEN!"
Nach Ablauf des Programms haben wir nun
also in A$ den Text "STRINGS KOENNEN ",
in B$ den Text "MIT ↑+↑ VERKETTET " und
in C$ "STRINGS KOENNEN MIT '+' VERKET-
TET WERDEN!" stehen.
Umgekehrt, beim Zerlegen eines Strings,
verhält sich dies allerdings etwas
schwieriger. Sie können hier leider
nicht mit dem Minuszeichen ("-") arbei-
ten. Dazu haben wir allerdings die
Stringfunktionen LEFT$, RIGHT$ und MID$
zur Verfügung, die sogar noch viel bes-
ser arbeiten, als es mit "-" möglich
wäre. Mit Ihnen kann man nämlich einen
String gezielt in Stücke zerhacken, ohne
dabei großen Aufwand zu haben.
Zum einen wäre da LEFT$. Mit dieser
Funktion können wir einen Teil aus einer
Stringvariablen isolieren, der von LINKS
nach RECHTS reicht. Hierzu übergeben wir
LEFT$ ganz einfach den zu bearbeitenden
String und, durch ein Komma voneinander
getrennt, die Anzahl der zu übernehmen-
den Buchstaben an. Dies geschieht etwa
folgendermaßen :
A$="BASIC IST TOLL"
PRINT LEFT$(A$,5)
Nach dieser Befehlssequenz sollten Sie
dann nur die 5 Buchstaben "BASIC" auf
dem Bildschirm stehen haben. Es wurden
also die ersten 5 Buchstaben aus dem
String A$ herausisoliert.
Ebenso verhält es sich nun mit RIGHT$,
nur daß nun die Buchstaben von RECHTS
nach LINKS isoliert werden, wobei sie
ihre Reihenfolge jedoch beibehalten,
nicht also rückwärts geschrieben sind !
Hier ein Beispiel :
A$="BASIC IST TOLL"
PRINT RIGHT$(A$,4)"
Nun erhalten Sie also die 4 letzten
Buchtaben des Strings A$, den Text
"TOLL".
Wem das noch nicht genügt, der kann auf
MID$ zurückgreifen. MID$ stellt quasi
eine Mischung aus LEFT$ (von "Links")
und RIGHT$ (von "Rechts") dar. Sie kön-
nen hiermit, wie der Befehl schon sagt,
eine Zeichenkette "aus der Mitte" eines
Strings herausisolieren. Hierbei müssen
wir, wie bei den beiden Verwandten von
MID$ auch, erst einmal den zu Untersu-
chenden Stringnamen angeben, gefolgt von
der Nummer des Buchstabens, von dem an
wir die folgenden Buchstaben übernehmen
möchten, und der Anzahl der Buchstaben,
die übernommen werden sollen; alle Para-
meter jeweils durch Kommata getrennt.
Den Text "IST" aus unserem Beispiel-
string "BASIC IST TOLL" können wir also
folgendermaßen isolieren :
A$="BASIC IST TOLL"
PRINT MID$(A$,7,3)
Hier werden also ab dem 7. Buchstaben
des Strings A$, 3 Buchstaben herausiso-
liert: das Wort "IST".
Jetzt werden Sie sicher sagen, "Na schön
und gut, doch wofür kann man denn so
etwas brauchen ?" Zugegeben, viele An-
wendungen finden die Stringfunktionen
vielleicht nicht, doch kann ich Ihnen
ein höchst wichtiges Problem aufzeigen,
das geradezu "wie geschaffen" für unser
Thema ist : die Eingaberoutine eines
Textadvetures zum Beispiel.
Wenn Sie diese Art von Spielen kennen,
so werden Sie sicher wissen, daß die
Eingaben an das Programm meist mit Hilfe
einer Kommandozeile abgewickelt werden,
über die die einzelnen Befehle an das
Programm gehen. Sie wissen sicher auch,
daß solche Befehle in aller Regel aus
Verben und Objekten bestehen, wie zum
Beispiel "NIMM BUCH". Hier haben wir
also ein Verb, das angibt WAS getan wer-
den soll und ein Objekt MIT DEM wir et-
was tun wollen. Nun gilt es also diesen
Kommandostring in seine einzelnen Unter-
worte aufzusplitten, damit wir keine
Probleme bei der Erkennung der Worte
bekommen. Wir müssen also in unserem
String nach Leerzeichen suchen, die die
Worte ja voneinander trennen, und bis zu
dieser Stelle ein Wort isolieren. Damit
unser Beispiel nicht komplizierter wird,
als es in diesem Rahmen sein soll, set-
zen wir einmal vorraus, daß nur 2 Worte
in der Eingabe vorkommen, daß also der
Anfang eines Strings, bis zum Leerzei-
chen, ein Wort bildet, und alles, was
danach folgt, ein weiteres. Erschwerend
kommt noch hinzu, daß wir ja nicht wis-
sen WIE LANG der gesamte Eingabestring
ist. Doch dieses Problem können wir mit
Hilfe einer weiteren Stringfunktion lö-
sen, der LEN-Funktion. Diese funktio-
niert denkbar einfach, wir müssen näm-
lich lediglich den Namen des zu untersu-
chenden Strings, in Klammern gesetzt,
nach dem Befehlswort LEN angeben. Etwa
so:
10 A$="OEFFNE TRUHE"
20 A=LEN(A$)
Danach steht in A der Wert 12, denn so-
viele Buchstaben enthält die Variable
A$. Nun können wir uns um die Analyse
des Strings kümmern. Zunächst einmal
eine Schleife, mit deren Hilfe wir fest-
stellen wollen, an welcher Stelle in
unserem String sich das Leerzeichen be-
findet. Hierzu bedienen wir uns dann
MID$. Er holt sich jeweils nur EINEN
Buchstaben aus unserem String, damit wir
prüfen können welches Zeichen wir vor
uns haben :
30 FOR I=1 TO A
40 X$=MID$(A$,I,1) :REM NUR EIN ZEICHEN
50 IF X$<>" "THEN NEXT
Die Schleife holt sich hier also nur
solange Zeichen aus dem String, wie die-
se ungleich dem Leerzeichen (" ") sind.
Ist dies nicht mehr der Fall, so sind
wir an dem Punkt angelangt, wo die Worte
getrennt werden. In der Laufvariable I
ist nun die Stelle des Leerzeichens in
unserem String gespeichert. Wir brauchen
uns die einzelnen Komponenten nur noch
mit Hilfe von LEFT$ und RIGHT$ in eige-
nen Variablen zuweisen. Hierbei ist noch
zu beachten, daß wir beim ersten Wort
auch das Leerzeichen am Ende mitbekommen
würden, würden wir I so benutzen. Da
dies jedoch nur behindernd ist brauchen
wir also lediglich alle Buchstaben bis
I-1 herauszuisolieren. Bei dem zweiten
Wort müssen wir dann auch erst noch be-
rechnen, wieviele Stellen wir von Rechts
gebrauchen können, das tun wir mit Hilfe
der Formel A-I. Das ganze sieht dann
folgendermaßen aus :
60 W1$=LEFT$(A$,I-1)
70 W2$=RIGHT$(A$,A-I)
80 PRINT"DAS ERSTE WORT IST : ";W1$
90 PRINT"DAS ZWEITE WORT IST : ";W2$
Wir haben also nun ein kleines Anwen-
dungsbeispiel für die bisherigen String-
funktionen durchgeführt. Nebenbei haben
wir da dann auch noch LEN kennenge-
lernt. BASIC kennt aber noch 4 weitere
Stringfunktionen. Zwei davon kennen wir
bereits, CHR$ und ASC, weshalb ich nicht
mehr auf diese eingehen werde, doch es
gibt noch zwei weitere.
Zum einen wäre da STR$. STR$ liefert
ganz einfach den String einer numeri-
schen Variablen, so wie sie mit PRINT
ausgedruckt worden wäre. So können Sie
zum Beispiel auf einfache Art und Weise
eine INTEGER- oder FLOAT-Variable einer
Stringvariablen zuweisen, wobei der
String dann halt die ASCII-Werte der
einzelnen Ziffern enthält. Zum Rechnen
können Sie diesen String natürlich nicht
mehr verwenden, jedoch kann diese Funk-
tion manchmal ganz von nutzen sein. Hier
einmal ein Beispiel :
A=1989
X$=STR$(A):REM IDENTISCH MIT 'X$="1989"'
Hiermit hätten wir also der Stringvaria-
blen X$ den String "1989" zugewiesen und
können diesen nun weiterverarbeiten.
Beispielsweise gibt es da eine Formel
zur Berechnung des Wochentages anhand
des reinen Datums die mit Parametern wie
"Jahrhundert" oder "Jahrzehnt" arbeitet.
Hierzu bietet es sich dann an mit LEFT$
und RIGHT$ eben jene Parameter zu iso-
lieren und mit der nun folgenden String-
funktion wieder in eine Zahl zurückzu-
wandeln.
Die Funktion von der ich rede heißt VAL
und tut genau das umgekehrte wie STR$.
Angenommen, wir hätten das Jahrhundert
aus "1989" mittlerweile herausisoliert
und fein säuberlich in der Variablen JH$
gespeichert. Dann könnten wir den String
"19" mit folgendem Befehl ganz einfach
zur Zahl 19 machen:
JH=VAL(JH$)
Das wars schon. Sie können nun wie ge-
wohnt mit JH rechnen, denn dort haben
wir nun tatsächlich den numerischen Wert
19 stehen, und nicht etwa die Zeichen-
kette "19".
Soviel zum Thema Stringfunktionen, ma-
chen wir nun weiter mit den ominösen
Befehlen, die eigentlich erst im Grafik-
kurs gekommen wären, ich werde Sie Ihnen
hier jedoch anhand eines anderen Bei-
spiels erläutern:
2.) Datenhandling im Programm :
-------------------------------
Bestimmt haben Sie schon einmal ein Ba-
sicprogramm aus einer Zeitschrift abge-
tippt, die NICHT über den Vorteil der
Magic Disk 64 verfügte, daß die Program-
me zum Heft alle auf einer Diskette mit-
geliefert werden. Dabei mußten Sie mit
ziemlicher Sicherheit (denn dies kommt
häufig vor) auch lange Kolonnen von Zei-
len abtippen, in denen am Anfang das
Befehlswort DATA stand, gefolgt von vie-
len Zahlen, alle durch Kommata voneinan-
der getrennt. Wie dieser Befehl schon
sagt, werden hier DAT(A)enwerte abge-
legt. Auf ein Programm selbst hat er
eigentlich wenig Einfluß - er wird ganz
einfach von BASIC überlesen. Nur in Zu-
sammenhang mit einem weiteren Basicbe-
fehl hat DATA überhaupt einen Sinn, ich
spreche von dem READ-Befehl. Im übrigen
könnte dieser ohne DATA auch wenig an-
richten, die beiden hängen also fest
zusammen und voneinander ab. READ ist
(wie immer) englisch und heißt "LESE".
Wir können den Computer also hiermit
anweisen ein Datenelement zu LESEN - und
woher nimmt er sich dieses Datenele-
ment? Natürlich von einem DATA-
Statement! READ liest nun also das er-
ste Datenelement hinter der ersten DATA-
Anweisung im Programm in eine Variable
ein, die wir ihm schlicht und einfach
nachstellen.
Ich gebe zu, daß es langsam vielleicht
etwas langweilig erscheint immer wieder
das Beispiel eines Textadventures durch-
zukauen, doch paßt dieses Beispiel hier
genau hin und erklärt hoffentlich ein-
deutig, wozu READ und DATA notwendig
sind.
Also angenommen, Sie wollten ein Textad-
venture schreiben, das mehrere Verben
und mehrere Objekte (wie das ja, schon
oben beschrieben, zu JEDEM Textadventure
gehört) verstehen soll. Zuerst haben wir
einmal die Eingabe vom Spieler in seine
Einzelteile zerlegt und in W1$ das Verb
und in W2$ das Objekt gespeichert. Nun
geht es darum zuerst einmal das eingege-
bene Verb zu analysieren und mit dem
Programmwortschatz zu vergleichen. Hier-
zu benutzen wir ein Variablenfeld (Sie
erinnern sich an das letzte Mal...) in
dem alle Verben gespeichert werden sol-
len. Damit das bei einem Programm, das
vielleicht 100 Verben verstehen soll
nicht in Arbeit ausartet, wollen wir die
einzelnen Verbdaten mit Hilfe einer
Schleife den Variablen zuordnen. Hierzu
legen wir alle Verben in DATA-Zeilen ab
und lesen sie, eins nach dem anderen,
ein und weisen sie somit einer Variablen
in unserem Feld zu. READ liest also im-
mer das nächste Element aus einem DATA-
Statement aus, solange bis es nichts
mehr zu lesen gibt. Das sollten Sie wis-
sen, damit READ nicht zuviele Daten ein-
zulesen versucht. Hier einmal ein Bei-
spiel, bei dem ich 7 Verben in dem Va-
riablenfeld VE$(X) speichern möchte. Wie
die Schleife schon zeigt, werden hier
auch nur 7 Datenelemente gelesen, (6
Elemente plus das 0. Element).
10 DIM VE$(6)
20 FOR I=0 TO 6:READ VE$(I):NEXT
30 DATA NIMM,GIB,OEFFNE,SCHLIESSE,SCHLAG
E,DRUECKE,RUFE
Somit hätten wir uns also das mühsehlige
Auflisten von Variablenzuweisungen ge-
spart. Sie müssen doch zugeben, daß fol-
gendes etwas umständlicher wäre :
10 VE$(0)="NIMM"
20 VE$(1)="GIB"
30 VE$(2)="OEFFNE"
40 VE$(3)="SCHLIESSE"
und so fort...
Doch nicht genug, in DATA-Statements
kann man nicht nur Strings ablegen, son-
dern auch INTEGER- oder FLOAT-Werte und
das dann noch bunt gemischt:
100 DATA 100,3.14,HALLO,2.689,BASIC,12
Alles worauf wir dann beim Lesen achten
müssen, ist, daß die einzelnen Elemente
auch den entsprchenden Variablentypen
zugeordnet werden. Es ist Ihnen ja mit
Sicherheit klar, daß wir nicht einfach
so einen Text einer INTEGER-Variablen
zuweisen können oder ähnliches.
Allerdings gibt es noch zwei Besonder-
heiten, die man in Zusammenhang mit DATA
erwähnen muß. Sie werden nämlich ganz
schöne Probleme bekommen, sollten Sie
einmal versuchen, ein Komma (",") in Ih-
ren Strings zu verwenden, die bei DATA
abgelegt sind. Wie wir wissen dient das
Komma ja zur Trennung der einzelnen Ele-
mente, was für den Computer heißt, daß
wir ihm da zwei einzelne Elemente, an-
statt nur einem gegeben haben. Machen
Sie also niemals folgenden Fehler:
100 DATA HALLO,IHR!
Hier haben wir nämlich die beiden
Strings "HALLO" und "IHR" abgelegt, ans-
tatt dem eigentlich gewollten Text "HAL-
LO,IHR!" In diesem Fall müssen wir den
abzulegenden String dann ganz einfach in
Anführungszeichen setzen, damit er rich-
tig erkannt wird, also :
100 DATA "HALLO,IHR!"
Und schon bekommen wir auch das, was wir
wollen. Es bleibt noch zu erwähnen, daß
dies derselbe Fall bei dem Doppelpunkt
(":") und bei Leerzeichen (" ") der Fall
ist. Sollten Sie also einmal in einem
Stringelement ein Komma, einen Doppel-
punkt oder ein Leerzeichen enthalten
haben, so müssen Sie dieses Element UN-
BEDINGT in Gänsefüßchen setzen. Bei
Strings, wo dies nicht zutrifft können
Sie sie auch weglassen (müssen aber
nicht).
Das zweite, was noch zu sagen wäre, ist,
daß man manche Datenelemente auch abkür-
zen kann. Das spart zum einen Speicher-
platz und zum anderen läuft das Programm
dann später auch schneller ab. Wenn man
nach einem Komma, das ja zur Trennung
der einzelnen Datenelemente dient, ein
weiteres Komma nachstellt, also prak-
tisch KEIN Datenelement angibt, so in-
terpretiert unser 64er diesen Datensatz
als den Wert 0. Hier ein kleines Bei-
spiel:
100 DATA 200,,,10,,,
Diese Zeile entspicht haargenau dem fol-
genden Ausdruck und bewirkt auch genau
dasselbe:
100 DATA 200,0,0,10,0,0,0
Der Unterschied ist, daß wir weniger
Tipparbeit hatten und somit Speicher-
platz gespart haben, UND daß die erste
DATA-Zeile auch noch schneller abgear-
beitet werden kann - mit einem Wort, nur
Vorteile.
Als Nächstes sollte ich vielleicht noch
erwähnen, daß READ grundsätzlich immer
das ERSTE Datenelement aus dem ERSTEN
DATA-Statement zuerst liest. Es ist da-
bei egal, WO sie Ihre DATAs im Programm
unterbringen, READ liest rigoros alles
durch, solange bis es keine Daten mehr
finden kann. Hierauf sollten Sie immer
achten, denn sonst kann es zu einem "OUT
OF DATA ERROR" kommen. Sie sollten auch
wissen, daß READ sich quasi "merkt" bis
zu welchem Datenelement es schon gelesen
hat. Dieser Merkspeicher ändert sich
solange nicht, bis Sie das Programm wie-
der mit RUN starten. Es wird hierbei
also der Merkspeicher wieder auf das
allererste Datenelement zurückgesetzt,
so daß Sie die Daten wieder von vorne
lesen können.
Für diese Funktion gibt es übrigens so-
gar einen eigenen BASIC-Befehl. Er heißt
RESTORE, was soviel heißt wie "zurück-
setzen". Er tut haargenau dasselbe was
auch unter anderem bei RUN passiert
(nämlich das Zurücksetzen des DATA-
Merkspeichers), nur daß Sie ihn mitten
im Programm aufrufen können, ohne hier-
bei das Ganze von vorne starten zu müs-
sen. RESTORE braucht übrigens keine Pa-
rameter.