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.