11.07.93 11.07.93 ================================================================================ Basic-Corner: Vergessen Sie Ihre Algebra! Lassen Sie sich nicht von dem Mißverständnis irreführen, man benötige umfangreiche mathematische Kenntnisse, um einen Computer zu programmieren. Manchmal stellt es sich sogar als hinderlich heraus, wenn man sich zu viel mit Mathematik beschäftigt hat. von Nikolaus M. Heusler Dieser Artikel wendet sich an alle, die bisher Probleme mit der Art hatten, wie der Computer Zahlen auffaßt, mit ihnen rechnet, sie verändert. Welche Unterschiede gibt es zwischen Konstanten, Variablen, Zuweisungen? Wir vermitteln Ihnen leicht verständlich grundlegende Kenntnisse der Computer-Algebra, die sich manchmal in der Tat wesentlich von der Naturwissenschaft unterscheidet. Hier finden Sie auch Erklärungen, wie genau Variablen in der Anwendung funktionieren - ein Kapitel, das offenbar gerade Einsteigern oft Probleme bereitet. Zum Beispiel wird in Basic der folgende Befehl einwandfrei akzeptiert und ausgeführt, obwohl er streng mathematisch gesehen reiner Unsinn ist: X = X+1 oder Z = Z+1 Mit einer solchen Formel würde sich ein Schüler vermutlich eine Strafarbeit einhandeln, denn man lernt doch schon in der ersten Klasse, daß in einer Gleichung beide Seiten gleich sein müssen. In Basic finden wir nicht nur solche Befehle wie X=X+1, sondern auch X=X+2 oder sogar X=X+10000. Der wesentliche Unterschied liegt darin, daß ein Computer solche Formeln ganz anders auffaßt als ein Mathematiker. Während in der Mathematik eine Variable, hier zum Beispiel das X, einen unbekannten Wert darstellt, den man durch Lösen der Gleichung ermitteln möchte, handelt es sich bei Basic um eine Methode, einen Wert zu speichern, der sich im Verlauf des Programms ändern kann. Normale Ziffern und Zahlen sind als »Konstante(n)« bekannt, sie ändern ihren Wert nie. In X=X+1 ist die 1 eine solche Konstante, und 1 ist immer gleich 1. Variablen sind Schachteln Eine Variable ist so etwas ähnliches wie eine flexible Zahl. Sie kann gleich sein mit jedem Wert. Und Sie können den Wert, den sie repräsentiert jederzeit im Programm per Befehl ändern: Der Befehl X=16 wird »Zuweisungsbefehl« (engl. assignment statement) genannt, weil er der Variablen X den Wert 16 zuweist. X wird also gleich 16 gesetzt, ein Befehl, den der Computer brav ausführt. Immer wieder beliebt ist auch der Vergleich einer Variablen mit einer Schachtel: Stellen Sie sich eine Streichholzschachtel vor, auf der außen der Name (zum Beispiel X) steht (Bild). In der Schachtel liegt ein kleiner Zettel, auf dem der Zahlenwert von X steht. Der Befehl M = 14 sucht die Schachtel mit dem Namen M und legt einen Zettel mit dem Wert 14 hinein. Der oben noch unverständliche Befehl Z = Z+1 wird jetzt ganz klar verständlich: Nimm die Schachtel mit dem Namen Z, öffne sie, lese die Zahl auf dem Zettel (zum Beispiel 123), erhöhe sie um eins (gibt 124), streiche die alte Zahl auf dem Zettel durch, schreibe die neue darauf und lege den Zettel wieder in die Schachtel zurück. Z hat jetzt den Wert 124. Fragen Sie jetzt später zum Beispiel mit PRINT X den Wert der Variablen X ab, öffnet der Computer die Schachtel mit dem Namen X und liest den darin enthaltenen Zettel: Die 16 erscheint wieder. Eigentlich ist X=16 die Abkürzung für LET X=16, also »sei X=16«. Da das LET-Schlüsselwort aber in den meisten Basic-Dialekten, auch auf dem C 64, wahlfrei ist, wird es oft weggelassen, und ist vielen Programmiern gar nicht mehr geläufig. In der Mathematik gibt es für solche Zuweisungen »X sei X plus 1«, soll also um eins erhöht werden, eine besondere Symbolik: X := X + 1 Der Doppelpunkt vor dem Gleichheitszeichen besagt, daß es sich hier um eine Zuweisung, nicht um eine nachrechenbare Formel handelt. In der Tat verlangen einige Programmiersprachen wie beispielsweise C den Doppelpunkt bei Zuweisungen an Variablen. In Basic ist er (zu diesem Zweck) verboten. Nachdem einer Variablen der Wert 16 zugewiesen wurde, behandelt der Computer sie immer wie eine 16, wenn er im Programmablauf auf die Variable stößt. Siehe unser obiges Beispiel: PRINT X ergibt 16. Der Vorteil, den die Verwendung von Variablen uns bietet, ist leicht zu begreifen. Die Variable kann ganz einfach auf vielfältige Weise manipuliert werden. Probieren Sie es aus, indem Sie folgendes kleines Programm mit RUN starten:1 10 X=16:PRINT X:X=X+1:PRINT X Sie bekommen als Ergebnis erst die Zahl 16, dann die 17 zurück, obwohl im Programm das X scheinbar für immer auf 16 gesetzt wird. Warum? Weil der dritte Befehl X=X+1 ein erneuter Zuweisungsbefehl an die Variable X ist, der zum aktuellen Wert (16) eins addiert (gibt 17). Der letzte Befehl gibt den neuen Wert 17 aus. Konstanten und Variablen Schön. Aber wie groß ist der Wert in X, wenn wir dem Programm gar nichts darüber sagen? Starten Sie das Programm nochmal, nachdem Sie den ersten Befehl gestrichen haben: 10 PRINT X:X=X+1:PRINT X Auf Ihrem Bildschirm erscheinen die Zahlen 0 und 1. Das liegt daran, daß fast alle Home- und Personal-Computer die Variablen vor dem Programmstart »initialisieren«, ihnen also einen definierten Wert geben: Die Null. Nebenbei bemerkt ist dies bei größeren Computern fast nie der Fall. Sollten Sie also Ambitionen haben, vielleicht später einmal einen Großrechner zu programmieren, denken Sie daran, bei Programmstart alle im Programm benötigten Variablen auf Null zu setzen, da sie sonst unbekannte oder sogar sinnlose Werte enthalten. Dies ist auch bei manch anderer Programmiersprache als Basic, zum Beispiel Pascal, Modula, C oder auch Maschinensprache der Fall. Um hier zu verhindern, der unvorhergesehener Datenmüll Ihre Berechnungen durcheinanderwirft, denken Sie an die Notwendigkeit der Initialisierung. In Basic ist dies, wie gesagt, nicht nötig, das erledigt schon der RUN-Befehl für uns. Es ist aber auch möglich, mitten im Programm plötzlich alle Variablen zu löschen: Der Befehl dazu heißt CLR (Abkürzung für »CLEAR«). Er bewirkt, daß der C 64 unwiderruflich alle Variablen aus seinem Gedächtnis streicht. Fragen wir jetzt beispielsweise nach einem CLR den Inhalt der Variablen A ab: PRINT A gibt der Interpreter eine Null aus, da er kein A mehr kennt. Sie merken schon, im allgemeinen ist der CLR-Befehl ziemlich sinnfrei. Dabei ist auch noch etwas anderes klargeworden. Sehen wir uns noch einmal das obere Beispiel an: 10 X=16:PRINT X:X=X+1:PRINT X ergab als Bildschirmausgabe erst 16, dann 17. Den alten Wert 16 vergißt der Computer für immer, sobald er den Befehl X=X+1 (X um eins erhöhen) abarbeitet. Das müssen Sie beachten, falls Sie den alten Wert später noch einmal benötigen. Man könnte ihn zum Beispiel in der Variablen XALT (oder XA) zwischenspeichern: 10 X=16:PRINT X:XA=X:X=X+1:PRINT X:PRINT XA Hier erscheinen die Zahlen 16, 17 und 16: Erst der Originalwert von X, dann der neue Wert nach X=X+1 und schließlich der in XA »gerettete« Originalwert. Sie haben jetzt einiges über die Annehmlichkeiten von Variablen gelernt. Kein Programm kommt ohne sie aus. Aber wozu braucht man Konstanten? Wir geben zwei Beispiele. Angenommen, Sie möchten ein größeres Programm schreiben, zum Beispiel ein Spiel. Irgendwo mitten im Programm steht auch das Unterprogramm, in dem dem Spieler ein Leben von seinem Konto abgezogen wird. Dazu enthält die Variable LE die Anzahl der Fehlversuche, die der Spieler schon unternommen hat. Bei drei Fehlern soll Schluß sein: 1000 LE=LE+1 1010 IF LE < 3 THEN (weiterspielen) 1020 PRINT "GAME OVER..." 1030 END Jetzt soll ein halbes Jahr später die Anzahl der Leben auf vier erhöht werden. Und dann beginnt die Suche, wo denn der Befehl steht (hier werden Sie in Zeile 1010 fündig). Viel einfacher wäre es, wenn Sie schon ganz am Anfang des Programms eine Variable ML (maximale Leben) definiert hätten, der der Wert 3 zugewiesen wird. Zeile 1010 vergleicht LE dann mit diesem Wert: 10 ML = 3 : REM maximale Anzahl Leben 1010 IF LE < ML THEN (weiterspielen) Der Wert von ML wird im ganzen Programm nicht mehr verändert, daher nennen wir ML eine Konstante, obwohl es sich technisch um eine Variable handelt. LE ist eine echte Variable, da ihr Wertin Zeile 1000, also mitten im Programm, verändert wird. Soll jetzt die Anzahl der Leben geändert werden, suchen Sie nur am Programmanfang und können hier bequem Änderungen eintragen, die sich später automatisch auf den gesamten Rest des Programms auswirken. Der zweite Vorteil ist nicht ganz so offensichtlich: Programme werden schneller, wenn man zum Beispiel ganz am Anfang eine Konstante 10 NU=0 definiert, und diese dann später für alle Zwecke verwendet, bei denen eine Null benötigt wird. Ein Beispiel: Erst die herkömmliche Version: 20 FOR I=1 TO 1000: D = 0 + 0: NEXT Hier soll tausend Mal die Summe Null plus Null berechnet und in der Variablen D gespeichert werden. Nicht sehr sinnvoll, aber es ist ja nur ein Test. Unser C 64 braucht dafür 4,22 Sekunden. Und nun ändern Sie einmal Zeile 20, indem Sie die Ziffer 0 durch die in Zeile 10 definierte Konstante NU ersetzen: 10 NU=0 20 FOR I=1 TO 1000: D = NU + NU: NEXT Diese Version erledigt doch ganz genau das gleiche, NU hat nun einmal den Wert 0. Und doch: Plötzlich ist der C 64 nach 3,47 Sekunden fertig: In 82 Prozent der Zeit! Ein gewaltiger Fortschritt, wenn man bedenkt, daß kaum etwas geändert wurde. Dieser Gewinn tritt freilich nur dann so vehement auf, wenn Sie die Konstante wirklich möglichst früh im Programm definieren. Der Computer durchsucht seine Variablentabelle (die Schachteln) nämlich in der Reihenfolge, in der sie angelegt wurde. Weitere Tuning-Hinweise dieser Art, wie Sie Ihren Basicprogrammen mit solch billigen Tricks gehörig auf die Sprünge helfen können, haben wir übrigens in der Basic-Corner in 64'er 8/93 bis 10/93 veröffentlicht. Variablennamen Sie sind bei der Wahl des Variablennamens nicht auf den Buchstaben X oder A beschränkt. Natürlich steht jeder Buchstabe zwischen A und Z zur Verfügung. Es sind sogar längere Variablennamen erlaubt. Dies ist ein sicheres Mittel, eigene Programme für andere (und ggf. sogar sich selbst) verständlicher zu gestalten. Soll beispielsweise eine Variable das Ergebnis einer Addition speichern, kann es sinnvoll sein, diese SUMME zu nennen, das ist aussagekräftiger als etwa ein S. Die verschiedenen Versionen von Basic behandeln die Variablennamen ganz unterschiedlich. In Basic 2.0 des C 64 und auch auf dem C 128 dürfen Variablennamen beliebig lang sein und aus Buchstaben und Ziffern bestehen. Einzige Einschränkung: Das erste Zeichen des Namens muß ein Buchstabe sein. C7 ist erlaubt, nicht aber 7C. Allerdings sind nur die ersten beiden Zeichen des Namens signifikant. Das heißt, bei der Auswertung der Namen berücksichtigt der Computer nur die ersten beiden Zeichen des Namens, MAX und MARTIN sind also für den Rechner identisch, während FEE und SEE unterschiedliche Variablennamen sind. Wer daran nicht denkt, hat später gegen mysteriöse Programmfehler zu kämpfen. Noch einen Haken hat die Sache: In Basic-Variablennamen dürfen grundsätzlich keine Basic-Schlüsselwörter vorkommen. Ein Beispiel wäre die Variable TOTAL. Während sie genauso harmlos aussieht wie SUMME, provoziert sie einen Syntax Error. Grund: Im Namen kommt das reservierte Wort TO vor, das sonst den Schleifen (z.B. FOR I = 1 TO 10) vorbehalten ist. Andere Beispiele für verbotene Namen: TANJA (enthält TAN) STORNO$ (beginnt mit ST) TILL (beginnt mit TI) REIFEN$ (enthält IF) VORWAHL (enthält OR) BEGRIFF (enthält IF) PRINZESSIN (enthält SIN) Wenn Sie schon einmal fremde Basicprogramm begutachtet haben, ist Ihnen aufgefallen, daß die wenigsten Programmierer mit Variablennamen arbeiten, die aus mehr als einem oder zwei Zeichen bestehen. Der Grund ist einfach: Lange Variablennamen kosten nicht nur teuren Platz im Arbeitsspeicher und auf Diskette, sondern verzögern auch die Programmausführung. Als kleiner Ausblick: IBM Basic erlaubt Variablennamen mit Buchstaben, Ziffern und Punkten, allerdings muß das erste Zeichen ein Buchstabe sein. Namen können beliebig lang sein, signifikant sind die ersten 40 Zeichen. Eine Variable darf zwar reservierte Wörter enthalten, aber nicht ausschließlich: TO ist als Variablenname tabu, gegen TOTAL hat zumindestens IBM Basic nichts einzuwenden. Bisher haben wir uns hier nur mit numerischen Variablen beschäftigt, also mit Variablen, die zur Aufnahme einer Zahl (etwa eines Rechenergebnisses) geeignet sind. Es gibt aber beispielsweise auch noch Textvariablen, die sogenannten »Strings« (engl. für Kette). Diese unterscheiden sich von numerischen Variablen durch das Dollarzeichen, das den Variablennamen abschließt. String lassen sich nicht zur Berechnung heranziehen. Dafür haben sie eine Fähigkeit, die den numerischen Variablen fehlt: Sie können beliebige Texte speichern, bis zu 255 Zeichen pro Variable. Die Zuweisung an eine Textvariable sieht ungefähr so aus: TEXT$ = "IRGEND EIN TEXT" Zum Beispiel: NAME$ = "HANS HUBER" Auch hier zählen für den C 64 wieder nur die ersten beiden Zeichen, der letzte Befehl ist also äquivalent zur kompakten Version NA$ = "HANS HUBER" Beachten Sie bitte auch die Anführungszeichen, in die der Text eingeschlossen ist. Begrenzt kann man auch mit den Strings rechnen, beispielsweise zwei Texte direkt aneinanderhängen. Wir definieren dazu die Variablen VNAM$ zur Aufnahme des Vornamens (VOR$ und VON$ sind nicht erlaubt, da OR bzw. ON darin vorkommt) und NACH$ für den Nachnamen: VNAM$="PETER" NACH$="MAIER" Jetzt könnten wir eine Variable NAME$ anlegen, in der der komplette Name gespeichert ist: NAME$ = VNAM$ + NACH$ Das Ergebnis sehen wir und mit PRINT NAME$ an: PETERMAIER. Der Computer hat unsere Anweisung blind ausgeführt, ihn stört nicht, daß zwischen den beiden Namen kein Zwischenraum kommt. Den fügen wir einfach durch eine neue Zuweisung ein: NAME$ = VNAM$ + " " + NACH$ Zwischen den beiden Anführungszeichen drücken Sie einmal die Leertaste. Ergebnis: PRINT NAME$ ergibt PETER MAIER. Probieren Sie es mit Ihrem eigenen Namen! Sie werden erkennen, es ist gar nicht so schwer, mit Variablen zu arbeiten. Wichtig bei Textvariablen ist vor allem das Dollarzeichen hinter dem Namen. Es sagt dem Computer, daß diese Variable nicht nur Zahlen, sondern ganze Texte bis hin zu 255 Zeichen Länge aufnehmen kann. Probieren Sie einmal NAME = "ADALBERT" Das Ergebnis ist ein ?TYPE MISMATCH ERROR, der C 64 hat gemerkt, daß es sich bei "ADALBERT" um einen Text (String) handelt, der keiner numerischen Variable (NAME) zugewiesen werden kann. Und was passiert, wenn man die Anführungszeichen einfach ausläßt? NAME = ADALBERT Der C 64 hat nichts dagegen?! Was ist passiert? Das Programm hat ADALBERT ebenfalls als Variablennamen aufgefaßt und weist der Variablen NA den Inhalt der (nicht definierten) Variablen AD (es werden ja immer nur die ersten beiden Zeichen berücksichtigt) zu. Das Ergbnis ist Null: PRINT NAME Achten Sie also darauf, nie das Dollarzeichen zu vergessen: NAME$ = "ADALBERT" Das Wort »Adalbert« in Anführungszeichen (engl. »quotes«) ist wiederum eine Konstante. Solche Text-Konstanten, die in Anführungszeichen im Programmtext stehen, nennt man auch »Literal«. Damit dürfen Sie nicht rechnen Den Vorteil, daß String-Variablen beliebige Zeichenketten aufnehmen können, bezahlen Sie mit der Einschränkung, daß man mit Strings nicht ohne weiteres rechnen kann - nicht einmal, falls der Text zufälligerweise eine Zahl ist: Z1$ = "1000" Z2$ = "50" »1000« und »50« sind für den Computer völlig zufällige und bedeutungslose Zeichenketten. Rechnungen sind nicht erlaubt: PRINT Z1$ / Z2$ ergibt nicht etwa, wie man erwarten könnte, das mathematisch stimmige Ergebnis 20, sondern eine Fehlermeldung. Mit Texten lassen sich eben keine Rechnungen ausführen. Einzige Ausnahme: Die String-Addition, die wir oben sogar schon gesehen haben (Zusammenfügen von Vor- und Nachname). Als »Rechenzeichen« dient das Plus-Symbol. Aber Vorsicht: Auch hierbei wird nichts ausgerechnet, der C 64 hängt einfach beide Ketten hintereinander: ERG$ = Z1$ + Z2$ und PRINT ERG$ ergibt nicht 1050, sondern 100050. Die oben erwähnte Einschränkung, daß Variablennamen keine Schlüsselwörter enthalten dürfen, gilt auch für Textvariablen. Für den Inhalt hat dies keine Bedeutung: Das erste Beispiel ist verboten, gegen das zweite hat der C 64 nichts einzuwenden: WORT$ = "TINTE" (enthält OR) FLUESSIGKEIT$ = "TINTE" Es stört nicht weiter, daß TINTE »INT« enthält. (Nikolaus Heusler) Wichtige Begriffe Default: Vorgabewert initialisieren: mit einem definierten Wert versehen/vorbelegen integer: ganzzahlig Konstante: unveränderlicher Wert, mit dem beispielsweise eine Variable initialisiert wird Literal: String-Konstante numerisch: als Zahlenwert quote: Anführungszeichen String: Zeichenkette Variable: Speicherplatz für einen Wert