![]() |
![]() |
In diesem Kapitel lernen wir, dass der Computer noch mit anderem umgehen kann als mit Zahlen. Schauen Sie sich mal folgendes Programm an:
10 LET HALLO=1 20 PRINT HALLO 30 PRINT "HALLO"
Lassen Sie es laufen. Die Ausgabe ist:
RUN 1 HALLO READY
Verstehen Sie, was da passiert? Bin Zeile 20 gibt das Programm den Inhalt der Variablen HALLO aus. Aber in Zeile 30 gibt das Programm gar keine Zahl aus. Es gibt einfach das Wort HALLO aus! Was ist denn da passiert?
Nun, der PRINT-Befehl kann nicht nur Gerechnetes und Speicherinhalte ausdrucken, er kann auch Zeichenketten ausdrucken. Texte zum Beispiel. Der Unterschied besteht in den Gänsefüsschen. Wird eine Zeichenkette im Programm von Gänsefüsschen eingeschlossen, wird sie als Zeichenkette und nicht als Variablenname interpretiert.
Und wozu soll das gut sein? Zunächst kann es ganz nützlich sein, die Zahlen, die man auf dem Bildschirm ausgibt, zu kommentieren. Hier eine verbesserte Variante des Mondlande-Programms:
1 PRINT "-----------------------------" 2 PRINT "MONDLANDUNG" 3 PRINT "-----------------------------" 10 LET TS=40 20 LET V0=30 30 LET G0=500 40 LET S0=200 50 LET R=100 60 LET VMAX=2 90 PRINT "HOEHE:" 91 PRINT S0 100 PRINT "GESCHWINDIGKEIT:" 101 PRINT V0 110 PRINT "TREIBSTOFF:" 111 PRINT TS 120 PRINT "WIEVIEL TREIBSTOFF ZUGEBEN?" 125 INPUT TR 130 IF TR>TS THEN TR=TS 140 LET TS=TS-TR 150 LET GM=G0^2/((R+S0)^2) 160 LET V0=V0-TR*3+GM 170 LET S0=S0-.5*GM-V0 180 IF S0>0 THEN GOTO 90 190 IF V>VMAX THEN GOTO 220 200 PRINT "SIE HABEN GEWONNEN!" 210 GOTO 230 220 PRINT "DIE FAEHRE IST ZERSCHELLT! OH JEH!" 230 PRINT "NOCHMAL? (1)" 240 INPUT A 250 IF A=1 THEN GOTO 10 260 END
10 PRINT "BEISPIEL FUER KOMMA-" 20 PRINT "TRENNUNG" 30 PRINT "A","B","C" 40 PRINT "BEISPIEL FUER SEMIKOLON-" 50 PRINT "TRENNUNG" 60 PRINT "A";"B";C" RUN A B C ABC READY
Das Komma sorgt für einen Tabulatoreffekt: Der nächste Ausdruck wird 8 Spalten weiter ausgegeben. Beim Semikolon wird der nächste Ausdruck unmittelbar hinter den vorhergehenden gehängt.
Eine PRINT-Zeile kann auch mit einem Komma oder einem Semikolon abgeschlossen werden:
10 PRINT "EINKOMMEN1"; 20 INPUT A RUN EINKOMMEN1?30000 READY
Der Effekt ist, dass der Cursor für das nächste PRINT oder INPUT direkt an die Ausgabe anschliesst. Auf diese Weise können Sie Ihren PC zu einer bmbastischen Jubelhymne auf Sie anstimmen lassen:
10 PRINT "NAME IST DER GROESSTE! _ _ _"; 20 GOTO 10
Die "_"-Zeichen stehen für ein Leerzeichen. Und statt NAME schreiben Sie natürlich Ihren Namen rein. Und das Semikolon am Ende von Zeile 10 dürfen Sie auf keinen Fall vergessen!
Auch der INPUT-Befehl kennt noch ein kleines Schmankerl. Statt INPUT A kann man auch INPUT "Text";A schreiben. Das ist eine Zusammenfassung von PRINT "Text"; und dann INPUT A: Es wird erst ein Text ausgegeben und dahinter kommt das ?, wo die Zahl eingegeben wird. Diese Form ist sehr nützlich, da man fast immer dem Nutzer vorher sagen möchte, welche Art Zahl er jetzt eingeben soll.
Stringvariablen können natürlich nicht mit Rechenoperationen verknüpft werden wie Zahlvariablen. Plus, Minus, Mal oder Geteilt hätten hier keinen Sinn. Trotzdem hat das + eine Bedeutung. Dazu ein Beispiel:
10 LET A$="123" 20 LET B$="456" 30 LET C$=A$+B$ 40 PRINT C$ RUN 123456 READY
+ verknüpft die beiden Strings also im wörtlichen Sinne: Er hängt sie aneinander.
Übungsaufgabe: Schreiben Sie ein Programm, das folgenden Bildschirmausdruck erzeugt:
***** * * * * * * * * * * * * *****
Sie sehen, dass Sie auf diese Weise mit dem C16 sogar sehr einfache Dinge malen können. Die erste Grafik!
10 LET A$="ABCD" 20 PRINT LEN(A$) RUN 4 READY
Die 4 sagt: Der String A$ ist vier Zeichen lang.
Dann wäre da LEFT$() und RIGHT$(). LEFT$(A$,3) gibt die linken 3 Zeichen von A$ aus, im Beispiel A$="ABCD" wäre LEFT$(A$,3)="ABC". Bei RIGHT$(A$,3)="BCD" sind's die rechten 3 Zeichen. Und MID$() greift sich schliesslich aus der Mitte einen Unterstring heraus: MID$(A$,Position,Länge) ist die genaue Syntax und das sieht dann am Beispiel so aus: MID$(A$,2,2)="BC", MID$(A$,2,1)="B", MID$(A$,3,2)="CD".
Intern sind Strings und Zahlvariablen gar nicht so weit auseinander, wie Sie vielleicht meinen. Es zeigt sich doch, dass ich am Anfang recht gehabt hatte: Im Grunde ist ein Computer eine Rechenmaschine und kann nur mit Zahlen umgehen. Tatsächlich speichert der Computer Strings als eine Kette von Zahlen. Jede Zahl ist dabei eine Nummer. Und da jedes Zeichen des Computers eine solche Nummer trägt, kann dann jeder Nummer ein Zeichen zugeordnet werden. Doch welche Nummer gehört zu den verschiedenen Zeichen? Mit Hilfe der ASC()-Funktion ist das leicht herauszufinden:
10 INPUT "ZEICHEN";A$ 20 LET A$=MID$(A$,1,1) 30 PRINT ASC(A$) 40 GOTO 10
Dieses kleine Programm printet Ihnen den Zeichencode für jedes eingegebene Zeichen. Sicherheitshalber sorgt Zeile 20 dafür, dass wirklich nur ein Zeichen in A$ steht, d.h. LEN(A$)=1 ist, sonst macht Zeile 30 nicht viel Sinn.
Die Umkehrfunktion zu ASC() ist CHR$(). Damit geht's noch übersichtlicher. Argument von CHR$ ist der Zeichencode und CHR$ ergibt das entsprechende Zeichen.
10 PRINT "NR","ZEICHEN" 20 I=0 30 PRINT I,CHR$(I) 40 LET I=I+1 50 IF (I<256) THEN GOTO 30
Dieses Progrämmchen druckt Ihnen eine ganze Tabelle mit allen Zeichencodes auf den Bildschirm. Warum nur von 0 bis 255? Weil es nicht mehr Zeichencodes gibt. Nicht beim C16 und (standardmässig) nicht mehr beim PC. Warum, das wird Ihnen im Kapitel "Bits und Bytes" erklärt. Hier sei nur erwähnt: Die Zeichenkodierung könnte theoretisch bei jedem Computertyp anders sein. Aber das wäre sehr unpraktisch. Vor allem wäre so kaum Kommunikation möglich. Daher hat man sich schon sehr früh in der Computergeschichte darauf geeinigt, einen bestimmten Vorrat an Zeichen einheitlich zu kodieren, nämlich den Bereich 32 bis 127. Das ist die s.g. ASCII-Kodierung. Die Tabelle, die das Progrämmchen ausdruckt, zeigt also in diesem Bereich die ASCII-Tabelle. Oberhalb von 127 sind meist die ganzen länderspezifischen Sonderzeichen, die bis heute keine vereinheitlichte Kodierung besitzen. Weswegen man bis vor kurzem tunlichst keine deutschen Umlaute in Emails nutzen sollte, weil sonst beim Empfänger anstelle der Umlaute nur komische Sonderzeichen zu sehen waren. Und weswegen man in Web-Adressen und Emailadressen keine deutschen Umlaute benutzen darf, auch heute noch nicht.
Seit ein paar Jahren beginnt sich eine andere Kodierung langsam zu verbreiten: UNICODE. Hier hat man mehr als 65000 verschiedene Codes. Damit kann man alle Zeichen aller Sprachen der Welt, selbst japanisch und chinesisch locker einheitlich vercoden. Webbrowser arbeiten tw. schon mit UNICODE, während Email weiterhin auf ASCII beruht.
Am oberen Progrämmchen sehen wir noch was: Warum haben wir in Zeile 20 die Variable I verwendet? Und nicht A, B, C ...? Nun, in der Mathematik ist es üblich, für Zählvariablen, s.g. Indizes, die Buchstaben i,j,k und l herzunehmen. Und das hat die Informatik übernommen. Daher hat man es sich angewöhnt, Zählervariablen mit I,J,K usw. zu benennen. Das ist für die Lesbarkeit des Programms sehr gut: Man erkennt am Namen sofort, dass es sich um einen Zähler handelt.
Nehmen wir an, Ihr Programm soll vom Benutzer eine Eingabe entgegennehmen. Dabei soll es ihm ermöglicht werden, entweder eine Zahl oder den Buchstaben Q (für "Quit") einzugeben. Wie machen wir das? Wir müssen uns doch entscheiden, ob wir den Benutzer eine Zahl oder einen String eingeben lassen. Oder? Nicht unbedingt. Wir können auch das eine zum andern machen. Casting nennt sich das in der Informatik. Wenn man Variablen oder Werte unterschiedlichen Typs ineinander umwandelt. Bei A=VAL(A$) versucht der Computer, A$ als Zahl zu interpretieren. Wenn A$="2.3", dann besitzt nachher A den Wert 2.3. Wenn A$="X3X", dann ergibt VAL(A$) keinen Sinn. In diesem Fall wird einfach eine Null zurückgegeben. Also Vorsicht beim Ergebnis Null! Dieser Fall muss im Programm immer überprüft werden.
Übungsaufgabe: Schreiben Sie ein Programm, das einen String darauf untersucht, ob es sich um eine Zahl handelt!
STR$ macht genau das Umgekehrte: Es wandelt eine Zahl in einen String um. Das geht natürlich immer. Wozu braucht man das? Nun, ein Beispiel: Für Tabellen o.ä. kann es nützlich sein, die Zahl rechtsbündig an einer Stelle des Bildschirms auszugeben. Das kann der C16 aber nicht von sich aus. Aber man kann es programmieren.
Übungsaufgabe: Schreiben Sie ein kleines Programm zur Honorarabrechnung. Es nimmt die Zahl der Stunden entgegen, multipliziert sie mit dem (im Programm fest gespeicherten) Stundensatz, gibt Stundenzahl und Nettohonorar aus, dann die MWSt (auf der Basis von 16%) und schliesslich das Brutto-Honorar. Soweit nicht schwer. Aber nun der Kick: Alle Ausgaben bitte rechtsbündig! Da werden Sie die STR$() bemühen müssen!
Eine gute Übung ist es, schon bekannte einfache Spiele nachzuprogrammieren. Die "Mondlandung" war unser erstes Beispiel. Hier kommt das nächste. Für die meisten Spiele fehlt uns aber noch eine für Spiele eminent wichtige Funktion:
Diese werden mit der Funktion RND() generiert. Es ist immer eine Zahl größer gleich null und kleiner 1. RND() braucht auch ein Argument (einen Übergabewert, den man zwischen die Klammer schreibt.). Der ist allerdings in diesem Fall sehr technischer Natur und soll hier erstmal nicht weiter erklärt werden. Mit RND(1) fahren Sie immer richtig. Das folgende Progrämmchen generiert 10 Zufallszahlen zwischen 0 und 1 und dann 10 Ganzzahlen zwischen 1 und 6, simuliert also in seinem zweiten Teil einen Würfel.
5 PRINT "REINE ZUFALLSZAHLEN" 10 LET I=0 20 PRINT I,RND(1) 30 LET I=I+1 40 IF I<10 GOTO 20 50 PRINT "WUERFELZAHLEN" 60 LET I=0 70 PRINT I,RND(1)*6+1 80 LET I=I+1 90 IF I<10 GOTO 20
Für das Testen von Programmen ist es unverzichtbar, dass die Reihenfolge der Zufallszahlen nachvollziehbar bleibt. Das heisst, wenn man das Programm zum zweiten Mal startet, kommt die gleiche Sequenz von Zahlen. Um das zu erreichen, ist es beim C16 notwendig, die RND-Funktion am Anfang einmal mit einem negativen Wert aufzurufen. Wenn Sie also die Zeile
7 LET A=RND(-1)
einschieben, dann kommt immer die gleiche Zahlenfolge.
Mastermind ist ein Spiel, bei dem ein Spieler 6 farbige Stecker so in einer Reihe anordnet, dass es der andere nicht sieht. Der andere muss nun durch Kombinatorik herausbekommen, welche Steckerkombination gewählt wurde. Anfangs wählt er eine zufällige Kombination. Der erste Spieler bewertet dann diese Kombination. Er sagt, wieviel Stecker die richtige Farbe haben und wieviel Stecker die richtige Position haben. Aber er sagt nicht, welche Stecker dies sind. Dies bleibt dann der Kombinationsgabe des aktiven Spielers überlassen.
Den Schwierigkeitsgrad von Mastermind kann man variieren: Je grösser die Anzahl der zu erratenden Stecker und je grösser die Farbauswahl, desto schwieriger.
Dieses Spiel wollen wir nun programmieren. Den passiven Part des ersten Spielers übernimmt der Computer. Es sieht schwerer aus, als es ist.
Zunächst müssen wir uns überlegen, wie das ganze für den Spieler aussehen muss. Die erste Frage ist: Was sind Stecker und was sind Farben? Nun, diese Rolle sollen Zeichen übernehmen. Nehmen wir z.B. die Buchstaben A bis F, dann sind 6 Farben im Spiel. Und die Steckeranordnung ist ein String. Hat die Anordnung 4 Stecker, ist der String eben 4 Zeichen lang. Gesucht wird also z.B. der String "AABF". Der ist aber für den Spieler unsichtbar. Der Benutzer wird nun aufgefordert, selbst einen String einzugeben. Z.B. gibt er dann "FAEF" ein. Und nun muss der C16 beurteilen, wieviel Buchstaben überhaupt richtig sind und wieviel an der richtigen Position sitzen. Im Beispiel müsste er ausgeben: 3 Buchstaben sind richtig (A und zweimal F) und zwei sitzen an der richtigen Position (2. und 4. Buchstabe). Und dann hat der Benutzer den nächsten Versuch.
Die Aufgabe gliedert sich also in
Bei der Prüfung müssen Sie eifrig von MID$() Gebrauch machen. Und bei der Stringbildung müssen Sie zunächst zufällige Zeichencodes in einem bestimmten Bereich (schauen Sie in der ASCII-Tabelle nach!) mit der RND()-Funktion bilden und diese dann mittels CHR$() in die Zeichen umwandeln. So, und jetzt genug der Tipps. Jetzt sind Sie dran!