Magic Disk 64

home to index to html: MD8904-KURS-BASIC_KURS_TEIL_4-1_:_VON_ADAM_UND_EVA...(TEIL_4)-7.1.html
     BASIC-Kurs:  "Von Adam und Eva..." (Teil 4)     
     ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾     
Hiermit möchte ich Sie zum vierten Teil  unseres  Ba-
sickurses  herzlichst  begrüßen.  Diesen Monat werden
wir uns noch ein wenig mit der formatierten  Program-
mierung  befassen und werden uns anschließend endlich
den lang versprochenen Schleifenbefehlen zuwenden.   
Letzten Monat hatten Sie ja  gelernt,  wie  man,  mit
Hilfe von REM und sogenannten "Doppelpunktzeilen" ein
wenig  Ordnung  in  einen  Programmtext  bringt. Eine
richtige "Programmierung" war das ja noch nicht,  zu-
mal  die von uns eingefügten Zeilen und Kommentare ja
nichts mit dem  eigentlichen  Programmablauf  zu  tun
hatten,  und wir sie genausogut auch hätten weglassen
können, wie ich zum Schluß andeutete.                
Deshalb kommen wir heute  zum  GOSUB-Befehl,  der  in
zusammenhang mit dem RETURN-Befehl uns ungeheuerliche
Weiten zur platzsparenden, einfachen und formatierten
Programmierung öffnet.                               
GOSUB steht für GO to SUBroutine, was  soviel  heißt,
wie GEHE zu UNTERprogramm, und ist in etwa vergleich-
bar mit GOTO. Hinter GOSUB wird ebenfalls  eine  Zei-
lennummer  angegeben,  zu  der  der Computer springen
soll. Bis hierhin tut GOSUB genau dasselbe, was  auch
GOTO  tut,  nämlich  ganz einfach zu einer bestimmten
Zeile im Programm springen. Die  Programmzeilen,  die
dort  stehen und folgen werden ganz normal abgearbei-
tet. Doch nun kommt der Clou:  nachdem  diese  Zeilen
abgearbeitet wurden, können Sie mit dem RETURN-Befehl
wieder  an die Stelle im Programm zurückspringen, von
wo der GOSUB-Befehl in das Untersprogramm  (so  nennt
sich  das  nämlich)  eingesprungen  ist. Dies hat den
Vorteil, daß Sie beliebige Programmsequenzen, die Sie
innerhalb eines  Programms  benötigen,  beliebig  oft
benutzen  können,  aber  nur EINMAL schreiben müssen.
Der Computer merkt sich jedesmal die Stelle, von wel-
cher Sie in das Unterprogramm eingesprungen sind, und
wird  jedesmal  auch  wieder dorthin zurückkehren. In
der Praxis sieht das so aus:                         
5 REM *****************                              
6 REM * hauptprogramm *                              
7 REM *****************                              
8 :                                                  
10 GOSUB 200                                         
20 PRINT"Hallo Leute..."                             
30 GOSUB 200                                         
40 PRINT"Unn weils so schön war, grad nochmal...";   
50 GOSUB 200                                         
60 END                                               
90 :                                                 
195 REM ************                                 
196 REM * demotext *                                 
197 REM ************                                 
198 :                                                
200 PRINT                                            
205 PRINT"Das ist ein Text, der hier zur Demon-"     
210 PRINT"stration insgesamt 3 Mal ausgedruckt"      
220 PRINT"wird."                                     
230 PRINT                                            
240 RETURN                                           
Genau  so  sollte ein gut formatiertes Programm übri-
gens aussehen. Vor jedem  Modul  (=Programmabschnitt,
das  hatten  wir  letzten  Monat  ja schon einmal...)
steht ein unübersehbarer Kommentar. Zuerst haben  wir
das  "HAUPTPROGAMM".  Der  Programmteil  also, der am
Anfang auch mit RUN  gestartet  wird,  und  der  alle
benötigten  Unterprogramme,  so  wie zum Beispiel das
Programm "DEMOTEXT", zu dem Zeitpunkt aufruft, zu dem
sie benötigt werden.                                 
Schauen wir uns doch einmal unser Programm ein  wenig
näher  an.  Gleich am Anfang, in Zeile 10, wird unser
kleines Unterprogramm schon beansprucht und  aufgeru-
fen.  Dann wird in Zeile 20 der Text "Hallo Leute..."
ausgegeben. Anschließend kommt wieder  das  Unterpro-
gramm  dran.  Dann kommt etwas aus dem Hauptprogramm,
nämlich der Text "Unn weils so schoen war, grad noch-
mal...".  Schließlich  und endlich wird DEMOTEXT noch
ein letztes Mal aufgerufen und das Hauptprogramm  mit
END  beendet.  Der  Ausdruck, den Sie somit erhalten,
sieht im Endeffekt dann so aus:                      
Das ist ein Text, der hier zur Demon-                
stration insgesamt 3 Mal ausgedruckt                 
wird.                                                
Hallo Leute...                                       
Das ist ein Text, der hier zur Demon-                
stration insgesamt 3 Mal ausgedruckt                 
wird.                                                
Unn weils so schoen war, grad nochmal...             
Das ist ein Text, der hier zur Demon-                
stration insgesamt 3 Mal ausgedruckt                 
wird.                                                
Sie sehen, obwohl Sie den Text, der hier, wie so  oft
angezeigt,  "insgesamt  3  Mal ausgedruckt wird", nur
einmal eingegeben  haben,  erscheint  er  tatsächlich
drei  Mal auf dem Bildschirm. Sie haben sich also er-
steinmal ein wenig Tipparbeit gespart, und dann  auch
noch Speicherplatz, da drei mal mehr Platz verbraucht
worden wäre, hätten Sie jedesmal unseren Text nochmal
eingegeben.  Außerdem  sieht  unser Programm so jetzt
schön sauber und ordentlich aus - Unterprogramm schön
vom Hauptprogramm getrennt...                        
Und es gibt da noch einen kleinen Vorteil:   angenom-
men, Sie sind gerade dabei ein Programm zu schreiben,
zu  dem  Sie  ein bestimmtes Unterprogramm benötigen,
das eine ganz bestimmte Aufgabe erfüllen soll. Welche
Aufgabe im Einzelnen, sei jetzt einmal dahingestellt.
Dieses Unterprogramm haben Sie vor längerer Zeit  al-
lerdings  schon  einmal in einem anderen Programm be-
nutzt, und haben es  dort  noch  voll  funktionsfähig
drin  stehen. Das einzigste, was Sie jetzt zu tun ha-
ben, ist das Unterprogramm aus Ihrem  alten  Programm
herauszuisolieren, und es dann in Ihr neues einzubin-
den. Also ein weiterer Vorteil  von  Unterprogrammen,
da  Sie  sie jederzeit wiederverwenden können, können
Sie sich Ihre Programme sozusagen aus vielen  kleinen
Modulen  (also  Unterprogrammen) "zusammenbauen", wie
als wenn Sie mit Bauklötzen einen  Turm  konstruieren
würden.                                              
Ich muß Ihnen allerdings gestehen, daß dies gar nicht
so  einfach ist, wie es sich anhört, da man beim  BA-
SIC V2.0 des C64 nicht so einfach riesige Programmab-
schnitte  löschen kann, geschweige denn, daß man ein-
zelne Module so  einfach  aneinander  hängen  könnte.
Doch  nicht verzagen, in einer der nächsten Ausgaben,
wird wahrscheinlich ein kleines Hilfsprogramm  hierzu
erscheinen, daß diese Aufgaben bewältigen wird.      
Wie oben schon erwähnt, kann man GOSUB auch zum  "he-
rumspringen" genauso  wie GOTO verwenden, doch möchte
ich  Ihnen  DRINGENDST  davon abraten. Denn wie eben-
falls schon gesagt, merkt sich der  GOSUB-Befehl  (im
Gegensatz zu GOTO) eben jene Stelle, von wo aus er in
ein  Unterprogramm eingesprungen ist. Da der Computer
allerdings nur  einen  begrenzten  Speicherplatz  für
solche  Rücksprünge  bereithält,  kann es Ihnen somit
passieren, daß Ihr Programm irgendwann aus  Speicher-
mangel  einen Fehler ausspuckt. Benutzen Sie also im-
mer GOTO, wenn Sie "nur" springen möchten.  Dies  ist
auch  ein  kleiner Hinweis für Sie, falls Sie mal ein
Programm haben sollten, das nicht so  laufen  sollte,
wie  Sie  es  wünschen. Eine häufige Fehlerquelle ist
nämlich auch die Tatsache, daß  vergessen  wurde, das
Unterprogramm  mit RETURN abzuschließen.  Sollte näm-
lich jetzt zufällig wieder der  Programmteil  folgen,
von  dem aus das Unterprogramm aufgerufen wurde, dann
wiederholt sich dieser Aufruf solange, bis der Compu-
ter  abbrechen  muß, da sein Merkspeicher "überläuft"
(so nennt man das, wenn bei einer internen  Operation
der  Computer  über  die  Speichergrenze hinaus einen
Zugriff machen muß). Das soll jetzt  natürlich  NICHT
heißen,  daß Sie ein Unterprogramm nicht wiederum von
einem weiteren Unterprogramm  aus  aufrufen  könnten.
Natürlich  geht  das,  Sie müssen nur jedes Unterpro-
gramm immer wieder ornungsgemäß mit dem RETURN-Befehl
abschließen, um keinen Ärger zu bekommen. Theoretisch
könnten Sie  sogar  24  Unterprogramme  untereinander
verschachteln,  doch werden Sie diese Grenze wohl nie
erreichen...                                         
Wollen wir uns nun endlich den  Scheifenbefehlen  zu-
wenden.  Zuerst  einmal,  was ist eine Schleife?  Wie
Sie sich vielleicht erinnern, hatten wir, beim Abhan-
deln  des GOTO-Befehls eine sogenannte "Endlosschlei-
fe" geschrieben. Deshalb Endloschleife, weil ein ganz
bestimmter Programmteil immer und  immer  wieder  ab-
gearbeitet  wurde,  so, daß das Programm endlos lange
weitergelaufen wäre, hätten wir es nicht mit RUN/STOP
angehalten. Hier nochmals ein solches Programm:      
10 PRINT"Das ist eine Endlosschleife...";            
20 GOTO 10                                           
Hier  wird  der Text "Das ist eine Endlosschleife..."
also immer wieder ausgegeben, da in Zeile 20 ja immer
wieder zu Zeile 10 verzweigt wird, womit  sich  unser
Programm  also  immer  wieder  selbst aufruft. Klarer
wird es, wenn Sie Zeile 20 wie folgt abändern:       
10 PRINT"Das ist eine Endlosschleife...";            
20 RUN                                               
Jetzt startet sich das  Programm  also  immer  wieder
selbst, ohne  daß es jemals zu einem Ende kommen wür-
de.                                                  
Sie  müssen  allerdings  zugeben,  daß solche Endlos-
schleifen, so  wie sie hier dargestellt  sind  zumin-
dest,  wenig  Sinn ergeben. Es wäre doch viel besser,
wenn man eine solche Schleife unter Kontrolle  hätte,
und  sie endlich machen könnte, so also, daß sie nach
eine bestimmten Anzahl von Durchläufen beendet wird. 
Zum Einen könnte man das, wenn wir uns auf unser bis-
heriges Wissen stützen, sehr  gut  mit  der  IF-THEN-
Klammer lösen. Nämlich so:                           
5 i=0                                                
10 i=i+1                                             
20 PRINT"DAS IST EIN TEXT"                           
30 IF i<>5 THEN 10                                   
40 END                                               
Zuerst  wird in Zeile 5 die Variable I auf 0 gesetzt.
Anschließend wird diese Laufvariable (so  wollen  wir
es einmal nennen), ihres Zeichens eine Floatvariable,
um  eins  erhöht.  Dann drucken wir den Text "DAS IST
EIN TEXT" aus. In Zeile 30 vergleichen wir nun, ob  I
den  Wert  5 enthält. Wenn nicht, dann wird wieder zu
Zeile 10 gesprungen  und  der  Vorgang  des  Um-Eins-
Erhöhens und des Ausdruckens wiederholt sich. Andern-
falls wird das Programm beENDet. Sie sehen, daß diese
Schleife nur 5 Mal durchlaufen werden kann,  da  sich
nämlich  bei  jedem  Durchlauf die Variable I um eins
erhöht,  hat  sie  nach  5  Durchgängen  den  Wert  5
tatsächlich erreicht. Also wird die Schleife abgebro-
chen, und es geht in Zeile  40  weiter  im  Programm.
Hiermit hätten wir also eine Endlichschleife geschaf-
fen,  doch dies geht auch einfacher und  übersichtli-
cher,  denn  BASIC stellt uns extra zur Schleifenpro-
grammierung zwei Befehle zur Verfügung, FOR und NEXT,
die die FOR-NEXT-Schleife bilden.                    
FOR-NEXT   arbeitet   ähnlich,  wie  unsere  IF-THEN-
Schleife. Auch hier benötigen wir eine  Laufvariable,
nur, daß wir hier gleich in einem Zug angeben können,
von welchem Wert zu welchem Wert gezählt werden soll.
Also  haben  wir hier die Zeilen 5 und 30 unseres er-
sten Schleifenprogramms in EINEM zusammengefaßt.  Se-
hen  Sie  sich doch einfach einmal dieses kleine Pro-
gramm an, das die selbe Arbeit verrichtet, wie  unser
letztes Programm, allerdings mit Hilfe von FOR-NEXT: 
10 FOR I=1 to 5                                      
20 PRINT"DAS IST EIN TEXT"                           
30 NEXT                                              
Das  war  alles!  Auf den ersten Blick sieht das zwar
genauso lang aus, wie unser erstes Schleifenprogramm,
doch der FOR-Befehl hat noch einige  Eigenarten,  die
ihn  zum  einen  komfortabler machen, und zum anderen
ÜBERSICHTLICHER, was ja außerordentlich wichtig  ist,
wie  wir  festgestellt  hatten. Nicht umsonst nämlich
hatte ich ein ganzes Kapitel der  formatiertien  Pro-
grammierung gewidmet!                                
Das  Übersichtliche  an FOR-NEXT ist, daß der gesamte
Schleifenrumpf, der Teil also, der immer  wieder  ab-
gearbeitet  werden  soll,  durch  FOR und NEXT einge-
grenzt wird. Sehen wir uns nun einmal an, was im  In-
nern  unsers  Computers  abläuft, wenn er eine solche
Schleife abarbeitet:                                 
In  Zeile  10  erkennt der 64er erst einmal (an FOR),
daß hier gleich eine Schleife  folgt.  Direkt  hinter
dem  FOR-Befehl  wird dann die Laufvariable mit einem
Grundwert "initialisiert", das  heißt,  daß  ein  be-
stimmter  Wert  als  Ausgangswert  für diese Variable
festgelegt  wird.  Diese  Initialisierung  entspricht
Zeile  5 unseres ersten Programms, hier wurde die Va-
riable 'I' auf 0 gesetzt. Daß wir  sie  nicht  mit  1
initialisierten,  wie  bei  FOR, liegt einfach daran,
daß sie  anschließend,  in  Zeile  10,  schon  auf  1
gezählt  wurde. Womit sie den selben Anfangswert hat,
wie in unserem zweiten Programmbeispiel.             
Wie  gesagt  haben  wir  nun die untere und die obere
Grenze festgelegt, innerhalb der der Computer  zählen
soll. In unserem Beispiel ist das von 1 bis 5.       
In Zeile 20 geht's jetzt weiter  mit  dem  Schleifen-
rumpf,  der hier nur diese eine Zeile, mit Nummer 20,
lang ist. Natürlich könnten  Sie  hier  auch  mehrere
Zeilen  stehen  haben,  Hauptsache ist, daß Sie diese
dann auch zwischen FOR und NEXT  sozusagen  "einklam-
mern".  Unser Schleifenrumpf besteht also aus der An-
weisung, den Text "DAS IST EIN TEXT" auszudrucken.   
In  Zeile  30  nun  trifft der Computer auf die NEXT-
Anweisung. Jetzt zählt er die Schleifen- oder Laufva-
riable  erst  einmal um 1 hoch. Entsprechend also der
Zeile 10 unseres ersten Programms:                   
10 I=I+1                                             
Anschließend prüft er, ob der Inhalt dieser  Variable
mittlerweile  größer ist, als der obere Grenzwert, ob
dieser also schon überschritten wurde. Ist  dies  der
Fall,  so  wird die Schleife beendet und der Computer
fährt in Programm fort. Ist die  Laufvariable  aller-
dings  noch  kleiner  oder  gleich  dem Grenzwert, so
wird wieder an den Befehl im Programm verzweigt,  der
nach  der  FOR-Anweisung  kommt. Dies wiederholt sich
dann halt solange, bis  der  Grenzwert  dann  endlich
überschritten wurde. Ich möchte hier auch noch darauf
aufmerksam  machen, daß die Laufvariable VOR dem Ver-
gleich hochgezählt wird. Deshalb  hat  Sie  nach  dem
Aussprung  aus der Schleife immer den Inhalt des obe-
ren Grenzwertes plus 1!!!  Dies zu  wissen  kann  äu-
ßerst  wichtig  sein, da hier manchmal Fehler gemacht
werden:                                              
FOR i=0 TO 3:PRINT"TEXT":NEXT                        
Diese Schleife zum Beispiel wird insgesamt 4 (!)  mal
durchlaufen,  da  von  0  nach 3 gezählt wird (also 3
Ziffern  plus  die  Null...).  Nicht  also,  wie  man
fälschlicherweise annehmen könnte, nur 3 mal!        
Hier sehen Sie übrigens auch, daß man  FOR  und  NEXT
nicht  unbedingt  in  eigene Programmzeilen schreiben
muß, es ist nämlich auch durchaus möglich sie in  EI-
NER   Zeile   zusammenzufassen,  vorrausgesetzt,  der
Schleifenrumpf ist nicht zu lang.                    
Grundsätzlich gilt:  alle  Befehle,  Anweisungen  und
Funktionen,  die  zwischen FOR und NEXT stehen bilden
alle gemeinsam den Schleifenrumpf, den Teil also, der
immer  wieder  von  der  Schleife  durchlaufen  wird,
unabhängig davon, wie die einzelnen Befehle innerhalb
von Programmzeilen verteilt sind.                    
Doch kann man mit FOR noch viel mehr anfangen!  Ange-
nommen Sie wollten nicht immer um 1 erhöhen,  sondern
immer um 2, weil Sie, aus welchen Gründen auch immer,
alle  2er  Zahlen, oder alle geraden Zahlen, benutzen
möchten. Hierzu kann man die STEP-Anweisung benutzen,
die an den FOR-Befehl angehängt wird, ohne diesen sie
nicht  existieren  kann, sprich nicht verwendbar ist.
Geben Sie doch einfach einmal folgendes ein:         
FOR I=0 to 10 STEP 2:PRINT I:NEXT                    
Die Ausgabe dieser Schleife sieht so aus:            
0                                                    
2                                                    
4                                                    
6                                                    
8                                                    
10                                                   
Eigentlich nichts neues mehr für uns. Hier wurde ganz
einfach  von  0  bis  10  gezählt,  allerdings in 2er
Schritten, wie man an der Ausgabe erkennen kann - der
Inhalt von 'i' war  immer  um  2  erhöht.  Auch  hier
galt:  erst als NACH einem Hochzählen um den Zählwert
(oder  die  sogenannte Schrittweite) der obere Grenz-
wert überschritten wurde, wurde die Schleife  verlas-
sen.                                                 
Es  mag  sein,  daß dieses Ihnen noch nicht ganz ein-
leuchtet, deshalb also  ein  weiteres  Beispiel.  Wir
hatten  bis  jetzt immer von einem kleineren Wert bis
zu einem größeren gezählt. Manchmal  könnte  es  aber
auch ganz nützlich für uns sein, rückwärts zu zählen,
beispielsweise von 5 bis 0 in 1er-Schritten, oder gar
in halben Zahlen, also in  0.5er-Schritten.  Das  ist
absolut kein Problem mit STEP. Der Wert hinter diesem
Anweisungswort  muß  ganz  einfach negativ sein, also
mit einem Minuszeichen (-) davor. Etwa so:           
FOR I=5 to 0 STEP -1:PRINT I:NEXT                    
Hier haben wir  dann  eine  "Rückwärtsschleife".  Sie
zählt  rückwärts  von  5 bis 0. Auch hier gilt:  erst
wenn der zweite Grenzwert, diesmal ist er  allerdings
kleiner als der erste, UNTERSCHRITTEN wurde, wird die
Schleife  verlassen.  Diesmal also erst, wenn der In-
halt der Zählvariable kleiner ist, als der Grenzwert,
zu  dem gezählt werden soll. Dies ist ein kleiner Un-
terschied, der bei Schleifen mit negativen Zählwerten
auftritt, an den man sich jedoch leicht  gewöhnt,  da
er im Grunde ja ganz logisch ist, oder?              
Das zum Thema Schleifen. Ich hoffe, Ihnen dieses Pro-
blem verständlich dargelegt zu haben. Nun möchte  ich
mich,  quasi zur Entspannung, einem etwas  leichteren
Themen zuwenden, sozusagen ein paar  kleine  Häppchen
als "Hors d'oevre" vorschicken, auf das was  nächsten
Monat auf sie zu kommt...                            
Beginnen wir mit einem  kleinen  Rechenoperator,  den
ich Ihnen bei unserer Rechnerei am Anfang dieses Kur-
ses verschwiegen habe. Es handelt sich hierbei um den
Exponentialoperator, der durch den 'Pfeil nach  oben'
('↑')  ausgedrückt  wird. Mit ihm können Sie die n-te
Potenz einer Zahl berechnen. Etwa 2 hoch  8,  oder  5
zum Quadrat. Geschrieben wird das so:                
PRINT 2↑8                                            
PRINT 5↑2                                            
Sie  können  diesem Operator natürlich genauso benut-
zen, wie die anderen Operatoren auch, also  ebenfalls
auch bei Variablenzuweisungen benutzen.              
Sollten Sie übrigens darauf bedacht sein,  Ihre  Pro-
gramme so zu programmieren, daß sie mit einem Minimum
an  Zeit  ablaufen, dann gebe ich Ihnen den Tip, Ihre
Quadrat-Potenzen (also die Potenzen, die  die  2  als
Exponenten, oder als 'Hochzahl' haben) mit dem Multi-
plikationsoperator '*' auszudrücken. Dies rechnet der
64er nämlich bedeutend schneller aus,  als  wenn  Sie
den Potenz-Operator verwenden würden. Also anstatt:  
PRINT X↑2 schreiben Sie besser:                      
PRINT X*X                                            
Dieses  führt  zum selben Ergebnis, verbraucht aller-
dings bedeutend weniger Zeit. Sie selbst dürften  das
vielleicht  nicht  direkt  merken, da es der Computer
für uns normal Sterbliche immer noch sehr schnell be-
rechnet,  aber  schreiben Sie doch vielleicht einfach
einmal eine Schleife, die eine solche Potenzoperation
vielleicht 1000 oder 2000 Mal durchführt, und stoppen
Sie dann doch mal die Sekunden, ich  denke,  daß  Sie
einen Unterschied feststellen müßten...              
Das nächste, was ich Ihnen nicht vorenthalten möchte,
ist die "DEF-FN"-Anweisung. Mit dieser Anweisung kön-
nen Sie ganze Funktionen in einem  Ausdruck  definie-
ren,  so  daß  sie diesen Ausdruck nur noch durch ein
kleines Namenskürzel aufrufen müssen. Angenommen, Sie
haben eine Formel, mit der Sie  durch  Eingabe  einer
Unbekannten eine gewisse Größe berechnen können.  Als
praktisches  Beispiel  will ich mich mal ein wenig an
der Kreisberechnung auslassen.  Nehmen  wir  an,  Sie
wollten  ein Programm schreiben, das Ihnen den Kreis-
umfang sowie den Kreisinhalt berechnet. Die dazugehö-
rigen Formeln lauten, wie wir wissen, wenn  wir  alle
schön in der Schule aufgepaßt haben:                 
Kreisumfang:  2rπ  (= 2*r*π)                         
Kreisinhalt:  r↑2π (= r↑2*π)                         
Da wir hier in unserem Kurs leider  keine  Sonderzei-
chen  haben,  habe  ich, um das Quadrat auszudrücken,
wie unser C64 auch, den Exponentenpfeil (↑)  benutzt.
Sie kennen Ihn ja mittlerweile. In Klammern sehen Sie
dann  die endgültige Computerschreibweise (da ja noch
die Multiplikations-Zeichen '*' eingefügt werden muß-
ten.                                                 
Die  Formel für den Kreisinhalt werden wir allerdings
gleich nochmal ein wenig abändern. Da wir ja die Qua-
drate  etwas  schneller  berechnen  wollen,  heißt es
jetzt also:  r*r*π (was ja dasselbe ist wie r↑2*π).  
Nun  müssen  diese  beiden  Funktionen  nur  noch mit
DEF FN in einem  Namen  definiert  werden.  Dies  ge-
schieht folgendermaßen:                              
10 def fnu(r)=2*r*π                                  
20 def fni(r)=r*r*π                                  
Mit DEF zeigen Sie dem Computer also an, daß Sie hier
eine Funktion definieren wollen. Dann geben  Sie  den
Namen  der  Funktion  an,  der sich immer aus dem FN-
Prefix, einem oder zwei  Buchstaben  und  dem ' (R)'-
Suffix  zusammensetzt. Das Prefix ist bei jeder Defi-
nition gleich, der eigentliche Name der Funktion wird
durch die beiden Buchstaben in  der  Mitte  bestimmt,
bei denen Sie nach den selben Regeln arbeiten  müssen
wie  bei  den  Variablennamen. Diese Regeln hatte ich
Ihnen, als wir die  Variablennamensgebung hatten,  ja
schon  einmal  aufgezählt. Zum Suffix sei nur noch zu
sagen, daß hier in Klammern immer die Unbekannte ste-
hen  muß,  die in der zu definierenden Funktionsglei-
chung (oder Formel) eingesetzt werden soll.          
Warum, werden Sie beim Aufruf  erkennen.  Ich  möchte
hier  jedoch  erst  einmal  wieder ein weiteres Stück
unseres Programmes einfügen:                         
30 print chr$(14)chr$(8)                             
40 print"[CLS]Programm zur Berechnung von Kreisum-   
fang"                                                
50 print"und -inhalt."                               
60 input"[2 DOWN]Radius ";r                          
70 u=fnu(r)                                          
80 i=fni(r)                                          
Die Zeilen 30-50 drucken die Titelzeile des Programms
aus. In Zeile 30 wird übrigens  wieder  mit  CHR$(14)
die  Kleinschrift  eingeschaltet  und mit CHR$(8) die
Umschaltmöglichkeit durch Drücken der SHIFT- und  der
COMMODORE-Tasten  blockiert. Wir hatten dies ja schon
einmal bei unserem Zylinderberechnungsprogramm...    
In Zeile 60 fragt das Programm jetzt nach dem Radius,
der nach Eingabe eines beliebigen Wertes in  der  Va-
riablen 'r' gespeichert wird.                        
Jetzt folgt endlich unser  langerwarteter  Funktions-
aufruf.  Sie sehen, daß in Zeile 70  das Ergebnis der
Funktion  erst  einmal  der  Variablen ' u' zugeornet
wird. Der Aufruf ansich gestaltet sich höchst einfach
und schmerzlos. Sie schreiben ganz einfach wieder den
Prefix 'FN' gefolgt vom Funktionsnamen und  dem  Suf-
fix, mit der unbekannten Variablen in runden Klammern
eingeschlossen - das wars schon. Jetzt müssen wir das
Ergebnis  nur noch ausdrucken, und das geschieht fol-
gendermaßen:                                         
90 print"Der Kreisumfang ist: "u                     
100 print"Der Kreisinhalt ist: "i                    
Was ja hoffentlich keinerlei Erklärung bedarf...     
Der  Clou  an den vordefinierten Funktionen ist also,
daß man eine Unbekannte gleich  in  den  Klammern  am
Ende  angeben  kann.  Sie  hätten die Funktion ebenso
auch so aufrufen können:                             
print fnu(1.5)                                       
Hier haben wir den Wert der Funktion also gleich  nu-
merisch angegeben, nicht also in einer Variablen. Der
Vorteil  von  solchen Funktionsdefinitionen liegt auf
der Hand. Angenommen, Sie haben eine  bestimmte  For-
mel,  die Sie in einem Programm wahnsinnig oft benut-
zen müssen. Mit DEF-FN können Sie  diese  also  immer
abkürzen, und haben Ihre Funktion immer sofort parat.
Mit  FN  haben Sie also eine Art Variable für Formeln
(oder Funktionen), weshalb FN als ' normaler'  Varia-
blenname  nicht zulässig ist. Sie können gerne einmal
versuchen der Variable 'fn'  einen  Wert  zuzuweisen,
doch  wird  Sie  der C64 dann nur mit einem lapidaren
SYNTAX ERROR belohnen...                             
Außerdem  sei  noch  hinzuzufügen, daß Sie eine Funk-
tionsdefinition ausschließlich NUR innerhalb von Pro-
grammen  durchführen  können.  Versuchen  Sie dies im
Direktmodus, so quittiert Ihnen das der Computer  mit
einem  "ILLEGAL DIRECT ERROR", einem "UNERLAUBTEN DI-
REKTANWEISUNGS FEHLER" also. Ebenso  wie  INPUT  bei-
spielsweise  ist  DEF außerhalb von Programmen unsin-
nig, weshalb dieser Fehler auftritt. Einmal definiert
allerdings, können Sie jede Funktion aus dem  Direkt-
modus aus aufrufen - andersherum geht es also...     
Beschäftigen wir uns nun noch ein wenig mit  der  be-
nutzerfreundlichen Programmierung. Das heißt, daß wir
unsere  Programme  so  schreiben wollen, daß sie auch
jeder Computeranfänger problemlos bedienen kann.  Ge-
nauergesagt möchte ich Ihnen die komfortable Program-
mierung von sogenannten "Menüs"  näherbringen.  BASIC
stellt uns hierzu 2 äußerst nützliche und komfortable
Befehle  zur  Verfügung,  die  auch sehr gut noch für
weitere Aufgaben zu verwenden sind.                  
Als  erstes will ich den Begiff "MENÜ" einmal klären.
Bei einem Menü handelt es sich um  eine  Zusammenfas-
sung  von Unterpunkten innerhalb eines Programms, die
der Benutzer einzeln aufrufen kann. Sie  kennen  dies
bestimmt   schon   von  meinem  kleinen  ASCII-Druck-
Programm namens "SHOWASC", das dem zweiten Teil  die-
ses  Kurses  beigefügt  war.  Hier wurden Sie nämlich
gefragt, welche Funktion des Programms Sie  wünschen.
Ich  zeige  Ihnen  hier am besten einmal das Menü von
SHOWASC, damit Sie sich ein besseres Bild machen kön-
nen:                                                 
-----------------------------------------------------
ASCII-Tabellen-Druck.                                
Written in 1988 by Uli Basters.                      
Bitte druecken Sie:                                  
====================                                 
 F1  - Ausgabe der Liste auf Drucker                 
 F7  - Ausgabe der Liste auf Bildschirm              
  E  - fuer Programmende                             
-----------------------------------------------------
Sie  können  hier  also zwischen 3 sogenannten "Menü-
punkten" wählen, die Sie durch das Drücken einer  be-
stimmten  Taste erreichen können. Kommen wir hier nun
zum ersten der beiden Befehle, die ich Ihnen vorstel-
len wollte: dem GET-Befehl.                          
Mit ihm können Sie einen Buchstaben von der  Tastatur
einlesen,  der dann - in einer Stringvariable gespei-
chert - jederzeit abgerufen  werden  kann.  Hier  ein
Auszug  aus dem Programm des Menüs von oben (ich habe
es aus Gründen der besseren Verständlichkeit ein  we-
nig abgeändert...):                                  
...                                                  
25 print"Bitte druecken Sie: "                       
26 print"===================="                       
30 print" F1  - Ausgabe der Liste auf Drucker"       
40 print" F7  - Ausgabe der Liste auf Bildschirm"    
50 print"  E  - für Programmende"                    
60 get a$:if a$=""then 60                            
In  den Zeilen 25-50 wird erst einmal der Text zu un-
serem Menü auf dem  Bildschirm  ausgegeben.  Wie  das
dann aussieht haben wir oben ja schon einmal gesehen.
In  Zeile  60 haben wir jetzt unseren GET-Befehl. Wie
Sie sehen, steht ihm die String-Variable 'a$' nach.  
Die  Taste,  die also auf der Tastatur gedrückt wird,
wird im ASCII-Code in dieser Stringvariablen  gespei-
chert. Hier könnte natürlich auch jede andere String-
variable stehen, nicht  aber  eine  Numerische,  oder
eine Intgervariable.                                 
Direkt  anschließend,  aber  immer  noch in Zeile 60,
kommt ein IF-THEN-Vergleich. Es wird geprüft, ob  der
Inhalt der Variablen a$="" ist. Sie werden sich viel-
leicht fragen, was  diese  2  Hochkommas  ausdrücken.
Nun,  ganz  einfach,  schreiben Sie irgendwo in BASIC
für einen String, bei einer Zuweisung, oder wie  hier
zum Vergleich, ein "" dann steht das für NICHTS, oder
auch  KEIN STRING. Es wird also hier bei uns geprüft,
ob 'a$' leer ist, oder ob ein String in  ihr  gespei-
chert ist. Dieser Vergleich  ist  notwendig,  da  der
Computer ja eine  Taste  in  'a$'  gespeichert  haben
könnte,  obwohl  Sie  gar  keine  gedrückt haben. Das
hängt ganz einfach mit internen  Vorgängen  zusammen.
Mit  GET  fragen  Sie nämlich grundsätzlich immer die
Tastatur ab, egal, ob jetzt eine Taste gedrückt  ist,
oder nicht - GET holt sich immer den aktuellen Tasta-
turstand in  die  ihm  nachgestellte  Stringvariable.
Sollte  also beim Aufruf von GET keine Taste gedrückt
sein, so brauchen wir gar nicht erst  weiterzumachen,
sondern  schicken den Computer gleich wieder auf GET.
Solange bis endlich eine Eingabe gebacht  wurde.  Wir
haben  hier also praktisch eine Endlosschleife produ-
ziert, die erst dann beendet wird,  wenn  eine  Taste
gedrückt wird.                                       
Jetzt  können wir prüfen, welche Taste dies war. Dies
funktioniert ganz  einfach  über  ein  paar  IF-THEN-
Abfragen, siehe auch die folgenden Zeilen:           
70 if a$="[F1]" then 300                             
80 if a$="[F7]" then 200                             
90 if a$="e" then end                                
100 goto 60                                          
Wie die eckigen Klammern ja anzeigen, haben wir hier-
wieder  2  neue  Sonderzeichen,  die   sehr leicht zu
erklären sind. Sie entstehen, wenn Sie innerhalb  der
Gänsefüßchen  die F1- (in Zeile 70) oder die F7-Taste
(in Zeile 80)  drücken.  Diese  beiden  Zeichen  sind
übrigens  gute  Beispiele für die Sonderzeichen, denn
obwohl sie nicht sichtbar sind,  wenn  man  sie  aus-
druckt,  sind  sie  doch relativ wichtig, da man ohne
sie die Abfrage der F-Tasten nur  schwer  realisieren
könnte. Sie könnten hier übrigens ebenso schreiben:  
70 if a$=chr$(133) then 300                          
80 if a$=chr$(136) then 200                          
Dies würde dasselbe bewirken, da die ASCII-Codes  133
und 136 ja den Tasten F1, und F7 entsprechen, die sie
nebenbei auch der ASCII-Tabelle im Bedienungshandbuch
des  64ers,  Anhang F, entnehmen können, oder Sie be-
nutzen ganz einfach SHOWASC.                         
Es wird hier also nach Zeile 300 verzweigt, wenn  der
Drucker  die Tabelle drucken soll, oder zu Zeile 200,
wenn sie auf dem Bildschirm dargestellt werden soll. 
Anschließend kommt in Zeile 90 unseres Programms noch
der Vergleich, ob 'a$' nicht den Buchstaben 'e' bein-
haltet. Ist dies der Fall, so wird das  Programm  mit
END beendet.                                         
Interessant  ist  noch Zeile 100. Hier wird wieder in
Zeile 60 zum GET-Befehl gesprungen,  also  zurück  in
unsere  Abfrageschleife.  Dies  ist  notwendig, da ja
auch noch andere Tasten, als F1, F7 oder e,  gedrückt
worden  sein  könnten - sei es aus Versehen, oder nur
weil der User das Programm einmal ärgern wollte.  War
dies  der  Fall,  so hat der Computer bis in Zeile 90
verglichen und festgestellt, daß keiner der 3  ASCII-
Codes  in ' a$' gespeichert ist. Jetzt würde er ja im
Programm ganz normal weitermachen. Da ich in (der nun
folgenden) Zeile 200 allerdings  das  Modul  abgelegt
habe,  das  die Ausgabe auf den Bildschirm übernimmt,
müssen wir ihn hier dann abgefangen, damit  er  nicht
unkontrolliert  in  eine  Unterroutine reinläuft, was
eben durch jenen besagten Sprung in die Zeile 60 rea-
lisiert wird.                                        
Der zweite Befehl,  den  ich  Ihnen  noch  vorstellen
möchte, heißt ON, und wird in Verbindung mit GOTO und
GOSUB benutzt. Er ist sozusagen eine  spezielle  Ver-
sion des IF-Befehls. Hinter ON folgt eine Formel, die
vom  Computer errechnet wird. Dies ist im einfachsten
Fall eine numerische Variable.  Dann  kommt  entweder
der  GOTO-  oder  der GOSUB-Befehl, gefolgt von einer
Liste mit Zeilennummern, die durch  Kommata  getrennt
werden. Praktisch sieht das etwa so aus:             
20 on x goto 100,200,300,400,500                     
Jetzt wird geprüft,  welcher Wert  in  'x'  enthalten
ist.  Ist  x=1, dann wird die erste Zeilennummer, die
in der Liste steht, angesprungen (wie  wenn  sie  ein
GOTO  100 ausführen würden). Ist x=2 dann wird die 2.
Zeilennummer angesprungen, bei  x=3  die  3.  und  so
fort...                                              
Diese eine  Zeile  entspricht  also  den  5  IF-THEN-
Zeilen:                                              
10 if x=1 then 100                                   
20 if x=2 then 200                                   
30 if x=3 then 300                                   
40 if x=4 then 400                                   
50 if x=5 then 500                                   
Sollte  x gleich 0, beziehungsweise negativ, oder gar
größer als die angegebenen Glieder der Liste sein, so
wird ganz normal im  Programm  fortgefahren.  Wollten
wir  unser  Programm  von vorhin also umschreiben, so
müßte das folgendermaßen aussehen.                   
60 input"Menüpunkt ";x                               
70 on x goto 200,300,400                             
80 goto 60                                           
Das  sieht doch schon gleich viel kürzer aus!  Aller-
dings darf man hier nicht vergessen, daß in Zeile 400
dann auch wirklich noch ein END-Befehl steht, da die-
ser  ja  in  unserem alten Programm direkt in der IF-
THEN-Abfrage kam.                                    
Ich habe hier übrigens ganz bewußt  den  INPUT-Befehl
benutzt, da wir ja gelernt haben, daß man bei GET nur
Stringvariablen einlesen kann. Hierbei haben wir dann
im  Endeffek  keine  Möglichkeit  mit  ON  zu  arbei-
ten, es sein denn man greift zu einem kleinen Trick: 
die Ziffern der Zahlen  sind  nämlich  im  ASCII-Code
alle  hintereinander  angeordnet.  Die 0 hat den Code
48, die 1 den Code 49 und so weiter, bis zur  9,  die
den  Code  57 belegt. Wird bei einer GET-Abfrage also
die 1 gedrückt, so enthält a$ den CHR$-Code 49.  Wenn
wir jetzt von dieser Zahl einfach den Wert 48 subtra-
hieren, so erhalten wir das Ergebnis 1, was ja  genau
die  Taste  ist,  die  gedrückt  wurde, nur haben wir
jetzt einen Zahlwert, mit dem ON etwas anfangen kann.
Das Programm hierzu müßte dann so aussehen:          
60 get a$:if a$="" then 60                           
70 on asc(a$)-48 goto 200,300,400                    
80 goto 60                                           
Hier haben Sie dann auch ein  Beispiel,  in  dem  wir
eine  ganze Formel benutzen, die zuerst berechnet und
dann ausgewertet wird. Wir haben dabei die, uns mitt-
lerweile  schon altbekannte, ASC-Anweisung angewandt,
um den CHR$-Code der in 'a$' gespeicherten  Taste  zu
erfahren.                                            
Wie eingangs schon erwähnt, könnten Sie hier auch den
GOSUB-Befehl verwenden, nur müssen Sie dann Ihre  Mo-
dule auch mit RETURN wieder abschließen. Denkbar wäre
auch,  daß man mit Buchstaben die Tasten abfrägt, wo-
bei man alphabetisch vorgeht. Da der  ASCII-Code  des
Zeichens 'a' den Wert 65 hat, müßten Sie hier nur den
Wert  64 subtrahieren, um brauchbare Zahlwerte für ON
herauszubekommen.                                    
Hiermit möchte ich nun für diesen Monat wieder einmal
schließen und mich bis Mai verabschieden.  Wir werden
uns dann, wie ich diesmal schon angedeutet hatte,  um
etwas höchst wichtiges kümmern, was unerläßlich  ist,
wenn man sich ein wenig mit der Grafik- und Soundpro-
grammierung des C64 beschäftigen möchte. Ich rede von
dem sogenannten Binärsystem  und  dem  Speicheraufbau
unseres kleinen Freundes. Mehr dann  nächsten  Monat.
Bis dann also, Ihr                                   
                                  Uli Basters.       
Valid HTML 4.0 Transitional Valid CSS!