P. 1
Pascal - Eine kinderleichte Einführung

Pascal - Eine kinderleichte Einführung

|Views: 7,729|Likes:
Published by Ralf Westphal
Einführung in Turbo Pascal aus dem Jahre 1985 von Ralf Westphal.

220 Seiten mit mehr als 60 liebevoll handgezeichneten Illustrationen. Außerdem Struktogramme, Listings und graphische Annotationen.

Der Text war ursprünglich als inoffizielles Lehrbuch für den Einsatz in der Schule des Autors gedacht. Dazu kam es dann aber doch nicht... Und auch kein Verlag konnte sich damals für das Manuskript erwärmen. Lehr- und Fachbücher in Deutschland sollten ernsthafter sein.

Mit dem Internet ist nun aber alles anders. Einer Veröffentlichung steht nichts im Wege. Viel Spaß beim Stöbern in einem Text zu uralter Softwaretechnologie.
Einführung in Turbo Pascal aus dem Jahre 1985 von Ralf Westphal.

220 Seiten mit mehr als 60 liebevoll handgezeichneten Illustrationen. Außerdem Struktogramme, Listings und graphische Annotationen.

Der Text war ursprünglich als inoffizielles Lehrbuch für den Einsatz in der Schule des Autors gedacht. Dazu kam es dann aber doch nicht... Und auch kein Verlag konnte sich damals für das Manuskript erwärmen. Lehr- und Fachbücher in Deutschland sollten ernsthafter sein.

Mit dem Internet ist nun aber alles anders. Einer Veröffentlichung steht nichts im Wege. Viel Spaß beim Stöbern in einem Text zu uralter Softwaretechnologie.

More info:

Published by: Ralf Westphal on Aug 22, 2013
Copyright:Attribution Non-commercial

Availability:

Read on Scribd mobile: iPhone, iPad and Android.
download as PDF, TXT or read online from Scribd
See more
See less

01/15/2015

pdf

text

original

Sections

P A S C A L Ei n© kinderleichte Einfuehrung

von Ralf Westphal

WESTPHAL, RALF: PASCAL - Eine kinderleichte Einfuehrung 1. Auflage, 1985 ISBN: leider noch keine

All rights reserved No part of this book may be translated or reproduced in any form without written permission from Ralf Westphal. (c) 1985 by Ralf "Westphal, 3044 Neuenkirchen Printed in Germany

Dem geneigten Leser /'r~,^' zum Geleit Da liegt sie nun vor each: die lang erwartete kinderleichte Einfuehrung in die Programsierspräche PASCAL. denen, die da fragen, uas dieses Heitere Buch zum Thema nun soll, sei gesagt, dass hiermit versucht wird, in (hoffentlich von allen so empfunden) Hitziger und lockerer Meise eine oft als sehr trocken eingestufte Sache leicht, in kleinen Haeppchen, zu vermitteln. Auf jeden Fall einmal nicht sooo bierernst, nie dies in zuvielen Fachbuechern geschieht, welche jedem Neuling das Ler nen nicht unbedingt leichter machen. Schliesslich kann man nicht von jedermann ernarten, dass er freinillig eine Programmierspra che lernt. Das Buch soll KEINE komplette Einfuehrung in die allerletzten Feinheiten von PASCAL sein/ Es soll KEINE Einfuehrung fuer Leute sein, die schon 5 Programmiersprachen beherrschen und nun eine sechste lernen Hollen. Es soll KEINE Einfuehrung sein, die auch in die Tiefe der theoretischen Informatik hinabstoesst und viel leicht Effizienzabschaetzungen fuer verschiedene Such- und Sor tieralgorithmen liefert. Es soll demjenigen eine Einfuehrung in PASCAL bieten, der bis her uenig oder keine Ahnung von Informatik hatte. Es soll die verirrten BASIC-Hacker auf den Pfad der Tugend bringen. Es soll die Grundlagen legen, die ein Verstaendnis weiterfuehrender Lite ratur ermoeglichen. Es soll Spass machen/ Jooo, das waer's wohl auch schon. Reicht. Hie schon ernaehnt, hier uird kein Anspruch auf {/ollstaendigkeit erhoben. Derjenige, der in die letzten Feinheiten eindringen moechte, sollte zusaetzliehe Buecher bezueglich PASCAL studieren. Davon abgesehen uird hier ein PASCAL-Dialekt benutzt (TURBOPASCAL), der znar sehr verbreitet, aber eben z.B. nicht auf Grossrechenanlagen verfuegbar ist. Bei Besonderheiten Hird jeneils darauf hingewiesen und ein Konsultieren der eigenen Handbuecher empfohlen. Bevor Ihr anfangt, sei Euch noch das Kapitel 3.11. ans Herz gelegt. Ihr koennt es ruhig schon zu Beginn der Lektuere lesen, auch Nenn das Verstaendnis fuer die Beispiele noch fehlt. Der Inhalt ist sehr nichtig und sollte schon bei Eurem ersten PASCALProgramm Anwendung finden. Lange Rede, kurzer Sinn, fangt einfach 'mal an. Mein Dank fuer die Unterstuetzung bei der Erstellung dieses Buechleins gilts Herrn Ralf Lange und dem Gymnasium Sol tau sowie ganz besonders Heloe Baumann, mit dem zusammen die ersten einein halb Versuchsmanuskripte in tagelanger Arbeit mit viel Spass ge schaffen Hürden. Neuenkirchen im Juli 1985 Ralf Westphal

INHALTSVERZEICHNIS Kapitel 1. 1.1. Ueberschrift Harte Schale Alles u. was neue Begriffe Kern kann Seite 1 1

Weicher man

Hardware oder Hardware, CPU

anfassen

1.2. Software oder Was man sich so alles ausdenken kann 3 Sofware, Maschinencode, warum PASCAL 1.3. 1.4. Der Algorithmus, Noch bei dem jeder mit muss 5 8

Schrittweise Verfeinerung, Struktogramme
einige Formalitaeten

Grammatik, Syntaxdiagramme

Das Programm Aufsucht und PROGRAM, BEGIN, END, Kommentare, Block, Name

Hege

12

3.

Man

nehme

-

oder

Sprachkonstrukte

15

3.1.

Wie

saqt

es

mir

mein

Computer

15

HRITEÜN), String, Character 3.2. Konstanten und ein kindgerechtes Spei ehermodel1 20

CONST, Konstanten, Vereinbarungsteil
3.3. Es ist doch nicht alles so konstant wie's aussieht 23 oder ... VAR, INTEGER, REAL, READ(LN), Variable 3.4. 3.5. Es Niedere laesst bitten: Weisung Seine Mathematik Herrlichkeit, die Wertsu30 34

DIV, MOD, SIN, COS usw., Standartfunktionen

:=, Wertzuweisung
3.6. 3.7. 3.8. 3.9. 3.10. Die Von Verzwicktes
I F, T H E N , E L S E

mit und nichts

Verzweigungen als die Wahrheit Computers oder Anfang ...

37 46 5fi 60 &6

Wahrheit den

T R U E , FA L S E , B O O L E A N , A N D , O R , N O T, > , < , . . .

Charaktern

unseres

CHAR, ORD, CHR

Etwas Das
WHILE, DO

Computer-Makramee Ende am

REPEAT, UNTIL

3 . 11 . P r o g r a m m i e r u n g i s t a u c h e i n e S a c h e d e r A e s t h e t i k 6 9 Optische Gliederung 3.12. 3.13. Es Da
FOR, TO, DOUNTO, DO

capo zu Tisch qebeten

73 79

wird

CASE, OF, ELSE

3.14. 3.14.1.

" E y,

was

is'n

das

fuer'n

Typ?..."

86 87
90 92 94 102 105

Skalartypen
SUCC, PRED, ORD

3.14.2. 3.14.3.
TYPE

Unterbereichstypen Neue In
ARRAY, OF, MAXINT

Typen Linie in

definieren angetreten...

3.15. 3.15.1. 3.15.2.

Wir entschwinden Mehrdimensionale Felder Aqainst

hoehere

Dimensionen

all...

Standarts

'STRING, LENGTH, CONCAT, COPY, POS, DELETE, INSERT, CLRSCR, CLREOL, GOTOXY

3.16. 3.17. What

Eine
S E T, O F, I N

Menge 'a Records

Neues d ' Ya have?

11 4 123

Kind

RECORD, END

3.18.

Von

oben

nach

unten

in

PA S C A L

128

3 . 1 8 . 1 . " T h e s a m e p r o c e d u r e a s e v e r y y e a r, J a m e s ! " 1 3 0
PROCEDURE

3.18.2.

Frisch

geschachtelt

ist

halb

gewonnen

136

3.18.3. Rin in's Unterprogramm, 'raus aus'rn Unterprogramm 143 3.18.4.
3.18.5.

Und
FUNCTION

jetzt

noch
nur fuer

mehr

Eigenes

151
161

Rekursionen

Schwindelfreie

FORWARD, (*$A-*), (#*A+*)

3.19. 3.19.1.
3.19.2. 3.19.3.

Wir
FILE, OF

schaffen Die
Wir Wir

fuer

die

Ewigkeit beginnt
lesen

166 167
170 174

Buerokratie
lernen lernen

ASSIGN, RESET, READ, EOF, CLOSE

schreiben

REWRITE, WRITE

3.19.4. 3.19.5.

Der

elektronische

Brief Schrecken

181 186

TEXT, READLN, WRITELN, EOLN

Ende ohne C**jT-*>, f**/*#->, IORESULT

> 1. Die
WITH, DO

Appendix

<

203 204

HJTH-Anweisung

2.
* , N I L , N E W, D I S P O S E

Zeiger

206

Literaturl

iste

210

Stichwortverzeichnis

am

Ende

Harte Schale - Weicher Kern
1.1 Hardware oder Al1es was man anfassen kann

Claus-Peter-Uwe frueher:

Das ist Claus-Peter-Uwe. Claus-Peter-Uwe arbeitet hier in seinem Buero. Er wartet auf einen Anruf von seinen Chef. Der Chef sagt ihm dann, was er tun soll.

Hier ist der Anruf von seinem Chef. Claus-Peter-Uwe schreibt eifrig mit. Nun weiss er, was er tun soll. Jetzt wartet er nur noch darauf, dass er anfangen darf.

Jetzt geht's los. Zuerst legt er sich alles, was er braucht zu recht, und dann faengt er an zu arbeiten: Er rechnet, er schreibt, er ruft an, er wuehlt sich durch Kart e i k a e s t e n , r e n n t i n s A r c h i v, r e n n t w i e d e r z u r u e c k , e r l e e r t A b l a g e k a e s t e n , f u e l l t s i e w i e d e r a u f u s w. . . .

Claus—Peter—Uwe ist fertig (man sieht's). Er hat alles so ge Nun ruft er diesen an macht, wie sein Chef es ihm gesagt hatte, und sagt ihm, dass er alles erledigt hat.

£ ^
C.l aus—Peter—Uwe heute:

Vo n s e i n e m C h e f w i r d e r l i e b e v o l l C P U g e n a n n t . D a s i s t n e u hochdeutsch und heisst Central Processing Unit <. = Zentrale- Ver arbeitungseinheit ) . Diese Zentraleinheit ist das Herz eines jeden Computers und verantwortlich fuer die korrekte Ausfuehrung aller Befehle, d.h. sie kuernrnert sich um eure Programme. C P U i s t h e u t e v i e l , v i e l s c h n e l l e r a l s f r u e h e r, a b e r, u n d d a s ist der Haken, man muss ihm ganz genau sagen, was er tun soll (manchmal werdet ihr euch schon wundern, wie strohdumm CPU heute ist!! ) . S e i n Te l e f o n i s t j e t z t e i n B i l d s c h i r m m i t Ta s t a t u r, a u f d e m d e r Chef seine Befehle eintippt, die CPU in seinem Speicher ablegt und nachei nander abarbeitet., Speicher — ob die kleinen Chips (nein, keine Paprika—Chips) oder die mehr oder weniger grossen, sich wie wild in einem Kasten d r e h e n d e n S c h e i b e n ( D i s k e t t e n o d e r e i n f a c h F l o p p i e s ) — , Ta s t a t u r, D r u c k e r, B i l d s c h i r m o d e r C P U s e l b s t , d a s a l l e s g e h o e r t z u r HARDWARE - man kann's anfassen -.

l.:

Software oder Was man sich so alles ausdenken kann

Jetzt kommen wir so allmaehlich zu dem, was euch eigentlich interessiert, den Programmen, die ihr schreiben wollt - auch SOFTWARE genannt -. Sie machen das Wesentliche an einem Computer a L i s , o h n e s i e g e h t n i c h t s . S e l b s t d e r t o l l s t e R e c h n e r, z . B . e i n Apple oder C-64 Cho ho ho), ist nutzlos, wenn kein Mensch sich erbarmt, ein Programm fuer ihn zu schreiben. Ihr wisst: die Programme werden von CPU ausgefuehrt. Das un gemein Laestige daran ist: CF'U versteht nur Zahlen als Anwei sungen. Ja, ihr koennt es ruhig glauben, nur Zahlen; dafuer ist er aber ungeheuer schnell. Ein Beispiel:
OEOOi 0E03: OE06: OE07: OEOAi OEÖB:

2A 11 19 22 C9 Ol

O B O E O A 00 00 00 00

Ve r w i r r e n d , g e l l ? D a s i s t e i n k l e i n e s B e i s p i e l , w i e s o e i n e Anweisungsfolge aussehen koennte, die CPU verstehen wuerde. Sie ist im sogenannten MASCHINENCDDE gesc*hrieben. Zu allem Uebel muss man die Zahlen in einem anderen Zahlensystem eingeben als wie man es sonst benutzt. Normal ist das Zehnersystem, hier jedoch wird das Sechzehnersystem benutzt (HEXADEZIMALSYSTEM). Zu kompliziert? Das dachten sich schon Leute vor euch und haben 'was besseres er funden... Die naechste Stufe:
LD LD A D D LD RET
ZAHL: DEFW HL, (ZAHL) DE, 10 HL, DE (ZAHL), HL

1

Schon vertrauter, man sieht sowas wie Worte usw. ihr versteht immer noch nichts' Das ist kaum verwunder Was, lich. Man hat naemlich die Zahlenkombinationen nur ein ganzkleinwenig zusammengefasst und den Befehlen Kuerzel als Namen gegeben: LD fuer LADE, ADD fuer ADDIERE usw.; frueher einmal war das eine gewaltige Verbesserung gegenueber den vermalledeiten Zahlen. Schlaue (nein, vielmehr faule) Programmierer und Wissen schaftler sannen letztendlich jedoch auf mehr Komfort... u n d h i e r i s t PA S C A L ( t r a r a t r a r a ) :
ZAHL ZAHL + 10

To l l , n i c h t ? I h r v e r s t e h t a u f A n h i e b w a s d a s b e d e u t e n s o l l , naemlich der Wert der Zahl ZAHL (wie immer er sein mag) soll um 10 erhoeht werden.

"Warum muss man denn dann PASCAL als Sprache erst Ich kann doch Deutsch! Versteht CPU das denn nicht mit ein wenig Muehe)?" Jeder weiss: Muehe allein qenueqt nicht!

entwickeln? (vielleicht

Eure Anweisungen muessen CF'U erst mal verstaendlich gemacht wer den, indem sie in seine Zahlensprache (Maschinencode) uebersetzt werden. Das muss schnell und einfach moeglich sein; ihr wollt d o c h n i c h t Ta g e d a r a u f w a r t e n , d a s s d e r C o m p u t e r e n d l i c h e t w a s fuer euch tut. Deutsch oder Englisch sind dafuer aber viel zu komplex und mehrdeutig! Was heisst z.B. DER GEFANGENE FLOH ? Na, hm, ohne Kontext und Gross-/Kleinschrift kommt man nicht darauf. Und ge rade das ist es, was wir von CPU nicht verlangen koennen, wozu er/es/sie zu dumm ist: zu VERSTEHEN! CPU fuehrt nur aus, versteht aber niemals! ! ! ! ! ! ! ! PASCAL ist hier der Retter in der Not. Mit dieser Sprache kann (ttar\ einfach, praezise, strukturiert (spaeter mehr davon) Programme schreiben, die sich fast wie von selbst uebersetzen l a s s e n ( g e g e n u e b e r D e u t s c h o d e r s o ) . I h r muesst das mal so glaub e n i m Ve r l a u f d i e s e r E i n f u e h r u n g w e r d e t ihr dem immer mehr zu stimmen koennen - j a , j a , a u c h d i e B A S I C - J u e n g e r d o r t i n d e r letzten Reihe -. Anmerkung: BASIC (gesprochen: Baessig) ist auch so eine Spra che, von der viele meinen, man koenne mit ihr toll programmieren. Stimmt sogar; man kann damit verdammt lange, komplizierte Pro g r a m m e s c h r e i b e n . A b e r d a s Ve r s t e h e n d i e s e r P r o g r a m m e s i e h t ungefaehr so aus: Ve r s t a e n d n i s e i n e s B A S I C - P r o q r a r n r n s = 1 Zeilenzahl des Programms' A c h , j a , z u a l l e m U e b e r fl u s s i s t PA S C A L n o c h l e i c h t e r l e r n b a r und bietet Moeglichkeiten zur Algorithmenformulierung fuer eine g r o s s e V i e l z a h l v o n P r o b l e m e n , s e i e s F i n z a n z b u c h h a l t u n g , Wa l z werksteuer ung, Muttis Kuechenverwaitung oder die Realisation eines Spiels. So, jetzt geht's an's Eingemachte...

4

1.3. Der Algorithmus, bei dem jeder mit muss Wir erinnern uns ans Claus-Peter-Uwe, den freundlichen Herrn mit Schreibtisch? Nun gut. Damals wie heute hat der Chef sicher ein Poblem, zu dessen Loesung er Claus-Peter-Uwe bemueht. Nehmen wir einmal artT der Chef wollte Kaffee fuer eine Be sprechung haben. Nun ist Claus-Peter-Uwe ein Hausmann mit zwei l i n k e n F u e s s e n , d e r i m N o r m a l f a l l s o g a r d a s Wa s s e r a n b r e n n e n laesst. Daher muesste der Chef ihm ganz genau erklaeren, was er wann wie tun soll. Dazu zerlegte er das Problem "KAFFEKOCHEN" in mehrere Einzelprobleme, als da waeren: 1. 2. 3. 4. 5. 6. 7. 8. 9. Wasser holen geholtes Wasser in die Kaffeemaschine giessen Filtertuete in den Filtereinsatz tun proportional zur Menge des geholten Wassers Kaffee in den Filter loeffeln Filter auf die Kanne setzen F i l t e r u n d K a n n e k o r r e k t i n K a ff e m a s c h i n e e i n f u e g e n Maschine einschalten warten w e n n K a ff e e d u r c h g e l a u f e n , d a n n s e r v i e r e n

Das komplexe Problem "KAFFEEKOCHEN" ist durch die Unterteilung konkreter und uebersichtlieber geworden. Sollte ein Tei1 problern immer noch zu kompliziert sein, so kann es noch weiter aufgespalten werden. Z.B. Punkt 1«, Wasser holen: 1.1 1.2 1.3 1.4 Kanne greifen mit Kanne zum naechsten Wasserhahn eilen Kanne mit Wasser fuellen mit gefuellter Kanne zurueckeilen

Dieses Spielchen kann man bis zur Haarspalterei treiben. Man nennt es allgemein die Methode der SCHRITTWEH SEN VERFEINERUNG. Obiges Beispiel mag trivial erscheinen; bei groesseren Proble m e n i s t d i e s e Vo r g e h e n s w e i s e d e s s c h r i t t w e i s e n Ve r f e i n e r n s — d . h . alle Problempunkte, die noch zu unuebersichtlich sind in kleinere Unterpunkte zu teilen, deren Loesung einfacher ist- jedoch von grossem Nutzen. Ein solches von ten eines guten wenn man sich 5 in welcher Form Also: 1. Ich soll ein Referat halten (wird weiter verfeinert) 1.1 Ich erarbeite das Referat (wird weiter verfeinert) 1.2 Ich halte das Referat 1.1.1 Ich praezisiere die Problemstellung des Referatsthemas (was will der Lehrer eigent lich hoeren?) vielen Lieber sc haetzt es Problem ist das Erarbei Referates. Dies erledigt sich fast von selbst, (fuenf) Minuten Zeit nimmt und ueberlegt, was und man vermitteln will (soll).

1.1.2 Ich trage mein Wissen zum Thema zusammen 1.1.3 Ich ziehe bei gravierenden Luecken weitere Quellen heran 1.1.4 Ich ordne das ganze Material 1 . 1 . 5 I c h r e d u z i e r e d a s M a t e r i a l a u f d a s We s e n t l i c h e 1 . 1 . 6 I c h b e r e i t e d a s M a t e r i a l a u f z u r Ve r m i t t l u n g S e h t i h r, s o e i n f a c h i s t d a s . U m a b e r w i e d e r i n R i c h t u n g C o m puter zu kommen, denn darum soll's ja eigentlich hier gehen: Beim Entwurf einer Anweisungsfolge, die schliesslich als Pro gramm von unserem Computer ausgefuehrt werden soll, bedienen wir uns der gleichen Vorgehensweise, wie wir spaeter noch sehen wer den. Dazu jedoch jetzt schon einige optische Gliederungsvorschriften, wie sie auch von Profis (ja, ja) benutzt werden: - Um jedes Teilproblem wird ein Kaestchen gezeichnet.
+ 1 ! Teilproblea 2 ! + + I Teilproblem 3 ! i

+ I Teilproblea 1 i + 1

+

+

Diese Kaestchen (Bioecke) werden in richtiger Reihenfolge untereinander angeordnet (Das, was zuerst getan werden s o l l , k o m m t o b e n d r a u f , w a s f o l g e n s o l l , k o m m t d r u n t e r u s w. )
+ f

i Teilprobleo 1 ! t 1 ! Teilprobleo 2 ! + + ! Teilproblea 3 ! t +

F a l l s Te i l p r o b l e m e n o c h e i n m a l a u f z u t e i l e n s i n d , s o l l t e d i e s i n g l e i c h e r We i s e d u r c h g e o r d n e t e K a e s t e n g e s c h e h e n .
+ + ■ Teilproblea 1 ! + + + + ! Teilproblea 2 ! <—+ / ! Teilproblea 2.1 I + 1 + < + + I Te i l p r o b l e o 3 ■ \ ! Te i l p r o b l e o 2 . 2 i + + i +

F'raktischerweise ist jedem Kastenstapel eine Ueberschrift zu geben, die das mit ihm zu loesende Problem charakterisiert.

Grossprobles: + + ! Teilproblea 1 ! + + ! Teilproblea 2 I + + I Teilproblea 3 I + +

Diese Blockdiagramrne werden allgemein STRUKTQGRAMME oder auch NAS5I-SCHNEIDERMANN-Diaqramme genannt. Die Aufteilung in solche Bioecke nennt man STRUKTURIERUNG. Schon den alten Roemern scheinen Struktogramrne gelaeufig ge wesen zu sein, auch dort hi ess es: Divide et impera ( Teile und herrsche ) Auch fuer den Computer rnuesst ihr die zu loesende Aufgabe in kleine Haeppchen aufteilen. Diese muessen noch einfacher und de taillierter sein als wie die obigen, da der Rechner viel unintel ligenter ist als Claus-Peter-Uwe. Und eben diese ganzen kleinen Haeppchen, die Anweisungsfolge, die eure Aufgabe loesen soll, die nennt man ALGORITHMUS. Und ein PROGRAMM ist ein Algorithmus in einer fuer den Rechner verstaendlichen Form, d.h. in einer Sprache, die er versteht ( f u e r u n s PA S C A L ) .

Auf zur naechsten Stufe:

1.4.

Noche i n ige Forma1itaeten

Tja, da kommen wir nicht drumherum.

Es sieht so aus: wenn i h r e i n P r o b l e m h a b t ( e i n q a n z t o l l e s n a t u e r l i c h , u n g e h e u e r s c h w e r u s w. ) u n d d a f u e r e i n e L o e s u n g a u f eurem Rechner programmieren wollt, dann entwerft ihr einen waaaaahnsinnigen Algorithmus und uebertragt ihn in die Sprache PA S C A L , d a m i t d e r C o m p u t e r m a l ' w a s z u t u n b e k o m m t .
Dabei ist aber auch eine Grammat i k zu beachten - wie im Deut schen oder Englischen -, d.h. ihr koennt nicht einfach sagen was ihr wollt, sondern ihr muesst euch an Konventionen halten: die PASCAL-ör ammat i k. Wenn ihr natuerlich zu Hause auch sagt "Nicht meine ess' Suppe ich!", dann gebt diese Einfuehrung doch bitte an einen anderen W i s s e n s d u r s t i g e n w e i t e r, s c h a d e e i g e n t l i c h . Nein, ihr seht, man muss sich schon in einer Sprache an eine Grammatik halten, sonst versteht man ja gar nichts mehr; und ge n a u s o i s t e s i n PA S C A L , n u r d a s i n d d i e R e g e l n l a n g e n i c h t s o kompliziert, dafuer aber strenger! S i n n d i e s e s K a p i t e l s i s t e s n u n , d i e S Y N TA X D I A G R A M M E e i n z u f u e h r e n . S Y N TA X b e d e u t e t s o v i e l w i e G r a m m a t i k . Diese ominoesen Syntaxdiagrarnme geben in toll uebersichtl icher F o r m a n , w i e i h r b e s t i m m t e PA S C A L - W o r t e u n d K o n s t r u k t e z u s a m m e n setzen duerft, damit ein zumindest syntaktisch richtiges Programm herauskommt. Ein Beispiel: satz:
verb: ->--■>---; STEHE )-->r->—' 6EHE i—>-

,'~"\ * + ♦ * —>--■{ ICH ;—>—! verb !—>-r—! ort i--r—>-

L < L
ort: ->--•\ IH HAUS r-

( N I C H T J -

> -

->--t">~v IH GARTEN J--->---f-->--->--{AUF DER STRASSE)-1

Hiermit koennen eine Menge nuetzlieber Saetze erzeugt Jedermann kann an seinem eigenen Grarnmatikverstaendnis ob sie korrekt sind; ist das so, dann sind sie auch den die dieses Syntaxdiagramm vorgibt, entsprechend gebildet

werden. pruefen, Riegeln, worden.

D a b e i b e d e u te t e i n Wo r t o d e r Ze i c h e n i n e i n e m K r e i s ( o d e r r u n den Kasten), dass man dieses Zeichen so, wie es dort steht, in den Satz uebernehmen muss. Siehe dazu auch ICH und IM GARTEN usw.

8

Ein ECKIGER Kasten bedeutet dass man IM EINER DEFINITION MIT DEM NAMEN der in ihm steht, nachschauen muss, was man einsetzen darf (wie's weitergeht). Als Laie kann man sich eine Eselsbruecke bauen, indem man die Darstellung als Strassenplan betrachtet, in welchem es Ein bahn Strassen und Anschlussplaene gibt. Dann wuerde obiges Beispiel etwa so aussehen.

?» erUubc: T» aehe Plan: ^ Siehe Plan; ^f» ICH
V£RB

DPT

4

Es sind alle Saetze erlaubt, die dadurch gebildet werden koen nen, dass ihr den Regeln der STVO folgend von links nach rechts durch das Syntaxdiagramm fahrt. Will sagen: nicht falschherum in eine Einbahnstrasse, nicht links abbiegen, wo nur rechts erlaubt i st usw. Ein "siehe Plan so-und-so" bedeutet, ihr rnuesst in dem ange g e b e n e n Pl a n n a ch sch a u e n , w a s i h r a n d e r Ste l l e tu n d u e rft, w i e 's weitergeht auf der Strasse. "erlaubt: so-und-so" sagt euch, welches Symbol oder Zeichen ihr in euren PASCAL-Satz aufnehmen rnuesst, um einen grammatikalisch korrekten zu bekommen. Z u r Ve r d e u t l i c h u n g e i n i g e g u e l t i g e S a e t z e , d i e n a c h d e m D i a gramm erzeugt werden koennen: ICH GEHE NICHT IM HAUS ICH STEHE IM GARTEN IM HAUS ICH GEHE IM HAUS AUF DER STRASSE IM GARTEN IM HAUS So koennten wir das Spielchen weitertreiben. Es ist jedoch schnell zu sehen, wie aus den Regeln tolle deutsche Saetze gebas telt werden koennen, die nicht unbedingt inhaltlich wirk l i c h k e i t s n a h s i n d , a u f a l l e F a e l l e a b e r G R A M M AT I K A L I S C H k o r r e k t , was ja das wichtigste ist.

H a l t , j e t z t d i e G e g e n s e i t e , e i n i g e U M G U E LT I G E B e i s p i e l e ( m i t Erklaerunq): ICH IM HAUS (es wurde nicht im Plan verb nachgeschaut, was einzusetzen ist, sondern einfach mit ort weiter gemacht ) ICH GEHE STEHE GEHE IM HAUS (nach GEHE in verb kann man nur in Richtung A u s g a n g v o n v e r b w e i t e r f a h r e n , m e h r e r e Ve r ben sind nicht moeqlich) Auf jeden Fall solltet ihr die Interpretation solcher Syntax diagramme verinnerlichen; sie tauchen alle nas'lang in der Profiliterattir auf. Sieht nur so kompliziert aus, ist aber eine erhebliche Er leichterung beim Erklaeren einer neuen Regel. Uebung macht auch h i e r d e n M e i s t e r. N o c h e i n B e i s p i e l , w e i 1 ' s f u e r d a s Ve r s t a e n d n i s s o w i c h t i g i s t : Jetzt die Bildung eines mathematischen Ausdrucks, in dem ganze Zahlen und die Operationen + und - vorkommen duerfen.

zahl: —>-7-l Ziffer :~r—>— -+ V

Ziffer:
.>__.

-\°

+ 1 r—f
♦_/£\_4 U S W .

ausdruck: + i —>--! zahl !+ +

operator: "v.*/ ...).
i

.„' . *l i

_

I

. t + t + | + ! zahl !—<—! operator !—+
t + * +

Sieht schon komplizierter aus, nicht wahr? Aber keine Sorge, ihr wisst doch, wie ein mathematischer Andruck aussieht, koennt also daran pruefen, ob ihr beim Durchgehen des Syntaxdiagramms und Ermitteln der gueltigen, damit erzeugbaren Ausdruecke einen F e h l e r g e m a c h t h a b t . . E i n e Ve r t i e f u n g d e s G e l e r n t e n e r f o l g t i n d e n weiteren Kapiteln, keine Angst.

10

Hier einige gueltige Ausdruecke nach dem letzten Syntaxdiagramm: 2 oder 12+2 oder 1+2-3+4-5+ 10000

Soweit die korrekten, jetzt ein paar ungueltige: 2+ (ihr seit nach operator nicht in zahl hineingegangen) 2+1) (woher soll denn die Klammer kommen?) 2+-1 (wer in operator war muss sofort 'raus dort; danach kann nur eine Zahl folgen!!) +12 (wer einen Ausdruck erzeugen will, der muss zuerst durch zahl durch!!) Mal ueberlegen... Ja, jetzt habt ihr das Ruestzeug um so r i c h t i g i n PA S C A L e i n t e i g e n z u k o e n n e n . V i e l l e i c h t r e k a p i t u l i e r t ihr noch 'mal die neu gelernten Beqriffe (ALGORITHMUS, MASCHINENCODE usw.) und Techniken (SCHRITTWEISE VERFEINERUNG, SYNTAXDIAGRAMME). Und dann auf ins naechste Kapitel...

11

Das Programm - Aufzucht und Hege In diesem kleinen Kapitel wollen wir schnell noch denen Recht geben, die da meinen, Informatik oder Programmieren sei eine sehr formalisierte Sache. Hier fuehren wir naemlich einige Regeln ein, die ihr immer beim Schreiben eines PASCAL-Programmes beherzigen m u e s s t . I s t n i c h t v i e l , a b e r. . . Wir setzen das Ganze noch vor das erste grandiose Prograrnmierprojekt (halt, nicht nach vorne schielen und schauen, was es ist), damit spaeter nicht immer die Frage kommt, warum, wieso einiges immer wieder in den Programmen auftaucht, aber nie erklaert wurde. Selbst Claus-Peter-Uwe hat sich solche Regeln gegeben: Er lobt s i c h s e i n e n Ta g e s a b l a u f , d e r f o l g e n d e r m a s s e n a u s s i e h t : - Arn Morgen setze ich ein Motto fuer die Tagesarbeit (z.B. Aufraeumen oder Pause oder Rechnen) - Dann lege ich mir die Dinge zurecht, mit denen ich waehrend des Tages arbeiten werde (Akten, Taschen r e c h n e r, K a r t e i k a r t e n u s w. ) - F o l g e n d u e b e r l e g e i c h , w e l c h e Ta e t i g k e i t e n i c h z u verrichten habe (Kaffee kochen, Akten durcharbeiten, Pause machen usw.) - Und dann, ja, dann mache ich den Plan, wie ich mir die ganze Arbeit ueber den Tag verteile, was ich wann tun w e r d e ( e r s t K a ff e e k o c h e n , d a n n A k t e n d u r c h a r b e i t e n , dann Diktat aufnehmen, Pause, Mittagessen, Aufraeumen, Feierabend oder aehnlich) In der Kunst des Programmierens mit PASCAL sieht das nicht ganz so schoen aus, wir rnuessen uns (wie immer) an eine Grammatik halten und schreiben:
PROGRAM dies und das tun;

(* hier die Dinge, mit denen ich 'was tue *) BEGIN (* hier der tolle Algorithmus, also, wie ich mit den oben aufgelisteten Dinge 'was mache #)
END.

Zunaechst 3 zu verinner 1 ichende Dinge: 1. PROGRAM, BEGIN, END sind Symbole der Sprache PASCAL! Wie die Worte Haus und Baum zum Deutschen gehoeren, so gehoeren sie zu PASCAL. Diese, und alle noch zu lernenden PASCAL-Symbole, schrei ben wir immer qross! 12

N e b e n b e i : ' ; " u n d " " u s w . s i n d a u c h PASCAL-Symbole, wir s c h r e i b e n s i e a b e r n i c h t g r o s s ( Ve r z e i h u n g ) , ein NAME oder BEZEICHNER ( j a , s o h e i s s t diesunddastun ist den das b bei ei u uns n s nunmal), nunmal), d en wir uns selbst ausdenken durften. Er entspricht Erwin oder Anabella im Deutschen, sie gehoeren ja auch nicht zur Sprache. Wir schreiben Namen (Bezeichner) immer klein. MERKE: ein Name darf nie so geschrieben werden wie ein SYMBOL (waere ja Quatsch wie: "haus GING IN DAS HAUS" oder so) 3. Die PASCAL-Symbole (* und *) schl Jessen einen Kommentar ein, den der Programmierer in das Programm einfuegt, um zu erlaeutern oder zu unterteilen. Ein Kommentar kann ueberall im Programm stehen, wo ein PASCALSymbol oder ein Bezeichner auftauchen darf; der Rechner interes s i e r t s i c h n i c h t f u e r 5 P f e n n i g d a f u e r. K o m m e n t a r e s i n d n u r i n t e ressant fuer Leute, die das Programm schreiben oder aendern wol len. Kommentare werden durch (* eingeleitet und reichen bis zum naechsten *) im Programm! Der gewissenhafte Leser wird sicher eine beabsichtigte Uebereinstimmung des geregelten Programmaufbaus mit Claus-Peter-Uwes Tagesplan entdeckt haben. Genau: diesunddastun ist unser Motto, es muss immer am Programmanfang stehen; danach folgt das Zurechtlegen der Dinge, mit denen etwas getan werden soll (wie das geht kommt spaeter) und zum Schluss noch unser geliebter Algorithmus, d.h. wie tue ich was mit den zurechtgelegten Sachen (steht dann zwischen BEGIN
und END).

Dieser formale Programmaufbau soll uns das strukturierte Schreiben von professionellen Programmen naeherbringen und mehr Uebersicht schaffen. Eigentlich doch eine gute Sache. D a r u m f o l g t h i e r d a s S y n t a x d i a g r a m m d a f u e r. I h r r n u e s s t e s n i c h t auswendig lernen oder so, nein, behaltet bloss gut, dass es hier steht, damit ihr es spaeter findet, wenn wir mal d'rauf zurueckkommen, denn noch ist nicht alles so vollstaendig erklaert: prograaa:
+ + + +

progranokopf:
+ +

—>—! prograoukopf !-• ->—! block !- . > . . . + + + +

->— PRQ8RAH

->—i progrananaae !—>--- > " >

block: + + + + ->—! vereinbarungsteil !—>—! anweisungsteil !—>
+ + + +

vereinbarungsteil: kosot spaeter, keine Sorge

13

anweisungsteil:

...naae:

^— + + + 1 t i ■{ BEGIN y—>—T--i anveisung !-;—>-~ END }--> —>—! buchstabe !—> 7-! buchstabe !-;---V _ s * + + ! ^ s t + j \f i + a u

V Vr>~<-~

* ! ""I

!

* Ziffer

+ —<

+

+ !-

Ta u c h t i r g e n d w o e i n e c k i g e r K a s t e n a u f , i n d e m e i n Wo r t s t e h t , welches mit ...naae endet ( z.B. prograaanaoe ), so ist die obige Definition ...naae zu verwenden. D.h. sei bstzuwaehl ende Bezeichner muessen mit einem Buchstaben beginnen und koennen mit Buchstaben oder Ziffern fortgesetzt werden (in bunter Mischung); Sonderzeichen sind nicht erlaubt! Die fast wichtigsten Dinge an diesem Diagramm sind der Punkt am Ende -ihr duerft ihn nie vergessen- und die Semikolons. Sie tauchen immer wieder auf (etwa wie's Komma im Deutschen). So, um auch die letzten Ungeduldigen zu beruhigen folgt nun endlich das erste PASCAL-Programm zum Eintippen und Freuen...

14

Man _ nehme .. -.....Pder Sp r a c hJkonst r u k t e

!. 1

Wie sagt es mir mein Computer

Da so sehr viel ueber die Seelenlos!gkeit der armen Computer geklagt wird, haben wir (und ihr) uns vorgenommen, den Rechner etwas menschlicher erscheinen zu lassen (wohlgemerkt erscheinen lassen, er ist es nicht!). Denn frustrierend nimmt es sich aus, wenn man sich ZLir Arbeit mit ihm anschickt, und er hat nur ein muedes READY oder ">" fuer uns uebrig. Wa e r e d o c h s c h o e n e r, w e n n e s e i n P r o g r a m m g a e b e , w e l c h e s , w e n n wir es laufen Hessen, uns mit einem freundlichen Gruss entgegen kaeme und unseren Namen kennen wuerde, nicht wahr? E i n Vo r s c h l a g , d e n w i r m a l s o u n v e r b i n d l i c h v o r b r i n g e n w o l l e n , ist das folgende Programm: PROGRAM freundlichsein} BEGIN
WRITELN; WRITELN;

WRITELN ( 'Heute ist der ', 21, ' .', 2, ' .', 1985 ); WRITELN ( ' Hallo, hallo, einen wunderschoenen guten ', 'Tag wuensche ich/' ); WRITELN; WRITE ( 'Ich freue mich schon sehr auf die ' ); WRITELN ( 'interessante Zusammenarbeit mit ' ); WRITELN ( 'Dir, meine liebe Erika Mustermann.' );
WRITELN;

WRITELN ( 'Dann wollen wir mal...' );
END.

Ihr rnuesst doch zugeben: ein sehr sehr angenehmes Programm, und zudem ist es auch noch lehrreich! Ihr lernt naehmlich die PASCALAnweisung kennen, mit der uns der Rechner etwas auf den Bildschirm schreiben kann. Im Englischen heisst "schreiben" natuerlich "write"; und in den Wissenschaften ist es nunmal ueblich, moeglichst viel ganz toll international auszudruecken, und da bedient man sich des Englischen. Will sagen: in PA S C A L und vielen anderen Programmiersprachen kommen eigentlich nur englische W o r t e a l s v o r d e fi n i e r t e S p r a c h s y m b o l e v o r.

Vo r d e r g e n a u e n B e s c h r e i b u n g m a l s c h n e l l n o c h d a s , w a s d e r Computer so ausgibt, wenn ihr das Programm laufen lasst (tut ihr ja sowieso, oder?):

-Heute ist der 31.2.1985 - Hallo, hallo, einen wunderschoenen guten Tag wuensche ich/ -Ich freue mich schon sehr auf die interessante Zusammenarbeit mit -Dir, meine liebe Erika Mustermann. -Dann wollen wir mal...

So rnuesste es bei euch auf dem Schirm aussehen. Die "-" vor jeder Zeile erscheinen natuerlich nicht; sie zeigen hier nur an, dass das Programm eine Zeile geschrieben hat. Aufgeschlossen wie ihr seid, habt ihr erkannt: CPU gibt auf dem B i l d s c h i r m d a s a u s , W A S I H R Z W I S C H E N D E M K L A M M E R N E I N T R A G T. D i e beiden Symbole WRITE und WRITELN geben dazu den Auftrag. E s k o e n n e n d e m n a c h Z a h l e n u n d Te x t e u n d e i n z e l n e B u c h s t a b e n geschrieben werden. Beispiele fuer beides bietet die Programmzeile, in der die Anweisung zur Ausgabe des Datums steht. Dort wird auch die Moeglichkeit deutlich, mehrere Dinge mit einer WRITE- oder WRITELN- An Weisung auf einmal ausgeben zu las sen; sie werden einfach, durch Komma getrennt, zwischen den Klammern aufgelistet. Zahlen setzt ihr einfach so zwischen schon erscheinen sie auf dem Schirm. die Klammern, und

Te x t e ( a u c h S t r i n g g e n a n n t ; m e r k t e u c h d a s W o r t ) u n d e i n z e l n e Zeichen (auch Character genannt; merken!) sind mit einem Hochkomma einzuleiten und mit einem Hochkomma abzuschlJessen. Das rnuesst ihr gut behalten, denn besonders das abschliessende Hochkomma wird oft vergessen, und das mag der Computer gar nicht gern. Wenn so ein String also ausgegeben werden soll, so schreibt der Rechner alles (!), was zwischen ' und ' steht auf den Schirm, und zwar so, wie ihr es eingetragen habt! Zu dem Programm oben, in dem alles mal vorkommt, noch einige Kur z-Bei spiele: Aufgabe Loesung in F'ASCAL Auf '+' '+?' '?' 123 ) den ) ) ); ) Schirm + +7 +? 123 123 kommt

Schreibe ein Schreibe &in und ein ? Schreibe die 123 WRITE

+ WRITE ( + WRITE ( WRITE ( '+', Zahl WRITE ( ( '123'

Ungueltig waere aber z.B. WRITE ( Te x t r n u e s s t e i n ' e i n g e s c h l o s s e n w e r d e n .

hallo

ihr

dort

).

Der

16

Lasst euch nicht stoeren durch die Form der Ausgabeanweisung f u e r d e n " H a l l o , h a l l o , . . . " — Te x t . E s m a c h t n i c h t s , w e n n a l l e s , w a s ihr mit einem WRITE- od. WRITELN-Befehl schreiben wollt, ueber mehrere Programmzeilen reicht. CPU gibt solange aus, bis er wieder eine sehliessende Klammer findet. Praktisch, wenn man eine Menge in eien Ausgabezeile stecken will, aber nur wenig Platz im Programm hat. Ihr werdet sicherlich schon den kleinen Unterschied zwischen WRITE und WRITELN festgestellt haben; WRITE gibt naemlich immer schoen der Fieihe nach aus, und zwar faengt es immer dort an, wo ihr zuletzt auf dem Schirm aufgehoert habt mit dem Schreiben. WRITE ( 'Hallo' ); WRITE ( 'Du da' ) ergibt also: HalloDu da Das zweite WRITE legt direkt hinter dem letzten geschriebenen Zeichen vorn ersten WRITE los, dem o naemlich. Die Befehlsfolge WRITELN ( 'Hallo' ); WRITE ( 'Du da' ) wuerde jedoch dieses Resultat bringen: Hallo Du da WRITELN schreibt seinen Sermon und... ja, dann setzt es die Position fuer das naechste Zeichen, welches irgendwann mal ausge geben werden soll auf den Anfang der naechsten Zeile! Genau dort faengt die Hfl JTE-Anweisung dann an mit dem Du da. Schreibt doch selbst mal kleine Programme, in denen ihr WRITE und WRITELN bunt mixt und dann staunt, was der Rechner so aus gibt . Jetzt aber mal eine kleine Kontrolles Habt ihr euch gewundert, warum nach jeder Anweisung ein Semikolon folgt? Wenn ja, dann blickt doch kurz mal in's vorige Kapitel. Dort findet ihr im Syn taxdiagramm von anweisungsteil, dass nach jeder Anweisung zwischen BEGIN und END ein ; stehen soll! Und schliesslich sind WRITE und WRITELN Anweisungen. (Fuer Schlaukoepfe: Das ; direkt vor dem END muss nicht sein, darf aber. Also lieber dort eins zuviel, als sonst eins zuwenig. Manche meinen zwar, w e r d o r t e i n e s s e t z t , d e r h a t PA S C A L n i c h t v e r s t a n d e n , a b e r. . . pah) Das ; soll die einzelnen Anweisungen voneinander trennen, genauso wie der Punkt in: ich tue dies, ich tue das. dann ende Es folgt das Syntaxdiagramm (vereinfacht) fuer die Ausgabe:

ausgabeanveisung: — > - - " - - ( H R I T E / - ; — >■— 7 > " V >—iT T V + ♦ --(hrITELN ;-" ~>-(?v-->•—;--! auszugebendes !-7 Cj.>" ^ ' " * ! Objekt ! !
* + V

v' 17

auszugebendes Objekt: string: + + ^ + + .„>....—>...j string j .„_> ...)../»").._>..__._. character :—-—>—CTj.—>
j + + * ■' a + + v

V

t

*

I

<

+ >—! zahl ! + + + character steht fuer Buchstaben und Ziffern, sowie Sonderzeichen!

ZAHL muessen wir nicht naeher erlaeutern. Jede ganze Zahl ist da recht, aber auch gebrochene, z.B. 12300,56, sind erlaubt. Bei diesen muss man aufpassen: statt des Kommas, welches die l e t z t e n b e i d e n S t e l l e n a b t r e n n t , m u s s i n PA S C A L , n a c h e n g 1 i s c h e r M a n i e r, e i n P u n k t g e s e t z t w e r d e n : od. 3 , 1 4 1 5 9 2 w i r d i n PA S C A L z u 3 . 1 4 1 5 9 2 8884,5498 " 8884.5498

Um das Mass voll zu machen noch eine kleine Spielerei, die jedermann beim Schreiben von Profi-Programmen gut zu pass kommen kann (nach dem Motto: auch wenn alles schiefgeht, lasst uns Profis sein). I n PA S C A L i s t e s m o e g l i c h , d i e A u s g a b e v o n Z a h l e n , S t r i n g s u n d Buchstaben zu formatieren, indem man hinter diesen einen : und eine Zahl schreibt. WRITE ( 'A':3 ) schreibt A ( ist ein Leerzeichen)

Die Zahl gibt an, wie gross das Feld ist, in dem der String (oder Character) rechtsbuendiq (!) ausgegeben wird; ist sie kleiner als die Stringlaenge, dann passiert nichts Besonderes: WRITE ( 'Hallo ihr'-.12 ) wird zu Hallo ihr W R I T E ( ' PA S C A L ' - . 2 ) w i r d z u PA S C A L W R I T E ( ' G u t e n Ta g ' ' . 2 0 ) w i r d z u G u t e n Ta g Bei Zahlen ist es genauso: WRITE ( 123:5 ) wird zu __123 WRITE ( -123:5 ) wrid zu _-123 Der Frei räum fuer die Zahl umfasst allerdings auch eine Stelle f u e r d a s e v t l . n e g a t i v e Vo r z e i c h e n ! WRITE ( 9989:10 ) ergibt dann 9989 (6 blanks + 4 Ziffern) Bei reellen Zahlen kann man zusaetzlich noch die Zahl der Stellen hinter dem Komma angeben: WRITE ( 3.141592:5:2 ) wird zu _3.14 WRITE ( 3.141592:10:6 ) wird zu _„3.141592

18

Hier sagt die erste Zahl (die 10), dass fuer den auszugebenden W e r t i n s g e s a m t 1 0 Z e i c h e n P l a t z s e i n s o l l ( i n k l . Vo r z e i c h e n u n d D e z i m a l p u n k t ! ! ) . D i e 6 ( b z w. o b e n d i e 2 ) m e l d e t : J e t z t a b e r n u r 6 (bzw. 2) Stellen hinter dem Dezimalpunkt ausgeben!! Eine famose Sache, nicht wahr? So ist es einfach jedem gege b e n , d i e t o l l s t e n Ta b e l l e a u f d a s s c h n e l l s t e a n z u l e g e n :
PROGRAM tabelle; (* dieses Programm legt eine einfache Tabelle an. Es dient zur Verdeutlichung der Formatierungsmoeglichkeiten in PASCAL #) BEGIN WRITELN; WRITE ( 'Tabelle vom 4.3.1985' );
WRITELN;

WRITELN ( 'Posten: Einnahme: Ausgabe:' ); WRITELN ( ' Auto', 0.0:10:2, 15000.50:14:2 ); WRITELN ( ' Miete', 678.70:10:2, 1268.0:14:2 );
WRITELN;

WRITELN ( 'Summe: ', 678.70:10:2, 16268.50:14:2 );
END.

19

Konstanten und ei n.k.i ndqer.echtes „Spei ehermodel.l_ Sicherlich habt ihr schon eine Menge probiert und mit den Schreibanweisungen gespielt, so dass es den meisten bestimmt l a e s t i g w a r , e i n i g e Te x t e , w e l c h e i n e i n e m P r o g r a m m w i e d e r u n d wieder auftraten, auch immer wieder und wieder hinzuschreiben. Schoener waere es doch, koennte man sie einmal irgendwo auffuehren und dann Lieber ein Kuerzel ansprechen. Oder wie ist es mit der allgegenwaertigen Konstanten Pi? Wird sie 'mal an 4 oder 5 Stellen im Programm benoetigt, so ist das s c h o n d u m m , e i n f a c h e r w a e r e a u c h h i e r, n u r F ' i s a g e n z u m u e s s e n und alles ist im Lot. D a s f o l g e n d e P r o g r a m m n u t z t d i e F a e h i g k e i t e n v o n PA S C A L i n dieser Richtung: PROGRAM konstantennutzer; CONST C# leitet die Konstantenvereinba rungen ein #)

pi - 3.141592; (» eine reelle Konstante *; rad - 'Berechnung mit Radius - ■ '; (* Textkonstanten- #) einh = ' Zentimeter'; (# Vereinbarung *> BEGIN WRITELN ( 'Es folgen Berechnungen von Kreisumfaengen...' );
WRITELN; WRITELN ( rad, 3:4, einh, '/ ergibt:',

2 # pi # 3:7:3, einh, ' als Umfang.' ); WRITELN ( rad, 125:4, einh, '/ ergibt:', 2 * pi # 125:7:3, einh, ' als Umfang.' );
END.

So oder aehnlich koennte ein problemgeladenens Programm aussehen, in dem die Benutzung von sogenannten KONSTANTEN alles viel einfacher macht. Zum ersten Mal haben wir jetzt auch etwas in den bisher nicht naeher erlaeuterten vereinbarungsteil ( siehe Kapitel 2 ) eingetragen. Das Syntaxdiagramm seht ihr weiter unten. D i e Ve r w e n d u n g v o n K o n s t a n t e n i s t d e n k b a r s i m p e l . I h r s c h r e i b t einfach den Namen hin, unter dem ihr z.B. eine reelle Zahl als Konstante vereinbart habt (siehe pi) , und schon denkt der R e c h n e r, i h r h a e t t e t d e n W e r t s e l b s t g e n o m m e n . D a s g i l t f u e r Text- und reell zahl ige und ganzzahl ige usw. Konstanten. Wenn CPU auf einh in der Ausgabeanweisung stoesst, dann s c h r e i b t e r d e n Te x t a u f d e n S c h i r m , d e n i h r e i n h z u g e w i e s e n habt, in diesem Fall ' Zentimeter'. Genauso mit rad und pi.

20

Das gilt in allen Lebenslagen, so auch in der Berechnung des Umfangs, d.h. in einem mathematischen Ausdruck. Te r m e a u s d e r M a t h e m a t i k , d i e + , - , * ( m a l n e h m e n ) u n d / ( t e i len) enthalten, koennt ihr uebernehmen Lind in die W/?77f-Anweisung einbauen. Auf dem Schirm erscheint dann das Ergebnis.

WRITE ( 'Das Ergebnis von 34+9/13 ist: ', 34 + 9 / 13 :5:2 )
Obiges lieferte auf dem Schirm (wenn's in einem Programm ist):

Das Ergebnis von 34+9/13 ist: 34.69
Zurueck zu den Konstantenvereinbarungen. zugehoerige Syntaxdiagramm: konstantendefinition —>—.CONST)—>—-—j konstantennaae !—>—v= f—>—! konstante !—>~-\\ V"—> Hier erst'mal das

V

V

*

.

.

-

.

,

--'

v

konstante:

-<•> - > - "■
V
i
i

+ + -I konstantennaue I-

■> -

V

+
i

+
+

V
;„>„...

1

-->

V —v - r

-I vorzeichenlose II zahl ! + + + + -! string I + +

Um die Einbindung ö&r Konstantenvereinbarung in ein Programm zu verdeutlichen, folgt das Syntaxdiagramm des vereinbarungsteil:

vereinbarungsteil (achtet auf spaetere Aktualisierungen): ->+ + -I konstantendefinition It + Der Vereinbarungsteil kann also auch leer sein!

Es ist noch zu erwaehnen, dass ein Konstantennarne im Programm nur benutzt werden darf, wenn dieser Name auch in der Konstantenvereinbarung definiert wurde! Ich sage ja auch nicht: Heute geht's mir aber piiiep. Keiner weiss, was piiiep heisst. Nur wenn ich vorher mit allen abge sprochen habe: So, hoert mal! Immer, wenn ich piiiep sage, dann meine ich "dreckig", klar? Dann kann ich sagen: Das Auto ist piiiep. oder auch: piiiep arbeite ich am liebsten.

21

In anderen Konstantendefinitionen duerfen auch nur Namen von Konstanten benutzt werden, die vorher vereinbart wurden:
CONST

minuseins ems
1}

•ems;

f* geht nicht, weil die *)

(# definition von eins hinter minuseins ist #)

CONST

eins - 1; minuseins = -eins;

(* so ist's gut

*)

D i e Vo r t e i l e v o n s o l c h e n K o n s t a n t e n v e r e i n b a r u n g e n l i e g e n f u e r jeden deutlich sichtbar auf der Hand: sie machen das Programm l e i c h t e r l e s b a r, d e n n p i s a g t j e d e m m e h r a l s e i n k o m p l i z i e r t e r W e r t . A u s s e r d e m i s t d a s P r o g r a m m l e i c h t e r w a r t b a r, d . h . e s k a n n s c h n e l l a n g e a e n d e r t e G e g e b e n h e i t e n a n g e p a s s t w e r d e n . Tr i t t z . B . Pi 35 mal im Programm auf und ein Unglueck geschieht, -die Mathe matik bemerkt, Pi ist nicht gleich 3.14, sondern 5.98,- dann tragt ihr nur einmal in den Konstantenvereinbarung den neuen Wert ein und schon laeuft alles wieder korrekt. Ueberall wird der neue Wert verwandt, doch ihr habt ihn nur einmal aktualisiert. MERKE: der WERT einer Konstanten bleibt waehrend de* gesamten F'rogrammlaufes gleich (konstant).
CONST tageimjahr = 365;

I m m e r, w e n n n u n t a g e i m j a h r b e n u t z t w i r d , d e n k t d e r C o m p u t e r sich 365. Das ist nicht zu aendern (es sei denn, ihr tragt hinter dem = die Zahl 366 oder so ein). Der Laie kann sich dies ungefaehr folgendermassen vorstellen: Fuer jede vereinbarte Konstante nimmt sich der Rechner ein k l e i n e s K a e r t c h e n v o n i r g e n d w o h e r. A u f d i e s s c h r e i b t e r d e n Konstantennamen, und auf der anderen Seite notiert er den Wert der Konstanten -alles mit nicht 1oesliehern Folienstift, damit man den Wert nicht aendern kann-:

Konstontenname

auf cJer anderen Seite der Wert

In den Faellen, wo nun ein Konstantenname im Programm auf taucht, nimmt CPU sich das Kaertchen mit dem Namen und schaut auf der anderen Seite nach, welchen Wert er bei seinen Operationen benutzen sol 1.

3 • 3 • Es ist doch nicht alles so konstant wie's aussieht oder Wie sage ich es meinem Computer D i e Ta g e d e s t r i s t e n A l l t a g s , i n d e n e n d a s R e c h n e r s a g e n k o n n t e t , e i n P r o g r a m m w a r, dasselbe tat, sind gezaehlt! Wir erklimmen nun die erste Stufe zur ueber die Maschine (unserem armen Rechner, immer gut). einzige, was ihr dem welc hes absolut i mmer absoluten Herrschaft bitte, behandelt ihn

Wie unvergleichlich knisternder ist doch die Atmosphaere bei der Ausfuehrung eines Programmes, dem ihr immer andere Werte ein geben koennt, OHNE den Programmtext aendern zu muessen! Als Einstieg vielleicht ein kleines Problem in Bezug auf Finanzierung eines Rechners:
PROGRAM prozentl;
CONST

die

meinanteil = 5; papisanteil =80; omisanteil - 15; V A R preis : INTEGER; BEGIN

C* ich bezahle 5 % vom Preis *) (* papi bezahlt 80 % *) (# auch omi muss 'ran, leider «> (n der preis wird waehrend des Programmlaufs erfragt/ *)

WRITELN ( 'Berechnung der absoluten Anteile, die von' ); WRITELN ( 'jedem einzelnen aufgebracht werden muessen: ' ); WRITELN; WRITE ( 'Bitte den Rechnerpreis eingeben: ' ); READLN ( preis ); WRITELN ( 'Mein Anteil:', preis^meinanteil/100 :6:2, ' DMf ); WRITELN ( 'Papis :', preis#papisanteil/100 -.6:2,' DM' ); WRITELN ( 'Omis :', preis»omisanteil/100 -.6:2, ' DM' ); END.

Die Anweisung READLN ( preis ) erwartet, sobald das Programm angelaufen ist, die Eingabe eines Preises (im Augenblick muss er leider noch ganzzahlig sein), also z.B. 500. Aufgrund dieses jetzt aktuell eingetippten Preises berechnet es die von jedem zu zahlenden Anteile am Preis. D e r Vo r t e i l l i e g t a u f d e r H a n d : i h r r n u e s s t e u c h , w a e h r e n d i h r das Programm eingebt, keine Gedanken ueber die Groesse des Kaufpreises machen. Zudem ist es moeglich (und sinnvoll) bei jedem neuen Start des Programms einen anderen Preis anzufuehren; keine Notwendigkeit das Programm selbst zu aendern!

Aber wie geht das genau? Aehmmmm, oehhhh, n un: A l s e r s t e s i s t e s n o e t i g e i n e VA R I A B L E z u v e r e i n b a r e n , w e l c h e spaeter den Wert, den wir ja immer aktuell neu eingeben wollen, aufnehmen kann. Im obigen Beispiel geschieht dies in den Zeilen
V AR preis : INTEGER;

p r e i s w i r d h i e r a l s Va r i a b l e d e fi n i e r t , d i e n u r g a n z z a h l i g e Werte aufnehmen kann (engl. INTEGER: bedeutet: ganze Zahl). Das PASCAL-Symbol VAR sagt dem R:echner, dass jetzt Variablendeklara tionen folgen; genauso wie CONST die Konstantendefinitionen ein— leutet. I s t e i n e Va r i a b l e e r s t m a l i n d e r b e s c h r i e b e n e n F o r m v e r e i n b a r t worden, so koennt ihr im Programm immer und immer wieder einen neuen Wert fuer sie einlesen, der dann in Rechnungen und Ausgabeanweisungen verwandt werden kann wie eine Konstante oder eine Zahl.
READLN ( preis )

READLN (wieder mal Englisch, READ = lies, lesen) ist die Anwei sung, mit der CPU einen Wert von euch anfordert, der dann einge tippt werden muss. Es ist deshalb sinnvoll, vor jeder Eingabean weisung (.READ oder READLN') einen Text auszugeben, der dem Pro grammbenutzer am Schirm sagt, was er gleich eingeben soll. Zur Einfuehrung in die Eingabeanweisungen:
eingabeanueisung: >---r-( READ r--7-->--{7}->—7-! einfache variable !--T—>—f ?}--—> + V V x. i einfache variable: miss Variable eines Skalar- oder Unterbe reichstyps oder Stringtyps sein. Hehr dazu spaeter.

---./reaüihV-+-

Der Befehl READ od. READLN erwartet dann die Eingabe von s o v i e l e n We r t e n , w i e i h r a n Va r i a b l e n i n K l a m m e r n h i n t e r d e m Symbol aufgefuehrt habt: READLN ( a, b ) READ

ihr rnuesst 2 Werte eingeben, z.B. 2 u.3 erwartet 3 Groessen als Eingabe.

( elementl, letzteselement, Schrittweite )

Solltet ihr wirklich mal den Wunsch haben, mit einer Eingabeanweisung mehrere Werte einlesen zu wollen, dann muessen beim Eintippen nachher die einzelnen Werte mit einem Leerzeichen voneinander getrennt werden! Nur nach dem letzten Wert ist die Ta s t e m i t d e r A u f s c h r i f t " C R " o d e r " R e t u r n " o d e r " E n t e r " z u b e taetiqen.
24

W i r d n u r R E A D L N - o h n e Va r i a b l e n i n K l a m m e r n - i n ' s P r o g r a m m eingesetzt, dann wartet der Rechner, wenn er diesen Befehl abar b e i t e t , a u f d a s D r u e c k e n d e r Ta s t e " R e t u r n " o d e r " E n t e r " , s o n s t nichts. Ein Wort noch zum Unterschied zwischen READLN und READ: Zunaechst einmal sind sie prinzipiell austauschbar. Unsere Empfehlung ist aber, READLN zu verwenden (falls nicht ausdruecklich anders angegeben). Im S t a n d a r d - PA S C A L (der u r s p r u e n g l i c h e n F o r m v o n PA S C A L , w e l c h e s i c h H e r r W i r t h a u s Zuerich ausgedacht hat) sind einige Spielereien (mit gebuffertem input -fuer Spezies-) vorgesehen, die allerdings nicht unbedingt i n a l l e n PA S C A L - D i a l e k t e n r e a l i s i e r t w u r d e n b z w. b e i d e r E i n g a b e v o n W e r t e n m i t t e l s Ta s t a t u r s o w i e s o n i c h t f u n k t i o n i e r e n ; a u s diesem Grunde lautet unsere Empfehlung fuer den Augenblick, READLN zu verwenden. Da weiss man, was man hat.

Mit diesem Ruestzeug ausgestattet, welches euch erlaubt, selbst d i e u n m o e g l i c h s t e n Va r i a b l e n e i n z u l e s e n , w o l l e n w i r u n s a u f d i e Vereinbarung solcher stuerzen:

Va r i a b l e n v e r e i n b a r u n g :
^^ + + _

typ
+

(vorlaeufig):
1 .

--->-~ VAR 5-"—7->— I variablennaae !-7—>--■■; : }->--! typ !—>---C7>7~> —>-«—(INTEGER)~T-^ \ \ + + V *~ + * V V >--< A

S

i

<' -—

,';\

i.

i

L - {.

real

^r

~

vereinbarungsteil (vorlaeufig): i) + 1 \ y t + a —I konstantendefinition !-— —I Variablenvereinbarung !— t i t +

D a m i t k a n n m a n s c h o n e i n e M e n g e m a c h e n . A l l e Va r i a b l e n n a m e n , w e l c h e d u r c h K o m m a g e t r e n n t v o r e i n e m Ty p b e z e i c h n e r ( . R E A L o d e r I N T E G E R ) s t e h e n , s i n d Va r i a b l e n d i e s e n Ty p s ! V AR anzahlt, menge, alter : INTEGER; f a k t o r, e r g e b n i s , p r o z e n t w e r t : R E A L ; a, b : INTEGER; E i n e Va r i a b l e n d e k l a r a t i o n d i e s e s A u s s e h e n s w u e r d e d i e Va r i a b l e n anzahll, menge, alter, a und b als vom Typ INTEGERr d.h. nur ganzahl ige Werte fassend, vereinbaren; faktor, ergebnis und prozentwert duerften, und das ist neu, reelle Werte aufnehmen (engl. REAL bedeutet real, reell).

D e r J W J £ < 5 £ # ~ We r t e b e r e i c h u m f a s s t i m a l l g e m e i n e n n u r d i e g a n z e n Zahlen von -32768 bis 32767 (!!!!), die obere Grenze wird dabei auch oft MAXINT g e n a n n t ; i s t e s a b e r n o e t i g , g r o e s s e r e W e r t e z u b e a r b e i t e n , s o h i l f t a l l e s n i c h t s , m a n m u s s a u f R E A L — Va r i a b l e n zuruec kqrei fen.
PROGRAM addition; (*? dieses Progarmm addiert 3 Zahlen und gibt das Ergebnis *) V AR summand1, summand2, summand3 : REAL; BEGIN WRITE ( '1. Summand: f >i WRITE ( '2. Summand: t ) ; WRITE ( '3. Summand: r >', READLN ( summandl > i READLN ( summand2 ) ; READLN ( summandS >;

WRITELN; WRITELN ( summand1:6::2,, ' + ' , s u m m a n d 2 : 6 : 2 , ' + T, summand3:6\■2 >r f - t summandl + summand2 + summandS :7:3 ); END.

Fuer die Summanden koennen 1 oder -2 oder 3.4 oder 123.005 oder 19345.987 oder -9876.000654 oder oder eingegeben werden. Es muessen nur mathematisch korrekte Zahlen sein. Bei dem Programm prozentl am Beginn des Kapitels dagegen, d u r f t e n w i r n u r P r e i s e w i e 5 0 0 o d e r 1 0 0 0 o d e r 5 o d e r. . . a n g e b e n . I s t j a a u c h k l a r, d e n n d i e Va r i a b l e p r e i s w a r v o m Ty p I N T E G E R , d . h a l l e i n g a n z z a h l i g e We r t e s i n d e r l a u b t ! s u m m a n d l u s w. s i n d j e d o c h R E A L - Va r i a b l e n , s i e d u e r f e n r e e l l e W e r t e a n n e h m e n . Zu dieser Problematik moechten wir euch eine Erweiterung unseres informellen Speichermodells, welches wir mit den Kaertchen fuer die Konstanten begonnen haben, vorstellen. S p e i c h e r m o d e l l d e s h a l b , w e i l C P U s i c h d i e W e r t e d e r Va r i a b l e n merken (speichern) muss. Irgendwo, so dass er sie, wann immer ein Gebrauch notwendig ist, schnell ermitteln kann. Bei den Konstanten hat er sich fuer jede einzelne ein Kaertchen gemacht:

KonstantenkärtcHen. ^3 Auf der anderen Selbe Stehb o/er Wert, hier tc = pl

26

B e i d e n Va r i a b l e n i s t e s e t w a s a n d e r s . H i e r b a s t e l t e r s i c h fuer jede vereinbarte einen kleinen Kasten, auf den er den Namen d e r Va r i a b l e n s c h r e i b t :

für eine *c: Kasten lateaer-\6r table Kasten für eine Real- Variable
bestimmten Diese Kaestchen fertigt CPU nach einem der S c h n i t t m u s t e r b o g e n a n ; d i e s e r r e p r a e s e n t i e r t d e n Ty p Va r i a b l e n , d . h . d e n W e r t e b e r e i c h d e r G r o e s s e n , w e l c h e i n den Kasten duerfen. Bei REAL eben nur reelle Zahlen, bei INTEGER n u r ganze Zahlen. So hat CPU auch intern schon eine kleine Mappe mit Schnittmustern fuer Kaesten der Typen REAL u. INTEGER:

Sc tin i tt musterböaea ür Vor iablen kästen der Typen. Real und lateger ö
Wenn man genau hinsieht, dann erkennt man, dass ein ßf/Jt-Kasten groesser ist, als ein INTEGEfi-Kasten. Der Grund fuer diesen Umstand ist in den Wertebereichen der Variablen zu suchen. Jeder weiss: die Menge der reellen Zahlen ist groesser als die Menge der ganzen Zahlen (OK, beide unendlich, aber erstere eben etwas unendlicher; das fand schon Herr Cantor im letzten Jahrhundert heraus). Daraus folgt: der groessere Wertebereich bekommt einen groesseren Kasten. W e i t e r s o l l d a m i t a u c h v e r d e u t l i c h t w e r d e n : Va r i a b l e n v o r n Ty p INTEGER koennen und duerfen nie Werte vom Typ REAL enthalten:

Ist oky ober

da paßt es nicht

ä
prtiS

7<\

Der eifrige Schueler der Sprache PASCAL merkt sich also: Versuche NIE einer Variablen vom Typ INTEGER einen REAL-Wert zuzuweisen, das passt nicht; aber eine Variable vom Typ REAL darf reelle und ganzzahl ige Werte bekommen! Oder noch allgemeiner (auch fuer spaeter): Va r i a b l e n d u e r f e n n u r We r t e e r h a l t e n . d i e d e m Ty p e n t s p r e c h e n . unter dem sie vereinbart wurden - kurz, praegnant, praezise.

27

S o l l C P U a l s o e i n e n W e r t i n e i n e Va r i a b l e e i n l e s e n ( m i t R E A D oder READLN), dann wartet er auf die Eingabe desselben von der Ta s t a t u r, d a n n w i r d d e r K a s t e n g e s u c h t , a u f d e m d e r g e w u e n s c h t e Variablenname steht, dann stellt CPU den eingetippten Wert in den Kasten: ^ Eingabe auf der Tastatur

65.7

READLN ( summandl )

1

^c^
J Ju*mm*&mcI -i I

Kasten der ^=a_> Variablen nach" oler Vereinbarung

Kosten rach der fiwoabe des neuen Wertes

S (

Kommt im folgenden der grosse Augenblick der Berechnung der S u m m e ( o b i g e s B e i s p i e l p r o g r a m m ) , s o s c h a ff t d e r R e c h n e r s i c h d i e b e n o e t i g t e n K a e s t e n h e r a n ( . s u m m a n d l u s w. ) , s c h a u t n a c h , w a s i n ihnen steht, und addiert das Ganze, danach die Ausgabe:

B e v o r m a n e i n e Va r i a b l e i n e i n e r O p e r a t i o n w i e d e r A d d i t i o n oder so verwendet, muss man umbedingt einen Wert in sie geschrie ben haben. Das kann mit einer Eingabeanweisung oder anders geschehen. Sollte das nicht getan worden sein, kommt keine Fehlermeldung, nein, nein, CPU nimmt dann irgendeinen Wert, den er sich ausdenkt, jedoch passt dieser euch meist ueberhaupt nicht. Wu e r d e t i h r a n d e r s h a n d e l n ? M u t t i s c h i c k t e u c h z u m E i n k a u f e n , ohne einen Zettel mit den einzuholenden Sachen mitzugeben. Tja, in dem Fall kauft ihr dann Teddies oder ein gutes Buch oder sonst e t w a s , g a r a n t i e r t a b e r n i c h t d e n K a e s e f u e r d i e g e p l a g t e M u t t e r. Ein kleines Phaenomen am Schluss (dazu ein Programmausschnitt): vorher
READLN ( preis ); READLN ( preis );

nachher Eingabe: S Eingabe: 12

l £ t<us

I

WRITELN ( preis:5 ); C* Ausgegeben wird 12 / *)

Nach dem zweiten Einlesen von preis ist der alte Wert (die 8) NICHT mehr 'drin, sondern die 12 !!

28

Als Ermahnung an die Experimentier freudigen:
READLN ( pi ) mit CONST

pi - 3.14; funktioniert nicht, Genauso muessen die Menge der von euch vergebenen Variablen namen in einem Programm und die der vergebenen Konstantennamen d i s j u n k t s e i n ! D . h . k e i n e Va r i a b l e d a r f d e n g l e i c h e n N a m e n w i e eine Konstante haben und umgekehrt. Wir kommen uns meist schon Lieber penibel vor, es hier zu erwaehn ^ n , a b e r d e n kt d a ra n : j e d e Va ri a b l e mu ss, w e n n si e i m Pro g ra mm v e r w e n d e t w i r d , v o r h e r i n d e r Va r i a b l e n d e k l a r a t i o n v e r e i n b a r t worden sein!

2y

3.4.

Niedere

Mathematik

"Ihr da, hoert mal! Da schreibt Ihr Seiten um Seiten ueber PA S C A L u n d s o , a b e r w i e d e r C o m p u t e r ( e n g l . t o c o m p u t e = berechnen) oder Rechner zu seinem Namen kommt, das hab' ich noch nicht gesehen." Tja, da ist schon 'was dran. Abgesehen von der Erwaehnung, dass man + u. - usw. in der Ausgabeanweisung verwenden duerfte, ist noch nicht viel gelaufen. Dabei verbringen viele viele Computer ihr ganzes Leben damit, vor sich hinzurechnen. Bitte, wenn ihr unbedingt wollt, dann sollt ihr auch das Wissen dazu bekommen.

W i e s c h o n e r w a e h n t , g i b t e s i n PA S C A L d i e m a t h e m a t i s c h e n O p e r a toren +, -, * und / . gewicht x * x + / a anzahl $ x + b ergaebe ist ein Durchschnittsgewicht

d i e PA S C A L - R e a l i s a t i o n v o n Xs- + AX + B (bekannt aus der Mathemati k) die Mehrwertssteuerhoehe

preis

*

14

/

100

ergibt

Ihr wisst ja, dass man streng unterscheiden muss zwischen Va r i a b l e n v o m Ty p I N T E G E R u n d d e n e n v o m Ty p R E A L . S o i s t n a e m l i c h vereinbart, dass der Operator / immer ein Ergebnis vom Typ REAL liefert: 91/2 10 / ist 5 ist dann dann eben eben 2.0 45.5 ( .0 zeigt, dass es ei n REALWert ist )

Aus diesem Grunde hat man zwei neue Operatoren eingefuehrt:

DIV MOD
z.B. 91 10 20

teilt

ganzzahlig den

ohne

Rest Rest einer

ermittelt

ganzzahligen Division

DIV DIV MOD 5 3

2

ist ist 2 ergibt ; 2

dann

45

ahhhh ein INTEGER-Viert (18 kann man g'rade noch durch 3 teilen) eben 1

91

MOD

2

ist

Die Resultate der Operationen DIV u. MOD sind immer vom Typ INTEGER*. Sie haben die gleiche Prioritaet wie * u. / in der Pun kt-vor-St r i c h-Rec hnung.

Natuerlich kann in PASCAL .auch die Freude des ungehemmten Klam mernsetzens voll ausgekostet werden:
( (( (a + b) * c MOD d ) + e * (f - g) DIV h) * i - j )

Ansonsten gilt aber Punkt-vor-. . . Damit den Noerglern vom Anfang auch etwas geboten wird, stellen w i r w e i t e r e m a t h e m a t i s c h e S t a n d a r d f u n k t i o n e n v o r, w i e m a n s i e alle nas'lang in Buechern findet. Dabei verwenden wir die Variable intreellT um anzudeuten, dass der Parameter der Funktion vorn Typ INTEGER oder REAL sein kann. Funktion in PASCAL
ABS ( intreell )

Erlaeuterung
Liefert den Absolutbetrag von intreell. ABS ( -3 ) ist 3 berechnet intreell2 SQR ( 2.5 ) ist 6.25 berechnet intreell ~* (Wurzel) SQRT ( 6.25 ) ist 2.5 na ja, ergibt Sinus von intreell SIN ( 0 ) ist 1 und den Cosinus liefert den arcus-tangens von int reell natuerlicher Logarithmus **»•—•" (e = 2.718281...)

SQR ( intreell ) SQRT ( intreell ) SIN ( intreell ) COS ( intreell ) ARCTAN ( intreell ) LN ( intreell ) EXP ( intreell )

Die Ergebnisse der soeben neu kennengelernten Funktionen sind immer vom Typ REAL\ Ausnahme: ABS liefert eines vom intreell-Typ. N o c h z w e i w e i t e r e F u n k t i o n e n , d i e i m m e r R e s u l t a t e v o m Ty p INTEGER zurueckgeben:
ROUND ( intreell ) auf-/abrunden, den Nachkommastel len entsprechend: ROUND ( 6.6 ) ergibt 7 ROUND ( 6.4 ) ergibt 6 liefert den ganzahl igen Anteil von intreell: TRUNC ( 12.7 ) ergibt 12 TRUNC ( 2 ) ergibt 2

TRUNC ( intreell )

O l t_f 1

Der Vollstaendigkeit halber stellen wir noch eine Standardfunktion vor, welche allerdings ein Resultat vorn Typ BOOLEAN liefert. Schlagt dazu doch 'mal in Kapitel 3.7. nach:

O D D ( i n t ) D e r P a r a m e t e r i n t m u s s v o m Ty p INTEGER sein. ODD liefert TRUE, wenn er eine ungerade ganze Zahl ist. ODD ( 15 ) ergibt TRUE
Urteilt selbst. Ist es nicht denkbar simpel, auch komplizierte R e c h n u n g e n i n PA S C A L z u v e r w i r k l i c h e n ? M a n s c h r e i b t ' s e i n f a c h s o hin, wie man es gewohnt ist. SIN ( x ) * COS ( y ) - SIN ( y ) * COS ( y ) oder SQRT a + b ( SQR # ( x ( ) z ) SQR ( y ( ) y ) ) oder oder

EXP

ABS

LN ( 3.4 ) - TRUNC ( x ) * ARCTAN ( z ) + SIN ( 3 ) L u sti g e Be i sp i e l e , g e l l ? Es i st m o m e n ta n sch w e r, si ch e tw a s Sinnvolles auszudenken, 'tschuldigung. Beim Herumspielen mit den Funktionen und Basteln von schoenen Ausdruecken, deren Ergebnis auf dem Schirm erscheinen kann, muss eines unbedingt beachtet werden: Genauso, wie b e sti m m te n Typ hat das Resultat Bei SIN einzelne Funktionen ein Ergebnis mit einem liefern - bei SIN ( x ) ist er REAL -, genauso e i n e s g a n z e n A u s d r u c k s e i n e n Ty p ! ( x ) + 3 ist er REAL, bei

TRUNC ( SIN ( x ) + 3 ) ist er jedoch INTEGER, weil die Funktion TRUNC Ergebnisse d i e s e n Ty p s l i e f e r t . Der Ergebnistyp ist immer dann REAL, wenn mindestens ein Operand (z.B. x in x + 3) vom Typ REAL ist, oder wenn ein Operator nur REAL-U&rte- als Rlesultat liefert (z.B. COS ( x ) in 4 + COS ( 3 ) - 2 ). I s t ' s a l l e r d i n g s u n s e r u n b a e n d i g e r W u n s c h , e i n E r g e b n i s v o m Ty p INTEGER zu bekommen, so koennen wir dies durch die Funktionen TRUNC und ROUND erreichen: TRUNC ( 4 + COS ( 3 ) - 2 ) liefert einen INTEGER-Uert, ROUND ( 3.5 ■*• ABS ( -3 ) ) ebenso

32

PROGRAM funktionenbeispiel;
CONST

pi - 3.141592;
V AR alpha, a, b : REAL;

BEGIN WRITELN ( 'Berechnung der Hypothenusenlaenge: ' ); WRITELN; WRITE ( 'Laenge der 1. Kathete: ' ); READLN ( a ); WRITE ( 'Laenge der 2. Kathete: ' ); READLN ( b ); WRITELN ( 'Daraus folgt die Hypothenuselaenge von',
S Q RT ( S Q R ( a > + S Q R ( b ) ) : 7 : 3 ) ; WRITELN;

WRITELN ( 'Und die Berechnung des Tangens von alpha: ' ); WRITELN; WRITE ( 'Winkel Alpha in Grad eingeben: ' ); READLN ( alpha ); WRITELN ( 'Tangens von alpha:', SIN ( alpha * pi / 180 ) / COS ( alpha * pi / 180 ) -.10:3 );
END.

Unsere Hoffnung ist, alle haben jetzt erstmal genug von komplizierter Mathematik. Ihr wisst nun, warum der Rechner Rechner heisst.

3.5. Es laesst bitten: Seine Herrlichkeit, die Wertzuweisung Das ist kaum uebertrieben. Die WERTZUWEISUNG ist von zentraler Bedeutung in der ganzen Informatik. Hier scheiden sich viele Geister -soll eine strenge Typkontrolle vorgenommen werden, sollen WertZuweisungen zwischen komplexen Strukturen moeglich s e i n u s w. - .

Ach was das ist. Moment, dazu eine k1eine Grafik mit Pr ogr amrnaussc hn i 11:
VAR

a, b, ergebnis

INTEGER-,

ergebnis := a + b;

(* die Wertzuweisung *)

J-j-x

twi
Polaroid Mo

s**

Um der War i ab 1 en ergebn is e i nen Wer t z uz uwei sen, er mi 11 el t der Rechner die Werte von a und b, fuehrt die Addition durch und p a c k t d e n e r r e c h n e t e n W e r t i n d e n K a s t e n - d i e Va r i a b l e — e r g e b n i s .
Allgemein: vertzuveisung (vorlaeufig):
+ + + + 1 f

variable: + + —>—! variablennaae !—>t +

—>—! variable !—>--(:=>->- -I ausdruck !—>

ausdruck (vorlaeufig):
+ + 1 +

•>--r—I aatheuatischer lern !—r—)
+ + +

-matlieaati scher tern ist fuer uns er st einmal ausreichend. Spaeter werden wir ihn praezisieren.

i variable !+

->-

ausdruck und variable werden spaeter noch verfeinert
34

D a s PA S C A L - S y m b o l : = k o e n n e n w i r u n s a l s e i n e n P f e i l v o r s t e l len, der dorthin weist, wohin das Ergebnis des Ausdrucks ge schrieben werden soll:
^ ~ ^ N

ergebnis

a + b

ft | +

L(JJ

D a b e i w e r d e n d i e I n h a l t e v o n Va r i a b l e n a u f d e r r e c h t e n S e i t e vorn Wert Zuweisung sop er at or (so heisst :=) nicht veraendert, die Va r i a b l e a u f d e r l i n k e n S e i t e a l l e r d i n g s b e k o m m t d a s R e s u l t a t d e s Ausdrucks als Wert. Folglich ist dies durchaus gestattet und haeufig zu sehen:
a + 1

(# der Wert von a wird um 1 erhoeht #)

N a c h d e m N o t i e r e n d e s We r t e s v o n a v o r d e r A d d i t i o n w i r d d e r Kasten erstmal wieder weggestellt, dann wird 1 addiert, und dann wird der Kasten von a wieder hervorgekramt, weil dort das Ergebnis hinein soll. So einfach und elegant. Mit der Wert Zuweisung ist es rnoeglich, Variablen Werte zu ge b e n , o h n e s i e d i r e k t v o n d e r Ta s t a t u r i n d e n K a s t e n e i n z u l e s e n .
READLN ( a ); b :- a; (# b hat dann den gleichen Wert wie a)

WICHTIG: Wie schon erwaehnt, duerfen Variablen vom Typ INTEGER keine REAL-vierte enthalten. So ist also bei ALLEN ZUWEISUNGSAN WEISUNGEN darauf zu achten, dass der Ergebnistyp des Ausdrucks a u f d e r r e c h t e n S e i t e . _ q . e n a u m i t d e m Ty p d e r Va r i a b l e n a u f d e r l i n k e n S e i t e u e b e r e i n s t i m m t , b z w. e i n e U n t e r m e n g e d e s s e n We r t e b e r e i c h e s d a r s t e l l t ( p r o f e s s i o n e l l : d i e Ty p e n m u e s s e n kompatibel sein)!
V AR i j INTEGER; r : REAL;

i := i; r := 2; r r :- i;
i := r;

(# gueltig *) 4.7; (K beides gueltig #)
(* dito, weil INTEGER-Bereich Unter menge von REAL-Bereich ist #)

(# halt, nicht gueltig #)
(# gueltig, weil TRUNC immer INTEGER liefert #)

i := TRUNC ( r );

SIN ( 1 ) + LN ( 3 );

C* gueltig *)

i :- COS ( 0.2 ) - ABS ( -2 ); (# ungueltig, Ausdruck liefert einen REAL-Wert *) 1 ji; (# geht nicht; links muss Variable stehen #) eine

r : = '12.34'; (* na, na, na. Das war wohl nichts. Natuerlich ungueltig/ *)

It is very important that... ohhh, Moment... also, dass ihr e u c h m e r k t , d a s s d i e Va r i a b l e , w e l c h e r e t w a s z u g e w i e s e n w i r d , LINKS vom := steht! Mit der Zeit koennt ihr gar nicht mehr anders denken, aber am Anfang ist es manchmal ungewohnt. Noch ein klitzekleines Beispiel zum Schluss:
PROGRAM tangenssimulation;
CONST

pi - 3.141592; V A R alpha, alpharad, tangens : REAL; BEGIN WRITELN ( 'Berechnung des Tangens von alpha:' ); WRITELN; WRITE ( 'Winkel in Grad eingeben: ' ); READLN ( alpha ); alpharad := alpha * pi / 180; (* Winkel umwandeln in das Bogenmass #) tangens := SIN ( alpharad ) I COS ( alpharad ); WRITELN ( 'Tangens von', alpha:5:2, ' = ', tangens:7:3 ); END.

Beispielhaft an diesem F'rograrnm ist die Auslagerung der Ta n g e n s b e r e c h n u n g a u s d e r W ß / T f - A n w e i s u n g . D a s i s t s o v i e l uebersicht 1 icher und zur Nachahmung empfohlen. a l p h a r a d v e r d e u t l i c h t e i n e n Vo r t e i l , d e n s c h o n d i e K o n s t a n t e n ansatzweise hatten. Wird ein Wert des oefteren benoetigt, so sollte er am Programmanfang als Konstante vereinbart werden, falls er vor Programmbeginn feststeht und sich waehrend des Pro g r a m m l a u f e s n i c h t a e n d e r t . Tr i ff t d a s a l l e s n i c h t z u , s o v e r e i n bart man ihn klugerweise als Variable und berechnet seine Groesse waehrend der Laufzeit des Programms (siehe alpharad) . Auf die Weise z.B wird hier die mehrmalige Auffuehrung von alpha * pi / 180 gespart.

Ve r z w i c k t e s m i t Ve r z w e i g u n g e n "Sein oder Nichtsein, (Hamlet)

"...- Muss ich mich entscheiden, So will ich ein Verbrecher lieber als Ein Tor von Ihren Augen gehen." (Marquis in Schillers dramatischem Gedicht "Don Carlos") "... Ja ich fuehle, und darin darf ich meinem Herzen trauen, dass sie - o darf ich, kann ich den Himmel in diesen Worten aussprechen? (Werther in Goethes dass sie mich liebt/..." "Die Leiden des jungen Werthers") "Wenn nun er es waere? Hinterher? Oder weil nicht? Oder das doppelte Ereignis?" (Molly Bloom in James Joyce' "Ulysses") Soweit unser kleiner Ausflug in die Literatur. Jedoch mag manch' williger Studiosus fragen, was das Rezitieren solle? Nun, nach kurzer Pruefung der obigen Ausfuehrungen stellt sich d e m a u f m e r k s a m e n L e s e r d o c h s o f o r t k l a r d a r, d a s s a l l e d i e s e P e r sonen eines gemeinsam haben: sie muessen Entscheidungen treffen und natuerlich in Abhaengigkeit dieser handeln. Da aber dies Entscheiden augenfaellig eine so wichtige Sache i s t , w o l l e n w i r k e i n e n M o m e n t z o e g e r n , a u c h i n PA S C A L d i e M o e g lichkeit einzufuehren, solches in der Gewalt zu haben, um damit verschiedene Aktionen alternativ abzuarbeiten. Zum Warmwerden zunaechst eine kleine Einfuehrung in die Notation und Rekapitulation der Struktogramme (wir haben sie bisher ja straeflich vernachlaessigt): "Sein oder Nichtsein..." steht zur Auswahl, ein wenig formeller angeben, so schrieben wir Wollten wir es

"röLLs Wir uns für Sein ent- v ^ Stkiecten haben

SEIH ? , '
+

i

Seite pur Aktionen, wenn
+

J A \ . '/ NEIN

^- wir uns fur's /Vichfcsein entschieden tahen

weiter ! Dolch I auf Erden ! nehmen ! + + vandeln ! den Leben !
! ein Ende !

nweisung oi.Anweisun

! setzen !
1

3

beide nur ausführen wenn Nichtsein

37

Zu beachten, aber leicht zu behalten ist, dass alles, was in dem Freiraum unter der Alternative JA steht, nur ausgefuehrt wird, wenn diese Alternative gewaehlt wurde. Alles unter NEIN n u r, w e n n N I C H T S E I N g e w a e h l t w u r d e . Das entspricht voll und ganz unserer Philosophie, alle Anweisungen von oben nach unten abzuarbeiten, welche uebereinander angeordnet sind (siehe: Der Algorithmus, bei dem jeder mit muss). Etwas konkreter wird dies, wenn wir uns bekaemen einen Anruf von einem Auftraggeber: vorstellen, wir

W i r : " S t e t s z u I h r e n D i e n s t e n . Wa s w u e n s c h e n S i e ? " Auftraggeber: "Ich haette gerne ein Pragramm, welches mir das Durchschnittsgewicht meiner Kuehe berechnet. Dabei will ich nur Gesamtgewicht und die Zahl der gewogenen Kuehe eingeben muessen. Laesst sich das zu einem vernuenftigen Preis realisieren?" W i r : " A b e r n a t u e r l i c h , m e i n H e r r. W i r w e r d e n I h n e n die Loesung binnen Kurzem zusenden. Beehren Sie uns bald wieder."

Sogleich setzen wir uns hin und stellen die Problemloesung als Struktogramm da:
+
t

+
+

! Einlesen des Sesaotgewichtes i ! Einlesen der Zahl der Kuehe !
*. : -* !

! v -v Zahl der Kuehe <= 0 ? *' ! ! JA "^ „'' NEIN I + 1 + ■ i i ! Fehlerneldung ! Durchschnitts- I ! ausgeben ! gewicht berech- I ! I nen. !
. i i i + i
i ■ ■ i i *

• I !

Ausgabe des Durchschnittsgewichtes Sehlussaeldung

I ! !

Eine Pruefung, ob die Zahl der Kuehe kleiner oder gleich 0 ist, e r s p a r t u n s v i e l K u m m e r, d e n n s o l l t e d e r R e c h n e r w i r k l i c h e i n e Division durch 0 durchfuehren wollen, so wuerde er abstuerzen, d.h. das Programm abbrechen und nur einen relativ nichtssagenden Kommentar geben. Aber so wie oben nimmt sich das viel viel eleganter aus.
38

Unsere freundliche* Fehlermeldung wird nur im Ernstfall ausgege ben, d.h. "Kuhzahl" kleiner oder gleich 0. Andernfalls berechnet CPU das Durchschnittsgewicht und gibt es aus. Die Schlussmeldung erscheint IMMER! Zu merken ist das daran, dass ihr Kasten unter der gesamten Abfrage steht, nicht nur unter einer Alternative! Nun das geldbringende Programm:
PROGRAM durchschnitt; V A R kuhzahl : INTEGER; f* es gibt nur ganze Kuehe *) gesamtgewicht, durchschnittsgewicht ; REAL; BEGIN WRITE ( 'Bitte das Gesamtgewicht eingeben (in Kg) ; ' ); READLN ( gesamtgewicht ); WRITE ( 'Bitte die Zahl der Kuehe eingeben : ' ); READLN ( kuhzahl ); IF kuhzahl > 0 THEN BEGIN durchschnittsgewicht := gesamtgewicht / kuhzahl; WRITELN ( 'Das Durchschnittsgewicht betraegt: ', durchschnittsgewicht :5:2, ' Kg' ); E N D ELSE WRITELN ( 'Es muessen mehr als 0 Kuehe sein/' ); WRITELN ( 'Wenn neue Werte berechnet werden sollen, bitte ', 'das Programm neu starten.' );
END.

Dem Kenner der englischen Sprache wird es sicherlich nicht schwerfallen, die Abfrage zu verstehen» Im Deutschen etwa so:
WENN kuhzahl GROESSER 0

DANN durchschnittsgewicht berechnen und ausgeben SONST eine Fehlermeldung ausgeben

39

Als Syntaxdiagramms

if-anweisung:

■> - ( . r )

bedingung

->—'then
y

) - > - -i anweisung !t +

-»-(ELSE}-

-■ anweisung !+ 1

anweisung:
4. +

strukturierte anweisung: + —>—---' verbundanueisung I—7v j 4 + + + + 4. A j

——I einfache anweisung !-—■ V 4 1 *
j t + -

-—! strukturierte !-— ! anweisung I
+ +

—-! bedingte anweisung !~

einfache anweisung: + + -7—! vertzuweisung !—7V + + A
j + 4 J

verbundanueisung:
/ N + + ---s

—>—i' DE6IN)—>—7—S anueisung !--•■■;-->—( END }--> \^J a + + V N--

t—! ausgabeanw. I—+ I t ♦ i I * + I t—! eingabeanw. !—+ I + 1 ! I + + ! t—* leere anweisung !—♦ + + bedingte anweisung (vorlaeufig):
+
4

leere anweisung:

4
4

-! if-anweisung !-

W i r h a b e n e i n r i c h t i g s c h l e c h t e s G e w i s s e n : o b e s g u t w a r, s o viele Diagramme aufeinmal vorzustellen? Probiert's mal» Muss j a nicht sofort sitzen und wird auch immer noch verfeinert. D i e Ve r b u n d a n w e i s u n g k e n n t i h r j a s c h o n a l s anueisungsteil. Die wenn andere WertZuweisung ist auch eine Anweisung, d.h. :hlossen werden; Anweisungen folgen, so muss ein Semikolon anges a b e r w e m e r z a e h l e n w i r d a s , w i s s t i h r ja schon, und es taucht in den Programmen immer wieder auf.

40

bedingung ist nicht naeher erlaeutert, da es sie so nicht in PA S C A L g i b t . W i r a p p e l l i e r e n d a a n e u r e n S c h a r f s i n n u n d e u r e Intuition. Bedingungen sind fuer uns zunaechst mathematische Ausdruecke, wie a >= b 10 = 12 13 <> 14 0 <= 99 fuer fuer fuer fuer a > b 10 = 12 13 £ 14 0 £ 99

Man muss also in PASCAL mittels der Tastatur ein wenig kungeln, um die korrekten mathematischen Zeichen zu erzeugen. R e c h t s u n d l i n k s d e r Ve r g l e i c h s o p e r a t o r e n m u e s s e n Ausdruecke stehen (z.B. (12 + 3) <= (c * d) ist gueltig). math.

Wichtig ist bei all diesem, dass Bedingungen WAHR: oder FALSCH sein koennen - sonst liesse sich ja auch keine Entscheidung treffen -, z.B. ist 10 = 12 nicht WAHR, 0 <= 99 ist WAHR, 13 <> 14 ist WAHR, a >= b ist FALSCH, wenn a = 1 und b =2 ist.

Kann wahr oder falsch Sein

wird QuSQeCührt (wenn die Bedtinouno wcihr isb.z.B. 40 h 0 . Auch THEN -Ewekj Genannt. ELSE(a»weisung')-^___ wind! nur aUSoeCühr^ wenn olie hd'mQungCbkch ist, Auch ELSt-ifcjeio oenannt. Der IF-Anweisung eventuell folgende Eiefehle werden Fall ausgefuehrt!
auf jeden

L.inbedingt Da die Syntaxdiagramme eindeutig, jedoch nicht schnell zu verstehen sind, schreiben wir 'mal einige moegliche K o n s t r u k t i o n e n m i t I F - A n W e i s u n g e n n i e d e r. D a b e i s t e h t a n w e i s u n g l , a n w e i s u n g 2 u s w. f u e r i r g e n d e i n e g u e l t i g e PA S C A L - A n w e i s u n g , b e d i n g u n g l u s w. f u e r e i n e g u e l t i g e PA S C A L - B e d i n g u n g :

IF bedingungl THEN anweisungl ELSE BEGIN anweisung2; anweisungS; END;

\ bedingung 1 ' ! '' ' JA x ,' NEIN i _v ♦ auweis. 1 ! anweis. 2 I
4 4 4 .

! anueis. 3 I

41

IF bedingungl THEN (* leere Anweisung #) ELSE anweisungl;

\ bedingungl . JA v ,NEIN ! anveis. 1 I

IF bedingungl THEN IF bedingung2 THEN anweisungl ELSE anweisung2;

bedingung 1 / J A i v v bedingung 2 ' ! ! JA\ ' NEIN ! 4 -/1 ! anu. 1 ! anw. 2 I , ' NEIN

IF bedingungl THEN BEGIN anweisungl; anweisung2; anweisung3; E N D ELSE IF bedingung2 THEN anweisung4 ELSE anweisungS;

4.

-^

! ! I

bedingung \ ^ JA V v v -

v

1 ^ ' '

^-

•" " NEIN

I i !

_x_l anweis. 1 I \ ■ • + 1 JA ! anweis. + 4. anweis. I anveis. +

...A bedingung 2 -- • ^ s \ v. ' v\ x^NEIN ! 2 + *■. * + 4 ! anweis. 5 ! 3 ! I !

IF bedingungl THEN IF bedingung2 THEN IF bedingung3 THEN anweisungl ELSE BEGIN anweisung2; IF bedingung4 THEN anweisung3 ELSE anweisung4; END;
bedingung 1

J A
bedingung 2 ' J A bedingung 3
n <:

fJEIN

, 'NEIN

\ J A V >

N E I N anweisung 2
_-4
/ I

anv. 1 !
*.
IN

I \ bedingung 4 • !

I JAs /'NEIN ! 4 -V 1 I anw. 3 I anueis. 4 i Ihr seht, das kann ganz schoen knifflig werden; aber legt man konsequent Struktogramrne dazu an, dann behaelt man in jeder Lage die Uebersicht. Fast exzessiv rueckt man die Programmzeilen ein, u m a u c h d o r t n o c h K l a r h e i t z u h a b e n ( d a z u i n K a p . 3 . 11 . m e h r ) . Drei Dinge, die im Umgang mit IF zu beachten sind: 1. Sobald mehr als eine Anweisung im THEN- oder £Z.S£-Zweig ausgefuehrt werden soll, muessen diese mit BEGIN und END geklammert werden! Sie bilden dann eine verbundanueisung. 2- Hinter der Anweisung, welche nach THEN steht darf KEIN Semikolon folgen. WENN es noch ein ELSE in der /f-AnWeisung gibt! Erst nach der Anweisung, welche auf ELSE folgt, i s t e i n S e m i k o l o n zu setzen, weil dort die /F-Anweisung endet. S o l l t e k e i n £ £ S £ - Z w e i g v o r h a n d e n s e i n , s o muss nach der THENA n w e i s u n g e i n " ; " s t e h e n , i s t j a k l a r. 3. Fuehrt man mehrere Zf-Anweisungen ineinander auf, so nennt man das SCHACHTELN. Ein wichtiger Ausdruck, der noch haeufiger vorkommen wird. Wie kleinere Schachteln in groessere passen, so kann man /F-Anweisungen ineinandersetzen. Siehe dazu das vorangehende Struktograrnrn. In Bezug auf diese Punkte solltet ihr euch nochrnal die obigen Beispiele ansehen.
43

Mmmmh, Moment. Da kommt uns gerade ein Sonderfall in den Sinn, den zu verachten sich nicht bezahlt macht. Darum eine kleine Deklamation dazu: Es wird die Hoehe eines Hauses angegeben. Wenn es niedriger als 1 0 m i s t , d a n n s a g e n w i r, e s s e i k l e i n . I s t e s g r o e s s e r a l s 5 0 m , dann sagen wir, es sei sogar sehr gross. Haeuser, die dazwischen liegen, interessieren uns nicht. Wir sind fuer Extreme. Struktoqrarnm dazu: — + + < Hausgroesse einlesen Hoehe >= 10 n ?

*r-

A J
—--/:■

N E I N

/ ! Hoehe > 50 q ? Schreibe: -v , ! Das Haus ist JA v -- 'NEIN I klein.

I Schreibe: I Das Haus ist ! sehr gross!
4

Umgesetzt in ein Programm:
PROGRAM hausgroesse; V AR hoehe : REAL; BEGIN WRITE ( 'Bitte Haushoehe eingeben; ' ); READLN ( hoehe );

IF hoehe >= 10
THEN IF hoehe > 50 THEN WRITELN ( 'Ohhh, ein sehr grosses Haus." ) ELSE WRITELN ( 'Schade, nur ein kleines Haus.' ); END.

Ti p p t e s ' m a l e i n , u n d l a s s t e s m i t v e r s c h i e d e n e n W e r t e n f u e r d i e H a u s h o e h e l a u f e n . N a , u e b e r r a s c h t ? K l a r, e s f u n k t i o n i e r t naemlich nicht ganz so, wie geplant. F u e r H a u s h o e h e n u e b e r 5 0 i s t a l l e s O K , a b e r d a r u n t e r. . . ! Selbst 20 m hohe Haeuser werden als klein bezeichnet, was ja n i c h t g e w o l l t w a r. wo liegt der Fehler? Gruebel, grurnmel, denk, denk,

44

Ganz einfach. Wir haben euch durch falsches Einruecken des E L S E — Z w e i g e s g e l e i m t . D e r g e h o e r t n a e m l i c h n i c h t z u m 1 . I F, sondern zum 2. IF; so sieht's korrekt aus:
IF hoehe >- 10
THEN IF hoehe > 50 THEN WRITELN ( ' ... ELSE WRITELN ( ' ...

Es wird ein ELSE—Zweig immer zum letzten IF gerechnet, welches k e i n e n h a t ; b z w. i m m e r z u m t i e f s t q e s c h a c h t e l t e n , , I F o h n e E L S E , K e i n e Ve r z w e i fl u n g a u f k o m m e n l a s s e n . E s g i b t e i n e L o e s u n g . Wollen wir Limbedingt unser obiges Programm verwirklichen, so ist d i e Ve r z w e i g u n g s a n w e i s u n g s o z u p r o g r a m m i e r e n : diese VerbunoWiweisunQ macht die innere IF-Anweisüno nach draußen unsLchtbqr, So dop otastLSE der äußeren zugeschlagen Wird I

IF hoehe >= 10 THEN/BEGIN IF hoehe > 50 THEN WRITELN ( 'Ohhh, ... ' ); ELSE WRITELN ( 'Schade, ...' ) t

oder
IF hoehe >= 10 THEN IF hoehe > 50
THEN WRITELN ( 'Ohhh, ...' ) ELSE <* hier nur die LEERE ANWEISUNG / *; ELSE WRITELN ( 'Schade, ...' );

45

3.7.

Die Wahrheit und nichts als die Wahrheit

In diesem Kapitel beschaeftigen wir uns mit Aussagen, Wahrheitswerten und der weiteren Vertiefung unseres Wissens ueber Ausdruecke und Vergleiche usw. Das klingt nicht nur trocken, das ist es auch. %J Cv CV ÖC\ m nein. jeder muss mal eine Durststrecke durchstehen. Danach koennt ihr aber gelaeutert die naechsthoeheren Weihen der Informatik in Empfang nehmen. Darum: Nicht kleckern, sondern jetzt mal 'rangehen... Aussagen -wie das Wort schon andeutet- sagen etwas aus. Um genauer zu sein: Aussagen kann man immer mit den Adjektiven WAHR oder FALSCH belegen. Drei Aussagen als Beispiel: "Schuluntericht ist meist langweilig." Aussage ist WAHR. "Aus diesem Buch kann man nichts lernen." Aussage Aussage ist FALSCH. FALSC "Dieses Buch ist sehr gut." Aussage ist WAHR. "Lass' uns schwimmen gehen, Ist keine Aussage.

O f t w e r d e n A u s s a g e n i n Ve r g l e i c h e n a n g e t r o ff e n ; d a s h a b e n w i r s c h o n i m l e tz te n K a p i te l g e s e h e n : 3 > 2 i s t e i n e A L i s s a g e . Auch Herr Wirth (ihr erinnert euch?) dachte sich schon, es sei nuetzlich, mit Wahrheitswerten in Programmen jonglieren zu koennen, und uebersetzte flugs wahr und falsch ins Englische: wahr wird zu TRUE f a l s c h w i r d z u FA L S E Man kann sie im Program verwenden, wo's passt:
IF TRUE

THEN WRITE ( 'Die Bedingung ist WAHR' ); Ein ££S£-Zweig eruebrigt sich, weil die Bedingung immer wahr ist, er wuerde nie angelaufen. Den gleichen Zweck wuerde: IF 2 - 2
THEN WRITE ( 'Ist auch immer WAHR' );

e r f u e l l e n . G e n a u s o k a n n m a n FA L S E e i n s e t z e n , der ££S£-Zweig angelaufen (falls vorhanden).

dann wird eben immer

T j a , s o a l l e i n h a b e n T R U E u n d FA L S E n a t u e r l i c h w e n i g S i n n , a b e r da haben wir die Phantasie des oben erwaehnten Herrn unters c h a e t z t . Z u d i e s e n b e i d e n K o n s t a n t e n h a t e r e i n e n n e u e n Ty p e r s o n n e n , d a m i t m a n W a h r h e i t s w e r t e a u c h Va r i a b l e n z u w e i s e n k a n n . Eigentlich nur konsequent, nicht? D i e s e r Ty p h e i s s t B O O L E A N . B e n a n n t n a c h G e o r g e B o o l e , e i n e m b e r u e h r n t e n M a t h e m a t i k e r. U n s e r t y p - S y n t a x d i a g r a r n r n e r w e i t e r t s i c h :

4&

typ (inaer noch vorlaeufig): —>—r—('iHTEfiER)—T—> II " A \ ' N ' +-J REAL r-+

♦ ~ VB 0 0 L E A N V +

Va r i a b l e n d i e s e n n e u e n Ty p s k o e n n e n u e b e r a l l d o r t e i n g e s e t z t w e r d e n , w o i h r s o n s t e i n e n Ve r g l e i c h s c h r e i b e n w u e r d e t . Nach dem internen Schnittmuster hergestellte Kaesten fuer sie sind sehr sehr klein; Kasten für INTEGER

0 *V KostenfürBOOLEAN

PROGRAM wahrheitsvariablen;
V AR

kleineshaus, sehrgrosseshaus : BOOLEAN;
hoehe : REAL;

BEGIN WRITE ( 'Bitte die Haushoehe angeben: ' ); READLN ( hoehe ); kleineshaus := hoehe <= 10; sehrgrosseshaus :- hoehe > 50; IF kleineshaus THEN WRITELN ( 'Schade, ein kleines Haus.' ) ELSE IF sehrgrosseshaus THEN WRITELN ( 'Ohhh, ein sehr grosses Haus/' ); END.

A n d i e s e m W i e d e r a u f g r i ff u n s e r e s A b s c h l u s s p r o b l e m s v o r n l e t z t e n Kapitel koennen wir mehrere Dinge sehen. Z u m e i n e n d i e e r w a e h n t e M o e g l i c h k e i t d e r Ve r w e n d u n g v o n B00Z.£M-Variablen immer dort wo eine Bedingung stehen muss; zürn a n d e r e n d i e Z u w e i s u n g v o n Wa h r h e i t s w e r t e n a n s o l c h e Va r i a b l e n . Als letztes noch, gewissermassen ein Nebeneffekt, die groessere Uebersichlichkeit eines Programmes durch sparsamen Gebrauch l o g i s c h e r ( B Q Q L E s c h e r ) Va r i a b l e n . Nochmal zur Zuweisung. Genauso, wie ein mathematischer Ausdruck e i n E r g e b n i s l i e f e r t , w e l c h e s v o m Ty p R E A L o d e r I N T E G E R i s t , genauso hat auch ein logischer Ausdruck ein Ergebnis. Dessen Typ ist BOOLEAN und kann somit jeder Variablen diesen Typs zugewiesen werden.

47

Beispiele fuer Ausdruecke
12 + 3 # (SIN ( x ) - z) ROUND ( z * 3.455 + x ) (z - 4.5) >= (SIN ( z ) + 3) a - 15 - f

Resu11 at st yp en
REAL INTEGER BOOLEAN BOOLEAN

Und immer wieder: der Unterschied zwischen Vergleichsoperatoren und arithmetischen Operatoren ist, dass erstere einen Wahr h e i t s w e r t ( T R U E o d e r FA L S E ) a l s E r g e b n i s l i e f e r n , l e t z t e r e a b e r einen Zahlenwert. Obwohl beide als Operanden mathematische Aus druecke verlangen. D i e P r i o r i t a e t d e r Ve r g l e i c h s o p e r a t o r e n i s t n o c h n i e d r i g e r a l s die von + oder --. D.h. man kann schreiben:
wahrheitsvariable := (12 + b) >= 13 wahrheitsvariable := 12 ■/■ b >= 13

oder

E r s t e r e s i s t e t w a s e i n d e u t i g e r, a b e r d i e K l a m m e r n s i n d n i c h t notwendig. Zu r E i n s c h a e r fu n g :
VAR Wahrheit ; BOOLEAN; i : INTEGER;

Wahrheit := 13 > 9; Wahrheit := Wahrheit; Wahrheit :- 9 <> 10; Wahrheit :- 10 + SIN ( 3.14 ) >= 0.5; Wahrheit :- 3 + 4 - i; -3 + Wahrheit; Wahrheit := TRUE;

ist cvk, Wohrheit bekömmt den Wert TRUE" ouch out, Wahrheit behält Seinen Wert ok, Wahrheit wirrJTRUF

alles klQv
nein, nein! 3+4. - L liefert, eine Zahl cxls Ergebnis / keinen Wahr heifcs wert] c|ekt auch n'Cnti X>er Operator +- muß einen mqth. Ausdiruck als «2. Operqnden haben!

ok!

Die Verwendung von logischen Variablen ist besonders dann sehr elegant, wenn eine Bedingung in einem Programm mehrere Male geprueft wird. In dem Fall deklariert man passend eine boolesche weisst ihr schnell den Wahrheitswert der oefter zu Va r i a b l e , pruefenden Bedingung zu und verwendet sie immer dann, wenn die Abfrage erfolgen soll: 48

VAR

bedingung : BOOLEAN;

bedingung :- (i + 9 * SIN ( z )) > EXP ( 1.002 ); (* sehr profimaessig #)

(* weiter unten im Programm folgt dann ; #) IF bedingung THEN ... ELSE ... IF bedingung THEN ... IF a > b THEN ... ELSE IF bedingung THEN ... Tja, wie jedermann leicht einsieht, man kann sich 'ne Menge Arbeit sparen. Wer wollte auch den Riesenvergleich so oft hinschreiben? Wir sind doch faul !

Aus dem Leben gegriffen: Vi e l w i r d d a v o n g e r e d e t , w e n i g e t u n e t w a s d a f u e r. G e m e i n t i s t der Computer im Haushalt, z.B. in der Kueche. Mutti moechte eine Entscheidungshilfe in Sachen Kochen. Hoho, die soll sie bekommen. Ver bal e Pr ob 1 ern f or rnul i er ung: Wenn ich mehr als 50 DM in der Haushaltskasse habe, dann kaufe i c h S t e a k s , h a b e i c h w e n i g e r, d a n n g i b t e s G r i e s s , e s s e i d e n n , ich hab' nur noch 1 DM, dann wird gefastet, sonst gibts Griess, w e n n n i c h t g e r a d e F r e i t a g o d e r D o n n e r s t a g i s t , a n d i e s e n Ta g e n gibt's dann Fisch. Sollte in der bekannten Illustrierten xxxxxx gerade eine Diaet laufen, dann gibt's das Diaet-Menue, egal wie die Finanzen sind.

49

Als Struktogramm:
+ + ! Einlesen, uieviel Geld in der Kasse ist
+— — i

I Wochentag einlesen — + Einlesen, ob eine Oiaet laeuft \.___*

\

Oiaet ?

JA \ -i -<_.

\

N E I N oelir als 50 DH ?

+--

JA\

'v

HEIN
"

-y*
I

I

\ weniger als 1 DH?' ! \ JA \ ,' NEIN i
.^K. 1

+-

t - . . - V- - >
!\ Do?/;

Fr ? / i \ / ! JA • NEIN I

+„_.V---+
IDiaetiHenue Steak ! fasten
Fi ! Fi IGriess seh ! seh! !

i ja, .nein:

+

50

Einen Moment, bitte, dann haben wir das auch als Programm: PROGRAM wassol1 ichessen; V A R geld : REAL; Wochentag, diaet : INTEGER; BEGIN WRITE ( 'Wieviel Geld ist in der Kasse: ' ); READLN ( geld ); WRITE ( 'Diaet in Zeitschrift? Wenn ja, dann 1, sonst 0: ' ); READLN ( diaet ); WRITE ( 'Wochentag (Mo=l, Di=2,...So=7): ' ); READLN ( Wochentag ); IF diaet - 1 THEN WRITELN ( 'Mmmmm, ein leckeres Diaetmenue." ) ELSE IF geld > 50
THEN WRITELN ( 'Kauf doch mal Steaks.' ) ELSE

IF geld > 1 T H E N IF Wochentag -4 (* d.h. Donnerstag *) THEN WRITELN ( 'Hurra es gibt Fisch.' ) ELSE IF Wochentag - 5 C# Freitag «> THEN WRITELN ( 'Mmmm, Fisch.' ) ELSE WRITELN ( 'Tja, nur Gries.' )
ELSE WRITELN ( 'fasten...' ); END.

Zugegeben ein relativ holes Beispiel, aber nagt nicht trotzdem in euch die Unzufriedenheit ueber die Unuebersichtlichkeit. OK, die ersten beiden Schachtelungsebenen gehen ja auch noch, aber zweimal abzufragen, wie der Wochentag ist, das ist einfach zuviel, und die Entscheidung zum Fasten, eieieiei... Man muesste schreiben duerfen:
IF Wochentag gleich 4 oder 5 THEN WRITELN ( 'Es gibt mal wieder Fisch/' );

Und tatsaechlich, trara trara, das geht so, oder aehnlich. Seit ehrlich, ihr habt's nicht zu hoffen gewagt. PASCAL sieht Verknuepfungen zwischen Zahlen vor (+, - usw.) und g e n a u s o g i b t e s d i e M o e g l i c h k e i t , b o o l e s c h e Va r i a b l e n z u verknuepfen. Dafuer stehen die Operatoren AND, OR, NOT zur Verfuegung. Sie entsprechen den Deutschen Worten UND, ODER und NICHT."

Einige verbale Beispiele: We n n K l a u s g r o e s s e r a l s P e t e r i s t U N D K l a u s g r o e s s e r a l s W i l l i ist, dann ist Klaus der groesste von den dreien. Wenn ich NICHT fahre, dann gehe ich, sonst fahre ich. Wenn ich gehe, dann gehe ich, sonst fahre ich. Hat den gleichen Effekt wie der vorangehende Satz. Wenn es dunkel ist ODER nach 0 Uhr ist, dann schlafe ich. Ebenso kann man in PASCAL formulieren, dass eine Anweisung nur ausgefuehrt werden soll, wenn mehrere Bedingungen gleichzeitig er fuelIt sind:

IF (a > b) AND (a > c) THEN WRITE ( 'a ist am groessten' ); IF (a - b) OR (b - c) OR (c = a) THEN WRITE ( 'mindestens zwei Werte sind gleich' )\
IF NOT (a = b) THEN ...

ist das gleiche wie IF a <> b
THEN ...

M i t A N D , O R u n d N O T k a n n m a n N U R A u s d r u e c k e , Va r i a b l e n u n d K o n s t a n t e n v e r k n u e p f e n . d e r e n R e s u l t a t , b z w. W e r t v o r n Ty p B O O L E A N i st !

V A R bl, b2, b3 : BOOLEAN; z : INTEGER;

bl := b2 AND b3 OR (2 > z);
IF (z - 4 < 90) OR b2 AND NOT b3 THEN ...

b2 := TRUE; b3 := FALSE;

bl := NOT b2;

b3 :~ z AND bl;

(* geht nicht, z hat Typ INTEGER *)

Nun verhaelt es sich so, dass logische Ausdruecke in denen AND usw. vorkommen nur unter bestimmten Bedingungen TRUE oder FALSE liefern. Um dies ein wenig zu erhellen, die grundlegendsten Wa h r h e i t s t a b e l l e n :
V AR

BOOLEAN; (# werden in der folgenden Tabelle be nutzt *)
! a AND b a OR b TRUE TRUE FALSE TRUE NOT a FALSE FALSE TRUE TRUE

+
TRUE TRUE FALSE FALSE i i ! ! TRUE FALSE FALSE TRUE ! ! ! ! TRUE FALSE FALSE FALSE

Da immer wieder die Aehnlichkeit zu den mathematischen Operatoren auftaucht, wollen wir euch auch nicht vorenthalten, d a s s e s e i n e P r i o r i t a e t e n a b f o l g e e b e n f a l l s b e i d e n Ve r g l e i c h s und logischen Operatoren gibt: Dort hat NOT die hoechste Prioritaet, dicht gefolgt von AND, auf dem 3. Platz rangiert OR, und weit abgeschlagen folgt das F e l d d e r Ve r g l e i c h s o p e r a t o r e n ( > , < , = , < = , > = , < > ) , s i e h a b e n a l l e g l e i c h e n Vo r r a n g . A u s d i e s e r Ta t s a c h e e r g i b t s i c h :
(2 > 3) AND (3 < 4) 2 > 3 AND 3 < 4

ist Sek korrekt und liefert ThLSE oJi,ofi.' f{Nd Wöft/eJu.3 verknüpfen, weiL es \6rmng vor < und > hot,' Also ^elit'S nicht (Kammern Sind Jetzt notwendig i

So, bevor am Schluss noch ein Bonbon auf euch wartet... Ohhh, nicht linsen, soll eine Ueberrasehung sein. Nun, also hier noch die Vereinfachung unseres Kuechenprogramms und ein neues Problem mit Loesung.

V AR

diaetmenue, fischmenue, steakmenue, fasten ; BOOLEAN; diaetmenue : = diaet - 1; steakmenue := NOT diaetmenue AND (geld > 50); fasten :- NOT diaetmenue AND NOT steakmenue AND (geld < 1); fischmenue := NOT diaetmenue AND NOT steakmenue AND NOT fasten AND ( (Wochentag - 4) OR (Wochentag - 5) ); IF diaetmenue THEN WRITELN ( 'Also ein Diaetmenue.' ) ELSE IF fischmenue THEN WRITELN ( 'Es gibt Fisch." ) ELSE IF steakmenu THEN WRITELN ( 'Es gibt leckere Steaks///' ) ELSE IF fasten THEN WRITELN ( 'Und wieder fasten...' ) ELSE WRITELN ( 'Griess, Griess alle Tage.

1

i'

Ist das nicht schoen uebersichtlich? Da bekommt man richtiq Hunger. Aber halt v o r d e m Ve r g n u e q e n n o c h ein wenig Prob1emwaelz en: B o o l e s c h e Va r i a b l e n h a b e n d e n g r o s s e n Vo r t e i l , d a s s s i c h m i t ihnen relativ natuer1ichsprachliche Problemformulierungen leicht und uebersieht lieh in ein Programm uebertragen lassen:

lies Zahl

gueltig

J A

^ "HEIM
s " j

! \ Priazahl ? , \

I JA\ „'NEIN ! Meldung t x< +
i
i

r
i

i

i

[Gratulation! Beileid I t

In ein Programm uebersetzt:
PROGRAM primzahltest; V A R zahl : INTEGER; primzahl : BOOLEAN; BEGIN WRITE ( 'Eine ganze Zahl zwischen 0 und 10 eingeben: ' ); READLN ( zahl ); IF (zahl >- 0) AND (zahl O 10) <* Gueltigkeitskontrolle *) THEN BEGIN primzahl :- (zahl > 0) AND (zahl < 8) AND (zahl MOD 2 <> 0) OR (zahl = 2); IF primzahl THEN WRITELN ( 'Ja, eine Primzahl." ) ELSE WRITELN ( 'Schade, keine Primzahl.' ); E N D ELSE WRITELN ( 'Junge, eine ungueltige Zahl//!' );
END.

Eine Gueltigkeitskontrolle wie oben gehoert auch z L i d e n d i e i h r e u c h m i t d e r Z e i t a n e i g n e n so 11t et. Profitechniken, I m m e r, w e n n We r t e e i n z u g e b e n s i n d , u n d s i e i n e i n e m b e s t i m m t e n Bereich liegen sollen, kann man eine solche Kontrolle anhaengen, damit eine folgende Berechnungsroutine nie auf ungueltige Werte aufbaut: z.B. entstehen Divisionen durch 0.

54

So jetzt das Es
LISW.

von dem wir gesprochen haben.

sind dies naemlich die Syntaxdiagramme sie werden die letzten Klarheiten beseitigen: additionsoperator: V
I

fuer

ausdruck

aultiplikationsoperator ... >. V
I

V
I

V
I

V
I

- > - T- - > — 7 — > " V V
i i

It, (/ | l DIV I I HOD 1 i AND )

' + .
y

) « > ;
1 ♦ >

Vergleichsoperator (nicht ganz voilstaendig):
—>—-—>-

vorzeichenlose konstante:
t f + + + t + 4 + + j A j

>--- :-«>—r~>i i I i

■>-

—>--7—! vorzeichenlose zahl !—7
j V .

V
I =

V
I

V
/ V

V

N / * I <>.t { > \ JI>= )f < M <=)

+—! konstantennaie '—+
j + i j

t—! -—>—+—>faktor (unvollstaendig):
+ 1

string

i—+

->—+-->—+-->tern: ! 7! a j j

—>—7
! V j ■

!

variable
+ + + t 1 1 * +

+ + ■>-! faktor i+ + + + + + -i faktor !-<-! nultiplika+ + J tionsopera' I tor +

*—! vorzeichenlose konstante i—+ + '(">-! ausdruck !---')% + J t i J : „„ * + ! +-n NOT >-->—-! faktor ! >-—+ / + + einfacher ausdruck;
t 1
+

->-r—>™ V ausdruck:
+ +

->---! tera !i

> i + + i —<—J tera !—<—! additionsoperator I + + + +
.. V + + > +

.. v

1 T. 1 A 1

—>—* einfacher ausdruck !-

-—>—! Vergleichsoperator !—>—! einfacher ausdruck i bedingung: ist ein ausdruck, dessen Resultat von Typ BOOLEAN ist

3a 8«

Vo n d e n C h a r a k t e r n u n s e r e s C o m p u t e r s

Nein, bitte versteht die Ueberschrift nicht falsch; natuerlich h a t d e r C o m p u t e r k e i n e n C h a r a k t e r. E r i s t n i c h t m a l m e n s c h e n aehnlich (ausserdem muesste es "Charakteren" heissen). U n d d o c h . . . c h a r a c t e r h a t e r. A c h t e t j e t z t a u f d e n U n t e r s c h i e d i n d e r S c h r e i b w e i s e : c h a r a c t e r u n d C h a r a k t e r. Wir meinen erstere. Insofern war die Ueberschrift gemogelt (aber gar nicht schlecht, gell?). Das Wort "character" bedeutet naemlich Buchstabe oder Zeichen, w e l c h e e s i n PA S C A L j a g i b t . W i r e r i n n e r n n u r a n d i e W R I T E Anweisung, z.B. WRITE ( 'A' ) schreibt einen Buchstaben (character) auf den Schirm. Genauso schoen waere es aber, koennte man auch einzelne B u c h s t a b e n v o n d e r Ta s t a t u r e i n l e s e n w i e Z a h l e n . Urn das zu bewerkstelligen, muessen wir einen neuen einfuehren: CHAR (eben die Abkuerzung von character).
V AR buchstabe : CHAR; v e r e i n b a r t e i n e Va r i a b l e v o m Ty p C H A R . S i e k a n n n u r e i n e n einzigen Buchstaben aufnehmen, z.B. A oder B oder * oder ) oder 9 o d e r V. o d e r 0 . I h r s e h t s c h o n , n i c h t n u r B u c h s t a b e n , s o n d e r n auch Sonderzeichen und Ziffern, um genau zu sein. D.h. alle Zei c h e n , d i e d u r c h d a s D r u e c k e n e i n e r Ta s t e a u f d e r Ta s t a t u r e r z e u g t werden koennen. I s t j a k l a r, d a s s m a n e i n e r C H ^ fi - Va r i a b l e n a u c h e i n e n We r t i m Programm zuweisen darf: buchstabe := 'A'; oder buchstabe := '0'; Ty p

READLN ( buchstabe ); funktioniert aber auch. Bei der Zuweisung eingeschlossen sein! Merke: buchstabe muss
i i i

das

Zeichen

wieder

in

Hochkornrnata

:-

'AB';

Zeichen ist in der Zuweisung erlaubt Va r i a b l e n i s t e b e n z i e m l i c h k l e i n :

ist falsch! Nur EIN Der Kasten einer CHAR-

$iehske,das nicht mehr hinein.

5fi

Ein letzter Hinweis gilt einem oft nicht so genau beachteten Unterschied zwischen '0' und 0. '0' ist ein Zeichen (Buchstabe), mit dem NICHT gerechnet werden kann. Mit der Zahl 0 dagegen kann man rechnen. Daraus folgt aber auch dies: buchstabe := '9'; buchstabe :- 5; ist korrekt und erlaubt, aber nicht, da man versucht einer CHAR -Variable einen JN7£G£ß-Wert zuzuweisen. Geht nicht!

In diesem Zusammenhang erinnern wir an die notwendige Uebereinstimmung von Typen in Zuweisungen und Ausdruecken.
V AR ch ; CHAR; i : INTEGER;

ch := '9'; i :3;

^0

v o mT yp CHAR
oh, oh, oh, das geht nicht/ Die Typen stimmen nicht ueberein,

i :■=■ i # 1 2 - c h ;

vom Typ INTF&ER
Das neue Syntaxdiagramm fuer TYP:

typ (leider iauer noch unvollstaendig):
-> -I INTEGER r > V ",~"_"' A

+ — i ' r e a l V- t +--/8D0lEANr-+ . v ■I I . +---''CHAR V-+

S o o o , d a m i t k e n n t i h r A L L E v o r d e fi n i e r t e n Ty p e n i n PA S C A L . Das sind schon eine ganze Menge. Zur Belohnung ein Beispiel Pro gramm:

PROGRAM wandeln; (*# wandelt eingegebene Kleinbuchstaben in Grossbuchstaben #) V A R
ch : CHAR; grossch : INTEGER;

BEGIN WRITE ( 'Bitte einen Buchstaben eingeben: ' ); READLN ( ch );
WRITELN; IF (ch >= 'a') AND (ch <= 'z') THEN BEGIN grossch := ORD ( ch ) - 32;

WRITELN ( 'Der zugehoerige grosse Buchstabe:', CHR ( grossch ) :3 ); E N D ELSE WRITELN ( ' > Es war kein kleiner Buchstabe.' );
END.

Tjaaa, nicht schlecht, Herr Specht. Ein gepfeffertes Beispiel, aus dem man eine Menge lernen kann. Vo r a u s g e s c h i c k t s e i , d a s s a l l e Z e i c h e n , d i e d e r R e c h n e r k e n n t , durchnumeriert sind: ^r Zeichen + t . / 0 1 2 r m O 7 * f a w * H Cf C> r * *
43 44 45 46 47 48 49 50 X Y Z 88 89 90 a b c 97 98 99 56 57 58 59 65 66 67

•-

x
120

y

z
121

■-■
122

"zugehörige
„ 0 ä Q

D i e s w a r e i n kl e i n e r Au szu g a u s d e m ch a ra cte r se t (to l l e s Wo r t, bedeutet: Menge aller Zeichen des Computers). Meist ist er dem ASCII nach versehluesseit. ASCII=American Standart Code for In formation Interchange (wer ASCII-Code sagt, hat irgendwas nicht verstanden -mal das C in ASCII anschauen-). Wenn das so ist (stimmt eigentlich immer), dann sind alle Ziffern und die Gross-ZKleinbuchstaben aufsteigend durchnum meriert (siehe oben). 'A' hat die Ordnungszahl 65, 'a' die Ord nungszahl 97 usw. Die Ordnungszahlen gehen von 0 bis 255, nicht weiter! D.h. es gibt nur 256 verschiedene Zeichen (Buchstaben). Aus diesem Grunde ist es auch erlaubt zu schreiben:
IF (ch >= 'a') AND (ch <= 'z>)

I n d i e s e r / ^ - A n w e i s u n g p r u e f t d e r R e c h n e r, o b d i e O r d n u n g s z a h l d e s B u c h s t a b e n i n d e r Va r i a b l e n c h g r o e s s e r o d e r g l e i c h d e r O r d n u n g s z a h l v o n ' a ' ( 9 7 ) b z w. k l e i n e r o d e r g l e i c h d e r v o n ' z ' (122) ist. Der 7"W£W-Zweig obiqer Anweisung wird also nur ausge58

fuehrt, wenn der Buchstabe in ch ein Kleinbuchstabe ist, d.h. zwischen 'a' und 'z' liegt! Merke: 'z' hat eine hoehere Ordnungszahl als 'a'! Um aber mit diesen Ordnungszahlen auch arbeiten zu koennen, sind zwei neue Funktionen zu lernen:

O R D ( c h ) c h m u s s e i n e C H A R - Va r i a b l e s e i n . Die Funktion liefert die Ordnungs zahl des Zeichens in ch, also einen INTEGER-Wert.
ORD ( 'A> ) ergibt 65.

CHR ( int ) int ist ein Ausdruck, der einen INTEGER-Wert als Resultat hat. Des sen Groesse sollte zwischen 0 u. 255 liegen. Das Ergebnis von CHR ist ein Wert vom Typ CHAR.
CHR ( 65 ) ergibt 'A'.

Mit diesem Wissen ausgestattet schaut euch bitte noch einmal das Listing des Programms wandeln an. Dort wurden ja CHR und ORD e x e m p l a r i s c h e i n g e s e t z t . D i e Ta t s a c h e , d a s s d i e K l e i n b u c h s t a b e n auf die Grossbuchstaben folgen, wurde dort genutzt, um eine Umrechnung zu verwirklichen. Zum Schluss noch die Methode, wie ihr herausfinden koennt, w e l c h e l u s t i g e n O r d n u n g s z a h l e n z u d e n Ta s t e n e u r e s R e c h n e r s gehoeren: PROGRAM Ordnungszahlen;
VAR

ch ; CHAR; (* wenn im Programm nur eine wichtige CHAR-Variable verwendet wird, so nennt man sie sehr oft ch od. c #) BEGIN
W R I T E ( ' Ta s t e d r u e c k e n : ' ) ; R E A D ( K B D , c h ) ; WRITELN;

WRITELN ( 'Ordnungszahl dazu: ', ORD ( ch ):3 );
END.

Als kleines Bonbon haben wir hier noch die Anweisung eingebaut, w e l c h e e s e u c h g e s t a t t e t , e i n Z e i c h e n i n e i n e Va r i a b l e n v o r n Ty p C H A R e i n z u l e s e n , O H N E d i e " R e t u r n " o d e r " E n t e r " o d e r " C R " Ta s t e betaetigen zu muessen. Das gewuenschte Zeichen erscheint aller dings NICHT auf dem Schirm. Entscheident ist, dass READ verwendet wird, und dass in den Klammern zuerst steht: KBD, und dann die Variable (.KBD bedeutet KeyBoarD oder Tastatur). W I C H T I G : D a s g e h t n u r i n T U R B O - PA S C A L s o ! ! ! S o l l t e t i h r e i n e a n d e r e PA S C A L - Ve r s i o n h a b e n , s o s e h t i m H a n d b u c h n a c h , o d e r schreibt einfach wieder READLN ( ch ). 59

*3 Q

EJ:jwa^._Cpm£u^ejiH^aJ^a_mee. oder Wie binde ich

E i n A r g u m e n t f u e r d i e Ve r w e n d u n g v o n C o m p u t e r n s o l l s e i n , m u n k e l t m a n , d a s s s i e g l e i c h b l e i b e n d e Ta e t i g k e i t e n o h n e Ermuedungserscheinungen immer und immer wieder mit wachsender Freude ausfuehren koennen. Bisher haben wir davon aber noch nicht allzuviel gesehen, denn unser Rechner legte sich nach einmaliger Durchfuehrung eines Programmes sofort wieder auf die faule Haut.. Diesen Missstand zu beheben, ist das erklaerte Ziel dieses und einiger folgender Kapitel. Kaum zu glauben, dass schon im Volksmund Schlei fen (engl, loop) eine grosse Rolle spielen. Eine 'Schleife' bedeutet eine b e s t i m m t e Ta e t i q k e i t s o l l w i e d e r h o l t a u s q e f u e h r t w e r d e n ! Beispiel: Der Krug geht solange zum Brunnen, bis er bricht.. Urn dieses Prob lern aufzuarbeiten, erst einmal eine logische Korrektur: da ein Krug nicht gehen kann, l a s s e n w i r F r e u n d C l a u s Peter-Uwe laufen. Also:
Claus-Peter-Uwe geht solange zum Brunnen, bis er bricht. Ueber tragen in ein Struktograrnrn ergibt sich:

WIEDERHOLE

!
i

i + ! CPU geht zu» Drunnen I + i
i

BIS

CPU

bricht

i

Der eingerueckte Block -die eigentliche Handlung, welche immer wieder ausgefuehrt werden soll- ist in einen groesseren Block mit NIEDERHOLE beginnt und mit einer ei nqeschlossen, welcher

Bedingung endet (Abbruchbedingunq), welche uns sagt, wie lange wiederholt werden soll; oben eben so lange, bis der gute ClausPeter-Uwe sich uebergeben hat. Fuer phantasielose Gemueter bereiten wir einmal das Lesen eines Buches als Wiederholungsanweisung auf:

60

W I E D E R H O L E

eine Seite lesen uablaettern

"+ <£- erst diese. Ariwßisuno *" ausführe"

-; BIS rueckvaertige Uuschlagseite erreicht

^

dann diese, ausführen

v

/ dorm prujen, ob die ^edinOuno Schon

/

erföHt St.

Im Struktorgramm verwenden wir NIEDERHOLE und BIS, um die g r o s s e n Ta t e n a b z u g r e n z e n , w e l c h e z u r o e f t e r e n A u s f u e h r u n g a n s t e h e n , i n PA S C A L w e r d e n w i r w i e d e r e n g l i s c h u n d s a g e n :
R E P E AT u n d U N T I L Dazu erstmal flugs das Syntaxdiagramm, damit gar keine Unklar heiten auftauchen:

/Weisungen-Solcinfle. QusfiihrerL b'S BediriQuriq 7w£ (.'efert,
repeat-anweisung:
--->-«/ REPEAT *-->---—! anweisung !--;—>--{ UNTIL T->—! bedingung !—>

v

I

*

+

k

v

v

y

+

+

-<-{ , t-

Daraus geht deutlichst hervor: alles, was wiederholt ausge f ü h r t w e r d e n s o l l ( d i e A n w e i s u n g e n ) , s t e h t z w i s c h e n d e n PA S C A L Symbolen REPEAT und UNTIL. Die wiederholte Ausfuehrung dauert so lange, bis die Bedingung hinter UNTIL TRUE liefert. Zum Aufbau von Bedingungen siehe auch die JF-Anweisung. Ok das war eigentlich schon alles. Tja, M m m m , a b e r n a g u t ; v i e l l e i c h t Anweisung. K l e i n i g k e i t e n z u r Ve r a n s c h a u l i c h u n g . alles zur doch noch
REPEAT-

einige

Zuerstmal schreiben wir ein schoeneres Programm, urn die Ordnungszahlen der Zeichen im character set unseres Rechners herauszufinden.

61

Ueberschrift ausaeben N I E D E R H O L E

ein Zeichen einlesen

i \\

Ende-Zeichen ? NEIN Ordnungszahl ausgeben !

\ JA \

BIS Ende-Zeichen eingegeben wurde !

t

1

Jetzt muss man nicht mehr fuer jedes Zeichen das Programm neu s t a r t e n . E i n e r i i i i i e s e n Ve r b e s s e r u n g ! PROGRAM nochmalwandeln;
CONST

endezeichen
VAR

'E';

(# wenn dieses zeichen eingegeben wird, hoert das programm auf #)

ch i CHAR; BEGIN WRITELN ( 'Ermittlung der ORD-Zahlen der eingegebenen 'Zeichen von der Tastatur.' ); WRITELN;
REPEAT

WRITE ( 'Zeichen eingeben (Programm beenden mit ', endezeichen, '): ' ); READ ( KBD, ch ); WRITELN; IF ch <> endezeichen
THEN WRITELN ( 'ORD-Zahl dazu:', ORD ( ch ):3 ); WRITELN;

UNTIL ch - endezeichen; END.

Selbsterklaerend, nicht wahr? Erwaehnenswert ist jedoch die Te c h n i k , w i e s c h o n i n d e r S c h l e i f e g e p r u e f t w i r d , o b b e s t i m m t e Anweisungen ueberhaupt noch ausgefuehrt werden muessen, oder gleich zum Schleifenende gegangen werden soll.

62

Zur Erbauung aller Mathematikfreunde moechten wir uns an dieser Stelle erlauben, ein wenig zur Erleichterung der Berechnung von Folgen und F^eihen beizutragen. Manchem mag das eine gewisse Erleichterung bringen. Problem: Die Berechnung der Glieder einer Folge sowie der S u m m e a l l d i e s e r G l i e d e r. E s m u s s d i e Z a h l d e r G l i e d e r u n d d a s erste Glied, sowie die Differenz zweier Glieder angegeben werden.

N I E D E R H O L E

+ einlesen der Gliederzahl
I einlesen des 1. Gliedes
4

I einlesen der Differenz

+ ! Sumse := 0; gliednunaer := t; + !W I E D E R H O L E

Sunae := Sumse + Glied

i i

! Glied := Glied + Differenz + i qliednunoer := gliednuaaer i ♦ 1

+
! BIS gliednunaer >= Gliederzahl i Fragen, ob noch eine Folge bei rechnet werden soll
4

BIS keine Folge sehr berechnen

Am beachtenswertesten an diesem Beispiel i s t z u m e i n e n , w i e erzwungen wird, eine gueltige Gliederzahl einzugeben, zum ander & n , d i e I N I X I A L j r ^ I E R Ü . N G , d . h . Vo r b e i e g u n g , v e r s c h i e d e n e r We r t e ( S u m m e u s w. ) v o r E i n t r i t t i n d i e S c h l e i f e , damit Sinnvolles ges c h i e b t . A l s l e t z t e s v e r i n n e r 1 i c h e m a n g u t , d i e Te c h n i k d e r a e u s seren Abfrageschleife, ob nocheinmal der F'rogramrndurchlauf qedenn BENUTZERFREUNDwuenscht wird. Eine sehr nuetzliehe Sache LICHKEIT steht an (fast) erster Stelle bei u n s . S c h l i e s s l i c h s o l l ja jeder sehen koennen, dass ihr auch die l e t z t e n K n i f f e i n d e r Programmierung beherrscht.

63

PROGRAM folgensumme;
VAR

gliednummer, gliederzahl : INTEGER; summe, glied, differenz : REAL; nochmal : CHAR; BEGIN WRITELN ( 'Berechnung der Glieder und Summe einer Folge.' );
REPEAT

WRITELN; (* Einlesen wichtiger Daten fuer die Folge *)
REPEAT

WRITE ( 'Gliederzahl der Folge (muss > 0 sein): ' );
READLN ( gliederzahl ); UNTIL gliederzahl > 0;

WRITE ( 'Erstes Glied: ' ); READLN ( glied ); WRITE ( 'Differenz zwischen zwei Gliedern: ' ); READLN ( differenz ); (# Initialisierung wichtiger Daten fuer die Berechnung *)
WRITELN;

WRITELN ( 'Gliednummer: Glied; Summe:' ); O Summe und Glieder berechnen und ausgeben #) summe := 0; gliednummer := 1;
REPEAT

WRITE ( gliednummer:7, glied:18:3 ); summe := summe + gl ied; WRITELN ( summe:13:3 ); g l i e d : - g l i e d * d i ff e r e n z ; gliednummer ;= gliednummer * 1; UNTIL gliednummer >= gliederzahl;
WRITELN;

C# Abfrage, ob noch eine Folge berechnet werden soll #) WRITE ( 'Keine Folge mehr berechnen, dann "N" eingeben: ' ); READ ( KBD, nochmal ); WRITELN; UNTIL (nochmal - 'N') OR (nochmal - '»');
END.

64

Der aufmerksame Leser wird sicher schon die Aufgabe von gl iednummer erkannt und als wichtig eingestuft haben. Diese Va r i a b l e n a e m l i c h d i e n t a l s Z A E H LVA R l Ä B L E . S i e z a e h l t , w i e o f t die Schleife schon durchlaufen wurde, und mit ihr wird geprueft, ob eine weitere Abarbeitung der Anweisungen in der Schleife von Noeten ist. Nicht extra erklaert haben wir die moegliche Schachtelung von fl f P f t f r - A n w e i s u n g e n , a b e r, . . . n a j a , e i n B e i s p i e l s a g t e b e n d o c h mehr als 1000 (in Worten: tausend) Worte. Mit der Einfuehrung der Schleifen habt ihr jetzt die ersten hoeheren Weihen zum passablen, nein, guten Programmierer empfangen. Wir erwaehnten es schon einmal. Diese Wieder hol ungsan Weisungen heben naemlich F'ASCAL von z.E<BASIC (oh, welch Fluch lastet auf diesem Wort) ab und ermoeglichen einem jeden das Schreiben strukturierter Programme OHNE das verpoehnte GOTO (wer's nicht kennt, hat Qlueck gehabt).

3.10.

Das,,

En

de

am

Anfang

Haarspalter unter euch, oder die ewigen Andersdenker, haben sicherlich schon die entscheidende Luecke in Claus-Peter-Uwes Gang zum Brunnen gefunden. Was naemlich, wenn dem armen Kerl schon aeusserst uebel ist, bevor er seinen ersten Weg zum Brunnen antritt, und er sich deshalb lieber gleich auf das Abort begibt?

C'est une problem tres defficile.
Das gilt jedoch nur fuer den des F'ASCAL noch nicht ganz Maechtigen. Jener wuerde vielleicht vorschlagen, folgendes zu tun: ... Aber halt, wir wissen nicht, was dieser freundliche Programmierer empfiehlt, wir empfehlen die WH7L£-Schleife. Z.B. in folgender Weise:

4

4

I SOLANGE Claus-Peter-Uwe noch ! nicht uebel ist I TUE
j 4 +

I I Claus-Peter-Uwe ! ! I geht zun Brunnen I
4 4

Im Deuschen SOLANGE und TUE, im Englischen WHILE und DO. Ganz einfach. Das funktioniert quasi so, als haetten wir eine IF— A b f r a g e v o r e i n e R E P E AT S c h l e i f e g e s t e l l t ; n u r i s t e s m i t W H I L E viel einfacher. Folgende Prograrnrnausschni tte daher gleichbedeu tend:

IF bedingung erfuellt WHILE bedingung erfuellt THEN R E P E AT DO ... UNTIL NOT bedingung erfuellt
Die Anweisungen im eingerueckten Block -sie sollen wiederholt ausgefuehrt werden- durchlaeuft der Rechner sooft die Bedingung hinter WHILE erfuellt ist, d.h. solange sie TRUE liefert. Also nicht BIS die Bedingung erfuellt ist, sondern SOLANGE. Ein wichtiger Unterschied! Liefert die Bedingung nie TRUE, noch nicht einmal bevor in die Schleife gegangen wird, so werden die Schleifenanweisungen nie ausgefuehrt. Man sagt auch, die WWJtf-Schleife sei eine abweisende Schleife. Im Gegensatz dazu werden die Befehle innerhalb einer /?£P£#r-Konstruktion mindestens einmal abgearbeitet. Jedoch jetzt erst das Syntaxdiagramm: Solomoe./ wie rjec/'nqunQ 7"RUb" ist AnwelSunQ ausführen uhile-anweisung;
^ —V H 4 _^ 4 4

•>—VHHILE,—>—! bedingung I—>-—DO >—! anweisung !—>

66

" M o o o o r n e n t m a l , J u n g s ! W o m i t k e n n s e i hne ich denn das Ende der A n w e i s u n g s f o l g e , d i e I N ö & r S c h l e i f e s t e h e n s o l l . B e i R E P E AT geschieht das durch UNTIL , a b e r h i e r. . . ? E n t w e d e r i s t d a s e i n M i s t b u c h , o d e r i h r r u e c k t ' m a l ' r a u s m i t d e r Sprac :h e. Hmrnm.

s e h r g u t , ein pfiffiges Kerlchen. Aber die Bemerkung Bravo ist das gerecht? Wir geben uns wirklich ueber dies Buch..., Muehe. Ehrlich! N u n g u t , d i e F r a ge w a r s c h o n b e r e c h t i g t . W i e m e l d e n w i r d a s Ende der zu wiederhol enden Anweisungsfolge? G a n z e i n f a c h ; e n t w e d e r, i n d e r S c h l e i f e s o l l n u r e i n B e f e h l ausgefuehrt werden, d a n n s c h r e i b e n w i r i h n h i n t e r DO und der Cornputer weiss, dass nur diese eine Anweisung in der S c h l e i f e a u s g e fuehrt werden soll; o d e r, b e i m e h r e r e n , k l a m m e r n w i r s i e d u r c h BEGIN u. END (d.h. wii machen daraus eine Verbundanweisung). In d e m F a l l w e r d e n a l l e Anweisungen zwischen dem BEGIN u. END waehrend eines Schlei f e n d u r c h l a u f s a b g e a r b e i t e t . Beispiele:
WHILE zaehler < 5 nur eine Anue>sum m <ier Schleife

DO zaehler := zaehler * 1;

WHILE (zaehler < 10) AND (summe < 100) DO BEGIN . , , o _ . . s u m m e : = s u m m e + x ; _ ^ « ™ < h e r, ■ ^ / " ^ " f 7 zaehler := zaehler + 1; ^ Müssen durch Bt&ltV und END; END oeklammert £&in .

N a t u e r l i c h , h i e r, w i e a u c h s o n s t u e b e r a l l , m a c h t a u c h n u r Uebung einen Meister. Deshalb: Annahme Ueb: Unser PASCAL besitzt nicht die Operatoren DIV und MOD, trotzdem bestehen wir darauf, den ganzzahligen Rest einer Division zu erfahren. Ok, dann mal aufgepasst...

4 4

4 4

! Rest := Divident; Zaehler := 1 I SOLANGE Rest > Divisor ! TUE !
4 + 4 4 4

I Rest := Rest - Divisor ! ! Zaehler := Zaehler * 1 !

Das dazugehoerige vol 1staendige Programm:

67

PROGRAM simulation; V A R divident, divisor, quotient, rest ; INTEGER; BEGIN WRITELN ( 'Berechnung von a DIV b und a MOD b...' ); WRITELN;
REPEAT

WRITE ( 'Gib a ein (>= 0): ' ); READLN ( divident ); WRITE ( 'Gib b ein (>= 0): ' ); READLN ( divisor ); WRITELN; UNTIL (divident >- 0) AND (divisor >= 0); quotient :- 0; rest :- divident; WHILE rest > divisor DO BEGIN rest := rest - divisor; quotient := quotient + 1; END; WRITELN ( divident:4, ' DIV ', divisor: 4, ' = ', quotients ); WRITELN ( 'MOD ':9, '= ':7, rest:4 ); END.

Aus der Formulierung der Bedingung folgt:
9 MOD 7=2 und 12 MOD 12 = 0 und 6 MOD 8-6 und 9 DIV 7 = 1 und 12 DIV 12-1 und 6 DIV 8 = 0

Es hat also alles seine Richtigkeit! Z u r Ve r i n n e r l i c h u n g n o c h e i n m a l d i e S t r u k t o g r a m m e f u e r b e i d e :
4 4

N I E D E R H O L E

SOLANGE Dedinqung I erfueilt I TUE !
4 4

! dies tun + ! das tun + BIS Bedingung erfuellt

!
4

dies das

:
4

!

:
4

Im naechsten Kapitel mal etwas fuer die Feinfuehligen unter euch... 68

3 . 11 . . P r o g r a m m i e r u n q i s t a u c h e i n e , S t ä c h e d e r A e s t h e t i k ! D a s t a u n t w o h l s o m a n c h e r. A b e r w i r m e i n e n e s g e n a u s o , w i e ' s da steht und fuegen das Kapitel quasi als Entspannung hier ein. Vielleicht ein kleines abschreckendes Beispiel. Leider muss als Suendenbock wieder BASIC herhalten, auch wenn eventuell nicht alle dieser Sprache maechtig sind. 10 PRINT"Divident: uiINPUTDTs?"Divisor: "iINPUTDR 20 R=DT:Q.=0 30 IFR<-DRTHENGOT040:R=R-DR:Q=Q+liGOT030 40 PRINTDT;" DIV ";DR;" = "';Q:PRINTDT;" MOD ";DR;" * ";R

Nur dem Gluecklichen oder sehr Erfahrenen ist es verqoennt, den Sinn des vorstehenden Programms schnell zu erkennen. Lasst euch jedoch sagen, dieses BASIC—Listing entspricht in seiner Funktion unserem Programm simulation aus dem letzten Kapitel. "Glaub' ich nicht. Kann ja jeder sagen. Ich erkenn' das nicht; ist mir viel, viel zu unuebersieht 1 ich. " S o o d e r a e h n l i c h s t e l l e n w i r u n s e u r e R e a k t i o n j e t z t v o r, d a m i t wir einen Aufhaenger fuer unsere folgenden (Er)Laeuterungen haben. Stimmt ihr jedoch nicht mit der fiktiven Lesermeinung u e b e r e i n , s o m a c h t e i n f a c h m i t d e m n a e c h s t e n K a p i t e l w e i t e r. Vielleicht geht euch spaeter noch ein Licht auf, wenn ihr eure Freunde mit verklaertem Kuenstlerblick vor dem Rechner sitzen seht.. Fuer die, die weiter mitlesen wollen: Vielleicht habt ihr euch schon immer gewundert, warum wir unsere Programme nicht in etwa so schreiben:
program unueber sichtlich; var a,b.c. integer; begin readln ( a, b ); c :- 0; repeat a s- a + b; c '.- c + 1; until c >- b; end.

Oooh ja, das ginge durchaus, ist aber schier undurchdringlich, will man ergruenden, was das Programm tut (es addiert b—mal b zu a hinzu» mindestens aber 1 mal). Ein kleine Verbesserung braechte die folgende Anordnung:
program etwasuebersichtlicher; var a,b,c:integer; begin readln ( a, b >; c :- 0; repeat a := a + b; c := c * 1; until c >- b; end.

G , 9

I m m e r n o c h n i c h t o p t i m a l ( i m Ve r t r a u e n , e s g i b t s o g a r B u e c h e r, in denen Listings in diesem Stil abgedruckt sind). Aber ueberlegt mal, warum das nicht so schoen ist. Der beste Lerneffekt wird doch erzielt, wenn man die Notwendigkeit einer Aenderung unmit telbar begreift und fordert. Ohne euch etwas aufdruecken zu wollen, erlaeutern wir 'mal kurz unsere Meinung. I s t d i e Ve r w o r r e n h e i t n i c h t d a r a u f z u r u e c k z u f u e h r e n , d a s s m a n nicht erkennt, was zusammengehoert'7' Will sagen, es ist schwer zu sehen, welche Befehle zur Schleife gehoeren, wo diese beginnt, ganz allgemein, es ist keine STRUKTUR irn Programm ersichtlich. Struktur, ein Eichlagwort, welches euch im Verlauf dieser E i n f u e h r u n g i n PA S C A L s c h o n m e h r m a l s u e b e r d e n W e g g e l a u f e n i s t (Struktogr amm, st r u k t ur i er t es Pr og r arnm i er en ) . Was macht nun seine Beliebheit aus, dass es in aller Munde ist? Ganz einfach, da Programute nicht nur geschri eben, sondern auch gelesen, d.h. verstanden werden sollen, muessen sie so gestaltet sein, dass sie jedermann leicht fallen. I n B u e c h e r n u n d l a e n g e r e n Te x t e n ( w i c h t i g b e i R e f e r a t e n ) g i b t es ja auch Absaetze und Ueberschriften, die die Orientierung im Te x t e r l e i c h t e r n u n d d a s V e r s t a e n d n i s f o e r d e r n s o l l e n . B e s o n d e r s Wichtiges ist sogar vielleicht noch farblich abgehoben. Etwas lax gesprochen sind Programme aber auch nichts anderes a l s Te x t e , i n d e n e n m a n s i c h l e i c h t z u r e c h t fi n d e n k o e n n e n m u s s j e v e n t u e l l , u m A e n d e r u n g e n a n z u b r i n g e n o d e r e i n f a c h n u r, u m d i e Funktionsweise zu verstehen. A u s d i e s e m G r u n d e w i r d i n PA S C A L e i n e r e c h t s t r e n g e O r d n u n g aufrechterhalten (die es in vielen anderen Programmiersprachen nicht gibt): es ist eine Kopfzeile zu schreiben, dann, und nur d a n n f o l g t d e r Va r i a b l e n v e r e i n b a r u n g s t e i l , i n w e l c h e m w i e d e r K o n s t a n t e n v o r d e n Va r i a b l e n d e k l a r i e r t w e r d e n m u e s s e n , d a n a c h endlich der Anweisungsteil, schoen geklammert durch BEGIN und £«0. Im Anweisungsteil kann man dann auch noch strukturierte Anwei s u n g e n b e n u t z e n ( . R E P E AT - u . W W / t f - S c h l e i f e , J f - A n w . ) , d i e j e d e m SOFORT deutlich machen, dass bestimmte Befehle wiederholt ausge fuehrt werden sollen oder nur in Abhaengigkeit einer Bedingung. Der Algorithmus, welcher als Struktogramm noch so uebers i c h t l i c h w a r, k a n n d a m i t , o h n e v i e l a n K l a r h e i t z u v e r l i e r e n , i n ein PASCAL—Programm Liebertragen werden. Kann, wohlgemerkt! Gegenbeispiele sind die beiden oben stehenden Listings. D a k o e n n e n a u c h R E P E AT u . U N T I L a l s S c h l e i f e n b e g r e n z u n g e n nichts mehr 'rausreissen. Wa s f e h l t , i s t e i n e O P T I S C H E G L I E D E R U N G . Wa s f u e r e i n S c h l a g wort! Gewissermassen wie das Bilden von Absaetzen oder Unter s t r e i c h e n i n Te x t e n , s o t e i l t d i e o p t i s c h e G l i e d e r u n g e i n P r o g r a m m i n z u s a m m e n g e h o e r i g e Te i l e ( z . B . S c h l e i f e n o d e r V e r b u n d a n w e i s u n g e n ) u n d h e b t D i n g e h e r v o r. E i n Te i l d e r o p t i s c h e n G l i e d e r u n g i s t a u c h d a s G r o s s s c h r e i b e n v o n r e s e r v i e r t e n W o r t e n ( PA S C A L - S y r n b o l e n ) u n d d a s K l e i n s c h r e i b e n von selbstgewaehlten Namen in den bisherigen Listings.

70

PROGRAM uebersichtlich; V AR a, b, c : INTEGER; BEGIN READLN ( a, b ); c :- 0; REPEAT a := a * b; c := c + 1; UNTIL c >- b; END.

Staunt da nicht der Fachmann? Wundert sich nicht der Laie? Einern jeden ist zumindest der Aufbau des Algorithmus nun schnell k l a r. D a s Ve r s t a e n d n i s d e r F u n k t i o n ( WA S t u t d a s P r o g r a m m eigentlich) folgt dann jedoch rapide? eher jedenfalls, als rnuesste man sich durch ein nicht optisch gegliedertes Programm wuehlen. U n d , ' m a l e h r l i c h , i s t d a s L i s t i n g n i c h t v i e l s c h o e n e r, k l a r e r, u n v e r w o r r e n e r, g e w i s s e r m a s s e n a e s t h e t i s c h ? O k , v i e l l e i c h t w i r d e s bei so einem Minibei spiel nicht deutlich. Schaut man sich aber Programme von einigen hundert Zeilen (siehe auch das lange Pro gramm im letzten Kapitel) an, so kann man meist sagen: sieht das L i s t i n g g u t a u s , d a n n i s t d e r A l g o r i t h m u s , b z w. d a s P r o g r a m m , auch in Ordnung.. "Das sind vielleicht ein paar Spinner. Programme muessen schoen a u s s e h e n u s w. . H a u p t s a c h e s i e l a u f e n s c h n e l l , w i e d a s L i s t i n g ausschaut ist mir doch egal. Ich weiss, was in dem Programm vorgeht!" Tr a u r i g , t r a u r i g , w e n n i h r e i n e s o l c h e M e i n u n g h a b t . U n d w e n n n u n d e r Ta g k o m m t , a n d e m z . B . e i n L e h r e r o d e r s o n s t w e r d a s Programm mal sehen (und verstehen) rnoechte, was dann? Unsere Meinung: Holland in Not! Oder legt mal ein Listing fuer 3—4 Wochen beiseite und versucht dann, das ganze ohne Beschreibung zu durchblicken. Gewissermassen um unsere Ernsthaftigkeit zu unterstreichen, moechten wir erwaehnen, dass schon andere Leute sich ueber die hier besprochene Problematik Gedanken gemacht haben! Zum einen Herr Wirth, dann die Erfinder der Struktogramrne und eine Menge L e u te i n d e n U S A , d i e s c h l i e s s l i c h a u c h e i n e N o r m h e r a u s g e b r a c h t haben, nach der PASCAL—st at ement s (engl. fuer Anweisung) aufzu schreiben sind. Fuer Spezis:: ANSI IEEüE — 797145-1978 ist die Norm. Nun, immer noch Spinner? Uns liegt fern, euch anhalten zu wol l e n , g e n a u n a c h Vo r s c h r i f t d i e S t a t e m e n t s a u f z u s c h r e i b e n , a b e r lasst uns wenigstens ein oder zwei Anhalte geben, wie man sich und anderen das Leben leichter gestalten kann (selbst fuer BASICAnhaenger faellt da noch etwas ab. T ja, so sind wir: grosszuegig, l i e b e n s w e r t u s w. ) : 71

VA R ^^*^ summe : primzahl jefcur^fcr,

Funktion REAL; :

Verwendet Vanablennamert ( cjie etwas über ihre <SeWeh

i.eersei(ßn 2uw? ^ibseben von logischen BOOLEAN} ^^ E^hmen ^

f
J

^~
diese

.S"n*g«
tortjbfen H*nF*Mr.

t
Eine fefaalfcifische. Jt>rrn (alle : in etoer Spalte) 1st Schon fur's huQt. Übersichtlichkeit:!( PASCAL-Symbole groß schreiben IF primzahl THEN BEGIN ^ -/ f*7 W RßfdZJ I T E ( (KBD, ' . . nochmal . ); WRITELN; E N D ELSE WRITELN ( '... {3^Qe,,UAS zu&'neim Verbund ötffer slruk kurierten r\nu&$mQ gehört, so stille, etwas eingerückt werden, um die 2usqmr/)eiqe.^ori(7l<eic zu verdeutlichen. * ^L— totbellarisck 7pr7n ^

summe := summe + summend; zaehler := zaehler + 1; UNTIL zaehler >- grenze;

R E P E AT

„**--"

i

WHILE zaehler > 0 ^rte te&r»\e. rwt ofer Übers/chUichhil: nß*Ji do begin ^/ -~ nie aescho.olet, n WRITELN ( 'Zaehler:', zaehler:3 ); Iwim^r zaehler :- zaehler - 1; und ^ ^ £«D; wmer wieder: Einrücken vo» ^nk/eisungsLeHe^

Jooo, das ist wahrscheinlich erstmal genug. Ihr bekommt mit der Zeit auch einen eigenen Stil, was das Formatieren von Anweisungen angeht. Die aufmerksame Lektuere dieses Buches sowie von Programmen, die ihr irgendwo abgedruckt seht, wird dazu beitra gen. Auf jeden Fall werdet ihr in Zukunft Struktograrnme besser verstehen und lieben lernen, da in ihnen schon durch die Wahl der Kastenforrn (und -aufbau) eine Uebersichtl ichkeit erzwungen wird. Unser Wunsch war es, eine kleine Bewusstseinserweiterung bei e u c h z u e r w i r k e n , e u r e A u g e n f u e r d i e P r o b l e m a t i k z u o e ff n e n u n d euch vielleicht etwas zu entspannen. Gleich geht's weiter mit Schleifen...

72

O 1 o

Da capo

N a c h u n s e r e m k l e i n e n A u s fl u g , j e t z t w i e d e r h a n d f e s t e s PA S C A L . Z u m l a n g s a m e n Wa r r n w e r d e n e i n S i m p e l p r o g r a m m - A u s s c h n i t t f u e r d i e G r u n d s c h u l e . D e r R e c h n e r s o l l m a l s o r i c h t i g s c h o e n z a e h l e n . Vo n 1 bis zu einer eingegebenen Zahl ( n ) .
zaehler ;- 0;

WHILE zaehler <- n DO BEGIN
WRITE ( zaehler:5 ); zaehler := zaehler + 1; END;

Z u m Ve r g l e i c h e i n a n d e r e s F r a g m e n t :
WHILE buchstabe <> ■'E' DO READLN ( buchstabe );

Preisfrage: wo liegt der Unterschied? Ganz, ganz einfach! In der ersten Konstruktion wird die Schleife n-rnal durchlaufen (wenn man zaehler vorher auf 1 gesetzt hat), d.h. einer VORHER feststehenden Anzahl entsprechend oft. Bei der zweiten Wieder holungsanweisung wird solange ein Buchstabe eingelesen, bis "E" eingegeben wird; vielleicht Srnal, oder Srnal oder lOOOrnal. Wir wissen es VORHER nicht! D a m i t a b e r n i c h t e i n e W H I L E - o d e r R E P E AT- f r n W e i s u n g b e m u e h t werden muss, wenn die Anzahl der Durchlaeufe vorher bekannt ist, und um auch der NASA eine elegante Loesung fuer ihr Count-Down Problem zu geben (spaeter etwas dazu), sah m a n s i c h b e i d e r S c h o e p f u n g v o n P A S C A L g e n o e t i g t , n o c h e i n e S c h l e i f e n a n We i s u n g vorzusehen.
FOR zaehler :- / TO n DO WRITE ( zaehler:5 );

tut dann genau das, was oben die erste WH7Z.£-Konstruktion leistet. Jetzt noch schnell das Syntaxdiagramm:

for-anveisung:

->--(for)-

-! variable !-->-■* : = /•

4

4

__

4

4

-I ausdruck !->-^DOHNT O)-

■>-! ausdruck !- ■)-- DO /->--! anweisung I— >
4 4

+

4

^

4

4

+

4

und auch noch das aktualisierte von strukturierte anweisung: strukturierte anweisung:
4 4

wiederholungsanwei5ung:
4 4

—>-- ! verbundanweisung !-

—>—-—j while-anueisung ! 7—>
y j 4 4 4 4 4 4 4 4 4 4 a j j >

4 « bedingte anweisung ! +
I .
4

+—! repeat-anweisung !—*
j j

4 +

+ 1
4

J ;

t—! Wiederholungsanweisung I—*

+—! for-anweisung ! +

Die Variable hinter FOR heisst auch LAUFVARIABLE und muss als Ty p e i n e n s k a l a r e n Ty p e n h a b e n ( w a s d a s n u n i s t , l e r n t i h r spaeter). Zunaechst reicht es zu wissen, dass INTEGER, CHAR und BOOLEAN skalare Typen sind; REAL aber NICHT! ! Oder zaehlt ihr 1 . 1 , 1 . 2 , 1 . 3 , 1 . 4 u s w. ; n e e e e , 1 , 2 , 3 , 4 i s t b e s s e r, v o r a l l e m , weil zwischen 1.1 und 1.2 noch unendlich viele reelle Zahlen 1i egen! D i e b e i d e n A u s d r u e c k e m ü s s e n v o m g l e i c h e n Ty p s e i n , w i e d i e Laufvariable! Sehr wichtig. Dabei gibt der erste den Startwert fuer die Laufvariable an, der zweite den Endwert, nach dessen Ueberschreiten die Schleife nicht mehr durchlaufen wird. 70 und D0WNT0 geben an, ob auf- oder abwaerts gezaehlt werden sol 1. Nocheinmal eine Gegenueberstellung:
V AR i : INTEGER;

(# i, j, k, 1 werden oft als Lauf variable vereinbart. Eine ueberkommene Tradition aus FORTRANTagen *>

im Programm:
<äCT Inialisierung i :=• 1; - *■ ' "

REPEAT

FOR i := 1 TO 10 DO WRITE^ i : 5 );

/

3,. Ausdruck

WRITE ( i : 5 ); i := i + 1; UNTIL i > 10;

10 bedeutet die Lauf vnriobk Wrd immer um A utiterqemllt

uird bei T0\\ durch den
2. AuSrJrMCk repräsentiert

74

Beide Auszuege zaehlen bis 10, aber welcher ist kuerzer, uebersicht 1 icher? A l s o , i m m e r, w e n n m a n v o r h e r w e i s s w i e o f t m a n e t w a s t u n w i l l , dann die FOR-Schleife benutzen. Wie noch nicht gesagt: TO bedeutet, die Laufvariable wird jeweils um 1 erhoeht, D0WNT0 bedeutet, sie wird um 1 vermindert. Und hier kommt dann auch die NASA ins Spiel, die ja andauernd von 10 hinunter bis 0 oder 1 zaehlen will, kaum dass sie mal so eine Rakete losschickt. Da koennen wir mit einem Programm natuerlich hilfreich in die Seite springen: PROGRAM countdown; C* No part of this programe may be reproduced, sold or transmitted, in any form or by any means, without permisson of the NASA. a)
VAR

k : INTEGER;
ch : CHAR;

BEGIN WRITE ( 'Press any key to start count down: ' ); READ ( KBD, ch ); WRITELN; WRITELN ( 'Starting count down now...' );
FOR k :- 10 D0WNT0 1 DO WRITELN ( k : 10 );

WRITELN ( ' > Ignition/ < ' ); END.

Die Preise fuer solch hochspezialisierte Programme liegen mit S i c h e r h e i t j e n s e i t s e u r e s Vo r s t e l l u n g s v e r m o e g e n s . D i e N A S A l a e s s t es sich eben etwas kosten. "Neulichs hab' ich ma' das eingegeben, un' nix passierte:
FOR i :- 10 TO 1 DO WRITE ( i );

Was hab' ich'n da falsch gemacht?" Nun janz einfach: wenn man aufwaerts zaehlen will, muss der Startwert kleiner (oder gleich) dem Endwert sein. Beim Abwaertszaehlen natuerlich umgekehrt! Vorhin sagten wir CHAR und BOOLEAN seien auch skalare Typen. Messerscharf habt ihr sicherlich schon gefolgert, dass man dann mit Variablen dieser Typen auch "zaehlen" koennen rnuesste. Genau! Wie schon einmal erwaehnt, sind alle Buchstaben durchnummeriert (Stichwort: Ordnungszahl). Ebenfalls TRUE und FALSE haben Nummern. TRUE hat die Ordnungszahl 0 und FALSE die 1. F o l g l i c h k a n n m a n v o n T R U E b i s FA L S E o d e r v o n » A ' b i s ' Z ' zaehlen. Beispiele dazu? Ok, hier sind sie...

Erstmal wollen wir sehen, welche Zeichen der Computer so hat, die ein durchschnittlicher Durchschnittsbuerger sich auf dem Schirm ansehen kann. Wir beginnen mit dem blank (' '), dann folgen viele Ueberraschungszeichen, und wir hoeren mit dem 'z' auf:
4

i FUER zeichen : = ' ' BIS 'z' ! TUE ! schreibe Ordnungszahl ! schreibe Zeichen
4

i i

i

+

PROGRAM lustigezeichen; V A R zeichen : CHAR; BEGIN FOR zeichen := ' ' TO 'z' DO WRITELN ( zeichen, ' - ', ORD ( zeichen ):3 ); END.

Noch witziger wird's, wenn ihr ueber die Ordnungszahlen geht und mal die Zeichen (mit CHR) zu den Nummern 0 bis 31 oder ab 128 (bis 255) anschaut. Meist passieren tolle Sachen, aber keine Garantie. Habt ihr eigentlich euren Kumpel, das DO, wiedererkannt? Es kam schon bei WHILE vor. Und... jaaaa, stimmt! Und eben so, wie dort, m u s s m a n a u c h h i e r, s o l l e n m e h r e r e A n w e i s u n g e n i n d e r F O R S c h l e i f e a u s g e f u e h r t w e r d e n , d i e s e z u e i n e r Ve r b u n d a n w e i s u n g zusammenfassen! Ein Beispiel dazu? Ok, mit noch mehr Ueberraschendem... I h r k e n n t j a s c h o n d i e Wa h r h e i t s t a b e l l e n ( u e b e r l e g , u e b e r l e g , w o h e r b l o s s ) . S e h t m a l b e i d e r E i n f u e h r u n g v o n A N D u s w. n a c h . G u t , w i r w o l l e n j e t z t n a e m l i c h d i e Wa h r h e i t s t a b e l l e d e s f o l g e n d e n Ausdrucks vom Flechner herstellen lassen: a AND b OR c (.a, b, c sind Variablen vorn Typ BOOLEAN).

76

4

4

FUER a := TRUE BIS FALSE T U E
4

FUER b := TRUE BIS FALSE T U E
4 4

FUER c := TRUE BIS FALSE! T U E
+ 4

I a, b, c schreiben
4

I Ergebnis von I a AND b OR c ! berechnen
4

i Ergebnis schreiben
4

Watt 'ne Schachtelei, aber im Programm doch recht uebersichtlich -durch optische Gliederung-:
PROGRAM wahrheitstabelle; VAR a, b, c : BOOLEAN; BEGIN WRITELN ( 'Berechnung von a AND b OR c:' ); WRITELN; WRITELN ( ' a b c Ergebnis:' );

FOR a := TRUE TO FALSE DO FOR b := TRUE TO FALSE DO FOR c := TRUE TO FALSE DO BEGIN WRITE ( a:5, b:6, c:6 ); WRITELN ( (a AND b OR c):10 ); END; END.

E i n l e u c h t e n d d i e p r o b l e m f r e i e Ve r w e n d u n g v o n b o o l e s c h e n Va r i a b l e n a l s L a u f v a r i a b l e . Neu allerdings, dass man deren Werte auch einfach so ausgeben kann! Tja, das haben wir uns aufgespart. Die Werte TRUE und FALSE w e r d e n d a b e i i n d i e S t r i n g s ' T R U E ' u n d ' FA L S E ' u m g e w a n d e l t u n d genau wie jeder andere String ausgegeben. Einlesen kann man sie aber nicht !

77

Fuer Spezis, solche, die's werden wollen und die, die immer alles ganz genau wissen wollen: FOR i := 1 TO 10 DO i :- i * 2; (# nicht die Laufvariable in der Schleife veraendern/ #) sollte man nicht machen (aber probierts mal). Die Ve r h a l t e n s w e i s e d e r F O R - S c h l e i f e i s t n i c h t s i c h e r v o r a u s s a g b a r. U n d d e r G e h e i m t i p z u m S c h l u s s : R E P E AT- u n d W H 7 t £ - S c h l e i f e n s i n d s c h n e l l e r a l s s o l c h e m i t F O R ( a u s s e r i n T U R B O - PA S C A L ) . Zum Ende der Schleifen noch die Gewissensfrage: Habt ihr euch schon mal ueberlegt, was passiert, wenn ihr in einer WHILE- oder /?£P£/)7-Anweisung eine Bedingung auffuehrt, die so beschaffen ist, dass die Schleife immer durchlaufen wird? Z.B.
WHILE DO ... TRUE oder R E P E AT UNTIL 3 > 4

oder aenhliches, nicht so offensichtlich Falsches. Probiert es lieber nicht, der Rechner (Freund CPU) haengt sich naemlich auf. Tja, so nennt man das. Er geraet in eine ENDLOSSCHLEIFE. Nur noch ein Ausschalten des Computers kann hier Abhilfe schaffen.

78

3.13.

Es

wird

zu

Tiseh

gebeten

Macht euch auf einige Menues gefasst! Aber bevor wir in k u l i n a r i s c h e Ve r z u e c k u n g e n a u s b r e c h e n , m u e s s e n d i e G r u n d l a g e n geschaffen werden. Fuer den muendigen Schueler rnoechten wir jetzt endlich auch etwas tun, in dem wir ihm ein Entschluesselungsprogramm fuer seine Zensuren geben. Er erfaehrt dadurch genau, wie seine Note im Klartext lautet: 1 = sehr gut; 2 = gut usw.
PROGRAM Zensuren!;
VAR

zensur : INTEGER; BEGIN WRITE ( 'Zensur (0 - Ende): ' ); READLN ( zensur ); WHILE zensur <> 0 DO BEGIN IF zensur - 1 THEN WRITELN ( 'sehr gut' ) ELSE IF zensur - 2 THEN WRITELN ( 'gut' ) ELSE IF zensur = 3 THEN WRITELN ( 'befriedigend' ) ELSE IF zensur - 4 THEN WRITELN ( 'ausreichend' ) ELSE IF zensur - 5 THEN WRITELN ( 'mangelhaft' ) ELSE IF zensur - 6 THEN WRITELN ( 'ungenuegend' ) ELSE WRITELN ( 'wie bitte?' ); WRITE ( 'Naechste Zensur (0=Ende): •' ); READLN ( zensur ); END; (* der WHILE-schleife *) END.

Also, als Struktogramrn rnoechten wir das nicht aufmalen. Haetten wir vorher gewusst, was fuer eine Arbeit das ist..., oh Mann. Wir sehen auch: manchmal ist es gut, wenn man von seinem gewohnten (optischen) Gliederungsstil abweicht, um Strukturen deutlich zu machen. Kurz noch zu einem Trick, den ihr dort seht. Wir haben naemlich vor der Schleife die Zensur erfragt und am Ende wieder. Das macht man so, um eine Jf-Abfrage in der Schleife zu vermeiden, die prueft, ob aufgehoert werden soll. Koennt ihr ja mal in euer Repertoire aufnehmen.

79

Jetzt jedoch zum Ungernuetl ichkeitsef f ekt, d.h. es soll euch an gesichts obiger verschachtelter Anweisungen unwohl werden und dann, dann kommt die grosse Erloesung. Es wird euch leicht um's Herz: the rescue is nigh; behold the C/)S£-statement descends from PASCAL—heaven to programmers earth., Auf Deutsch: eure mentale Dissonanz wird durch das Erscheinen der C$S£~AnWeisung in vollkommene Harmonie verwandelt. case-anveisung: —>—(CASE1—>—! ausdruck I—->-'-{ OfV>-t--t-! konstante !--T—>--<:">->--! anweisung !-7->-(end)-->
! r \ i,J~</ L i

War doch nicht zuviel versprochen, oder? Wie? Ihr seht den Vo r t e i l n o c h n i c h t ? N a , d a n n m a l e i n n e u e s P r o g r a m m Z e n s u r e n : PROGRAM zensuren2; V A R zensur : INTEGER; BEGIN WRITE ( 'Zensur (0 - Ende): ' ); READLN ( zensur ); WHILE zensur <> 0 DO BEGIN IF (zensur > 0) AND (zensur < 7) T H E N CASE zensur OF 1 2 3 4 5 6 : : : : : : WRITELN WRITELN WRITELN WRITELN WRITELN WRITELN ( ( ( ( ( ( 'sehr gut' ); 'gut' ); 'befriedigend' ); 'ausreichend' ); 'mangelhaft' ); 'ungenuegend' );

END r# der CASE-Anweisung #) ELSE WRITELN ( 'wie bitte?' ); WRITE ( 'Noch eine Zensur (0 » £NZ>£.>: ' ); READLN ( zensur ); END; (* der WHILE-Anweisung *) END.

CASE.

S u p e r, n i c h t ? ! G l i e d e r u n g i s t a l l e s , g u t u n t e r s t u e t z t d u r c h

80

Ein paar Erlaeuterungen: Der Ausdruck hinter CASE ist der Selje.kJ;_or., aufgrund dessen Wert entschieden wird, welche Anweisung innerhalb des CASE—Statements ausgefuehrt wird - naemlich diejenige, deren davorstehende Konstante dem Wert des Selektors entspricht. Geben wir im Beispiel 1 ein, so wird das WRITELN hinter der K o n s t a n t e n 1 a u s g e f u e h r t , b e i 2 d a s h i n t e r d e r 2 u s w. Tr i ff t keine Konstante den Wert des Ausdrucks, so passiert in der CASEAnweisung nichts! Diesen Fall muessen wir selbst abfangen, daher auch der aeussere JF-Befehl! D i e K o n s t a n t e n u n d d e r S e l e k t o r m u e s s e n e i n e n s k a l a r e n Ty p haben (genau wie bei FOR) und in diesem uebereinstimrnen! Die Anweisung nach einer Konstanten kann natuerlich auch eine Verbundanweisung sein, keine Frage. Bevor ihr eui : h r i c h t i g e r h o l t , h i e r n o c h e i n e Ve r b e s s e r u n g d e r CflSf-Anwei sung, d i e j e d o c h n i c h t d e m S t a n d a r t - PA S C A L e n t s p r i c h t :
case-anweisung:

/« ->---fCASEi—>—J ausdruck !—><0F>->^ 4 ♦

4 i I 4 4

4 V

^ 4

4 4

4 V

-! konstante \—{—)---•. y~>—\ anweisung i~)---<-V ,

.> ->—i'elbe)—>—

)__/End>->
anweisung .-

r

D i e s e s n e u e E L S E e n t s p r i c h t d e m E L S E b e i I F. E s f a e n g t a l l e Faelle ab, die nicht durch Konstanten in der CflS£-Anweisung abgedeckt sind. In zensuren2 koennen wir also schreiben:

WHILE zensur <> 0 DO BEGIN CASE zensur OF 1
2

! WRITELN i■ WRITELN WRITELN 3 i 4 :, WRITELN 5 i, WRITELN 6 :• WRITELN ELSE WRITELN

( ( ( ( ( ( (

'sehr gut' ); 'gut' ); 'befriedigend' ); 'ausreichend' ); 'mangelhaft' );
■' u n g e n u e g e n d ' ) ;

'wie bitte?' );

END; f> der CASE-Anweisung *) END; (* von WHILE a)

81

Die vorgesetzte Zf-Abfrage entfaellt somit; Uebersicht1ickkeit war also noch steigerungsfaehig!

die

Eine einzige Restriktion ist, dass zürn Auswaehlen einer Alter n a t i v e n u r K o n s t a n t e n v e r w a n d t w e r d e n d u e r f e n . S c h a d e z w a r, a b e r na ja... V A R a, b : INTEGER;

CASE a OF 1 b END; : : .. ..

cjehc nicht 1 b ist önt Variable t es muß ober eine Konstgnte dort stthtn

Programmbenutzer aus mehreren Alternativen bewusst auswaehlen, so nennt man das -sinnigerweise- ein(e) Menue(auswähl) Aehnlich der Auswahl aus einer Speisekarte.

Wa s d a s g a n z e a b e r m i t M e n u e s z u t u n h a t , f r a g t i h r e u c h , einfach. Laesst man naemlich den qan; Oooch, das is'

Z u r E i n f u e h r u n g i n d i e s e s e h r b e l i e b t e u n d w i c h t i g e Te c h n i k e i n k l e i n e r " d e s k - t o p c a l c u l a t o r " ( = T i s c h - o d . Ta s c h e n r e c h n e r ) . Wir lesen 2 Zahlen ein und verknuepfen sie nach des Benutzers Wunsch,,

W I E D E R H O L E

zwei Zahlen einlesen Hernie zeigen u. auswaehlen Auswahl =
i

i i
4
i

/ f
-4 ^-4

iaddie-lsubtra-imilti-idivi-l SchlussIren Ihieren Ipliz. 'die- ! aeldung ! ! ! ! ren ! --/>
Auswahl () 'E' /

J A
! Ergebnis anzeigen
4

/

•Ijein

BIS Auswahl = 'E' ist

82

Gleichzeitig habt ihr jetzt auch das zu CASE passende Struktogramm kennengelernt. Nehmt demnach beim Entwurf immer ein grosses Blatt. PROGRAM taschenrechner;
V AR

opl, op2, ergebnis : REAL; wähl BEGIN
REPEAT CHAR;

WRITE ( 'Erster Operand; ' ) ; R E A D L N ( o p l ) ; W R I T E ( ' Z w e i t e r " : ' ); READLN ( op2 );
WRITELN; REPEAT

WRITE ( 'Operatoren: + - a / E - Ende des Programms: ' ); READ ( KBD, wähl ); ('*? bis gueltige wähl getroffen *) UNTIL (wähl = '+') OR (wähl = '-') OR (wähl = '#') OR (wähl = '/') OR (wähl - 'E'); CASE wähl OF
t+s
I —!

> * ' ' / '

ergebnis ergebnis ergebnis ergebnis

:::= :=

opl opl opl opl

+ * /

op2; op2; op2; op2;

(# Division durch 0 wird nicht abgefangen/ #)

WRITELN ( 'Sie haben einen simplen Rechner ', 'sehr, sehr gluecklich gemacht.' );
END;

IF wähl <> 'E' THEN WRITELN ( opl:9:3, wahl:2, op2:9:3, ' = ' ergebnis:9:3 );
UNTIL wähl END. 'E';

Zur Arbeitsweise des Programms: kein Kommentar. ( B e ) m e r k e n s w e r t b e i d e r Ve r w e n d u n g v o n M e n u e s i s t d e r grundlegende Aufbau:

S3

NIEDERHOLE
4 4 4

I
i

4 + 4

! Zeige die Haiti uoegl ichkeit en ! ! Lies die Haiti des Benutzers !

I Eraittle nit CASE die ge- i ! wuenschte Funktion u. fuehre I ! sie aus !
4 4
i i

BIS Wahl = Endezeichen I

Eraittle nit CASE die gewuenschte Funktion.

Typisch auch die Auswahl durch einen einzigen Buchstaben (Zei chen), der moeglichst "intelligent" sein sollte, d.h. er hat Bezug zur ausgewaehlten Funktion. Eingebuergert haben sich im grossen unterschied!iche Menuedarstellungen: und ganzen

zwei

Menue zur Stichwortverwaltung: Neue Stichwoerter aufnehmen > N < Ein Stichwort Ige sehen > L < Angaben zu einem Stichwort
aendern > A <

Stichworte

listen >

> E

S

< <

Programmende

Bitte den Buchstaben ihrer Wahl : Es kann dann zwischen N und L und ... und E gewaehlt werden, die gewuenschte zugehoerige Funktion wird ausgefuehrt, und danach zeigt das Programm wieder dieses Menue.

84

Eine tabellarische Auflistung ist sehr uebersicht1 ich! Die Wa h l b u c h s t a b e n w u r d e n d e n A u f g a b e n , w e l c h e s i e b e z e i c h n e n , entsprechend sinnig gewaehlt. Keinem nuetzte es, bezeichnete man "Programmende" mit Y und "Ein Stichwort loeschen" mit M oder so. Ein zweites Muster:
LISTE: Ldsten d. stichworte; 0(hne seitennummern; vorher S(ortieren; E(nde:

Hier wurde das ganze Menue mal in eine Zeile gepackt (platzsparend); die moeglichen Auswahlbuchstaben sind als einzige g r o s s g e s c h r i e b e n , s o w i e d u r c h e i n e K l a m m e r " ( " v o m i h r e m Wo r t abgetrennt (der Uebersichlichkeit halber). Drei Tips noch, um sich einen professionelleren Anstrich zu geben: 1. Zu jedem Menue sollte eine Ueberschrift erscheinen, damit man einen groben Anhalt hat, wo im Programm man sich befindet. 2. Habt ihr ganz ganz Grosses vor und ein ueberhaupt nur wichtiges, langes, kompliziertes Programm, so erweist es sich als sehr nuetzlich, wenn man in den Menues eine Hilfsfunktion aufru fen kann, welche eine kurze Erlaeuterung zu den moeglichen Menueauswahlpunkten gibt. Z.B.:
HAUPTMENUE: Adifuegen; L(oeschen; V(eraendern; S(ortieren; Hdlfe; E(nde:

G i b t m a n n u n H f u e r H i l f e , s o e r s c h e i n t e i n k u r z e r Te x t , d e r beschreibt, was passiert, wenn man A oder L oder V usw. drueckt. 3. Der voellig abgehobene Programmierer schreibt seine Menues sowieso nur in Englisch:
MAINMENUE: A(ppend; D(elete; Adter; S(ort; H(elp; Q(uit:

E r w i r d i n s b e s o n d e r e d u r c h k u e r z e r e Te x t e ( W o r t e ) b e l o h n t , d i e das gleiche wie ihre Uebersetzungen bedeuten, jedoch viel praegnanter sind. Eine Gewoehnung an die gute englische Fachliteratur erfolgt somit wie von selbst.

85

3. 14.

"Ey, was is'n das fuer'n TypJ

Nicht, dass wir euch einige Herren vorstellen wollen, nein, es geht um eine Erweiterung des Typbegri ffs von PASCAL. Bisher mussten wir jeder Variablen einen Typ zuordnen (.INTEGER, CHAR usw.) oder Konstanten hatten einen IMPLIZITEN Typ, der sich aus ihrem Aufbau ergab (1.3 ist vorn Typ REAL, 'A' vom Typ CHAR
Lisw. ) .

Alles dreht sich, alles bewegt sich gewissermassen um den Angelpunkt Typ. Es tut uns echt leid, aber dieses Kapitel wird n'bueschen trocken (hust, hust), d.h. wenige bis gar keinevollstaendigen dafLier aber eine Menge Wissen. Zum Glueck ist Programme,
allgemein bekannt: Wischen ist Macht! Zunaechst ein etwas vol Istaendigeres Syntaxdiagrarnrn fuer typ:

typ (unvollstaendig):
4 4

einfacher typ:
4 4

—>—-—! einfacher typ IV + + ! * 1 -—' strukturieter !I typ I
4 4

——! skalartyp i—>—7—> V + * ;
■ 4 4 j

+--! Unterbereichs !—♦ II typ ! ! ! + + !
j 4 4 4 4 j

4 j typnaiae ! +

strukturierter typ werdet er st mal zu einfacher typ. .

ihr demnaechst

kennenlernen.

jetzt

O e h h h h m r n m m , n u n , t j a , e i n e i n f a c h e r Ty p i s t z u n a e c h s t e r s t m a l kein strukturierter Typ -ist ja klar-, d.h. ein einfacher Typ setzt sich nicht aus noch einfacheren Bausteinen zusammen. Er ist quasi das Atom der strukturierten Datentypen. Moooment, ihr kennt ja schon Typen, die zur Klasse der e i n f a c h e n Ty p e n g e h o e r e n : C H A R , B O O L E A N , I N T E G E R u n d R E A L * . S e h r gut. Man kann sie unter typnaae im obigen Syntaxdiagramm einordnen. Aber was ist mit den beiden anderen Kaesten: skalartyp und so? Die Antwort:

86

3.14.1
skalartyp:

Skalartypen

->—'(*>-->-~—! nue I—;—>—'>>--> * 4 + u

I

y~v

i

Sie sind gewisser massen der Grundtyp von PASCAL.. Wird einer Va r i a b l e n b e i d e r D e k l a r a t i o n e i n S k a l a r t y p z u g e o r d n e t , s o w i r d der Wertebereich_ dieser Variablen als geordnete Menge festgelegt. Die moeglichen Werte werden durch Namen bezeichnet. Was das bedeutet? Keine Ahnung! Stop, stop, stimmt nicht, natuerlich wissen wir's, wartet mal einen Augenblick, dann wird es selbst euch deutlich. V A R tag ( montag, dienstag, mittwoch, donnerstag, frei tag, samstag, sonn tag );

färbe : (rot, gruen, blau, gelb ); geschlecht : ( maennlich, weiblich ); (# oh, wie heikel #) Ist doch toll, was man selbsterklaerend das ist.
sc

vereinbaren kann.

und wie

montag, dienstag oder rot, gruen oder maennlich, weiblich sind We r t e , d i e d i e e n t s p r e c h e n d e n Va r i a b l e n t a g , f ä r b e u n d g e s c h l e c h t annehmen koennen. Genau wie einer INTEGER-Variab1en der Wert 134 zugewiesen werden darf. tag färbe geschlecht montag; tag := sonntag; J ^ a[[& ^wlftÄSwöJ rot; maennlich; j Merk, x mohtag usw. sind keine Strims

D i e Wo r t e ( N a m e n ) m o n t a g , r o t u s w. s i n d M e n g e n e l e m e n t e (Konstanten des Skalartyps), keine Strings! Man kann also auch nicht schreiben: tag :- mittwoch; WRITELN ( tag ) Stopping, oben ist noch das Stichwort geordnete Menge gefallen. Das bedeutet -wie jeder leicht einsieht-, dass jedem Element eine Ordnungszahl (woher kennen wir das wohl, hmmm?) zugewiesen ist; Beispiel ist hier die geordnete Menge der Zeichen des Computers. Die Ordnung wird durch die Reihenfolge des Aufzaehlens der Namen in den Klammern festgelegt. Als Ordnungszahlen fuer die g u e l t i g e n W e r t e d e r Va r i a b l e n t a g e r g i b t s i c h :

87

montag dienstag mittwoch donnerstag freitag samstag sonntag 0 12 3 4 5 6

Merke: es wird immer von 0 an gezaehlt. Existiert eine Ordnung, so koennen wir fuer einzelne Elemente auch ein Nachfolgeelement (engl.: successor) und ein vorangehen des Element (engl.: predecessor) festlegen. So ist der Nachfolger von montag das Element dienstag, von diesem ist es mittwoch usw. Der Vorgaenger von samstag ist freitag, davon donnerstag usw. Also alles menschenfreundlich und simpel. Doch um noch einen obendrauf zu setzen, gibt es dafuer auch vordefinierte Funktionen:
SUCC ( x ) liefert das Nachfolgeelement des Elementes, welches x enthaelt (oder x ist). SUCC ( dienstag ) ergibt mittwoch. P R E D ( x ) l i e f e r t d e n Vo r g a e n g e r. färbe j- blau; PRED ( färbe ) ergibt demnach gruen als Resultat. ORD ( x ) kennen wir schon. Wir erhalten die Ord nungszahl von x. ORD ( weiblich ) ist eben 1.

A u f a l l e Va r i a b l e n , d e r e n Ty p e i n S k a l a r t y p i s t , k o e n n e n u n d muessen wir die uns bekannten Regeln anwenden: bei Zuweisungen i m m e r g l e i c h e ( b z w. k o m p a t i b l e ) Ty p e n , d i e Ve r g l e i c h s o p e r a t o r e n ( < , > = , < > u s w , ) gelten, da jedes Element eine Ordnungszahl hat
(.montag < dienstag i s t T R U E , w e i b l i c h = m a e n n l i c h d a g e g e n FA L S E ) . Und wir koennen sie z.B. verwenden: in FOR- und C^S£-Anweisungen munter

V A R färbe : (rot, blau, gelb, orange, braun)'.

FOR färbe i DO BEGIN

rot TO braun ORD ( färbe ), Farbe:
>',

WRITE ( 'ORD CASE färbe OF
rot blau gelb orange braun END; END; : : : : : WRITELN WRITELN WRITELN WRITELN WRITELN

( ( ( ( (

'rot' ); 'blau' ); 'gelb' ); 'orange' ); 'braun' );

le/o/cr muß man tme so «tcW/iche Enksdlksduho vornehmen, witl man mehr nur die OfdmrüS&hiem erfahren. ^ WrfELNifcrbe) Qerit nicht [

88

Am guenstigsten ist es, ihr schreibt mal einige kleine P r o g r a m m e , i n d e n e n i h r e i g e n e Va r i a b l e n s k a l a r e n Ty p s v e r e i n b a r t und dann mit SUCC und PRED und ORD herumspielt. Vielleicht baut ihr eine Menueauswahl ein, ueber die ihr bestimmt, welche der vorgenannten Funktionen ausgefuehrt werden soll.

83

14.

Unterbereichstypen

Vo n d e fi n i e r t e n S k a l a r t y p e n ( w i e m a n n e u e Ty p e n d e fi n i e r t s e h e n wir irn naechsten Kapitel) oder den Standarttypen CHAR, BOOLEAN, einen Te i l - o d e r INTEGER (nicht aber REAL !!) kann man Unterbereich festlegen. Dazu ist in der Definition der kleinste und der groesste Wert des Unterbereichs anzugeben, Kl ar dass die untere Grenze nicht groesser als die obere sein darf. unterbereichstyp;
4 4 4 4

-! konstante I—

r

4 4

4 4

V - > - -I konstante !-

S o d a r f m a n f o l g e n d e Va r i a b l e n v e r e i n b a r e n : V A R buchstabe tag
wahr
'A nt . f. 7 * /. . r

1..31;
: TRUE..TRUE;

Die so d e k1ari er t en Variablen d uer f en (und k oen n en) nur Werte annehmen, die in dem Unterbereich enthalten sind, fuer den sie definiert wurden. buchstabe 'A'; buchstabe
'S';

Ok!

buchstabe :~ 'a';
wahr

-—- fans ober nicht! 'a' ist nicht ""AVZ' enthalten!

FALSE;

tag

■ 1 r

tag

32-

y

au weihet 1 FqUch!

Der Hauptvorteil der Unterbereichstypen liegt darin, dass Va r i a b l e n , d i e w i r k l i c h n i c h t d e n v o l l e n We r t e b e r e i c h e i n e s Skalartypen (oder Standarttypen) ausschoepfen sollen, ein genau definiertes Intervall daraus zugewiesen bekommen koennen. Dies ermoeglicht zum einen eine bessere Speicherverwaltung, zum anderen aber auch eine Ueberpruefung zur Laufzeit des Programmes, o b d e r Va r i a b l e n e i n W e r t z u g e w i e s e n w i r d , d e n s i e n i e a n n e h m e n soll. So fuehrt die Zuweisung: tag :~ tag - 1; zu einem Programmabbruch, wenn tag dadurch einen Wert bekommt, der nicht im angegebenen Unterbereich liegt. Und das ist sinnvoll, weil man daran sieht: aha, aha, irgend etwas stimmt mit dem Programm nicht!

90

Auch die Lesbarkeit und Seibstdokumentation von Programmen wird erhoeht. Es ist nun moeglich, (passend gewaehlten) Namen ihren Wertebereich gleich an der Nasenspitze anzusehen. Speicherplatz kann mit ihnen oekonomischer genutzt werden, weil z . B . d i e Va r i a b l e t a g l ( m i t 1 . . 3 1 ) w e n i g e r R a u m b e l e g t , a l s o q u a s i e i n e n k l e i n e r e n K a s t e n h a t a l s e i n e Va r i a b l e t a g 2 v o m Ty p
INTEGER. V AR tagl V AR

1..31;

tag2 ; INTEGER;

Merke aber: beides sind JNT£iSj£R-

B e i d e s i n d j a v o m Ty p I N T E G E R , n u r tagl : - tag2 f un kt i on i er t tagl darf eben nicht alle Wert annehmen, die tag2 haben darf. Ein Fehler tritt nur dann auf, wenn tag2 z.B. gleich £54 ist, das waere zu gross fuer tagl.

91

14« »ii.

Neue Typen definier en

Wenn wir schon 'was machen, dann aber auch ganz, jawollll. D e s h a l b l e r n t i h r h i e r, w i e m a n n e u e Ty p e n d e fi n i e r e n k a n n , n i c h t w i e b i s h e r i m m e r n u r n e u e Va r i a b l e n u n d K o n s t a n t e n . D a m i t w i r d dann auch der Vereinbarungsteil abgeschlossen.
typdefinition:
4 4 H +

—>--f TYPE »■-->-

-! typnane !-

-i typ i-

vereinbarungsteil:
->V 4 4 4 4 a

->-

->V 4 4 + 4

+—! konstantendefinition !—+

y 4 + * +—! typdefinition !—+
4 4

+—! Variablenvereinbarung i-

U p p s , w a s d a s s o l l ? N i c h t s o s c h n e l l . Erstmal merkt euch, dass • f a l l s i h r w e l c h e machen wollt— VOR den d i e Ty p d e fi n i t i o n e n Konstan t endef i nitJonen Va r i a b l e n d e k l a r a t i o n e n und HINTER den stehen muessen! Gemerkt? Dann weiter... Erwaehnt haben wir einmal, was der Computer so macht, wenn er d i e Ve r e i n b a r u n g e i n e r Va r i a b l e n fi n d e t : e r s u c h t i n s e i n e n Schnittmustern und bastelt danach einen Kasten. D e r T r i c k m i t d e n Ty p d e fi n i t i o n e n i s t n u n , d a s s i h r m i t d i e s e n gewissermassen neue Schnittmuster vereinbaren koennt.
TYPE

tage = ( mo, di, mi, do, fr, sa, so );
VAR

Wochentag : tage;

tage heisst jetzt ein neuer Basteibogen fuer CPU, nach dem er d a n n e i n e n K a s t e n z i m m e r t , w e n n e r a u f e i n e Va r i a b l e t r i f f t , d i e mit diesem neuen Typ vereinbart wird (.Wochentag z.B.). Mal einige —nicht unbedingt intelligente- Beispiele:

92

CONST

an fang = 1; ende = 10;
TYPE tfarbe

( gruen, rot, blau, gelb ); rot..gelb; ( oma, opa, tante, onkel, geschwister ); 1..49; an fang..ende;
INTEGER;

tgrundfärben tverwandte tlottern tbereich ganzzahlig
V AR farbe

: tfarbe; color

tgrundfarbe;

verwandte : tverwandte; lottozahlen : tlottern; ganzezahl : ganzzahlig; So richtig wichtig wird das erst, wenn ihr die strukturierten Datentypen kennenlernt. Doch sei erwaehnt, dass diese M o e g l i c h k e i t d e s A u s d e n k e n s v o n n e u e n Ty p e n , w e l c h e v o l l k o m m e n gleichwertig sind zu den vordefinierten Standarttypen, erstens zur Uebersicht 1ichkeit von Programmen beitraegt, zum anderen unerlaesslich fuer die Datenabstraktion ist (spaeter mehr davon) und zu guter letzt die Lesbarkeit foerdert. A l s B e i s p i e l : d e r Ty p B O O L E A N - w i r a l l e k e n n e n u n d l i e b e n i h n ist so vereinbart:
TYPE BOOLEAN

( FA L S E , T R U E ) ;

Irgendwo wurde das fuer alle PASCAL-Programmierer auf das man sich nicht mehr d'rum kuemmern muss.

mal getan,

Ein k l e i n e r Ti p : d e fi n i e r t i h r s o l u s t i g v o r e u c h hin neue Typen, dann waehlt doch deren Namen in der Weise, dass immer noch ein "t" am Anfang steht. Aehnlich wie's oben in den letzten B e i s p i e l Ve r e i n b a r u n g e n g e m a c h t i s t . S o k o e n n t i h r i m m e r, wo irn Programm ein Typ name auftauchen soll, pr Liefen, ob es auch einer ist; er sollte dann naemlich ein "t" vorangestellt haben.

3.15.

In Linie angetreten.

Wie die Ueberschrift schon andeutet, wird es jetzt ein wenig militaerisch. Hattet ihr bisher lediglich mit einzelnen Indivi duen zu tun (Variablen), so rnuesst ihr euch nun an den Umgang mit ganzen Massen von ihnen gewoehnen. Um zeitgemaess zu bleiben: denken wir mal, eure Gemeinde vergibt an euch den Auftrag, ein Programm zu schreiben, mit welchem die Bestaende einzelner Baumarten in der Umgebung des Ortes erfasst und ausgewertet werden sollen. Zu berechnen sind die Gesamtzahl an Baeumen und der Anteil der einzelnen Arten an dieser (prozentual).
BauQbestandser fassung:
4 4

I Einlesen der absoluten Baua- ! ! zahlen pro Bauaart ! ! Berechnung der Gesamtzahl i
4 +

! Berechnung der prozentualen I I Anteile je Bauoart !
+ 4

Einlesen der absoluten BauBzahlen pro Art:
4 4

Berechnung der Gesautzahl:
4

FUER Bauaart := Fichte BIS Sonstige! TUE I
4 4 4

! Gesautzahl :- 0 FUER Bauaart := Fichte BIS Sonstigel TUE I
4 4

! Lies BauQzahl der Bauoart !

! Gesaatzahl := Gesastzahl + I ! Bauozahl der Bauoart !

Berechnung der prozentualen Anteile:
4

4

FUER Bauoart := Fichte BIS Sonstige ! TUE I
4 4 4

! Prozentualen Anteil berechnen I

Diese Formulierung als Struktogramm ist doch recht einleuchtend, oder? Man geht mit einer Schleife einfach durch alle Baumarten und liest die zugehoerige absolute Anzahl ein oder berechnet deren prozentualen Anteil. Dumm nur, dass uns dazu keine Moeglichkeiten in PASCAL gegeben werden -bisher zumindest-; nein, nein, es liegt nicht an der S c h l e i f e , s o n d e r n a n d e n Va r i a b l e n , m i t d e n e n w i r d i e D a t e n z u den Baumarten erfassen wollen.

94

Sollten wir vielleicht schreiben:
WRITE WRITE WRITE WRITE ( ( ( ( 'Zahl 'Zahl 'Zahl 'Zahl der der der der Fichten: Tannen : Eichen : Birken : ' ' ' ' ); ); ); ); READLN READLN READLN READLN ( ( ( ( fichtenzahl ); tannenzahl ); eichenzahl ); birkenzahl );

u s w. , o d e r gesamtzahl := fichtenzahl + tannenzahl + eichenzahl + ...
Nee, das koennt ihr nicht verlangen. Aber bitte, es steht jedem frei . . . Der Faule sinnt jedoch auf Abhilfe, und in den siebziger J a h r e n , a l s P A S C A L a u s d e r Ta u f e g e h o b e n w u r d e , s t a n d e n d i e Schoepfer der Sprache anscheinend vor einem aehnlichen Problem. Daraufhin erfanden sie die FELDER! Felder, ein sehr wichtiger Begriff in der Informatik, sind s t r u k t u r i e r t e Va r i a b l e n . D . h . s i e s i n d v o n e i n e m s t r u k t u r i e r t e n Ty p , w e l c h e w i r i m l e t z t e n K a p i t e l n o c h v e r s c h w i e g e n h a b e n . Was man sich darunter nun vorzustellen hat? Sehr einfach: Felder sind die Zusammenfassung von vielen (mehr als 1) Objekten ( Va r i a b l e n ) - d i e a l l e v o m s e l b e n T y p s i n d - u n t e r e i n e m N a m e n .

We proudly present: BIRNE. Tja, eben nur EINE Birne, genauso, w i e w i r b i s h e r n u r e i n z e l n e - u n s t r u k t u r i e r t e - Va r i a b l e n deklariert haben.

Wow, that's great! And here are the friends of our special guest BIRNE! Applause for the BIRNE-group... Was fuer ein Showereignis! Ihr seht, die BIRNE-group ist zusam m e n g e s e t z t a u s l a u t e r M i t g l i e d e r n v o m Ty p B I R N E . S e l b s t m i t v i e l Scharfblick lassen sich ihre Elemente (Mitglieder) nicht mehr durch ihr Aeusseres unterscheiden. Wir muessen ihnen Nummern geben:

D

3 c?

Wollt ihr nun ein Interview mit einzelnen Mitgliedern der Gruppe machen, so habt ihr sie inetwa folgendermassen anzureden: " N u n , H e r r B I R N E - g r o u p H r. 1 , w i e a l t s i n d s i e ? " o d e r "Wie ist ihre Einstellung zu F'ASCAL, Mister BIRNE-group Nr. 5?" Etwas umstaendlich, aber jeder kann eindeutig angesprochen werden. 95

Zurueck zum Programmieren mit PASCAL. Betrachten wir die soeben vorgestellte Showtruppe naemlich von dieser Seite, so stellt sie fuer uns ein Feld da, in weichern jedes einzelne Element (Feldelement) den Typ BIRNE hat. In PASCAL saehe das so aus:
TYPE birne =

(a was birne genau ist, interessiert uns momentan nicht #)

VAR b i r n e g r o u p : A R R AY ( . 1 . . 6 . ) O F b i r n e ; Uppps, vielleicht etwas schnell, aber schon haben wir die Deklaration von Feldern kennengelernt. Gut, wenn schon, denn schon.. .

array-typ:
4

£Lj
4

Index t y ?
_ ___ 4 4

-->--- ARRAY —•>- -'(TV-)--;---! einfacher typ I---—>—i.)")—>—ToF V->—j typ I—>

strukturierter typ (vorlaeufig):
+ 4 4 4

statt .) nh0( (, kgnfl mfln au^h 3 ur\cj l verwenden

—>—I array-typ !—>—

Da ihr i nz wi sc hen e r h e b l i c h e E r f a h r u n g m i t P A S C A L u n d nur eine kurze Erlaeuterung und dafuer Syntaxdiagrarnrnen habt, l i e b e r ' m a l ' n B e i s p i e l mehr» to array (engl.), bedeutet ordnen, aufstellen; d.h. das Symbol A R R AY z e i g t a n , d a s s e i n s t r u k t u r i e r t e r Ty p g e w u e n s c h t w i r d , e i n Feld. Die einzelnen Komponenten eines solchen Feldes werden durch Indizes gekennzeichnet. Bei der BIRNE-group waren es einfach die Zahlen 1 bis 6. Es muessen aber nicht notwendigerweise Zahlen als I n d i z e s v e r w a n d t w e r d e n , d a r u m b e s c h r e i b t d e r e i n f a c h e Ty p zwischen f. und .), was fuer Werte erlaubt sind (siehe auch vor hergehendes Kapitel). Gleichzeitig wird durch den Indextyp festgelegt, wieviele Elemente das Feld hat! O F u n d t y p d e fi n i e r e n d e n Ty p ,
ARRAY haben.

welchen alle Komponenten des

I n Z u k u n f t f a e l l t e s a l s o j e d e m l e i c h t , mit einem Schlag, sagen w i r m a l 1 0 0 0 Va r i a b l e n z u d e fi n i e r e n :
VAR

tausendvariablen

ARRAY (.1..1000.) OF CHAR;

96

Um euch vor dem ersten Programm einen Einblick in die Vielfalt der moeglichen Deklarationen zu geben, einige Beispiele:
CONST

n = 8; letzteszeichen - 'S';
TYPE

tbuchstaben = ARRAY (.'A'..letzteszeichen.) OF BOOLEAN; tbaumarten - ( fichte, tanne, eibe, birke, buche ); tbaeume - ARRAY (.tbaumarten.) OF INTEGER; tboolesch = ARRAY (.BOOLEAN.) OF anzahl; t z a h l e n * A R R AY ( . l . . n . ) O F - 1 . . 1 0 0 ; V A R buchstaben baumzahl prozentual boole zahlen tbuchstaben; tbaeume; ARRAY (.tbaumarten.) OF REAL; tboolesch; tzahlen;

D i e o b i g e n Ve r e i n b a r u n g e n w e r d e n w i r u n t e n i n w e i t e r e n Erlaeuterungen noch verwenden. Also im Auge behalten! Die ersten Grundlagen fuer unser Qeko—Programm sind ja schon gelegt; Suchspiel, wo... ? " V i e l e n D a n k , l i e b e A u t o r e n , d a s s i c h s o v i e l u e b e r PA S C A L lernen darf. Sie sind zu guetig. Es guaelt mich allerdings die fuer mich wichtige Frage, wie ich denn nun die sogenannten K o m p o n e n t e n o d e r F e l d e l e r n e n t e a l s Va r i a b l e n a n s p r e c h e n k a n n . Bitte, geben Sie dazu eine Erlaeuterung." Oh, nicht zuviel des Lobes. Sie machen uns erroeten. hier die Antwort auf ihre Frage:
array-konponentes
4 4

Dennoch

->—! arrayvariable !- >---((" ^-->-----i ausdruck i—:—>—(j1»—> + 4 *-—- + V
J \ . -<■ '

E i n e n o r m a l e Va r i a b l e s p r e c h e n w i r u e b e r i h r e n N a m e n a n , natuerlich ist das bei Feldern auch so. Allein, wenn wir eine einzelne Komponente auswaehlen wollen, so muessen wir deren Index noch hinzufuegen. Im Interview sagten wir: "Herr BIRNE-group N r. 1 " o d e r a e h n l i c h .

97

Mit PASCAL gesprochen: dasselbe aus!

birnegroup C 1 J

, das sagt genau

z

6

Ifldi, izes

1^ birneoroup[3] odtr ^Birneqroup Mitglied Hr.Z Der Ausdruck in array-koaponente muss ein Resultat vorn selben Typ liefern, wie einfacher Typ bei der Feldvereinbarung vorschreibt! Zum versprochenen Aufgriff der obigen Definitionen: buchstaben (. 'A' .) buchstaben (. CHR ( 78 ) .) boole (. TRUE .)

geht nur, wenn das Zeicben.weUnes CHR(78) liefert iV> Werberetc/i V„ (ebtes zeichen Ist!

boole (. baumzahl (. fichte .) > baumzahl (. tanne .) .) -<- Ver-Schacktelt^ber" erlaubt zahlen (. 10 + 4 - x .)

.Sehr schon, qber das, EroeWs muß i«1 Bereich 4..n liegen Q£rit nicht I Index muß vom Typ k bäum arten 5eir\ J

prozentual (. 'A' .)

Jedesmal, wenn wir so eine /JÄ/wy-Komponente auswaehlen, dann e r h a l t e n w i r e i n e Va r i a b l e , d i e v o n d e m Ty p i s t , d e n w i r b e i d e r Ve r e i n b a r u n g h i n t e r O F g e s c h r i e b e n h a b e n ! ! ! Z u w e i s u n g e n u s w. s i n d nach allen Regeln der Kunst erlaubt: prozentual (. birke .) := baumzahl (. birke .) / gesamtzahl * 100; oder boole (. (10 > x) AND (30-2 < y) .) := zahlen (. 4 .); "Die Phantasie an die Macht" koennte man sagen. Erlaubt ist was gefaellt; immer unsere Regeln im Hinterkopf, natuerlich! Und als Belohnung jetzt das Baurn-Programrn:

98

PROGRAM baeume; TYPE

tbaumarten = ( fichte, tanne, kiefer, eiche, buche, ei be, birke, sonstige ); tanzahl - ARRAY (. tbaumarten .) OF INTEGER; tprozent - ARRAY (. tbaumarten .) OF REAL;
VAR

baumzahl : tanzahl; prozentual : tprozent; gesamtzahl : INTEGER; art BEGIN WRITELN ( 'Eingabe der Zahl der Baeume der einzelnen Arten:' );
WRITELN;

:

tbaumarten;

WRITELN ( ' Artenschiuessel:' ); WRITELN ( ' 1 - Fichte; 2 - Tanne; 3 - Kiefer; 4 - Eiche' ); WRITELN ( ' 5 = Eibe; 6 = Birke; 7 = Sonstige' );
WRITELN;

(# Lesen der Baumzahlen u. Ermittlung des Gesamtbestandes #) gesamtzahl := ö; FOR art := fichte TO sonstige DO BEGIN WRITE ( 'Art;', ORD ( art );2, ' Anzahl: ' ); READLN ( baumzahl (. art .) ); gesamtzahl := gesamtzahl + baumzahl (. art .); END; (* FOR a) (* Berechnung der prozentualen Anteile der Arten am Gesamtbestand der Baeume

*)

FOR art :- fichte TO sonstige DO prozentual (. art .) := baumzahl (. art .) / gesamtzahl * 100; <# Tabellarische Ausgabe der Daten #)
WRITELN; WRITELN;

WRITELN ( 'Baumbestand:', gesamtzahl:7;0, ' Baeume' ); WRITELN ( 'Baumart; Absolut; Prozentual;' ); FOR art :- fichte TO sonstige DO WRITELN ( ORD ( art );5, baumzahl (. art .) :16, prozentual (. art .) :18:2, ' 7.' ); END.
y9

Das einzige Manko aft diesem feinen F'rogramm ist die fehlende woertliche Entschluesselung der Arten. Vielleicht spaeter mehr dazu. g e s a m t z a h l h a b e n w i r a l s R E A L - Va r i a b l e v e r e i n b a r t , w e i l w i r a n n e h m e n , d a s e s i m B e r e i c h d e r G e m e i n d e m e h r a l s M A X I N T, d . h . 32767, Baeume gibt (erinnert euch an den Wertebereich von INTEGER). Zur Einsparung einer fOfl-Schleife legten wir auch noch die Berechnung der gesamtzahl in die des Einlesens der An zahl . Wir glauben eine weitere Eroerterung zum Efeispie 1 eruebrigt sich, so dass wir mit einigen Besonderheiten der Felder weiter machen koennen. Mit baumzahl (. fichte .) spricht man ein Element des Feldes a n . Ve r g n u e g t e s Z u w e i s e n i s t e r l a u b t : baumzahl (. fichte .) := baumzahl (. tanne .) (* z. B. *)

E i n C l o u v o n PA S C A L i s t a b e r, d a s s s e l b s t Va r i a b l e n s t r u k t u r i e r t e r Ty p e n i n Z u w e i s u n g e n v o r k o m m e n d u e r f e n , s o l a n g e sie den selben Typ haben!
V AR feldl, feld2 : ARRAY (. 1..100 .) OF CHAR; f e l d 3 : A R R AY ( . 1 . . 1 0 0 . ) O F B O O L E A N ; f e l d 4 : A R R AY ( . 1 . . 5 0 . ) O F C H A R ; f e l d S : A R R AY ( . 1 . . 1 0 0 . ) O F C H A R ;

feldl := feld2; feldl := feld3;

1st erlautt. Die Werte aller Hemente von {elc{3, werc/en den entsprechenden Komponenten von PetcM ?uoewiesen.

oeht weht.' 3i'e Wornponer&er\[ype-n stimmen nicW uberein!

feld2 := feld4;

unerlaubt! $ie leider haben unter schiedliche Ansaht von Elementen.

feld2 :- feld5;

? Wq, wq£ ajauht ihr?

Zum letzten Beispiel: Das funktioniert nicht! Warum? Beide Felder haben doch gleichen Komponententyp und gleichen Indexbereich. Macht nichts, es geht nicht. Solange die Felder nicht mit einer e i n z i g e n ( a l s o d e r s e l b e n ) Ve r e i n b a r u n g d e fi n i e r t w e r d e n , d e n k t CPU (genaLier das Ueber set zungsprogr amm), dass feld2 und feldS e i n e n u n t e r s c h i e l i c h e n Ty p h a b e n .

100

Besser waere:
TYPE

tfeld : ARRAY (. 1..100 .) OF CHAR; V A R feldl, feld2, feld5 : tfeld;

oder

V A R feldl, feld2 ; tfeld; feldS : tfeld;

S t e l l t e u c h d a s s o vor Z u w e i s u n g e n k l a p p e n n u r, w e n n f u e r dasselbe Schnittmuster verOperanden rechts und l i n k s v o n wandt wurde.
feldl u. feld2 wurden mit dem gleichen Schnittmuster h e r g e s t e l l t , b e i f e l d S ( v o r d e m Ve r b e s s e r u n g s v o r s c h l a g ) w u r d e a b e r e i n n e u e s a n g e l e g t , a l s C P U a u f d a s Wo r t A R R AY g e s t o s s e n war. M i t d e r v e r b e s s e r t e n Ve r e i n b a r u n g u e b e r t f e l d p a s s i e r t s o e i n Mahleur nicht, da immer der tfeld-Ba&te-lbogen genommen wird.

101

3. 15. 1. Wir entschwinden in hoehere Dimensionen M i t e i n i g e m Ve r w u n d e r n w i r d m a c h e r n b e s t i m m t a u f g e f a l l e n s e i n , dass in der Definition von ARRAY-TYP folgendes auftauchte:
4 a t f f v v ^ S

... —>---(. ,-—>-;-—! einfacher typ !---—>—r .))— ...

l

I

\

i

Das zu erklaeren ist Aufgabe dieser kurzen Abhandlung. Um mit den Kistendiagrammen vertaut zu bleiben, hier mal 'was fuer den haptisehen Lerntyp:
V AR feld : ARRAY (. 1..6 .) OF INTEGER;

Ok, das sieht ja noch jeder ein, was aber, wenn wir eine solche Ve r e i n b a r u n g v o r n e h m e n ( o f f e n s i c h t l i c h i s t s i e n a c h d e m S y n t a x diagramm erlaubt):
VAR feld : ARRAY (. 1..3 .) OF ARRAY (. 1..3 .) OF INTEGER;

W e r d e n n i c h t 3 F e l d e r d e s Ty p s A R R AY ( . 1 . . 3 . ) O F I N T E G E R u n t e r d e m N a m e n f e l d z u r Ve r f u e g u n g g e s t e l l t ?

feldM

feldU][3]

— £WßJEI
Id [3]

Genau, und sie lassen sich wie gezeigt ansprechen. Will man dann aber nur den 2. Kasten des 1. Feldes, so schreibt man: feld (. 1 .) (. 2 .)

Spricht ein anies Feld an 3

wählt aus dem angesprochenen Feld eine Komponente aus.

io:

Und schon haben wir ein zweidimensionales wia im richt'gen Leben, dort gibt's auch Schachfelder oder Stundenplaene. TYPE

Feld vereinbart. solche Sachen,

Fast z.B.

figur - ( koenig, bauet-, dame, laeufer, springer, türm, leer ); fach - ( mathe, englisch, deutsch, geschi >; t a g - ( M , d i , m i , d o , f r, s a ) ;
VAR s c h a c h : A R R AY ( . ' A ' . . ' H ' . ) O F A R R AY ( . 1 . . 8 . ) O F fi g u r ; p l a n : A R R AY ( . t a g . ) O F A R R AY ( . 1 . . 6 . ) O F f a c h ;

So kann indem man schach oder das plan oder einen plan

man

die

Figur,

die

auf

einem

Feld

steht,

festlegen,

(. in mi

'E* der .)

.) 4. (.

(.

4

.)

:am ;-

bauer Mittwoch geschi

schreibt,

Fach (.

Stunde 4 mit do .) all

festlegen,

ganzen (.

Ta g ,

seinen .)

Stunden ansprechen.

stäx M o . A f,i!r,. 2 3
l\
hcseh'.

Di.
Engl.

Mi. / /

Do..

Frf

Mal, M o l k Milke
fcwkh
Moth« ttahi Gec^.-

5
< o

H Mo, i sw

Hiaf».Std

i pUtrv,o][T]
Zugegebenermassen ist das ein wenig umstaendlich, wer schreibt schon bei vi erdimensionalen Feldern (die gibt's!) schon 4mal ARRAY hin? Me, ne, ne, da macht man das so:
VAR p a n d i a e n s i o n a l : A R R AY ( . 1 . . 4 , 1 . . 5 , 1 . . 3 , 1 . . 6 . ) O F I N T E G E R

103

Ein 4—dimensional es Feld. Seine JW7£G£/}-Komp onen ten werden dann z.B. so ermittelt: pandimensional (. 2, 3, 1, 6 .) Das zu zeichnen, erspart uns. Mit 3 Dimensionen geht's gerade noch:
V AR dimSd : ARRAY (. 1..3, 1..3, 1..2 .) OF CHAR;

dirvt3d [3,3 ,Ä]

a.3)iw-

dim [3-, 3-, 4]
3.3)tmenS»c»n

/Wfbaii des Feldes dimM- Herke'.clirn3d [3] w<We die Menstruldur ansprechenderen Kosten mit * gekennzeichnet Sind (diso ein Ä-dimensiorsol«, Teld)!

Wer dafuer den Basteibogen machen moechte, soll sich ruhig melden. CPU hat ganz schoen zu keulen. Ve r s t e h t s i c h n a t u e r l i c h v o n s e l b s t , d a s s a l l e A u s d r u e c k e , d i e einen Index fuer eine Dimension berechnen, nur Werte im vereinbarten Bereich liefern duerfen. dim3d (. 4, 7, 9 .) waere also schon mal nicht ok. U e b e r l e g t m a l , w i e d u r c h d i e v o r g e s t e l l t e n Ve r b e s s e r u n g e n d i e Felder schach und plan neu vereinbart werden koennten. Wir haben schon eine Menge gesehen, was man mit ganzen Feldern anstellen kann, nur eines geht nicht:
READLN ( feldl );

oder

WRITE ( feld2 );

So schoen es waere, aber Feldinhalte lassen sich nur ueber ihre Komponenten einlesen oder ausgeben. Weiss doch jeder, dass READ u n d W R I T E n u r m i t Va r i a b l e n b z w. K o n s t a n t e n f u n k t i o n i e r e n , d i e eines einfachen Typs sind. Nach dem Motto: Simpel ist schoen. Eine sehr sinnvolle, NICHT STANDARTMAESSIGE Einschraenkung des zuletzt Gesagten folgt sogleich... 104

O 1 er •">

Aoainst al1.

Standarts

Stimmt, in diesem Kapitel beschreiben wir einige Funktionen und Moeglichkeiten, die nicht im Standard-PASCAL vorgesehen sind, al lerdings in den meisten Dialekten (wir benutzen hier TURBO PASCAL) in der einen oder anderen Form zu finden sind. U n d d a i h r e h e r m i t e i n e m M i c r o c o m p u t e r - PA S C A L i n K o n t a k t kommt, als mit einer Standartimplementation, dachten wir uns, dass die Infos hier ganz interessant seien. Mit eurem bisherigen Wissen konntet ihr toll Zahlen und Buchstaben einlesen und ausgeben. Was ist aber zu tun, wenn man z.B. seinen Namen oder einen laengeren Text eingeben moechte? Das kurze Programm oeffnet die erste Tuer dazu:
PROGRAM liesname; V AR name : STRING (. 20 .); INTEGER; BEGIN WRITE ( 'Bitte Namen angeben: ' ); READLN ( name ); WRITELN; FOR i := 1 TO 10 DO WRITELN ( ' ':i, 'Hallo ', name ); END.

Die Ausgabe ist etwas aufgepeppt, ansonsten ein Simpellisting. N e u i s t d i e Ve r e i n b a r u n g d e r Va r i a b l e n n a m e . M a n k a n n s i c h diese ungefaehr so vorstellen:
V AR n a m e : A R R AY ( . 1 . . 2 0 . ) O F C H A R ; ( # i s t n i c h t d a s g l e i c h e wie STRING (. 20 .) / Nur ungefaehr/ #)

Wichtig ist: Das Feld hat den Komponententyp CHAR. Wird eine Va r i a b l e v o m Ty p S T R I N G ( e i n n e u e r Ty p , a b e r a u c h v o r d e fi n i e r t ) vereinbart, so besteht sie aLts lauter char actern. Alles, CHAft-torioibtai, die unter dem 3e2e?/cWr / i ^ rtcime 2usftm»«e^^eLLLÜ-LU !J U 1.I..UJLLLÜ f°ßt W-

105

S t r i n g s k e n n e n w i r j a s c h o n a u s d e n K o n s t a n t e n Ve r e i n b a r u n g e n . Dort war ein String folgendes: String:
4 4

•>---(7>">---7-! character !--j—>--(»"J—> * + + V

Jetzt definieren wir aber einen richtigen string-typ: string-typs

S~*\
v _ y

-J

+
+


4 ^ y

--->---, STRING ,-->--/(.}—>—: konstante !—>—(.)Y->

Die Konstante muss im Bereich von 1..255 sein! Sie gibt an, w i e v i e l e Z e i c h e n d i e Va r i a b l e f a s s e n k a n n , d . h . w i e l a n g d e r S t r i n g , d e n w i r d e r Va r i a b l e n z u w e i s e n w o l l e n , m a x i m a l s e i n d a r f - leider eben hoechstens 255 Zeichen lang. Z u r Ve r a n s c h a u l i c h u n g e i n i g e e x a m p l e s : V A R name tag : : STRING (. (. 2 10 .); .); I I Mit I I L_l LJ l_J

STRING

w L

automarke : STRING (. 20 .); I 1 I L_i i i 3 *1

10

Die einzelnen Buchstaben koennen wie bei normalen Feldern mit
name (.1.) oder tag (. 2 .) oder automarke (. 15 .)

angesprochen werden. MERKE: Die untere Indexgrenze ist 1 ! WertZuweisungen bewirken dieses: vorher nachher

name := 'Peter'; I I 1 I l I l I I I I |P|eitieir| i i | | I name : = ' H e i n z - G u e n t e r ' ; l h e | t ) e ) r ) | | I I i l Ü | e | i \ n \ l \ ~ i & m l e p r i i

Beim zweiten Mal wird einfach der Namensrest, der name ueber die erlaubten 10 Zeichen hinaus fuellen wuerde, weggelassen. Um mit Strings richtig arbeiten zu koennen, existieren noch eine Menge vordefinierte Funktionen, die wir im Folgenden mal vorstellen rnoechten. Ihr koennt sie auswendig lernen oder immer wieder nachschlagen, auf jeden Fall sind sie extrem nuetzlich.

106

Ein grosses, tolles, waaaaaahnsinnig schickes Programm, in dem sie alle wieder auftauchen, wird dann die Arbeitsweise mit ihnen im Ernstfall verdeutlichen. Funktionen zum Umgang mit Strinass
LENGTH ( string )

Gibt die Anzahl der Zeichen in string als INTEGER-Groesse zurueck. string ist eine Variable oder Konstante. i := LENGTH ( 'Hallo' ) hinterher hat i den Wert 5
i := LENGTH ( " ) " 0,

denn " ist der LEERSTRING. i :- LENGTH ( '123456789' ) hinterher hat i den Wert 9

CONCAT ( quellel, quelle2, ... ) Ergibt einen neuen String, in dem alle Strings (quellel, q u e l l e 2 , . . . ) a n e i n a n d e r g e h a e n g t s i n d . q u e l l e l u s w. k o e n n e n Konstanten oder Variablen sein.
«

sl := CONCAT ( 'Ich sage', ' guten ', 'Tag' ) nachher hat sl den Inhalt 'Ich sage guten Tag'. s l : = C O N C AT ( s l , ' z u D i r ' ) n a c h h e r h a t sl den Inhalt 'Ich sage guten Tag zu Dir'.

COPY ( quelle, index, laenge ) quelle muss ein String sein, index u. laenge INTEGERAusdruecke. Es wird die Zeichenkette zurueckgegeben, welche ab quelle (.index.) beginnt und laenge Zeichen umfasst. WRITE ( COPY ( 'Viel Spass wuensche ich', 6, 14 ) ) ergibt die folgende Ausgabe: Spass wuensche

POS ( muster, quelle ) Ergibt den Index in quelle, ab welchem der Text muster in quelle ist als INTEGER-Wert. WRITE ( POS ( 'Ich', 'Du und Ich' ) ) schreibt 8 WRITE ( POS ( 'ich', 'Ihr koennt mich mal' ) ) schreibt 13 WRITE ( POS ( 'Du', 'Nicht drin' ) ) schreibt 0, weil 'Du' nicht in 'Nicht drin' ist.

107

DELETE ( ziel, index, laenge ) Loescht aus der STRING-Variablen ziel die Zeichenkette, die bei ziel (.index.) beginnt und laenge Zeichen umfasst. sl := 'Ein Beispiel mit Pfiff; DELETE ( sl, 1,4) hinterlaesst in sl den String 'Beispiel mit Pfiff .

INSERT ( quelle, ziel, index > q u e l l e i s t e i n e S t r i n g - K o n s t a n t e o d e r Va r i a b l e , z i e l e i n STRING-Variable und index ein INTEGER-Ausdruck. Es wird quelle in ziel ab ziel (.index.) eingefuegt. s l : = ' E i n Ta g ' ; I N S E RT ( ' s c h o e n e r ' , s l , 4 ) e r g i b t i n sl den neuen Inhalt: 'Ein schoener Tag'. Wir hoffen, die Beispiele geben genug Aufschluss ueber die Funktionen und Moeglichkeiten dieser vordefinierten Routinen. Experimentiert einfach mal mit ihnen und schaut euch an, was so herauskommt. E r w a e h n t s e i n o c h , d a s s - z u m i n d e s t i n T U R B O - PA S C A L - f o l g e n d e s gleichwertig ist: sl := CONCAT ( '123', '345', '567' ); sl :- '123' + '345' + '567';

Ein Leerstring, oben taucht er kurz mal auf, ist eine Zeichenkette mit der Laenge 0, als Konstante '' . Damit das Ganze einen runden Abschluss vor dem ersten Mammutbeispiel bekommt, noch ein paar nuetz1iche Dingelchen:
CLRSCR

ist eine vordefinierte Funktion, die den ganzen Bildschirm leer macht.
CLREOL

ist auch vordefiniert und loescht alle Zeichen in der Zeile, in welcher der Cursor (die Schreibmarke des Rechners) steht, ab des sen momentaner Position.
G0T0XY ( x, y )

stellt den Cursor in die Spalte x in der Zeile y auf dem Schirm. Folgende Schreib- od. Leseoperationen erfolgen dann von dort, x muss im Bereich 1..80, und y im Bereich 1..24 liegen. Spx[[eJ/tek/- y<, 2v -Spotte &ö /Zeile 4

r

,

-

<Z~~^ 108

Bildschirm

C L R E O L u s w. g i b t ' s a u c h n i c h t i m S t a n d a r d , a l s o i m m e r e r s t vergewissern, ob sie vorhanden sind. Bei TURBO schon. "Wolle ma's hinein lasse? Nahallamarsch..." Hier das bisher aufwendigste und schoenste Programm, fuer das keine Muehen und Kosten gescheut wurden!

109

PROGRAM zeileneditor;

Mit diesem Programm werden die TURBO-Funktionen INSERT, DELETE, POS CONCAT, LENGTH, GOTOXY, CLREOL, CLRSCR eingefuehrt. //// Sie gehoeren nicht zum Standard von PASCAL //// zeileneditor ermoeglicht die Eingabe einer Textzeile auf dem Schirm. Diese wird in der Variablen zeile gespeichert. Um die Eingabe einfach zu gestalten, ist die Verwendung mehrerer Steuerfunktion vorgesehen. Diese werden saemtlich durch ControlCar acter angesprochen. Control-Character bedeutet, dass die Taste mit der Aufschrift CTRL und GLEICHZEIT IG eine Buchstaben taste gedrueckt werden. Schreibweise: 'SS bedeutet CTRL-S, also Taste CTRL und Taste S Steuerfunktionen in diesem Programm: AS : Ein Zeichen zurueck, ohne es zu zerstoeren. AP : Ein Zeichen vorwaerts. AF : Eine Zeichen kette in Richtung Zeilenende suchen und Cursor darauf positionieren. Atf ; oder der Rueckwaertspfeil ( <- ). Loescht das Zeichen hinter dem Cursor (in Richtung Zeilenanfang). " ■ G : Loescht das Cursorzeichen. CR : bedeutet die Taste RETURN oder ENTER. Schliesst die Eingabe ab.

CONST

maxlaenge =60;
CTRLS = 19; CTRLD = 4; CTRLF = 6; CTRLH = 8; CTRLG = 7; CR = 13;

VAR

suchstring, zeile : STRING (. maxlaenge .); neuindex, index : 1. .maxlaenge;
ch : CHAR;

110

BEGIN (# ++++++++++++ Bildschirm fuer Eingabe der Zeile vorbereiten ++++++++++++ *) CLRSCR; WRITELN WRITELN WRITELN WRITELN WRITELN C» Bildschirm leer machen *)

( 'Steuerzeichen:' ); ( ,AS = Cursor nach links; "D - Cursor nach rechts;' ); ( ""G = Cursorzeichen loeschen; '-H - Zeichen vorCursor loeschen;' ); ( fAF - Zeichenkette in Richtung Zeilenende suchen;' ); ( 'CR = Abschliessen der Eingabe.' );

GOTOXY ( 1, 12 ); WRITELN ( 'Zeile: ' ); WRITE ( ' A', 'A';maxlaenge-1 ); C# +++++++++++++++¥■++■&■/■ Zeile jetzt endlich einlesen ++++++■/■++■/■+++++■/■+■/■++++ #) zeile := index := 1; REPEA T GOTOXY ( index +7, 12 ); READ ( KBD, ch ); (# +++++++++ falls kein Steuerzeichen, dann in Zeile einfuegen +++++++++ #) IF ch >~ ' ' THEN BEGIN IF index > LENGTH ( zeile ) (u zeichen am zeilenende #) THEN BEGIN WRITE ( ch ); zeile := CONCAT ( zeile, ch ); E N D ELSE BEGIN (# zeichen einfuegen *) INSERT ( ch, zeile, index ); WRITE ( COPY ( zeile, index, LENGTH ( zeile ) - index + 1 ) ); END; "; (» Zeile leer machen *)

IF index < maxlaenge THEN index := index * 1;
END

Oü~f~t~t-++++++ ab hier die Steuerzeichen interpretieren +++++++++++++#)
ELSE CASE ORD ( ch ) OF

CTRLS : IF index > 1 THEN index := index - 1 ELSE WRITE ( CHR ( 7 ) ); f*f einmal piepen *) CTRLD : IF index < (LENGTH ( zeile )+l) THEN index ;= index + 1 ELSE WRITE ( CHR ( 7 ) );

111

CTRLH : IF index > 1 THEN BEGIN index ;= index - 1; DELETE ( zeile, index, 1 ); GOTOXY ( index-f-7, 12 ); WRITE ( COPY ( zeile, index, LENGTH ( zeile ) - index + 1 ) );
CLREOL; E N D ELSE WRITE ( CHR ( 7 ) ) ;

CTRLG : IF index <= LENGTH ( zeile ) THEN BEGIN DELETE ( zeile, index, 1 ); WRITE ( COPY ( zeile, index, LENGTH ( zeile ) - index + 1 ) ); CLREOL; (* weil jetzt letztes zeichen in zeile doppelt auf schirm ist *) E N D ELSE WRITE ( CHR ( 7 ) ); CTRLF : BEGIN
GOTOXY (5, 1 );

WRITE ( 'Suchstring: ' ); CLREOL; READLN ( suchstring ); neu index := POS ( suchstring, zeile ); IF neuindex > index THEN index :~ neuindex; END;
C R (# RETURN #)

ELSE WRITE ( CHR ( 7 ) ); (* unerlaubtes zeichen kommentieren *-)
END; (* von CASE #) UNTIL ORD ( ch ) = CR; WRITELN; WRITELN;

WRITELN ( 'Das Ergebnis: ', zeile ); END.

ii:

Ha, wenn ihr denkt, jetzt sei genug, oh nein. Bevor wir euch in's naechste Kapitel entlassen noch eine Wissenserweiterung: Wir erwaehnten, Strings haetten eine bestimmte Laenge, die man mit LENGTH feststellen kann. Stimmt, dann gilt aber auch:
'Hallo' < 'Hallo ihr da'

Der String 'Hallo' ist kleiner (kuerzer) als der String 'Hallo i h r d a ' . S i e h t j e d e r e i n . E s g e l t e n d a h e r d i e Ve r g l e i c h s o p e r a t or en auch fuer Str i ng s! S t o p , s t o p , e s g e h t n o c h w e i t e r. Wa s i s t m i t :
'Hallo' < 'Holla'

Sie sind beide gleich lang. Denk... . Es ist naemlich so, dass nicht nach der Laenge eines Strings entschieden wird, ob einer kleiner oder gleich einem anderen ist, sondern nach dem Inhalt. Will sagen: CPU vergleicht -an den Zeichenkettenanfaengen beginnend— die Zeichen in den Strings. Je nach dem, ob die Ordnungszahl gleich, kleiner oder groesser ist, als die des Zeichens aus dem anderen String, wird entschieden, ob die Strings gleich, kleiner oder nicht sind. Zu kompliziert? Beispiele:
'Hallo' 'Hallo' = < 'Hallo' 'Holla' TRUE, TRUE, ist 'a' < klar 'o' gilt/

'Hallo' < 'Hallol' TRUE, weil d. erste String kuerzer ist.
'abcde' > 'abcEFG' TRUE, weil 'd' > 'E' ist.

Konkret kann man dies ausnutzen, (alphabetisch) werden sollen o.ae..

wenn

Strings

sortiert

11 3

£>. 1 6.

Eine Menge Neues

'ne ganze Menge Obst, gell? Da gibt's eine Birne, einen Apfel, Ananas und Bananen. Man koennte diese tollen Fruechte eigentlich zu einer Menge, genannt "Obst", zusammenfassen. Hinterher sind wir dann gewappnet, wenn jemand kommt und fragt: "Habt ihr in der Menge Obst auch Kirschen?" "Nein, in der Menge Obst sind Kirschen nicht enthalten." oder "Gebt mir bitte den Apfel in eurer Menge Obst?" ... Danke. Ist jetzt noch ein Apfel

"Nein, natuerlich nicht. Du hast ihn gerade bekommen." Genug des Kaufmann-Spiels. Gesehen habt ihr jedenfalls, dass man Dinge in Mengen (engl. set = Menge) zusammenfassen und mit diesen auch Operationen ausfuehren kann. Fragen, ob ein Ding in der Menge ist, ein Element aus der Menge entfernen und noch v i e l e s m e h r. M a t h e m a t i s c h Vo r b e l a s t e t e n u n t e r e u c h i s t d a s k l a r e r w e i s e nichts Unbekanntes mehr. Die kennen schon die Menge der natuerlichen Zahlen (^ oder die der Ganzen Zahlen"^ B e l i e b t i s t d i e D a r s t e l l u n g m i t t e l s Ve n n - D i a g r a m m e n :
Menge "Obst1 Menoe" FisschrankiMl '

Zwei Mengen, wie wir sie im taeglichen Leben mit wenig Muehe finden. W e r h a e t t e e s n i c h t s c h o n g e a h n t ? Wa s i m A l l t a g e i n e g e w i s s e B e d e u t u n g s p i e l t , d a s s k a n n i n PA S C A L e i g e n t l i c h a u c h n i c h t fehlen. Nur werden dort Mengen nicht mit kleinen Kreisen dargestellt oder definiert, sondern so:

114

set-typ:
— ->. — x t

--->--CSET)—>---lOFV->—! einfacher typ i—>

strukturierter typ (vorlaeufig):
4 4

--->--—! array-typ !-- ) V + + v
J 4 4 4 4 j

'— -! set-typ I--1

I n d i e s e r W e i s e k o e n n e n w i r a l s o M e n g e n a l s Va r i a b l e n d e fi n i e ren, in dem wir sie als vom set-typ seiend deklarieren. Nach OF ist die Grundrnenge anzugeben, sie ist ein Skalartyp oder Unterbereichstyp, aus der die zukuenftigen Elemente, welche wir in die Menge (Mengenvariable) tun wollen, sein duerfen. V A R x : SET OF 1..3 Mit dieser Deklaration kann x die folgenden Inhalte haben:

leer

enthoLt

oi

fj

{

j-*

»

r

,

iWtleW

<-"*

<M

Hi

{d,l]

Die Schreibweisen mit -C und > sind die zugehoerigen mathematischen. Zwischen -C und 3- stehen dann die in der Menge befindlichen Elemente aus der Grundrnenge. Noch einige Beispieldefinitionen:
TYPE

tzeichen = SET OF ' '..'z'; tfärben - (rot, gruen, blau, gelb, braun); tfärbe = SET OF tfarben;

V AR x , y, z : S E T O F 0 . . 5 ;

farbenmenge : tfarbe; darstellbar : tzeichen;
ch i : : CHAR; INTEGER;

115

x , y, f a r b e n m e n g e u s w. s i n d M e n g e n v a r i a b l e n . S i e k o e n n e n e i n e Menge aufnehmen. Wie aber koennen wir ihnen eine solche geben? Mit den obigen Deklarationen alleine koennen wir naemlich nur wenig anfangen. Zu fragen, ob 3 in der Menge x ist hat noch k e i n e n Z w e c k . D a v o r h a t PA S C A L d i e N o t w e n d i g k e i t g e s e t z t , x , y usw. erstmal Elemente zuweisen zu muessen.
Hier sind t und] statt (. .) WogUdi N aenge: ^ —

-.>../r.)—>-r

>
1

r---(

•">>->
I

r~\ ' 4—>—• ausdruck !—>—r~. j—>—! ausdruck ausdruck !—>—7!—>—7—+ -j-\ .. ...—>—! " V t * * V

r \

D i e A u s d r u e c k e m u e s s e n d a b e i W e r t e h a b e n , d i e d e m Ty p d e r Grundmenge entsprechen. Beispiele zu obigen Vereinbarungen:
(.rot..blau, (.'A'..'Z', (.rot, (.CHR blau, (65) .. braun.) 'a'..'z'.) gelb.) CHR oder oder (70).) oder (.' (.0. oder (.0..5.) 1','2','3'.) .1,2,3. (.i-1 .. .5.) i+1.) oder oder oder oder

(. PRED (gruen), SUCC (blau)..braun .)

S c h o n b e i m O b s t h a e n d l e r s a h e n w i r d a s Vo r h a n d e n s e i n v o n Operationen mit Mengen. Desgleichen sind sie in der Mathematik zu finden. Da deren Schreibweisen jedoch nicht so einfach mit e i n e r n o r m a l e n Ta s t a t u r z u e r r e i c h e n s i n d , g e l t e n d i e s e Kon ven t i on en: Bedeutung: Menge Ve r e i n i g u n g Durchschnitt Di f ferenz Tei1menge Obermenge Element von leere Menge Gleichheit Ungleichheit math. Schreibweise: in PASCAL so: ( . . . . ) + *

£
U
f\ \

]

c.
^

£

IN
(. .

P

oder {}
=
j.

r
116

D i e O p e r a t o r e n + , - * u n d d i e Ve r g l e i h s o p e r a t o r e n b e k o m m e n einfach eine neue Bedeutung, wenn sie auf Mengen angewandt w e r d e n . A d d i e r e n u s w. k o e n n t i h r Z a h l e n w e i t e r h i n d a m i t , k e i n e Sorge. Neu ist nur IN. Damit kann man schnell pruefen, ob ein Wert in einer Menge enthalten ist: Statt
IF (ch = 'A') OR (ch (ch - 'O OR (ch (ch - '+') THEN ... 'B') OR 'X') OR

schreibt man einfach:
IF ch IN (.'+', 'A' ..'C, 'X' .) THEN ...

andere Moeglichkeiten: WHILE ch IN darstellbar DO...
REPEAT
mm*

IF gruen IN farbenmenge THEN ... WHILE CHR ( i ) IN darstellbar + (.'Q'.) DO ...

UNTIL ORD ( ch ) IN (.1..26.)

IF i+l IN x*y THEN...

Mensch, wenn nun aber nicht alle den vollen Plan von der Arbeit mit Mengen haben? Die wissen dann ja gar nicht so recht, was die ganzen famosen Operatoren so tun! Da m u s s A b h i l f e h e r. K u r z e E r l a e u t e r u n g e n m i t k i n d g e r e c h t e n B i l d e r n zu den einzelnen Operationen:
Hmmrn, einen Moment,

V A R a, b, c : SET OF 1..5;

Vorher

nachker:
b:

Ci:

a b

1, 2, 3 .); 4, 5 .);

O

0

q;

©

^

c :- a + b;

b :
c * (. 2, 4, 6, 1 .);

a - (. 2 .);

117

b :
b := (. .);
M A

o
Es stimmen nicht O.U.C Elwenle. uDsrein Jet2-t stiwwen al(£ Elemente überein, deshalb Liefert offlLSF

a = c l i e f e r t FA L S E

6)
" ©

a < > ( . 1 , 3 . ) l i e f e r t FA L S E

eist einefe'ilfYiertciel
c <= (. 1..4,5,6,7,8 .) liefert TRUE

c >= a

liefert TRUE

C ist eine Obermwe

M i t d e m n e u e n Ty p e r g i b t s i c h j e t z t a u c h e i n e A e n d e r u n g d e s B e g r i ff e s a u s d r u c k . H i e r d i e n e u e Ve r s i o n v o n FA K TO R d a f u e r :
faktor:
4 4 4 4 4 1 * •

Vergleichsoperator:

J Qenge j V V VN, V
t

V
i

V
l

V
i

j variable ! ♦
4
4 4 4 1 + 4

."V/V'TV'
r ■ i i ii i i ii

4

J
j j

i

i

*-■ -i vorzeichenlose Konstante !—*

i._>__i_>_i-_>-i_>.i._>_i_>_^__>

—i ( ^ ! ausdruck !
— t +

0>-r
-> +

■■— (HOT,—->—i faktor +!4

Seid ihr schon darauf gekommen, dass man nun auch ganze Felder von Mengen vereinbaren kann? Etwa in der Weise:
TYPE tmenge - SET OF 1..200; t f e l d = A R R AY ( A . . 1 0 . ) O F t m e n g e ; V AR feldl, feld2 : tfeld;

X1ö

Ueberprueft daraufhin nochmal, ob ihr von selbst die Idee g e h a b t h a e t t e t . We n n n i c h t , d a n n v e r b e s s e r t e u e r Ve r s t a e n d n i s d e r Struktogramme! Ihr glaubt doch nicht, wir wollen solche Selbstverstaendlichkeiten immer wieder auffuehren. D.h. in Zukunft l e g e n w i r e t w a s m e h r S t r a ff h e i t a n d e n Ta g . O d e r d o c h n i c h t . . . ? Wie sieht's aus, Interesse an einem kleinen Programm? Ok, auf geht's Buam:

119

PROGRAM mengen; (#++++++++++++++++++++++++++++++++++++^ Das Programm verdeutlicht die neu eingefuehrten Mengenoperationen. Dazu koennen 2 Mengen vom Benutzer mit Zeichen aus CHAR gefuel It werden. Anschliessend ist die Anwendung der Mengenoperatoren auf diese Mengen durchfuehrbar.

CONST

tk = 'Die Verknuepfung der Mengen 1 u. 2 mit ';
TYPE

tmenge - SET OF ' '..'z'; V A R menge i
ch, tch BEGIN

ARRAY (.1..3.) OF tmenge;
1..3; CHAR;

(# +++++++++++++++++++++++++ INITIALISIERUNGEN +++++++++++++++++++++++++++ #) menge (. 1 .) :- (. .); menge (. 2 .) :- (. .); menge (. 3 .) :- (. .); (# +++++++++++++++++++++++++ Menueschleife REPEAT WRITELN; WRITELN WRITELN WRITELN WRITELN WRITELN WRITELN WRITELN WRITELN WRITELN WRITELN WRITELN WRITELN ( WRITELN ( WRITE ( WRITELN; WRITELN;

+++++++++++++++++++++++++++ #)

'Es koennen zwei Mengen 1 u. 2 verknuepft werden, Zur' )\ 'Verfuegung stehen folgende Funktionen:'); ' 1 u. 2 : Eingabe der Mengeninhalte' ); > « Durchschnitt von 1 u. 2 bilden' ) } ' + Vereinigung' ); Differenz' ); statt <= : Test, ob 1 Teilmenge von 2' ); statt >- : Test, ob 1 Obermenge von 2' ); Test, ob 1 u. 2 gleich' ); Test, ob 1 u. 2 ungleich' ); Pruefen, ob ein eingegebenes Zeichen i n 1 ' ) ; Ende des Programms' );
>}

);

REPEAT READ ( KBD, ch ); U N T I L c h I N ( . ' 1 ' , ' 2 ' , ' *■' , ' + * , ' - ' , ' < ' , ' > ' , ' = ' , ' ? ' , ' I', ' i', 'E', 'e' .); CLRSCR;

120

(# ++++++++++++++ Interpretation des gewuenschte» Zeichen ++++++++++++++++ a) CASE ch OF (# ++++•/■+++++++++++++++ Mengeninhalt einlesen ■/■+++++++++++++++++■/■+■/■+++++++ a) ' 1' '2' : BEGIN WRITELN ( 'Bitte die Zeichen, welche in der Menge ', ch, ' enhalten sein sollen, hinter ">" ein-' ); WRITELN ( 'geben. Beendigung durch ein Zeichen, welches', ' nicht in " ".."z" enthalten ist.' ); WRITE ( '>' ); i := ORD ( ch ) - ORD ( '0' ); menge (. i .) :- (..);
READ ( KBD, tch );

WHILE tch IN (.' '..'z'.) DO BEGIN WRITE ( tch ); menge (. i .) := menge (. i .) + (.tch.); READ ( KBD, tch ); END; END; (* ++++++++++++++++++++ Verknuepfungen von Mengen +++++++++++++++++++++++ *) '#' : menge (. 3 .) := menge (. 1 .) * menge (. 2 .); '+' : menge (. 3 .) s- menge (. 1 .) + menge (. 2 .); '-' : menge (. 3 .) := menge (. 1 .) - menge (. 2 .); (# ++++■/•+++++++++++++ Vergleichs- u. Testoperationen ++++++++++++++++++++ n) '<' : WRITELN ( tk, '<= ergibt: ', menge (. 1 .) <f- menge (. 2 .) ); '>' : WRITELN ( tk, '>= ergibt; ', menge (. 1 .) >= menge (. 2 .) ); '=' : WRITELN ( tk, '= ergibt: ', menge (. 1 .) - menge (. 2 .) ); '?' : WRITELN ( tk, '<> ergibt: ', menge (. 1 .) <> menge (. 2 .) ); 'V : BEGIN WRITE ( 'Zu testendes Zeichen eingeben: ' ); READ ( KBD, tch ); WRITE ( tch )'; WRITELN; WRITELN ( 'Test, ob das Zeichen in Menge 1 ist ergibt: ', tch IN menge (. 1 .) ); END; END; (# von CASE *)

121

(a +++++++•/■++++■/■+++ Ausgabe der Mengen nach Verknuepfung +++++++++++++++++ #)
I F c h I N ( . ' # ' , ■' + ' , ' - ' . ) THEN BEGIN WRITELN ( 'Operation ist: ', ch ); FOR i := 1 TO 3 DO BEGIN WRITELN; IF i < 3 THEN WRITE ( 'MENGE; ', i, ': ' ) ELSE WRITE ( 'ERGEBNIS: ' ); FOR tch sT O DO IF tch IN menge (. i .) THEN WRITE ( tch ); END; (» von FOR *) END; (* von IF #) UNTIL ch IN (.'E', 'e'.); END.

Das waren ueber 140 Zeilen an Prograrnrntext Wer da den Ueberblick behalten hat, der kann schon 'was. Hoffentlich hat es zur Bereicherung eures Verstaendnises der Mengen und ihrer N u t z u n g i n PA S C A L b e i g e t r a g e n . Bevor ihr jedoch wild anfangt, herurnzuMENGEN, noch ein kleiner Weh r mut st r op f en, Sets koennen nicht mehr als 2SS Elemente e n t h a l t e n ! D i e Ve i n b a r u n g
V AR m : SET OF 1..1000;

waere folglich unerlaubt! Gueltig dagegen ist V AR n : SET OF CHAR; , da CHAR nur 256 Zeichen (Elemente) umfasst. In ein paar stillen Stunden koennt ihr euch auch noch einmal d e n K o p f d a r u e b e r z e r b r e c h e n ( a b e r n u r, w e n n i h r bis hierher unaufmerksam gelesen haben solltet), warum man keine reellen Zahlen als Grundmenge eines Sets nehmen darf und aus welchem G r u n d e d i e s e Ve r e i n b a r u n g u n e r l a u b t i s t : V A R warum SET OF INTEGER; f# na, wer weiss die Loesung? *)

12:

3.17.

What Kind 'a Records d'Ya have?

Bleiben wir ruhig im Augenblick 'mal bei der Frage nach heissen Scheiben. Sicherlich ist es so manchens Traum, ein tolles Programm zu schreiben, mit dem man seine Plattensammlung verwalten kann. Da werden dann Interpret, Info, ob LP oder S i n g l e , Ti t e l d e r F ' l a t t e u s w. e i n g e g e b e n u n d d e r R e c h n e r verwaltet die Daten schoen. Die Gretchenfrage ist, welcher Art die Datenstruktur sein soll, d i e a l l d i e w i c h t i g e n I n f o r m a t i o n e n a u f n e h m e n s o l l . E i n Vo r schlag, der machbar ist, sieht so aus:
CONST

maximale plattenzahl - 100; (# fuer Anfaenger im Sammeln *)
TYPE

tbereich

1..maximaleplattenzahl;

tinterpret - STRING (.20.); t p l a t t e n t y p = B O O L E A N ; ( # T R U E = L P ; FA L S E = S i n g l e * ) ttitel STRING (.30.); VAR

interpret plattentyp titel

A R R AY ( . t b e r e i c h . ) O F t i n t e r p r e t ; A R R AY ( . t b e r e i c h . ) O F t p l a t t e n t y p ; A R R AY ( . t b e r e i c h . ) O F t t i t e l ;

Ist doch gar nicht so schlecht, oder? Will man dann z.B. alle Inf or mat i on en ueber d i e 4 7 » F ' l a t t e h a b e n , s o g e h t d a s i n d i e s e r We i s e ; WRITELN ( 'Interpret : ', interpret (.47.) ); WRITE ( 'Plattentyp: ' ); IF plattentyp (.47.)
THEN WRITELN ( 'LP' ) ELSE WRITELN ( 'Single' ); WRITELN ( 'Titel

', titel (.47.) );

"'tschuldigung, ich habe mir so ein F'rogramm in PASCAL nach dem o b i g e n M u s t e r g e s c h r i e b e n . G a n z t o l l . M e i n t i h r, i c h k a n n d a s a n irgendeinen verkaufen? Ich wuerde gerne ein paar Groschen dazuverdienen." Nun, wer ei n Programm verkaufen moechte, der muss davon erstrnal ein Listing machen. Arn besten, Du laesst Dir das F'rogramm auf einem schoenen Drukker ausgeben. Si eher lieh ist es ein sehr, sehr langes F'rogramm. In dem Fal1 s o l l t e s t D u n i c h t v e r s a e u m e n , d a s b e d r u c k t e P a p i e r direkt vom Dr L i e k e r a u s i n e i n e n d a v o r g e s t e l l t e n P a p i e r k o r b f a l l e n zu lassen. Denn dieser ist der einzig richtige Ort fuer so ein Programm. Natuer1 ich ist ein PASCAL—Programm zur F'lattenverwaltung nach obigem Muster totaler Schwachsinn. Mann, wozu denn dann PASCAL, wenn nach der Holzhackermethode programmiert wird?

1 2 C

Aber nun gut, eigentlich konntet ihr ja noch nicht wissen, in welcher Weise der Profi das Problem loest. Kennzeichnend ist, dass unter einer Bezeichnung, z.B. "F'latte", alle zugehoerigen Daten der heissen Scheibe zu finden sein sollen. Genauso, wie man im Personalausweis alle Infos ueber eine Person findet. D a s g u t e a n PA S C A L i s t . . . ? N a , e b e n d a s , d a s s m a n s o e t w a s d o r t machen kann: alles unter einem Begriff zusammenzufassen. I n e i n e m F e l d ( A R R AY ) k o e n n e n w i r v i . e l . e Va r i a b l e n G L E I C H E N Ty p s unter einem Namen vereinigen. I n e i n e m Ve r b u n d , s o h e i s s t d e r n e u e Ty p , k o e n n e n w i r \ f a r i a b l e n U N T E R S C H I E D L I C H E N Ty p s z u s a m m e n f a s s e n . A u f E n g l i s c h i s t Ve r b u n d gleich record. FLier eine Platte ergaebe sich daraus folgender Aufbau:
VAR

tplatte

RECORD interpret ; STRING (.20.);

typ
titel END;

; BOOLEAN; (* LP oder Single *) : STRING (.30.);

Unter dem Namen tplatte finden wir dann alle Informationen wieder. Wie, das zeigen wir gleich. Erstmal das passende Syn taxdiagr amm:

record-typ:

—>—(RECORD^—>—i konponentenliste !—>---'eND-->

konponentenliste +->4 ___ 4 4

strukturierter typ:
4 4

kooponentennaae ',---—>--■i : *•-->—! typ i—7—> _ 4 u ^ 4 + V '-* -< i ;J/"
-<-

-7—i array-typ i—7V + * ;
j t 1 4—1 set-typ !--+ ! ! 4 4 + 4 + 4 j j

+—! record-typ !—•i-

Um das in der Praxis bewundern zu koennen, 'mal ein erweiterter Verbund fuer eine F'latte. Huch, Moment, wer hat's eigentlich gemerkt, dass naemlich S c h a l l p l a t t e a u f E n g l i s c h a u c h r e c o r d h e i s s t . . . . W a s , n u r so wenige, dabei haben wir uns echt Muehe gegeben mit der Ueberschrift als Wortspiel

124

Doch hier wieder die rauhe Praxis: TYPE tzeile tsongs tdatum
STRING (.30.);

(# sehr grosszuegig *)

ARRAY (. 1..10 .) OF zeile; (# muss ausreichen *>
RECORD

tag : 1..31; monat : 1..12;
jähr : 1900..2050; END;

tplatte

RECORD

interpret typ titel songs


m

tzeile;
BOOLEAN;

* tzeile;
I

tsongs;

kauf datum, ' tdatum; erseheinungitdatum • preis END;
V AR * REAL;

platten : ARRAY (. 1..100 .) OF tplatte; platte : tplatte;
Die Komponenten, also typ, interpret usw., des Verbundes koennen von beliebigem Typ sein, d.h. auch wieder ein Verbund. Klar, dass die Definition des Record datum seiner Verwendung in tplatte vorausgehen muss! Gegenueber unserer ersten Moeglichkeit -die mit Feldern- ist diese Loesung viel viel uebersichtlicher. alle relevanten Daten unter einer Bezeichnung zusammen. mehreren Sie fasst

Fragt nicht erst nach der Methode, um eine Record-Komponente ansprechen zu koennen. Hier ist sie:

record-koaponente:
4 4 _ 4 4

-->—I record-variable I—>— .J-->—I koaponentennaoe !—>
4 4 4 4

125

Anhand von Beispielen sieht's so aus: platte.preis :- 19.80;

l(lar träqt den Preis ein.
Ut Ja eine HEAL-Variant

WRITELN ( platte.interpret ); -* ■

Schreibt den fVrjmen des Interpreters

platten (. 3 .).preis := 14.45;

platten [3] tst vom Typ tplatte (!) darum dqhintßr erst den Punkt 2ur Komp^entenQuiwa/)/.

platten (. 55 .).songs (. 2 .) := 'Hello Dolly';

platten [/*.?}. kowf datum ist wieder platten (.13 .).kaufdatum.tag ;= 31; platten (. 13 .).kaufdatum.monat := 2;
ein Mzcordl Um eine seiner Kompo nenten auszuwählen rn^ß wieder "," Uoromert\

usw. usw.. Verbünde wie auch Felder kann man beliebig schachteln. Es ist jedoch immer strengstens darauf zu achten, w e l c h e n Ty p m a n b e i m A n s p r e c h e n e i n e r K o m p o n e n t e h a t :

platten (.31.) platten (.31.).preis platten (.31.).songs platten (.31.).songs (.1.) platten (.31.).kaufdatum

ist vom Typ tplatte ist vom Typ REAL ist vom Typ tsongs ist vorn Typ tzeile ist vom Typ tdatum

platten (.31.).kaufdatum.jähr ist vom Typ 1910..2050
E i n g r o s s e s P l u s d e r F e l d e r u n d Ve r b ü n d e i s t e s , d a s s m a n m i t ihnen auch Gesamtzuweisungen taetigen kann:

statt platten (.1.).pre is :- platte.preis; platten (A.).typ :- platte.typ;
solange, bis alle Komponenten von platte nach platten (.1.) uebertragen sind, kann man schreiben:

platten (.1.) :- platte;
und schon ist alles geritzt.

126

D a s g e l i e b t e K i s t e n d i a g r a m m f u e r d i e R e c o r d - Va r i a b l e :
TYPE

ttest = RECORD
a, b : REAL; c : INTEGER; d : BOOLEAN; END;

lest.cl test, a

VAR

test : ttest;

testfeld : ARRAY (.1..4.) OF ttest; testfeldt teslfetdC3]x

testfeld [4Lo|

Seid nicht enttaeuscht, aber in diesem Kapitel verzichten wir einmal auf Prograrnmauszuege. Die Verwendung von Records wurde ob en ja r ec h t aus f ueh r lieh er 1 aeut er t.. Zudem sind in vielen, j e t z t n o c h f o l g e n d e n L i s t i n g s Ve r b ü n d e i n r e g e m G e b r a u c h , s o dass, wer will, dort nachschauen kann. Bevor ihr zum naechsten Kapitel uebergeht, solltet ihr viel leicht, um das bisher Gelernte zu festigen, noch ein oder zwei Prograemmchen schnitzen. Kann nicht schaden. H a l t , w a s h o e r e n w i r. . . I h r h a b t k e i n e P r o b l e m e ? K a n n n i c h t sein, und wenn doch, dann fragt eure Bekannten. Irgendwer wird schon ein Problem haben (vielleicht mit der Beziehungskiste oder so), dass ihr hervorragend loesen koennt - so als Fingeruebung gewisserrnassen. . .

127

18. Von oben nach unten in F'ASCAL Als geplagter Schueler oder einfach tiiiierisch gestresster Erdenbuerger (und das gehoert heute ja zum guten Ton) moechte man meist alles in kleinen leichtverdaulichen Haeppchen serviert be kommen . Aber z umi ndest n i c ht zuvi el e In for mat i onen mi t ei nern Mal -wohlmoeglich muesste man sich dann uebermaessig anstrengen, um alles zu verstehen-. In diesem Sinne haben wir schon in einem der ersten Kapitel die Methode der strukturierten Programmierung eingefuehrt. Ihr erinnert euch noch? Grosse Probleme in kleinere Probleme zerlegen, solange, bis man die Kleinstprobleme alle rnuehelos loesen konnte, wenn moeglich gleich in PASCAL. Danach dann alle diese Kl einstloesungen zusammenpacken und... und schon hat man ein Programm, welches unser Anfangs-Grossproblem loest. D i e s e s Vo r g e h e n , v o n g a n z g r o b z u g a n z f e i n , v o n o b e n n a c h unten, von schwierig zu leicht, nennt man TOP-DOWN-Entwur f oder TOP-DOWN-Programmierung. Unbedingt merken!! Das Zusammensetzen der Kleinstloesungen, die nun alle schon in einer Programmiersprache geschrieben sind, zu einem Gesamtprogramrn, das nennt man BQTTQM-UP-Proqrammierung. Der Entwurf fuehrte uns aus den Hoehen (TOP) der Kompliziertheit hinab (DOWN) zur totalen Einfachheit. Das Zusammensetzen danach leitet uns dann von dort unten (BOTTOM) wieder nach oben (UP). Und schon fertig. So einfach ist's. Schade war es bisher lediglich, dass uns F'ASCAL relativ wenig unterstuetsende Mittel dazu in die Hand gab» Ok, Datenstrukturen koennen wir nun so entwerfen (wir erwaehnten das Stichwort der Datenabstraktion). Abstrahieren be deutet dann, dass wir komplexe Strukturen sozusagen hinter einem einfachen Namen verstecken, wir abstrahieren vom konkreten Auf bau. Denkt dabei an den Verbund tplatte. Beim Entwurf der Daten struktur fuer ein F'lattenverwaltungsprograrnm gehen wir sinnvol lerweise so vor (TOP-DOWN):

128

platten : tplatten; •ok im rWf-enblick wissen wir mr,
daß o'lc Infos uW Ratten Inder Variablen pUfren au finden Sind-

S!

Ol

d
0

t p l a t t e n - A R R AY ( . l . . n . ) O F t p l a t t e ; Jetzt haben wir uns Schon konkreter überlegt / wie plafien organisiert sein Soll, hm hesken eben als Teß, m dem für Jede Plmte die Infos okgeU<jb sind.

tr

n

tplatte

RECORD interpret typ

kaufdat END;

titel songs preis

STRING (.ilaenge.); Jebt erst deßnieren wir q&nom, ttyPt k.'c d;e Wo.s über &nefwe STRING (.tlaenge.); a„ssehen «Sollen. /?£/}£; datum; In t/eileren •Schritte« ww.ssen wir noch Isonos u. datum konkretisieren,

u s w. u s w. , s o l a n g e , b i s w i r alle Typen und Konstanten usw. auf das genauste bestimmt haben. Hinterher gehen wir d'ran und setzen den ganzen Kladeradatsch in einem PASCAL—Programm zusammen. Mit den Konstantendefinitionen b e g i n n e n d . . . b i s s c h l i e s s l i c h z u r Va r i a b l e p l a t t e n : B O T TO M - U P. R a s t l o s e G e i s t e r, p h a n t a s i e v o l l e G e m u e t e r o d e r k u r z : a l l e L e s e r d i e s e s B u c h e s s t r e b e n j e d o c h n a c h m e h r. D e r G r u n d e r s c h l i e s s t sich auch dem Letzten, wenn man bedenkt, dass der Anweisungsteil eines Programmes meist sehr viel umfangreicher ist a l s d e r Te i l z u r Ve r e i n b a r u n g v o n D a t e n . D . h . i n e r s t e r e m w i r d m e h r n a c h M o e g l i c h k e i t e n z ü r n Ve r b e r g e n v o n I n f o r m a t i o n e n h i n t e r s i m p l e n Namen (information hiding) gerufen. Wenn's denn sein soll, dann fuehren wir eben die dazu noetigen M i t t e l PA S C A L ' S e i n . T j a a a a , d i e g i b t ' s n a e m l i c h .

129

t!> . 18« 1 i

"The ..same .procedure as every year, James!"

Gewiss, es ist komplex das Thema, aber wir werden es schon moeglichst kindgerecht servieren. Eingefuehrt werden soll naemlich das UNTERPRQGRAMM-Konzept in PASCAL. "Wat is'n Untaprojrarn? Lind sagen. . . " Nu, da stelle wa uns rna janz dumm

Genau, wer erkennt ihn nicht, den Lehrer Boemrnel. Leider ist es uns nicht gelungen, ihn fuer eine kurze Abhandlung ueber Unterprogramme zu verpflichten. Ihr rnuesst deshalb unseren vielleicht paedagogisch nicht ganz so guten Stil entschuldigen. UNTERprogramme sind, wie der Name schon vermuten Programme INNERHALB eines grossen Programms Hauptprograrnms). Unterprogramme enthalten Algorithmen e i n e s Te i l - o d . U n t e r p r o b l e r n s d e s g r o s s e n P r o b l e m s , dem Hauptprogramm bearbeitet werden soll. Mal an einem Struktoararnm verdeutlicht: dann koennten wir im Prograrnrntext schreiben:
4

laesst, kleine (des sogn. zur Loesung welches mit

--+

! Unterprob]en 1 ! Unterproblea 2 ! Unterprob]eo 3
4 — +

BEGIN unterprobleml; unterproblem2;
unterproblemS; END.

Eine direkte Uebersetzung also moeglich geworden. Man und schreibt diese hin, wann rithmus, der sich hinter dem beitet haben will.

des Struktogramrns in ein Programm ist gibt den Unterproblernen einfach Namen immer man im Prograrnrntext den Algo Unterprogramrnnamen verbirgt, abgear

D i e Vo r t e i l e . d i e s i c h d a r a u s e r g e b e n : 1. Benoetigt man einen Algorithmus mehrmals, d.h. an verschiedenen Stellen im Programm, so kann man ihn als Unterprogramm vereinbaren. Das Einfuegen seines Namens in den Prograrnrntext genuegt dann. Man muss nicht immer alle seine Befehlsfolgen nochmal und nochmal hinschreiben. 2. Um Programme Liebersichtlicher zu gestalten, lagert man sehr komplexe Programmabschnitte in Unterprogramme aus. Schaut sich dann irgendwer den Prograrnrntext einmal an, so muss er sich nicht staendig mit diesem komplexen Algorithmus herumschlagen, sondern sieht einen ihm alles sagenden Namen (den Unterprogrammnamen). 3 . S o l l t e e i n Te i l e i n e s A l g o r i t h m u s o e f t e r g e b r a u c h t w e r d e n jedoch mit wechselnden Parametern (Eingabegroessen), s vereinbart man zweckmaessigerweise ein Unterprogramm. 4. Unterprogramme Algorithmen. erlauben rekursive (kommt spaeter)

130

5. Bei langen Programmen verlangt das Gebot des strukturierten Programm!erens (siehe auch Punkt 2.) das Auslagern von Prograrnmtei len in Unterprogramme. Schluss vorstellen: jetzt mit lustig, die Prozeduren. genug geredet
wir

duer fen

Die Prozeduren sind der erste Unter programrntyp, den ihr kennenlernen sollt. Mit ihnen kann man so programmieren, wie wir's oben angepriesen haben.
Addieren:
4 4

Eingabe:
4 + 4 4 4 4

Eingabe !
4

I Lies 1. Zahl I I Lies 2. Zahl !

Verarbeitung I
4

Ausgabe !
4

Verarbeitung:
4 4

•Ergebnis := i. Zahlt ! I 2. Zahl !
4 4

Ausgabe:
+ 4 4 4

! Ergebnis ausgeben !

Und das Programm dafuer:
PROGRAM addieren; V A R zahll, zahl2, ergebnis ; REAL; PROCEDURE eingäbe; BEGIN WRITE ( 'Erste Zahl : ' ); READLN ( zahll ); WRITE ( 'Zweite Zahl; ' ); READLN ( zahl2 ); END; PROCEDURE Verarbeitung; BEGIN ergebnis := zahll + zahl2; END; PROCEDURE ausgäbe; BEGIN WRITELN ( 'Ergebnis: ', ergebnis:7:2 ); END; BEGIN f# hier beginnt das Hauptprogramm #) eingäbe; Verarbeitung; ausgäbe; END. 131
•E>n U,

hterprooirctmm

Schaut euch doch jetzt 'mal das Hauptprogramm an. Welche Grazie zeigt sich dort, einfach schoen! Kleine Haeppchen, jeder erkennt sofort die Struktur des Loesungsalgorithmus. Will man's jedoch noch genauer wissen, so schaut man sich das Unterprogramm an. Wer' s nicht wissen rnoechte, der laesst es eben. J a d o c h , i s t u n s a u c h k l a r, d a s s s i c h d i e Ve r e i n b a r u n g v o n Prozeduren bei diesem kleinen Problern eigentlich noch nicht l o h n t , a b e r z u m Vo r f u e h r e n . . . Hier mal das Syntaxdiagramm zur Vereinbarung von Prozeduren:
Prozedurvereinbarung (vorlaeufig):
4 4 4

->—fpROCEDURE^

■>—! prozedurnane !- ->--{?>-->—! block !—>- \ ' ^
4

vereinbarungsteil (hurra, jetzt konplett):

•>-

->-

->-

->-

->-

+—! konstantendefinition '—+ +—! typdefinition !—+ ♦—! Variablenvereinbarung i—+
4 4 4 4 4 4

-<4 4

-<-

---<—i prozedurvereinbarung !—7

.1
a
4

v

4

>

4

1
y
4

*

+

+

—<—I funktionsvereinbarung i—

Deutlich ist die grosse UebereinStimmung mit dem Diagramm fuer Programme zu erkennen. Statt PROGRAM schreibt man jetzt einfach PROCEDURE. Das ist ja auch genau dem entspreched, was wir vorhin meinten, als wir sagten, Unterprogramme seien F'rogramme im kleinen. Merke: hinter dem END des Anweisungsteils einer Prozedur kommt KEIN Punkt, sondern ein Semikolon. al 1 e Unterprograrnrnnamen, Nur der Vollstaendigkeit halber: Va r i a b l e n n a m e n , Ty p n a r n e n u s w. u s w. m u e s s e n v e r s c h i e d e n s e i n ! Helle Koepfe werden schon 1 aengst bemerkt haben, dass mit block im Syntaxdiagramm von prozedurvereinbarung auch die Deklaration v o n Va r i a b l e n , T y p e n u s w . u n d w i e d e r P r o z e d u r e n / F u n k t i o n e n i n n e r halb eines Unterprogramms erlaubt wird. Geeenau! Und schon wieder eine Uebereinstirnmung mit dem Hauptprograrnm. Wozu das nuetzlich sein soll? Seht ihr gleich... Unser neues Problem lautet... mal sehen... ahhh, dort! Lautet a l s o : Ve r t a u s c h e d i e I n h a l t e z w e i e r Va r i a b l e n . Daraus folgt sogleich.

13-;

PROGRAM tauschen;
V AR

variablel, variable2, hilfsvariable : INTEGER; PROCEDURE vertauschen; BEGIN h i l f s v a r i a b l e :■ v a r i a b l e l ; v a r i a b l e l : ■ variable2; v a r i a b l e 2 :■ hilfsvariable;
END;

BEGIN (* Hauptprogramm *) WRITE ( '1. Variable: ' ); READLN ( variablel ); WRITE ( '2. Variable: ' ); READLN ( variable2 ); vertauschen; WRITELN ( '1. Variable - ', variablel:5, ' und ', ' 2 . Va r i a b l e - ' , v a r i a b l e 2 : 5 ) ;
END.

h i l f s v a r i a b l e b e n o e t i g e n w i r, w e i l w i r u n s w a e h r e n d d e s Ve r t a u s c h e n s d e n W e r t v o n v a r i a b l e l m e r k e n m u e s s e n . D e r g i n g e sonst ver1or en. Da gerade ueber hilfsvariable gesprochen wurde, rnoechten wir noch eure geschaetze Aufmerksamkeit auf den Umstand lenken, dass d i e s e Va r i a b l e n u r i n d e r P r o z e d u r b e n u t z t w i r d . S i e i s t a l l e i n fuer den Vertauschungsvorgang wichtig! Warum also vereinbaren wir sie zusammen mit variablel u. variable2 im Hauptprogramrn? Besser waere doch:
VAR

variablel, variable2 : INTEGER; PROCEDURE vertauschen; V A R hilfsvariable : INTEGER; BEGIN hilfsvariable variablel variable2 END; variablel; variable2; hilfsvariable;

BEGIN (* Hauptprogramm #;

1 OO

Na, wie schaut's aus? Einverstanden? Der Effekt ist der g l e i c h e , n u r m a c h e n w i r j e tz t d a v o n Ge b r a u c h , d a s s m a n i n n e r h a l b von Unterprogrammen auch Objekte vereinbaren kann. Tut man das, so nennt man die dort deklarierten Dinge LOKALE OBJEKTE. h i l f s v a r i a b l e i s t j e t z t a l s o e i n e l o k a l e Va r i a b l e . Der Vorteil liegt auf der Hand. Wir muessen uns im HauptProgramm ueberhaupt keine Gedanken mehr machen, WIE die Wer t e d e r Va r i a b l e n v e r t a u s c h t w e r d e n . Vo r h e r w a r d a s n o e t i g , denn e s m u s s t e d i e d a z u n o t w e n d i g e Va r i a b l e h i l f s v a r i a b l e d e k l a r i e r t werden. Nun aber denken wir nicht fuer 5 Pfennig mehr daran, sondern verlassen uns voll auf das zustaendige Unterprogramm. Sollte sich d o r t d a n n b e i d e r P r o b l e m l o e s u n g f u e r " Ve r t a u s c h e n z w e i e r Va r i a b l e n " z e i g e n , d a s s w i r n o c h d i e e i n e o d e r a n d e r e Hilfsvariable benoetigen, na, dann vereinbaren wir sie eben schnell noch lokal im Unterprogramm. Diese Vorgehensweise alles, was fuer das Hauptprogramm nicht von essentieller Bedeutung ist, in einem Unterprogramm lokal zu vereinbaren oder auszudruecken, nennt man "information hiding". Die genauen Informationen ueber einen Algorithmus werden h i n t e r dem Unter progr arnmnamen versteckt. Noch ein schnuckel iger F'rogrammauszug. So s d e r a e h n l i c h , w i e d o r t g e z e i g t , k a n n m a n p r o b l e m f r e i m i t s k a l a r e n Va r i a b l e n umgehen.
PROGRAM waldbestand;
TYPE

tbaumarten = (fichte, tanne, kiefer, buche, eiche, sonstige); tbaeume = ARRAY (.tbaumarten.) OF INTEGER; V AR anzahl ; tbaeume; artenname : STRING (.8.); art : tbaumart; PROCEDURE entschluesseln; (* dieses Unterprogramm soll die Baumart in der Variablen art in einen String umwandeln, damit man die Art auch auf den Bilschirm schreiben kann #) BEGIN CASE art OF fichte tanne kiefer buche eiche sonstige artenname artenname artenname artenname artenname artenname 'Fichte'; ' Ta n n e ' ; 'Kiefer'; 'Buche'; 'Eiche'; 'Sonstige'.

END; dt von CASE if) END; (if von entschluesseln #)

134

BEGIN C*? des Hauptprogrammes #) ... (if hier kann irgendetwas stehen (aber nicht die Punkte /) *) Of ++++++++++ Zahl der Baeume pro Art einlesen +++++++++++ #) FOR art := fichte TO sonstige DO BEGIN WRITE ( 'Zahl der ' ); entschluesseln; (n art in String wandeln if) WRITE ( artenname, 'n eingeben: ' ); READLN ( anzahl (.art.) ); END; ... Of hier kann irgendwas stehen, ist jetzt unwichtig #) (it ++++++++++ Baeume u. ihre Anzahl ausgeben +++++++++++++ #) WRITELN ( 'Baumart: FOR art :~ fichte TO sonstige DO BEGIN entschluesseln; Anzahl:' );

■ . .. hier Steckt die mOX, Strinolonoe arm

WRITE ( artenname, y anzahl (.art.) : 29 - LENGTH ( artenname ) );
END;

Of hier genauso x) END.

Trick. um eine {ormoitierte Ausgabe mit verschieden, Unaen SlWnGS m erhalte*!

Haetten wir unser Waldbestandsprogramm aus einem der vorangehenden Kapitel in der Weise programmiert, dann waere unser "Schluessel" (Zahlen statt Baumartennamen) ueberfluessig gewesen. I h r s e h t j e d o c h e i n , d a s s d i e s e Te c h n i k e r s t d u r c h e i n e P r o z e d u r moeglich ist, denn wer wollte die CASE-Anweisung zum Entschluesseln mindestens 2-mal hinschreiben? Wir jedenfalls nicht.

135

1 1 p ">

Fr_is£h_jg.eschachtelt_iist halb gewonnen ihr schon von den Schlei fen und

Den Begriff kennt Ve r z w e i g u n g s a n w e i s u n g e n .

Wirft man jedoch einen ziemlich scharfen Blick auf die Syntaxdiagramme prograaa und prozedurvereinbarung so stellt man fest, dass in beiden block auftaucht. Somit ist es auch moeglich Bioecke zu schachteln. B i o e c k e a b e r e n t h a l t e n Va r i a b l e n v e r e i n b a r u n g e n u n d d e r g l e i c h e n m e h r. E i n z i e m l i c h g e s c h a c h t e l t e s P r o g r a m m s a e h e d a n n s o a u s :

PROGRAM sehrgeschachtelt; V AR x, y : REAL; k, i : INTEGER; PROCEDURE pi;
*f J

~ v m

INTEGER; b : BOOLEAN;

PROCEDURE pH; V AR k, i : REAL; BEGIN x := x + k;
* 0 m

Slack M

END; (*t ende von pH *)
BEGIN Of von pi it) x := i l 2;
am*

Slock ri

Blockt
^

END; (it von pl *) PROCEDURE p2; VAR y : CHAR; BEGIN
m m m

READLN ( y ); END; Of von p2 #) BEGIN Of des Hauptprogramm #,' x := i / 2; WRITE ( y ); END.

Blockt

106

" J u n g s m a c h t d o c h k e i n e n M i s t ! Wa s s o l l e n d i e s e K i n k e r l i t z c h e n nun schon wieder, hm mm? Als wenn wir nicht schon genug Probleme haetten." Oh, ein ungestuemer Zeitgenosse, dabei wollten wir gerade wieder etwas erklaeren, damit ihr eure Probleme noch eleganter loesen koennt. Na ja, 'scheint eine Einzelstimme gewesen zu sein, dann koennen wir weitermachen... W i r e r i n n e r n u n s a n d e n B e g r i f f " l o k a l e Va r i a b l e " ? G u t , d a s Gegenstueck zu diesem ist ein GLOBALES Objekt (z.B. eine globale Va r i a b l e ) . G l o b a l w e r d e n a l l e D i n g e g e n a n n t , d i e d i r e k t i m B l o c k O vereinbart sind, z.B. pl, p2, x usw. pll nicht, weil pll im Blockl deklariert wurde! BlockO ist immer der zum Hauptprogramm gehoerende Block. Bioecke, die INNERHALB eines Blocks vereinbart sind, heissen UNTERGEORDNET : Blockl, Blockl1 und Block2 sind BlockO untergeordnet. Blockl1 ist aber auch Blockl untergeordnet. So lange und breite Erklaerungen machen wir auch nicht zum S p a s s , d e s h a l b f r a g t s i c h e i n j e d e r, w a s d e r S i n n d i e s e r H i r a c h i e ist. Ve r b u n d e n m i t d e n B i o e c k e n i s t d e r G U E LT I G K E I T 5 B E R E I C H v o n Objekten. Grundsaetzlich gilt erstmal: alle Objekte eines Blockes sind auch in untergeordneten Bioecken gueltig! Nicht in uebergeordneten. F u e r e u c h g i l t z u n a e c h s t : e i n e Va r i a b l e , e i n e n s e l b s t d e fi n i e r ten Typnnamen usw. darf man nur benutzen, wenn er gueltig ist! Leicht erklaeren sich auch die Begriffe "lokal" und "global". Globale Dinge, also die aus BlockO, duerfen eben ueberall ver wandt werden, lokale Dinge nur in ihrem Block oder untergeordne ten. Einige Beispiele: pl,p2 pll b ist ist sind nur nur in in in BlockO Blockl Blockl gueltig. und gueltig. gueltig. Blockl1

Zum Gueltigkeitsbegriff rnoechten wir noch den Ausdruck "Sichtbarkeit" hinzuf Liegen; dazu ist es wichtig sich zu erinnern, dass man alle Dinge (Objekte), die man im Programm benutzen moechte, VOR ihrer ersten Benutzungsstelle definiert!

137

TYPE

tzeit - RECORD zeit : tuhrzeit; datum : tdatum; E N D ;
tdatum = ARRAY (.1..3.) OF INTEGER;

tuhrzeit = RECORD stunden, minuten : INTEGER; END; So nicht! Denn tdatum und tuhrzeit muessen VOR ihrer Benutzung i n t z e i t d e fi n i e r t w e r d e n ! V O R b e d e u t e t i m m e r t e x t u e l l v o r, d . h . im Programmtext naeher zum Prograrnrnanfang hin. Wenn ihr das verinner 1icht habt, dann wird es euch nicht schwerfallen dies zu begreifen: E i n O b j e k t i s t n u r d a n n s i c h t b a r. w e n n e s g u e l t i g i s t U N D v o r der Steile seiner Nutzung vereinbart wurde! Sichtbar heisst, dass man ein Objekt auch benutzen darf! G u e l t i g a l l e i n g e n u e g t n i c h t m e h r. S o i s t p 2 i n B l o c k l 1 N I C H T s i c h t b a r, p l j e d o c h i n B l o c k 2 u n d i n Blockll. Ausserdem sind pl und p2 (nicht aber pll'.l) in BlockO sichtbar! Kurze Pause, damit ihr euch das alles am Bei spiel progr amrn 'mal ansehen koennt (was geht wem textuell voran usw.)... Hallo, alle wieder da? Schoen! Habt ihr gesehen, dass man p2 nicht innerhalb pl aufrufen darf? Hoffentlich! Vielleicht eine kleine Grafik gefaellig'' Stock /l/j

ÜlotkZ

Block/

138

Monumental, gell? Es soll ganz deutlich sein: E i n O b j e k t ( Va r i a b l e , P r o z e d u r , T y p b e z e i c h n e r sichtbar, wenn man sich auf einem hoehergelegenen oder dem Block, in dem es definiert wurde. Kann Variable b oder Blockl! sehen, wenn er auf BlockO u s w. ) i s t n u r Block b e fi n d e t d e n n CPU die ist?

seh rqeschac h fe. (t

Dagegen, wenn wir uns auf Bloc kl1 befinden,

ßlocltf
ä 393i//l : ? » 7Va8 : <'x

Mock von p/J

dann koennen wir alles ueberblicken. Nur zum Ende duerfen wir j e t z t n i c h t s c h a u e n , w e g e n t e x t u e l l e m Vo r a n g e h e n . Solltet ihr das alles jetzt schon begriffen haben, denn normalerweise kommt das erst mit der Zeit und Erfahrung, dann gehoert ihr zu den ganz fitten Burschen. Lob! Andernfalls graernt e u c h n i c h t . E v e n t u e l l v e r s t e h t i h r d a s N a e c h s t e b e s s e r.

139

Es geht um die rnister ioese Ueber einst immun g von Var iabl enn amen. D i e Va r i a b l e y ( : R E A L ) i n B l o c k O u n d d i e Va r i a b l e y t ' j C H A R ) i n Block2 haben gan: o f f e n s i c h t 1 i c h . selbst Erstklaessler erkennen e s . d i e s e l b e n Namen, Darf man das? Bisher galt doch: alle

selbstgewaehlten Namen muessen verschieden sein. Oeehhmmm stimmt? gut aufgepasst. Doch hier, wie auch sonst irn Leben, gilt: Ausnahmen bestaetigen die Regel. Betrachten wir das Phaemomen von einer anderen Seite. Wenn i n e i n e m P r o g r a m m i m B l o c k O z w e i Va r i a b l e n d e k l a r i e r t w e r d e n , so bastelt CPU sich 2 Kaesten, Weiss jeder H a e t t e n d i e beiden K a e s t e n d e n g l e i c h e n N a m e n , s o w u e s s t e k e i n e r, w e l c h e r K a s t e n genommen werden muss, wenn der Name auftaucht beide Variahkn

/im ölelcben Jlock

Q

*—N

falsch! foe/chen Kasten Soll CPU nehmen]

Werden aber Variablen in u n t e r s c h i e d l i c h e n B i o e c k e n v e r e i n b a r t . dann laeuft das anders ab. W i r d z . B . e i n e Va r i a b l e y i n e i n e m B l o c k d e k l a r i e r t , u n d i n e i n e m u n t e r g e o r d n e t e n B l o c k w i r d n o c h m a l e i n e Va r i a b l e y d e k l a r i e r t - s i e k a n n j e d e n b e l i e b i g e n Ty p h a b e n , d a n n w i r d d e r K a s t e n der Variablen des untergeordneten Blocks auf den Kasten der zuvor d e fi n i e r t e n Va r i a b l e n g e s t e l l t :

/L

y

^- Kaste« der oleichmrnaen VfoWoble« ans dem untergeordneten %Lock

CPU schaut immer, wenn so'n Kastenstapel fuer einen Namen da ist, in den obersten Kasten::
leichnamioe, &rlah\tr> aus übergeordnete» 3l»cl(?n.3et2t UnsicIiLtiAr!

t

nier nachschauen, welcher ti&k Qenorrtwien werden Soll; wen* man im unlergeorolwetew Stock ist.

D i e s e Vo r g e h e n s w e i s e i s t n a t u e r l i c h n u r f u e r s i c h t b a r e O b j e k t e so kompliziert. Man kann es sich auch so vorstellen, dass ein Objekt in einem untergeordneten Block ein Objekt in einem uebergeordneten unsichtbar macht, wenn es den selben Namen hat. Dies gilt fuer den untergeordneten Block und alle Bioecke die ihm nun wieder untergeordnet sind. Schweinisch kompliziert hoert es sich an, ist es aber nicht. des Z u r Ve r d e u t l i c h u n g d i e n o c h w e i t e r g e h e n d e B e s p r e c h u n g verschachtelten Programms:

140

R E A D L N ( y ) ; i n B l o c k 2 l i e s t e i n e C H A R - Va r i a b l e ein, naemlich die, welche in Block2 vereinbart wurde. y : REAL wurde dadurch unsichtbar gemacht. x := i / 2; in Blockl benutzt die x a u s B l o c k O u n d d i e I N T E G E R - Va r i a b l e i a u s B l o c k l ! x :i / 2; in BlockO benutzt nur aus BlockO. Alle anderen sind nicht gueltig! REAL-Mariable

die

Va r i a b l e n

i, j : INTEGER; in Blockl macht die Definition von i in BlockO unsichtbar! Wird i in Blockl benutzt, so kann s i c h n u r d e r We r t d e r l o k a l e n Va r i a b l e n i a e n d e r n , i a u s B l o c k O kann nicht angesprochen werden! it k ; REAL; in Blockl 1 macht die Va r i a b l e i a u s B l o c k l U N D d i e Va r i a b l e i a u s B l o c k O u n s i c h t b a r f u e r B l o c k l 1 , ebenso wird k aus BlockO "versteckt". Fuehrt man i in Blockl1 an, s o w i r d i m m e r d i e l o k a l e Va r i a b l e a u s i h m v e r w a n d t . Te s t e t d o c h e i n m a l d a s f o l g e n d e P r o g r a m m a u s : PROGRAM verschachtelter; V AR a : REAL; b : CHAR;

PROCEDURE pl; V AR c : INTEGER; b : BOOLEAN; PROCEDURE pll; V AR a : INTEGER; PROCEDURE pill; V AR a : CHAR; BEGIN a := 'A';

WRITELN WRITELN ( WRITELN ( WRITELN ( END;

( ' ' '

'Hier Wert Wert Wert

ist von von von

pill: a: ', b: ', c: ',

' a b c

); ); ); );

BEGIN Of von pll #) a := 123;
WRITELN WRITELN WRITELN WRITELN END; ( 'Hier ist pll:' ); ( ' Wert von a: ', a ); ( ' Wert von b: ', b ); ( ' Wert von c: ', c );

pill;

BEGIN Of von pl a) c :- 99; b := TRUE; WRITELN ( ' H i e r i s t p l ' >', WRITELN ( i We r t von a : ' , a >', WRITELN ( r We r t von b : ' , b >; WRITELN ( f Wert von c : ' , c >-, END;

pll;

141

PROCEDURE p2; V AR a : BOOLEAN; PROCEDURE p21; V AR b : BOOLEAN; BEGIN b := FALSE; WRITELN ( WRITELN ( ' WRITELN ( ' WRITELN ( ' END;

'Hier Wert Wert Wert

ist von von von

p2I' a: ', b: ', c: ',

); a ); b ); c );

BEGIN (# von p2 *) a := FALSE; WRITELN ( 'Hier ist p2' ); WRITELN ( '■ Wert von a: ', a ); WRITELN ( ' Wert von b: ', b ); WRITELN ( ' Wert von c: ', c ); p21; END;

BEGIN (a des Hauptprogramms it) a :- 12.3; b :- 'B'; pi;
p2; END.

Wir Lieberlassen euch eurem Erstaunen. Lest das Kapitel lieber mehrmals, bevor ihr zürn naechsten u e b e r g e h t . S p r e c h t e u c h m i t M u t t e r o d e r Va t e r a u s , d i e s i c h e r immer ein offenes Ohr haben fuer eure Probleme mit PASCAL. Fuer die Unverdrossenen schl lessen wir jedoch noch ein Kapitel an. . .

142

3.18.3. Rin in's Unterprogramm, 'raus aus'm Unterprogramm Wir bemuehen uns jetzt redlich, alles weniger abstrakt zu halten. Vo r h i n , d a s Ve r t a u s c h u n g s p r o g r a m m , d a s w a r s o s c h o e n u e b e r si cht lieh.. Bleiben wir doch dabei, mit einer Aenderung: wir r n o e c h t e n n i c h t n u r d i e Va r i a b l e n v a r i a b l e l u n d v a r i a b l e 2 v e r t a u s c h e n , s o n d e r n a u c h d i e Va r i a b l e n a u n d b s o w i e z a h l l u n d
zahl 2.

D e r Vo r e i l i g e w u e r d e j e t z t s c h n e l l z u r Ta s t a t u r g r e i f e n u n d c a . drei verschiedene Prozeduren dafuer schreiben. W i e g e s a g t , d e r Vo r e i l i g e . D e r B e d a c h t e l i e s t e r s t h i e r w e i t e r und bereichert sich um einiges nuetzliches Wissen. D e r Vo r z u g d e r U n t e r p r o g r a m m e i s t n a e m l i c h , d a s s s i e n i c h t n u r auf lokale und globale Objekte zugreifen koennen, sondern auch au-f Parameter. Parameter sind euch in vielen Lebenslagen schon begegnet. Ihr wisst z.B., dass folgende Parameter fuer eure Note in einer Ar beit mitverantwortlich sind: eure Motivation, euer Wissen, S c h i e r i g k e i t s g r a d d e r A r b e i t , Vo r u r t e i l e d e s L e h r e r s e u c h gegenueber. I n d e r g l e i c h e n We i s e k o e n n e n P a r a m e t e r d i e A k t i o n e n i n e i n e m Unterprogramm beeinflussen.
PROGRAM tauschen2; V AR variablel, variable2, a, b, zahll, zahl2 : INTEGER; PROCEDURE vertauschen ( VAR x, y : INTEGER ); V AR hilf : INTEGER; BEGIN hilf X't x y; y hilf; END; (# von vertauschen #) BEGIN vertauschen ( variablel, variable2 ); vertauschen ( zahll, zahll );
» m m

vertauschen ( a, b ); vertauschen ( variable2, zahll );
m m M

END.

143

Jeder der Aufrufe von vertauschen bewirkt, dass die Werte der Var i ab 1 en i n den Kl aminer n ver t ausc ht wer den. Zunaechst das passende Syntaxdiagramrn: paraoeterliste:
V * ♦■ t 1 A .)„_—Uy--—>—r~7~! v v 1 ' 1 t paraaetername 1—7—>—(T)—>—I typnaae ! >—() )~
V V
l

<

{ f y.
V

<my- --<~~^>-

^

A

A

+

1

->-

prozedurvereinbarung: ___ + + + + + + ~->~<PROCEDURE>-->•— i prozedurnane !—•>---! paraaeterliste !— >—fjV- >—! block !—>—([">->
4 4 4 4 " 4 4

Die Parameter in der Parameter 1iste heissen "formale P a r a m e t e r " . S i e s i n d p r a k t i s c h l o k a l e Va r i a b l e n d e r P r o z e d u r u n d h a b e n a u c h d e r e n S i c h t b a r k e i t u s w. . x u . y s i n d h i l f g l e i c h g e stellt. So schwer es faellt, aber ohne Mathe kommen wir jetzt nicht aus. Alle kennen die Funkt i on:
f (x) = 2 # x;

x ist der formale Parameter der Funktion. Er beeinflusst das Ergebnis, wenn wir die Funktion benutzen. Sagen wir irgendwo: y - f ( 2 ) oder y - f ( z+2 ) d a n n s i n d 2 b z w. z + 2 d i e a k t u e l l e n P a r a m e t e r. S i e w e r d e n i n d e r Funktion fuer x eingesetzt. Formale Parameter sind die P l a t z h a l t e r f u e r d i e a k t u e l l e n P a r a m e t e r. Dadurch, dass wir in der Parameter 1iste waehlen koennen, ob wir v o r d i e P a r a m e t e r n a m e n VA R s c h r e i b e n w o l l e n o d e r n i c h t , e r g i b t sich noch eine notwendige Unterscheidung, die wir erlaeutern muessen: S c h r e i b e n w i r v o r e i n e n f o r m a l e n P a r a m e t e r k e i n VA R , s o w i r d nur der Wert (!) des aktuellen Parameters an die Prozedur uebergeben, wenn man sie aufruft! Was im Unterprogramm dann mit dem formalen Parameter geschieht, ob ihm ein neuer Wert zugewiesen wird oder sonst was, das alles interessiert den aktuellen (!) Parameter ueberhaupt nicht!!! Man nennt solch einen f o r m a l e n P a r a m e t e r a u c h " c a l l b y v a l u e " — P a r a m e t e r, w e i l n u r d e r Wert uebergeben wird.

144

S c h r e i b e n w i r v o r e i n e n f o r m a l e n P a r a m e t e r a b e r VA R , s o l a e u f t al les anders.. Die kleinste Aenderung des formalen Parameters im Unterprogramm wird SOFORT -ohne langes Fackeln- auch auf den aktuel 1 en (__!_.) uebertr agen ! Es wird naemlich nicht der Wert des aktuellen Parameters an das Unterprogramm uebergeben, sondern e i n e I n f o r m a t i o n , w e l c h e Va r i a b l e ( s i e i s t d e r a k t u e l l e F ' a r a r n . ) den Platz des formalen Parameters im Unterprogramm einnehmen soll. Damit ist es moeglich, alle Aenderungen des formalen Para meters sofort an den aktuellen weiterzugeben. Solche formalen P a r a m e t e r n e n n t m a n a u c h " c a l l b y r e f e r e n c e " - F ' a r a m e t e r.

:al 1—by—value, cal1-by:all~by-value, call-by-reference, reference, cal1-by-value, cal1-by-reference, cal1-by-value, call:all you on the phone, cal1-by-value, call-byby—ref erence, r e f e r e n c e , c a l l - b y. . Stop, genug memoriert.
Offensichtlich war es in unserer Prozedur vertauschen noetig, zwei cal1-by-reference-Parameter zu verwenden. Ist ja auch sonnenklar, denn die Vertauschungsoperation sollte sich auf die aktuellen Parameter <.a, b, zahll, zahl2, variablel u. variable2) auswirken. Nach dem Motto: "Wir bauen uns ein Esszimmer mit Durchreiche", hier eine grafische Verdeutlichung: PROCEDURE ( a, b : INTEGER; VAR c : INTEGER; VAR d : BOOLEAN ); BEGIN END;

durchreichen

E i n VA R i n d e r P a r a m e t e r 1 i s t e g i l t i m m e r n u r f u e r d i e Parameternamen, die unmittelbar hinter ihm bis zum naechsten Typnamen aufgefuehrt werden!
beide CflU-by,, r e f e r e n c e y n i e r q i U VA n n i c h t m e h r } PROCEDURE ( a : INTEGER; VAR b, c : INTEGER; d : INTEGER; VAR e : BOOLEAN; VAR f : REAL ); / Anderzr Typ, «also nieder VAU olo.w.sthreitan

14!

Sicherlich habt ihr schon ein intuitives Verstaendnis erlangt, welches euch sagt, wie ihr nun ein Unterprogramm mit so vielen Parametern aufrufen rnuesst. Nichts desto trotz hier eine formali sierte Beschreibung:

Prozeduranweisung:
4 4 4 4
L

^ v

v

r
^

<_"\»
4 +
>

4

r
1

T
* ^
I

-! prozedurnaae 1—7—>—(0—>---—i aktueller Paraaeter ! >—C) y--—>

aktueller paraaeter:
4
V 4 4

4
A

—>~7—! ausdruck !—71
4

*

+
4

!

+—! variable !--+

Dazu einige kleinere Bemerkungen: 1. Die Zahl der aktuellen Parameter muss bei jedem Aufruf eines Unterprogramms mit dessen Zahl an formalen Parametern ueber ei nst i mmen. vertauschen < a, b, zahll ) geht also nicht. 2. Die Typen der aktuellen Parameter muessen immer auf das G e n a u s t e m i t d e n Ty p e n d e r f o r m a l e n P a r a m e t e r n u e b e r e i n s t i m m e n .
PROCEDURE t ( a : BOOLEAN );

mit dem Aufruf: t ( 12.3 ) geht nicht, weil als a k t u e l l e r P a r a m e t e r e i n A u s d r u c k v o m Ty p B O O L E A N e r w a r t e t w i r d ! 3. Die aktuellen Parameter fuer call-by~reference-Parameter m u e s s e n I M M E R Va r i a b l e n s e i n ! D e n n w o h i n s o l l t e s o n s t e i n g e a e n derter Wert zurueckgegeben werden? Der Aufruf: vertauschen ( a, 123 ) ist also falsch! 4 . D i e a k t u e l l e n P a r a m e t e r f u e r c a l 1 - b y - v a l u e - Va r i a b l e n k o e n n e n Va r i a b l e n o d e r K o n s t a n t e n o d e r A u s d r u e c k e s e i n .
PROCEDURE f ( x : REAL );

mit den Aufrufen: f ( y ); f ( y+3 ); f i s t g u e l t i g , w e n n y v o m Ty p I N T E G E R o d . R E A L i s t .

(

SIN

(

y

)

);

5 . D i e a k t u e l l e n P a r a m e t e r, m u e s s e n i n d e r g l e i c h e n R e i h e n f o l g e aufgefuehrt werden, wie die formalen, denen sie zugeordnet werden sol 1en!

146

" O h o , d i e v e r s u c h e n s a u f d i e h a r t e To u r, a b e r n i c h t m i t m i r. Ich werde jetzt..." Moment, Moment.... bitte noch nicht gehen/aufhoeren. Ist das nicht alles ziemlich einsichtig? "Doch, schon, aber immer nur Gerede; eine Erklaerung jagt die naechste; keine Prograrnmbeispiele, sondern immer nur neue Ausdruecke: information hiding, formell Parameter oder so und dann cal1-by-blablabla." Nur nicht verzweifeln. Ihr arbeitet mit einem Englisch-Lehrbuch ja auch mehrere Jahre und rnuesst nicht alles beim ersten Mal v e r s t e h e n . . D a h a b t i h r e u r e K u m p e l u n d L e h r e r, m i t d e n e n i h r d ' r u e b e r s p r e c h e n k o e n n t . Wa r u m n i c h t a u c h i n PA S C A L ? I s t d o c h auch eine Sprache. Aber gut, erstmal ein Beispiel:

147

PROGRAM stringfunktionen; (#++++++++++++++++++++++++++++++++++++++++^ Mit den Prozeduren in diesem Programm werden die vordefinierten Funk tionen POS, INSERT und DELETE nachgebildet.
¥-++++++++++++++++++++++¥-+++++++++++++++++++++-/-+++^ CONST

maxlaenge - 255;
TYPE

maxstring = STRING (.255.); tstring = STRING (.maxlaenge.); V A R i : INTEGER; s : tstring;

(#++++++++++++++++++++++++++++++++++++++++++++++^ Der String suchstring wird in der Zeichenkette quelle gesucht. Wird er gefunden, so enthaelt index den Index in quelle, ab welchem suchstring dort zu finden ist. Sonst ist index - 0.
+++++++++++++++++++++++++++++++++++++++++^

PROCEDURE position ( suchstring, quelle : maxstring; VAR index : INTEGER ); V A R gefunden ; BOOLEAN; grenze : INTEGER; BEGIN grenze := LENGTH ( quelle ) - LENGTH ( suchstring ) + 1; index := 1; gefunden := FALSE; WHILE (index <= grenze) AND NOT gefunden DO BEGIN gefunden ;~ (suchstring = COPY ( quelle, index, LENGTH ( suchstring ) )); index :- index + 1; END; IF gefunden THEN index :- index - 1 ELSE index := 0; END; Of von position a)

143

Nachbildung der Funktion INSERT. In den String ziel wird der String quelle ab Index index eingefuegt. Sollte durch das Einfuegen eine Zeichenkette entstehen, die laenger als tstring es erlaubt sein sollte, so wird nichts eingefuegt! ++++++++++++++++++++++++++++++++++++++++++++^ PROCEDURE einfuegen ( VAR ziel : tstring; quelle : maxstring; index : INTEGER ); BEGIN IF LENGTH ( ziel ) + LENGTH ( quelle ) O maxlaenge T H E N ziel := CONCAT ( COPY ( ziel, 1, index-1 ), quelle, COPY ( ziel, index, LENGTH ( ziel ) )
>}

END; dt von einfuegen *)

(*++++++++++++++++++++++++++++++++++++++^ Und noch die Routine DELETE nachbilden. Der String der Laenge zeichenzahl wird ab Index index in ziel geloescht. +++++++++++++++++++++++++++++++++++++++^ PROCEDURE loeschen ( VAR ziel : tstring; index, zeichenzahl : INTEGER ); V A R index2 : INTEGER; BEGIN IF index <- LENGTH ( ziel ) THEN BEGIN index2 :- index + zeichenzahl; (# Index des ersten Zeichens, welches nicht mehr ge loescht werden soll #) ziel ;~ CONCAT ( COPY ( ziel, 1, index - 1 ), COPY ( ziel. index2, LENGTH ( ziel ) - index2 + 1 )
>', END;

END; (it von loeschen a)

149

BEGIN (it Hauptprogramm if) (# Beispiele fuer den Aufruf der oben definierten Prozeduren if) s := 'Ihr wuerdet mich erfreuen mit einem Geschenk'; WRITELN ( 'Der String: ', s ); position ( 'ich', s, i ); WRITELN ( '"ich" wurde gefunden bei Index: ', i:3 ); WRITELN;

s := 'Ein FEH fehlerhafter String'; WRITELN ( 'Der String : ', s ); position ( 'FEH', s, i ); loeschen ( s, i, 3 ); WRITELN ( 'Der String jetzt: ', s ); WRITELN;

position ( 'feh', s, i ); einfuegen ( s, 'nicht mehr ', i ); WRITELN ( 'Der String jetzt: ', s ); END.

Wer bisher noch glaubte, vordefinierte Funktionen seien heilig und unendlich kompliziert, der hat hoffentlich seine Meinung jetzt geaendert. Lest viele viele Programme und schaut euch die dort verwandten Parameter in den Unterprogrammen an. Dadurch bekommt ihr schneller eine Ahnung, wie wir das hier Gesagte gemeint haben.

150

3.18.4.

Und _ j etzt noch mehr E i_g en es

In der guten Hoffnung, ihr habt euch schon sehr Prozeduren auseinandergesetzt, rnoechten wir euch Funktionen vorstellen.

mit nun

den die

Die Parallelen zwischen den vordefinierten Routinen INSERT und DELETE zu Prozeduren sahen wir im letzten Beispiel. Wie stehts aber mit P0S7 position stimmte nur annaehernd damit ueberein. Und schon sind wir mittendrinn. POS -wie auch SIN und COS und O R D u s w. - i s t e i n e F U N K T I O N ( k e i n e P R O Z E D U R ) . B e i d e s s i n d U n t e r programrntypen, klar, der Unterschied liegt in ihrem Zweck. Funktionen sollen immer ein Resultat liefern. Meist en s dies dann auch gleich in einen langen Ausdruck eingesetzt. wird

E r l a e u t e r n w i r ' s a n d e r m a t h e m a t i s c h e n F u n k t i o n Ta n g e n s v o n x : S i e e x i s t i e r t i n PA S C A L n o c h n i c h t , a l s o r n u e s s t e n w i r i m m e r, wenn sie irgendwo benoetigt wird, schreiben:
SIN ( x ) / COS ( x )

welches

TA N

(

x

)

entspricht.

I s t d i e s n u r e i n m a l n o e t i g , s o m a c h t d a s n o c h n i c h t s . Ta u c h t d e r Ta n g e n s a b e r 5 b i s 1 2 m a l a u f , s o w i r d d i e S c h r e i b a r b e i t 1aest i g. Wir fassen uns daher ein Herz und definieren eine eigene neue Funktion.

T angens: i \ COS ( x ) = 0 ? ' !
I 1 V V I xi

! JA \ s HEIM !
4

^jl

4

ITAH ( x ) ! wird {unendlich I gross

TAN ( x ) : SIN ( x ) COS ( x )

Dieses Aussehen sollte sie ungefaehr haben. Na schoen, PASCAL ergibt sich das:
FUNCTION tan ( x : REAL ) : REAL; VAR

i n

cosinus : REAL; BEGIN cosinus := COS ( x ); IF cosinus <> 0 THEN tan :- SIN ( x ) / cosinus ELSE tan := 1000000.0; (# unser Wert fuer Unendlich it) END; (it tan #)

151

Hallo, Du, dort in der letzten Reihe! Ja, Du! Selbst Dir ist aufgefallen, wie aehnlich Prozeduren und Funktionen in ihrem Aufbau sind, nicht wahr? " K l a r, s o n n e n k l a r, Gruesse..." Ich, aehmmm, darf ich noch ein paar

Danke. Seht ihr. Zur Verdeutlichung:

funktionsvereinbarung:
-i
4 4

+
4

*
4

1
+

+
4

+
"

i
4

+
4

—>--<TUHCTIOH>->~S funktionsnane !-->--! paraneterliste !-->-<?)•->--', typnaoe i-->--<?v->--: block !~>-Q~>

Dass ihr nun, solltet ihr eine Funktion statt einer Prozedur vereinbaren wollen, FUNCTION statt PROCEDURE schreibt, ist nicht weiter schwer. Die Parameter1iste und Prozeduren zu behandeln. der Block sind genauso, wie bei

Wie aber schon angedeutet liegt der wesentliche Unterschied im anzugebenden Typnarnen (inkl. Doppelpunkt) hinter dem Funktionsname/ der Parameterliste. Dieser Typ(name) legt naemlich fest, Resultat ist, das die Funktion liefert. liefert ein Resultat! von welchem Merke: jede Typ das Funktion

B e i t a n i s t e s v o m T y p R E A L . L o g i s c h , e i n Ta n g e n s w e r t i s t e i n e reelle Zahl. In diesem Sinne rnoechten wir euch zeigen, wie einige vordefinierte Funktionen dann aussehen: FUNCTION SIN ( x : REAL ) : REAL;

FUNCTION ORD ( ch : CHAR ) : 0..255;

FUNCTION CHR ( Ordnungszahl : INTEGER ) : CHAR;

FUNCTION TRUNC ( x : REAL ) : INTEGER;

FUNCTION POS ( suchstring, quelle : tstring ) : INTEGER;

FUNCTION ODD ( ganzezahl ; INTEGER ) ; BOOLEAN;

152

Das sollte genuegen. Aus den Parametern der Funktion wird jeweils genau EIN Resultat geschnitzt. Der Funkt ionstyp (, der hinter der Parameterliste) muss ein skalarer oder Unterbereichstyp sein! REAL geht aber auch. Verbünde, Felder oder so'was geht demnach nicht!

Jenau. Bis eine Funktion ihre Arbeit beendet hat, muss mindes tens einmal in ihrem Anweisungsteil ihrem Funktionsnamen ein Wert, der vom Funktionstyp ist, zugewiesen worden sein! Siehe dazu auch die Zuweisungen: tan := ... in der /F-Anweisung unserer Tangensfunkt ion!. Diese Zuweisung ist noetig, damit die Funktion ueberhaupt ein Resultat an ihrem Aufrufsort abgibt! Dazu verschiedene Syntaxdiagrarnme:
wertZuweisung:
4 4

s

tatemeht

-7 ! variable ! 7—>—1 := )-—>-

-! ausdruck ■4 4

4

4

V
j

+

*

7

v^

4 4

1 4

5

+--! funktionsname !--+

funktionsaufruf: -<4 4 4 4
4 4

- i j y

4 4

—>—! funktionsnaae I- ->-"—(£>■->■

—1 aktueller paraseter !>

faktor:
4 4

.)-..—} funktionsaufruf I—7v I j j + 4 t +_ 4 4 + 4 v j ; j

+—I variable !—+

4—; vorzeichenlose !--+ ! I Konstante ! I
u 4 4 *

:
.

+
4

+
1

1
!

*-\^—\ ausdruck I—\Jy+ ; + + j *—( NOT )--)-! faktor !--+ —' t +

15o

Noch einmal kurz zurueck zu unserer tollen Funktion tan. Wurde sie nun von uns im Programm vereinbart, so koennen wir ueberall an den Stellen, an denen sie sichtbar ist, statt
y :- SIN ( x ) / COS ( x ) oder y :- y # SIN ( x ) / COS ( x ) + SQR (SIN ( x ) / COS ( x ))

schreiben
y := tan ( x ) oder

y := y * tan ( x ) + SQR ( tan < x ) )

Wieviel mehr Uebersichtlichkeit das bringt, ist schon an diesen k l e i n e n A u s d r u e c k e n z u s e h e n . W e l c h e Ve r b e s s e r u n g e n b e i n o c h komplizierteren Ausdruecken, die wir durch Funktionen ersetzen, zu erzielen sind, kann man sich kaum ausmalen. Zur Erinnnerung: Da Funktionen immer Resultate liefern, koennen sie nur in Ausdruecken verwandt werden! Und nun, liebe Kinder gebt fein acht, wir haben euch was mitgebracht: Zwei (in Zahlen: 2) F'rogramme, die euch viel viel Spass bereiten sollen: Zuerst, als hommage an unseren Namensgeber fuer die hier erklaerte Programmiersprache, Herrn Blaise Pascal: Das Pascal'sehe Dreieck Die einzelnen Zahlen des Dreiecks werden durch

frt\_nl_ Jv k!(n-k)!
berechnet,

154

PROGRAM pascal;
CONST

zeilen = 10; V A R zeile, spalte : 0..Zeilen;

FUNCTION binom ( n, k : INTEGER ) : INTEGER;

FUNCTION fakultaet ( x : INTEGER ) : REAL; Of Fakultaet von x (geschrieben: x!) ist: 1 * 2 * ... # (x-1) # x *) V AR i : INTEGER; f : REAL; BEGIN f := 1.0; IF x > 0 THEN FOR i := 1 TO x DO f := f it i; fakultaet := f; END; (a fakultaet if)

BEGIN (a binom #) binom :TRUNC ( fakultaet ( n ) / ( fakultaet ( k ) it fakultaet ( n-k ) ) );

END; (# binom it)

BEGIN dt Hauptprogramm *) FOR zeile :- ö TO zeilen-l DO BEGIN WRITELN; WRITE ( ' ': (zeilen-zeile)a2 ); FOR spalte ;- 0 TO zeile DO WRITE ( binom ( zeile, spalte ) : 4 ); END; END.

155

Und zum Schluss die Aufloesung des Raetselss Wie kann ich eine mat h emat i sc he Funktion auf d em Bildschirm darstellen? Die zu malende Funktion muss jeweils neu in's Programm eingetragen werden!

PROGRAM funktionsgraph; CONST

Zeilen - 22; spalten =80;

(it Zeilen auf Schirm: 1..Zeilen #) dt Spalten : 1..spalten #)

TYPE twerte = ARRAY (.1..spalten.) OF REAL;

V AR

funktionswerte : twerte;

Of hierhinein werden erstmal alle Funktions werte des Intervalls xmin..xmax ge schrieben *)

xmin, xmax : REAL; ch : CHAR;

FUNCTION f ( X : REAL ) : REAL; BEGIN

IF x = 0.0
THEN f := 1000000.0 ELSE f := SIN ( x ) / x;

dt wieder mal unendlich it) (if fuer eine andere Funktion muss diese Zeile jeweils geaendert werden #)

END; f* f *)

156

Alle Werte der Funktion f im Intervall xmin..xmax berechnen

PROCEDURE allewerte ( xmin, xmax : REAL ); V A R
x, dx : REAL; INTEGER;

BEGIN (a ++++++++ Festlegen der Schrittweite bis zu naechsten x-Wert +++++++++++ #) (ü ++++++++ in Abhaengigkeit von der Bildschirmbreite +++++++++++ *) IF (xmax <= 0) OR (xmin >- 0) THEN dx := ( ABS ( xmax ) - ABS ( xmin ) ) / spalten ELSE dx := ( xmax - xmin ) / spalten; (n ++++++++++++ Berechnen aller Funktionswerte im Intervall *++++++++++++ it) GOTOXY ( 1, zeilen+1 ); CLREOL; WRITELN ( 'Einen Moment, ich berechne die Funktionswerte:' );
CLREOL;

x := xmin; FOR i J- / TO spalten DO BEGIN WRITE ('.'); funktionswerte (.i.) := f ( x ); x :■= x + dx; END; END; dt allewerte *) (a naechster x-Wert «>

(* fuer jeden Wert einen Punkt *)

157

Ermittlung des Maximalwertes aller Funktionswerte

FUNCTION maximum : REAL; V AR i : INTEGER;
max : REAL;

BEGIN max := funktionswerte (.1.); (* nehmen wir 'mal so an #) FOR i :- 2 TO spalten DO IF funktionswerte (,i.) > max THEN max := funktionswerte (,i.); maximum := max; END; (a maximum it)

Ermittlung des kleinsten Funktionswertes +++++++++++++++++++++++++++++++++++++++++++++++++++++++++^ FUNCTION minimum : REAL; V AR i ; INTEGER; min : REAL; BEGIN min :- funktionswerte (.1.); FOR i :- 2 TO spalten DO IF funktionswerte (.i.) < min THEN min :- funktionswerte (.i.); minimum :- min; END; (it minimum #)

158

(#++++++++++++++++++++++++++++++++++++++++^ Zeichnen des Graphen der Funktion im Intervall xmin..xmax aufgrund der berechneten Werte

PROCEDURE zeichnen ( xmin, xmax : REAL ); V AR min, max, dy, yh : REAL; x, y : INTEGER; ch : CHAR;

BEGIN allewerte ( xmin, xmax ); min := minimum; max i= maximum;
CLRSCR;

(# erst alle Funktionswerte berechnen it) (it die aeussersten Extrema ermitteln *)

(it +++++++ Die kleinstmoegl iche Auf loesung in y-Richtung ermitteln +++++++ n) IF (max <= 0.0) OR (min >~ 0.0) THEN dy := ( ABS (max) - ABS (min) ) / Zeilen ELSE dy := ( max - min ) / Zeilen; (H ++++++++++•/■+++ jetzt ersteinmal den Graphen zeichnen ++++++++++++++++++ #) FOR x := 1 TO spalten DO BEGIN y ;= TRUNC ( ( max - funktionswerte (. x .) ) / dy );
GOTOXY ( x, y ); WRITE ( '.' ); END;

(it +++++•/■++++++++■*■ Noch erlaeuternde Werte hinzufuegen +++++++++++++++++++ *)
IF (max >= 0) AND (min <= 0) (it d.h. y=0 ist auf Schirm *) THEN yh := 0 ELSE yh :- max -IIa dy; GOTOXY ( 1, TRUNC ( (max - yh) / dy ) ); WRITE ( yh :7:2, ' ->' );

GOTOXY ( 1, zeilen+1 ); WRITELN ( 'Zum Menue? Dann irgendeine Taste druecken: ' ); WRITE ( 'X-Intervall: Xmin:', xmin:7:2, ' Xmax;', xmax:7:2, ' / ', ' Y- I n t e r v. : Y m i n : ' , m i n : 7 : 2 , ' Y m a x : ' , m a x : 7 : 2 ) ; READ ( KBD, ch ); END; Of zeichnen #)

159

BEGIN (* Hauptprogramm #)
CLRSCR; REPEAT

GOTOXY ( 1, zeilen+l ); WRITE ( ■ 'Funktionsgraph; Z(eichnen der Funktion; E(nde: ' );
READ ( KBD, ch ); IF ch IN (.'Z', 'z'.) THEN BEGIN REPEAT GOTOXY ( 1, zeilen-f-1 ); CLREOL; WRITE ( 'Untere Grenze des X-Interval I (Xmin); ' ); READLN ( xmin ); GOTOXY ( 50, zeilen-f-1 ); WRITE ( 'Obere Grenze (Xmax): ' ); READLN ( xmax ); UNTIL xmax > xmin;

zeichnen ( xmin, xmax );
END; UNTIL ch IN (.'e', 'E'.); END.

160

O • X O M W I

Rekursionen nur fuer Schwindelfreie

Damals, Leipzig einundleipzig, jaaa, da haben wir gesagt, dass alle Objekte in dem Block sichtbar sind, in dem sie definiert wurden, und in allen, die untergeordnet sind. E i n e g a n z b e s o n d e r s e i g e n w i 11 i g e A u s w i r k u n g z e i g t d a s , w e n n m a n schreibt:
PROCEDURE pl ( x : INTEGER ); BEGIN

pl ( 100 );
END; (a pl a)

p A ruß sich selbst auf /

Dieses Phaemornen des sich-selbst-auf ruf ens nennt der Fachmann DIREKTE REKURSION. Das ist etwa so, als wuerde man sich im Supermarkt der Firma xxxx auf dem Ueberwachungsrnonitor sehen, der uns zeigt, wie wir uns auf dem Ueberwachungsmonitor sehen, der uns zeigt, wie wir uns auf dem Ueberwachungsmonitor sehen, der uns zeigt, wie.... Schurz beiseite, jetzt ist Schulz. Ihr seht, eine ziemlich schwindelnd machende Sache, die Rekursion.

Schreiben wir aber doch 'mal eine lustige kleine rekursive Prozedur:
PRROGRAM schwindelig;

PROCEDURE rekursiv; BEGIN WRITE ( 'Du da und ' ); rekursiv; END; BEGIN rekursiv; WRITELN ( 'Du da auch.' ); END.

161

D e r s c h l i t z o h r i g e PA S C A L — J u e n g e r h a t n a t u e r l i c h s c h o n h e r a u s , wie die Ausgabe aussieht: Du da und Du da und Du da und Du da und na ja, usw. am Schluss dann:

.... und Du da und Du da auch.

Tippt es doch einfach ein und lasst Ueberraschung wird gewaltig sein. Hihihihihi...

es

laufen.

Die

Ha, reingefallen? 'tschuldigung. Aber erst aus Erfahrung man klug (grins). Jeder hat also gemerkt: So geht's nicht!

wird

Der Haken ist der Urnstand, wir hielten es bisher nicht fuer noetig, durch eine Abbruchbedingung der ewigen (!) Rekursion einen Riegel vorzuschieben. So rief sich die Prozedur auf und auf und auf und auf und ... ohne ein Ende zu finden. Moral von der Geschieht: ohne Abbruch geht es nicht! Also immer eine passende Bedingung einbauen: PROGRAM schonbesser; PROCEDURE rekursiv ( n : INTEGER ); BEGIN WRITE ( 'Du da und ' );

IF n > 0
THEN re kursiv ( n-l ); END; (» rekursiv it) BEGIN rekursiv ( 20 ); WRITELN ( 'Du da auch.' ); END.

I n d i e s e r We i s e g e h t ' s . B e i j e d e m A u f r u f v o n r e k u r s i v w i r d e i n e kleinere Zahl als aktueller Parameter uebergeben. Dadurch ist gewaehrleistet, dass irgendwann irgendwo n gleich 0 ist. Und dann ruft sich die Prozedur nicht mehr auf, sondern es geht zurueck zur allerersten Aufrufstelle (bei uns ins Hauptprogramm). Um uns einen serioesen Anstrich zu geben, fuehren wir jetzt eine ganz professionelle rekursive Prozedur ein. Man findet sie in jedem besseren Fachbuch (also auch hier).

16^:

Die Fakultaet einer Zahl ist rekursiv definiert durch: 1 fuer n—O
n

v n * (n-1)! fuer n>0
Wir hatten die Fakultaet schon einmal in unserem Programm pascal benutzt; jedoch lange nicht so elegant!
FUNCTION fakultaet ( x : REAL ) : REAL; BEGIN

IF x > 0 THEN fakultaet := x * fakultaet ( x - 1 ) ELSE fakultaet ;= l; END; (it fakultaet #) Welche Grazie sich hier doch zeigt, hachchch. Seufz. Zu beachten ist die Abbruchbedingung! Wenn x <= 0 ist, dann wird der Funktionswert auf 1 gesetzt und ein "Ruecksturz" (nicht gerade aus dem Hyperraum, aber...) zur ersten Aufrufstelle e r f o l g t . A u t o m a t i s c h w i r d d a b e i d i e F a k u l t a e t b e r e c h n e t , t o i 111 . Unser Merksatz: Jeder rekursive Algorithmus laesst sich auch iterativ beschreiben! dass man st at t eines rekursiven Au f r u f s Iterativ bedeutet vielleicht eine Schleife verwendet (siehe die alte Loesung fuer die Funktion fakultaet). Rekursive Algorithmen benutzt man, wenn's absolut elegant aussehen soll, wenn's urnbedingt noetig ist oder wenn man sich das Im a g e e i n e s Wi s s e n d e n g e b e n r n o e c h t e . Ein F'roblern, welches hier mit hineinspielt ist, was etwa in folgendem Fal1 getan werden soll:

PROCEDURE pl ( a, b : INTEGER ); BEGIN

p2 ( a, a > b );
»mm

END; (it pl *)
PROCEDURE p2 ( VAR X : INTEGER; c : BOOLEAN ); BEGIN

pl ( 100, 99 );
mm a

END; (* p2 a)

163

Dies nennt man INDIREKTE Rekursion. Indirekt deshalb, weil p2 sich nicht selbst aufruft, sonder dazwischen erst pl schaltet. Nach unseren bisherigen Kenntnissen kann man das so jedoch nicht machen! p2 ist fuer pl nicht sichtbar! Wir erinnern uns? Textuel1 es Vorangehen? Gut behalten. Abhilfe schafft das Symbol FORWARD. Wir koennen damit ein Unterprogramm "vorwaerts" (nach vorne) sichtbar machen. Dazu schreiben wir vor der ersten Stelle, an der das Unterprogramm benoetigt wird, seinen Kopf und dann nur FORWARD:

PROCEDURE p2 ( VAR x : INTEGER; c : BOOLEAN ); FORWARD; <==-> r . . , n ^- hier nvifwn UnterproQyQmmmp{.

und fonwm
PROCEDURE pl ( a, b ; INTEGER ); BEGIN

p2 ( a, a > b );
m m 0

END; (it pl if)

PROCEDURE p2; BEGIN

pl ( 100, 99 );
0 0*

END; Of p2 »)

hier d((nn nur noch pROQEJiORE /TMCTiotJ und der linterprvorarwiname. ■ So we,, natürlich! c%r Unter pfQQrntn™ block!

FORWARD repraesentiert guasi den Block des Unterprogramms, der a b e r e r s t b e i d e r w i r k l i c h e n Ve r e i n b a r u n g s t e h t . Kommt endlich die Stelle, an der das Unterprogramm dann konkret definiert werden soll, so muss man dort nur noch PROCEDURE oder FUNCTION und den Namen schreiben. Der Rest ist ja aus der
FORMARD—Deklaration schon bekannt.

Bei Funktionen ist der Vo r w a e r t s d e k l a r a t i o n a n z u g e b e n !

Funktionstyp

nur

i n

der

Eine Bsonderheit einiger PASCAL-Dialekte ist, dass man dort CPU (besser: Dem Uebersetzungsprogramm) ausdruecklich Bescheid sagen muss, will man ein rekursives Unterprogramm schreiben. In TURBO-PASCAL muss man VOR das Unterprogramm <pcu. sol K£/A/ Slonk zuzeiten
OtüA-it) * und 4 / F •♦o V

schreiben, und hinter das Unterprogramm dann:
(it$A-f-if)

164

Wer's ganz genau wissen rnoechte, der sollte im Handbuch fuer das Uebersetzungsprogramm (auch Compiler genannt) nachlesen.
(*$A-*) FUNCTION fakultaet ( x : REAL ) ; REAL; BEGIN
a m m

END; (it fakultaet a) (#$A+*) i s t i n T U R B O - PA S C A L d i e r i c h t i g e S c h r e i b w e i s e .

165

3.19.

Wir

schaffen

fuer

die

Ewigkeit

Nur noch wenige Seiten bis zum Ende. Hurra! Dann ist's geschafft. Wir haben uns einmal durch PASCAL durchgearbeitet. S t o p ! S t o p ! K e i n e u e b e r t r i e b e n e E u p h o r i e . Vo r d i e s e s Z i e l h a b e n die Goetter noch die Dateien gestellt. Ein Berg, der erstmal bezwungen sein will. Keimte in euch denn niemals der Wunsch, euren muehsam gesammel ten Daten, die mit den tollsten Programmen bearbeitet werden, ein Dasein zu bescheren, welches laenger waehrt, als bis zum Abschal ten des Rechners? Die Programme ueberdauern ja auch, bis ihr zur naechsten Sitzung an den Computer kommt. Ja, so ist's recht! Es muss in euch wuehlen... das unbaendige Ve r l a n g e n n a c h s o l c h e i n e r M o e g l i c h k e i t m a c h t e u c h n e r v o e s . . . E s muss irgendwie gehen, dass die Daten vor der Zerstoerung durch ein Ausschalten geschuetzt werden, man muss sie dauerhaft " r e t t e n " k o e n n e n . A b e r w i e , w i e - , « -■ o

Mittels Dateien, ganz einfach. Man legt eine Datei an. Enttaeuscht? Oh, niemand hat eine Ahnung, was Dateien sind? Na schoen, dann fangen wir ganz vorne an und erklaeren es.

166

3.19.1

Die Buer okr at i e beg innt

D a t e i e n ( e n g l , fi l e ) e n t s p r e c h e n K a r t e i e n i n e i n e m A r c h i v. J e d e Kartei hat einen Namen, jede Kartei hat einen Inhalt, der a u f Kaertchen steht und ganz bestimmte Angaben umfasst (manchmal nur Z a h l e n , m a n c h m a l N a m e n u n d A d r e s s e n u s w. u s w. ) . D a s A r c h i v i s t meist soweit weg, dass eine Zusammenarbeit mit ihm erheblich al< laenger dauert haette man alle wichtigen Sachen auf dem Schreibtisch (d.h. im Speicher von CPU -die Kaestchen und so-)

Ls

Die. Kasten enthalten
jeweils eint K.orlei,

E H E s a g ]

3)er Name steht awf olem Kärtchen

Kommen wir von den Karteien zu den Dateien, dann finden wir diese auf einem "ext er ne-n Sp e i c h er med i um" , z.B. einer "FloppyDisk" oder einer "Platte". Meist sind's diese runden Schlabberscheiben ("Floppies"). Diese Speichermedien werden auch "Massenspeicher" genannt, weil sie eine Unmenge von Daten speichern koennen (auch nach Abschalten des Rechners!). D e r M a s s e n s p e i c h e r i s t d a n n u n s e r A r c h i v, i n d e m w i r u n s e r e Dateien speichern. Dateien bestehen -wie Felder auch- aus einzelnen Komponenten, z . B . l a u t e r Z a h l e n o d e r Ve r b ü n d e o d e r o d e r o d e r. K e i n e G r e n z e n fuer die Phantasie. Wollt ihr nun die Daten in einer Datei lesen oder aendern, so rnuesst ihr zunaechst eine Dateivariable (Filevariable) anlegen, bei Feldern ist's ja ebenso.
file-typ:
4 4

strukturierter typ:
4 4

- - > - -(FILE V- •>—(ÖF>- -)---! typ !--->

+

1-

-->---—j fiie-typ !—-V + + t
j + + ; +—I array-typ I—+
i + 4 >

j

4

4

j

*■—! set-typ !—+ I * + I
j 4 4 4 4 j

♦—i record-typ!—+

1S7

TYPE

tdatei = FILE OF REAL; tperson - RECORD name, vor name alter END;
STRIN (.20.); INTEGER;

tpersonendatei = FILE OF tperson;
VAR

zahlendatei : tdatei; rasterdatei : tpersonendatei; zahlendatei delariert eine Datei, in welcher viele viele REALWe r t e s t e h e n , r a s t e r d a t e i e i n e , d i e e i n e U n m e n g e v o n Ve r b u n d e n vorn Typ tperson beinhaltet. Jeder erkennt auf Anhieb, dass Felder wie auch Dateien aus lauter typgleichen Komponenten bestehen. D e n Vo r t e i l d e r D a t e i e n , e i n e d a u e r h a f t e S p e i c h e r u n g v o n D a t e n zu ermoeglichen, erkaufen wir uns jedoch mit einigen Unannehmlichkeitens 1. Auf die Komponenten einer Datei kann nur S E Q U ENTIELL zugegriffen werden. D.h. man kann ein Element lesen und dann das naechste und dann das naechste usw.5 die Moeglichkeit auf das 1., 2., 7., 1000. und das letzte GLEICHZEITIG oder BELIEBIG (in irgendeiner F:ei hen folge) zuzugreifen, besteht nicht. Als Beispiel kann uns wieder die Kartei dienen. Dort koennen wir immer nur von vorne nach hinten die einzelnen Kaertchen durchblaettern. Rueckwaerts geht's nicht. Wir duerfen auch keine Karte ueberspringen.

d«"es Kärtchen betrachten wir Gerade

2. Wir koennen immer nur den Inhalt einer einzigen Komponente i n d e r D a t e i b e t r a c h t e n , g l e i c h s a m w i e d u r c h e i n F e n s t e r. S o l l das naechste Element inspiziert werden, so muessen wir unser Fenster weiterruecken. Selbstredend verlieren wir dadurch den Blick auf das vorangehende Element.

y
80
-2r w /
"Fensber

filetamponevice

HTS

i f

S O

Zoo

M-

S-

J?

weiteraeruckt ai^das höchste Bereut 168

Genug der Nachteile (sie treten spaeter noch deutlich heraus). Ein Vorteil, der nicht unbeachtet bleiben sollte, ist die potentiell unbegrenzte Groesse von Dateien. Bei Feldern mussten wir uns immer schon bei der Deklaration entscheiden, wieviele Elemente sie umfassen sollen (siehe Index typ). Diese Beschraenkung faellt weg, deklarieren wir ein File. Dort hinein koennen iö, 1000, 5000 oder mehr -je nach Wunsch und Platz auf dem Massenspeicher- Komponenten hineingeschrieben wer den. "Und wie kann man nun mit den Dateien, die so unendbehrlich sind, arbeiten?" K o m m t s o f o r t , d e r H e r r. . .

169

3.19.2.

Wir

lernen

lesen

Wie die Ueberschrift schon andeutet, wollen wir euch zunaechst das Ritual beibringen, welches noetig ist, will man den Inhalt einer Datei lesen. Und wieder ist die Uebereinstimmung mit einem Archiv nicht zu uebersehen: - Erst muessen wir den Namen der Kartei festlegen, welche wir betrachten rnoechten. - Danach oeffnen wir die Kartei (wir ziehen die Schublade heraus) und richten dabei unser Fenster so ein, dass wir die erste Karte in der Kartei betrachten. - Dann koennen wir munter lesen. - Am Schluss machen wir die Schublade wieder dicht, wir schliessen die Kartei. S e h r s i m p e l , s e l b s t B e a m t e v e r s t e h e n e s . K l a r, d a s s i n PA S C A L das Ganze etwas anders aufgeschrieben werden muss: V AR datei : FILE OF REAL; komponente : REAL; Unsere Beispieldefinition, an der wir erstmal alles erlaeutern. D e r Ty p d e s F i l e ( a l s o s e i n e r K o m p o n e n t e n ) i s t R E A L . ASSIGN ( filevariable, filename ) Wir benennen die Datei auf des Massenspeicher, mit der wir arbeiten wollen. Immer wenn wir spaeter im Programm die filevariable (z.B. datei) verwenden, weiss der Rechner, dass wir uns auf die Massenspeicherdatei mit dem Namen filename beziehen. Dort stehen unsere zu lesenden REAL-Werte. filename ist ein String, der einen Dateinamen enthaelt, wie ihr ihn auch angebt, wenn ihr einen Programmtext retten wollt. ASSIGN ist KEINE Standardprozedur. Es gibt sie nur in TURBO PASCAL. Wie's in anderen Dialekten aussieht, dass muss man im Compiler-Handbuch nachschlagen. Beispiel: ASSIGN ( datei, 'ZAHLEN.DAT )

170

RESET ( filevariable ) Die Datei wird geoeffnet. Das Fenster wird auf die erste Komponente gestellt. Vorher muss der filevariablen ein Dateiname zugeordnet worden sein (mit ASSIGN/). jeder sieht: die Kartchen sind Beispiel: RESET ( datei ) f^ qeblatter t o

der Karteikasten wurde aeoj^net
READ ( filevariable, varl, var2, Hurra, wir koennen die Daten aus dem File lesen. Latuernich mit READ. Ganz fest rnuesst ihr euch merken, dass, will man nicht von der Tastatur lesen sondern aus einer Datei, man die filevariable der Datei als erstes in der Klammer auffuehrt. Dahinter koennen dann Variablen stehen, die ALLE von dem Typ sein muessen, den auch die Filekomponenten haben/ Beispiel: READ ( datei, komponente )

Es passiert folgendes: Der Rechner nimmt die Daten der Filekomponente, die er im Augenblick durch sein Fenster sieht, u n d p a c k t s i e i n d i e Va r i a b l e ( h i e r : k o m p o n e n t e ) . D a n n s t e l l t e r geschwind sein Fenster auf das naechste Fileelement.

-100

%5-

Zoo

jetzt READ ( filevariable, varl )

<?~ der y&t der '" Tileltömponenbe wurde im dlit Variable ein-

4QÖ

15

hrt-

oelesen, ...

*?
dc\& TensUr wurde ou£ die nächste fikkomponente k/eiUroerücktj
Merke: READLN nicht bei Dateien benutzten!
EOF ( filevariable ) Eine vordefinierte Funktion, die TRUE od. FALSE liefert. TRUE ergibt sie, wenn das Fenster ueber das letzte Element in der Datei (welche zu filevariable gehoert) hinausgeschoben wurde. EOF bedeutet End Of File. Liefert EOF TRUE, so sollte man tunlichst nicht mehr versuchen, von der Datei zu lesen/ Beispiel: EOF ( datei )

171

ir

Zoo

Das T«nster steht hinter der letzten Tilekomysonenten {derTöo). BOF curdle. jet?t Tftuf Liefern

Diese Funktion ist deshalb wichtig, weil wir ja nie wissen, wieviele Komponenten in der Datei stehen - ein Vor- und Nachteil. Folglich kann man ohne sie nie entscheiden, ob man schon das letzte Element gelesen hat.

CLOSE ( filevariable ) Wir schliessen die Datei wieder. Das ist immer zu tun, wenn man nicht mehr mit ihr arbeiten moechte. Nach CLOSE ist filevariable KEIN Dateiname mehr zugeordnet. Sollte irgendwann wieder der Wunsch bestehen, mit filevariable zu arbeiten, so muss man zuerst wieder ASSIGN und RESET benutzen. CLOSE ist keine StandardPASCAL-Prozedur/ E i n e k l e i n e B e m e r k u n g n o c h : d a s F e n s t e r, w e l c h e s u n s i m m e r nur eine Komponente sehen laesst, kann nur mittels READ und RESET verschoben (ueber die Elemente bewegt) werden. RESET stellt es immer wieder auf die erste. Na schoen. Nach dieser recht ausfuehr1ichen Erlaeuterung ein Bei spi elProgramm: PROGRAM elementezaehlen; V A R datei : FILE OF REAL; komponente ; REAL; elemente : INTEGER; BEGIN elemente := 0;
ASSIGN ( datei, 'ZAHLEN.DAT' ); RESET ( datei ); WHILE NOT EOF ( datei )

dt einen Namen geben if) (it Datei oeffnen #) dt pruefen, ob Datei ende erreicht #)

DO BEGIN READ ( datei, komponente ); <# Komponente lesen n) elemente :- elemente + l; END; CLOSE ( datei ); (* am Schluss Datei wieder schliessen #>

WRITELN ( 'In der Datei "ZAHLEN.DAT" sind ', elemente:5, ' Zahlen (Elemente) enthalten." ); END.

172

Wir haben einfach mal die Existenz einer Datei mit Namen 'ZAHLEN.DAT' angenommen. Ihr findet alle eingefuehrten Prozeduren und Funktionen wieder, in harmonischem Zusammenspiel. Vo r d e m L e s e n e i n e r K o m p o n e n t e a u s d e r D a t e i s o l l t e i m m e r geprueft werden, ob nicht vielleicht schon das End-Of-File erreicht ist. In dem Fall also nicht lesen! Deshalb haben wir oben eine WHILE-Schle-i fe benutzt. Fuer die Laessigen sei erwaehnt, dass, wenn man nur aus einer Datei gelesen hat, nicht urnbedingt CLOSE benutzt werden muss. Aber lieber einmal mehr CLOSEn, als einmal zu wenig.

173

3. 19.

Wir lernen schreiben

Bis eben haben wir noch annehmen muessen, es gaebe eine Datei, wie wir sie uns wuenschen. Das aendert sich jetzt. Wir erzeugen uns das File, das wir haben rnoechten, selbst. Die Unterschiede l e i c h t e i n s e h b a r. :um Lesen aus Dateien sind relativ gering und

M i t R E S E T h a b e n w i r u n s e r F e n s t e r a u f d i e e r s t e Komponente einer bestehenden Datei gestellt. Da wir jetzt aber keine Datei h a b e n , f u n k t i o n i e r t d a s n i c h t , v e r s t e h t j e d e r. Aus diesem Grund benutzen wir vor dem Schreiben REWRITE ( filevariable ) mit REWRITE wird ein neues File auf dem Massenspeicher erzeugt, welches den Namen traegt, den wir vorher der filevariablen mit. ASSIGN zugeordnet haben. Eine evtl. andere Datei diesen Namens wird in dem Fall geloescht// Das Fenster zeigt nach REWRITE auf keine Komponente -ist ja auch noch keine da/-. Genauer: das Fen ster steht am Fileende. In unserem Archiv wuerden wir uns einen nagelneuen Kasten schnitzen, der spaeter die Kaertchen unserer Kartei aufnehmen soll. Auch ein kleines Namensschild wuerde er bekommen. Beispiel: REWRITE ( datei ) ^ //

_?
•°^%>

WRITE ( filevariable, ausdruckl, ausdruckt,... ) Selbstverstaendlichst/ Beim Lesen READ, beim Schreiben WRITE. Wieder muss als erstes in den Klammern die Filevariable angegeben werden, damit der Rechner die Werte von ausdruckl usw. nicht auf den Bildschirm malt, sondern in die Datei. Selbstredend, aus druckl usw. muessen den selben Typ haben wie die Filekomponenten. Es wird eine Komponente im File erzeugt (dort wo das Fenster steht), der Wert der Variablen dort eingetragen und dann das Fenster vorwaerts, hinter das neue Element, ans Fileende verschoben. flier ist r\och kemc Komponente l EOT ist TRuF

AL

174

jetzt

WRITE ( filevariable, varl )

^Z

4

f r

Wert dtr Vdr/aMen in's Tenster schreiben und dieses weiterschieben \

iL

■i O

Das war's. Mehr muss man nicht wissen, um in eine Datei zu schreiben; zumindest, wenn man sie neu erzeugen (krei eren) will. We n n i h r n u n a l l e s N o e t i g e i n s F i l e g e p a c k t h a b t , d a n n r n u e s s t ihr auf alle Faelle CLOSE ausfuehren! Sehr wichtig! Sonst sind keine Daten in der Datei!!!
PROGRAM dateien; V A R datei : FILE OF INTEGER; : INTEGER; dateiname : STRING (.20.); ch : CHAR;

PROCEDURE lesenundzaehlen; V A R elemente : INTEGER; BEGIN elemente ;- 0; CLRSCR; WRITELN ( 'Die Dateikomponenten:' ); ASSIGN ( datei, dateiname ); RESET ( datei ); WHILE NOT EOF ( datei ) DO BEGIN READ ( datei, k ); elemente := elemente + 1;
WRITE ( k:5 ); END;

(a Komponente auf Schirm zeigen *)

WRITELN; WRITELN ( 'Elementzahl in der Datei: ', elemente;5 ); END; (it lesenundzaehlen a)

175

PROCEDURE neuerzeugen; BEGIN ASSIGN ( datei, dateiname ); (it Dateinamen zuordnen a) REWRITE ( datei ); (» Datei neu erzeugen it) R E P E AT (it lesen u. eintragen, bis eine Zahl < 0 eingegeben wird a)

WRITE ( 'Eine Zahl fuer die Datei (<0, dann Ende): ' ); READLN ( k ); IF k >= 0 THEN WRITE ( datei, k ); (it Element in Datei schreiben it)
UNTIL k < 0;

CLOSE ( datei ); END; (* neuerzeugen *)

(n

wichtig

hier

/

*)

BEGIN (a Hauptprogramm a)
REPEAT WRITELN; WRITELN;

WRITE ( 'N(eue Datei erzeugen; L(esen einer Datei; E(nde: ' ); READ ( KBD, ch ); WRITELN; WRITELN; IF ch IN (.'N', 'n', ' V , ' 1'.) THEN BEGIN WRITE ( 'Dateiname: ' ); READLN ( dateiname ); END;
CASE ch OF

'N', 'n' : neuerzeugen; 'L', '1' : lesenundzaehlen;
END; UNTIL ch IN (.'E', 'e'.); END.

In diesem kurzen wie simplen Programm sind alle grundlegenden Te c h n i k e n f u e r d i e D a t e i Ve r a r b e i t u n g e n t h a l t e n . W a s j e t z t n o c h k o m m t, s i n d kl e i n e re Erw e i te ru n g e n o d e r Ve ra l l g e me i n e ru n g e n . Die Funktionsweise des Beispiels muessen wir doch nicht noch erlaeutern, oder? Gut.

176

Und noch'n Trick fuer Respektlose. Wir haben zwar gesagt, dass, wenn man in eine neue Datei schreiben will, nur REWRITE, WRITE und CLOSE verwandt werden duerfen, aber man kann auch mit RESET operieren bevor CLOSE erfolgt. Das ist nicht ganz sauber und sollte vermieden werden, aber es geht. Der Effekt ist, man steht nicht mehr am Fileende (wie nach REWRITE immer), sondern auf der ersten ins neue File eingetragenen Komponente,. "Is' ja heiss. Mensch toll, was man so mit einem Computer m a c h e n k a n n . E c h t . N u r. . . ' n k l e i n e s P r o b l e m , z u d e m m i r n o c h keine elegante Loesung eingefallen ist: Wie kann ich'n meinetwegen die 5. Komponente in einer Datei aendern? Der Rest soll genauso bleiben, wie er is'." Famos, das passt genau ins Konzept. Es waere ja auch grosser Quatsch, koennte man nur lesen oder voellig neue Dateien anlegen. Genauso sinnvoll ist es auch, nur einzelne Elemente zu aendern oder weitere Komponenten an eine bestehende Datei anzufLiegen. Bei einer Kartei funktioniert's ja auch. Wie aber koennen wir ein beliebiges Element veraendern? Denken wir an unser Fenster. Beim Lesen wird ein Fi le-Kornponenteninhalt gelesen und das Fenster auf den naechste gestellt, beim Schreiben wird in's Fenster geschrieben und dann weitergestellt.. D a r a u s e r g i b t s i c h u n s e r e Te c h n i k : Angenommen, wir rnoechten das n-te Element abaendern: - Datei oeffnen mit RESET, also Fenster auf 1. Element. - n-1 Komponenten lesen, einfach nur lesen. Damit verschieben wir unser Fenster auf das n-te Element.. Das, welches wir aendern wollen. - Fenster steht auf n-ter Komponente, jetzt den neuen Wert dafuer ins File eintragen. - Datei sehliessen. So einfach. Das funktioniert, wenn wir nur n-1-Elemente lesen, weil nach dem Lesen der x—ten Komponente das Fenster auf der x+1ten steht. Ve r d e u t l i c h t e u c h d e n Vo r g a n g w i r k l i c h a n h a n d d e s F e n s t e r s . Einsichtig, nicht wahr?

177

Als Prozedur:
V AR

datei : FILE OF telement; name : STRING (.20.); dt Dateiname «>

PROCEDURE aendern ( n ; INTEGER; neuerwert : telement ); (a aendern der n-ten Filekomponente. Der Wert der Variablen neuerwert wird eingetragen. Die Filekomponenten werden von 0 ab gezaehlt/ #)
V AR i : INTEGER;

k : telement; BEGIN ASSIGN ( datei, name ); dt kann wegfallen, wenn es schon mal gemacht wurde #)
RESET ( datei );

i :- 0; WHILE NOT EOF ( datei ) AND (i < n) DO BEGIN READ ( datei, k ); (# nur lesen, bis man das Element vor dem zu Aendernden erreicht hat #) i :~ i -t- 1; END; IF NOT EOF ( datei ) THEN WRITE ( datei, k ) (# Komponente aendern if) ELSE WRITELN ( 'Die Komponente ', n:5, > gibt es nicht." ); CLOSE ( datei ); (it zur Sicherheit a) END; (» aendern *) Das CLOSE am Ende ist nicht unbedingt noetig, wenn man anschliessend mit der Datei weiterarbeiten rnoechte, z.B. noch andere Records (Komponenten) aendern.. Ja, ja, ja. Stimmt. Wir haben euch beschwindelt. Man kann also doch schreiben, wenn auch nur RESET zur Dateioeffnung benutzt w u r d e . . Ve r z e i h t u n s d i e s n o c h e i n m a l .

178

Im obigen Beispiel sind wir nicht umhin gekommen, zu pruefen, ob es die n-te Komponente -welche ja schliesslich geaendert werden sollte- ueberhaupt gibt. Daraus koennen wir jetzt einen Nutzen ziehen, wenn wir naemlich nicht abbrechen, sollten wir das Datei ende vorher erreichen, sondern.... sondern neue -nagelneue- Elemente an die bisherigen anfuegen, d.h. die Datei vergroessern. Damit ist es uns in die Hand gegeben, bestehende Dateien zu erweitern, ohne sofort eine neue anlegen zu muessen (mit
REWRITE).

Unter Uebernähme der obigen Datei definition folgende Prozedur zum anhaengen neuer Komponenten:

ergi bt

sich

PROCEDURE neueselementlesen ( VAR element VAR anfuegen

telement; BOOLEAN );

(* liest den Inhalt eines neuen Elementes von der Tasta tur nach element ein. anfuegen wird FASLE, wenn mit dem Anhaengen neuer Komponenten auf gehaert werden soll #) BEGIN END; (* neueselementlesen *)

PROCEDURE anfuegen; V AR

neu : telement; anfuegen : BOOLEAN;
BEGIN RESET ( datei );

(it ASSIGN wurde schon irgendwo ausgefuehrt *)

WHILE NOT EOF ( datei ) DO READ ( datei, neu ); (* Fenster hinter letztes Element in Datei stellen #) (if +++++ jetzt die neuen Komponenten lesen u. anfuegen -t-f-f-f-t-f- #)
REPEAT

neueselementlesen ( neu, anfuegen ); IF anfuegen THEN WRITE ( datei, neu ); UNTIL NOT anfuegen; CLOSE ( datei ); END; (a anfuegen it) READ u. WRITE interessiert es also recht wenig, ob die Datei mit RESET oder REWRITE geoeffnet wurde. RESET stellt das Fenster eben nur auf das erste Element, REWRITE loescht dagegen alles, was in der Datei steht. 179 ( i t n u r, f a l l s w i r k l i c h Schluss sein soll #)

Wir lernen: REWRITE braucht man nur selten. Ve r i n n e r 1 i c h e n s o l l t e i h r a u c h , d a s s READ ( datei, element ); WRITE ( datei, element ) NICHT auf die gleiche Filekornponente zugreifen. Ueberlegt doch einmal, wie ein Programm zum Kopieren einer Datei in eine andere aussehen muss. Beachtet, es werden jetzt 2 Dateivariablen benoetigt!

ISO

3.19.4.

Der

elektronische

Brief

Heute, im 20. Jahrhundert, ist es schon fast verpoent, Briefe zu schreiben; nicht zuletzt durch das Motto "Ruf doch 'mal an.". Neuen Reiz rnoechten wir der alten Kornrnuni kationsart in diesem Kapitel geben. Eigentlich rnuesste es uns leicht fallen, denn schliesslich sollen Computer ja zu allem moeglichen nuetzlich sein. Ist auch richtig. Jetzt, wo wir die Dateien kennengelernt haben, ist es uns ein leichtes, seitenlange/buchdicke Briefe zu schreiben und zu speichern. Irgendwann lassen wir sie dann 'mal ausdrucken. Briefe bestehen aus Buchstaben, d.h. wir muessten folgende Deklaration taetigen:
V AR brief : FILE OF CHAR;

Da FILE OF CHAR in der Informatik und sonst auch so sehr be liebt ist, hat man dafuer einen eigenen vordefinierten Typ ge schaffen: V A R brief : TEXT; bedeutet genau dasselbe. Stellt's euch so vor:
TYPE TEXT = FILE OF CHAR;

Gut, das ist aber nicht das Wesentliche an diesem Kapitel. Nein, wir rnoechten auf einige Feinheiten hinweisen, wenn man aus Te x t fi 1 e s ( s o h e i s s e n d i e n a e m l i c h ) l i e s t o d e r i n s i e s c h r e i b t . Dabei wird in den meisten Faellen naemlich READLN u. WRITELN verwendet. Also die Routinen, welche wir bei anderen Files nicht anwenden sollten. Zur Einstimmung:

181

PROGRAM einfacherbrief; V AR brief

:

T E X T;

briefzeile : STRING (.100.); name : STRING (.20.); BEGIN WRITE ( WRITELN WRITELN WRITELN WRITELN
WRITELN;

'Name fuer Briefdatei: ' ); READLN ( name ); WRITELN; ( 'Hinter ":" immer eine Briefzeile eingeben (nicht laenger ' ); ( 'als 100 Zeichen)/' ); ( 'Soll der Brief abgeschlossen werden, dann einfach nur "*"' ); ( 'als 1. Zeilenzeichen schreiben und Zeile abschliessen.' );

ASSIGN ( brief, name ); REWRITE ( brief );
REPEAT WRITE ( ':' ); READLN ( briefzeile );

IF briefzeile (.1.) <> '*' THEN WRITELN ( brief, briefzeile ); UNTIL briefzeile(.l.) = '*'; CLOSE ( brief );
END.

Mit diesem Programm behandelt werden, wie teien. Mutige koennen's mit obigem mini-Editor Te x t fi l e s e r z e u g e n u n d lassen.

koennt ihr Dateien erzeugen, die genauso e u r e P r o g r a m m fi l e s . B e i d e s s i n d Te x t d a ja einmal testen und ein kleines Programm (so nennt man Programme, mit denen man bearbeiten kann) schreiben und uebersetzen

H a t ' s g e k l a p p t ? N a s e h t i h r. I s t d o c h s c h o e n . Warum denn nun WRITELN u. nicht WRITE, fragt ihr. Ok:

LJUjjejsj lil&ltl lelLMel lZ|e|t|l|e| * Mt in *****
So koennte z.B. eine Zeile aussehen, die ihr eingegeben habt. Der String hat die Laenge 19. Wenn ihr nun die Zeile in das File uebertragt, dann gibt es 2 Moegli chkeiten:

18;

WRITE ( briefzeile )

iVloirlhi-fclrl I dir ( Unj3> I t ie \& I |i|S|t| )g|i|n|e| |Z|e[i'lt|&| 2>er Text war schon t»^> Tile. Wird immer nur mit WRITE gearbeitet, so werden alle Strings, p l a t s c h , a n e i n a n d e r g e s e t z t . S p a e t e r s i e h t m a n n i c h t m e h r, w o d e r eine aufhoert und der andere anfaengt. Genau wie bei: WRITE ( 'eine zeile' ); WRITE ( 'noch eine zeile' ); WRITE ( 'eine dritte' ); dabei erscheint auf dem Schirm:

eine zeilenoch eine zeileeine dritte
Nicht sehr ueberzeugend. Benutzt man dagegen WRITELN WRITELN ( briefzeile ) ieilenendjeicnfn iVloMhleM loMHi I H^lDli le \s I \l\s\h\ le|i|"lel \2 le I»' \L I dLp | , so wird hinter jede eingetragene Zeile ein bestimmtes Zeichen gesetzt, welches sagt: Halt, hier ist eine Zeile zu Ende. WRITELN ( 'eine zeile' ); WRITELN ( 'noch eine zeile' ); WRITELN ( 'eine dritte' ); ergibt ja auch:

eine zeile noch eine zeile eine dritte
So moegen wir's.

Natuerlich hat READLN auch etwas mit diesen ominoesen Zeilenendzeichen zu tun. READ ( s ) liest immer nur soviele Zeichen aus der Datei, wie in s maximal hineinpassen. Danach laesst READ das Fenster auf dem ersten, nicht mehr gelesenen Buchstaben stehen. READLN ( s ) liest zwar die gleiche Anzahl von Zeichen ir\ s ein, stellt das Fenster aber danach auf den naechsten zu findenden Zeilenanfang!
V AR a, b : STRING (.5.); In der Datei steht folgendes: lFliiniai iZleliUieiftiPl' i£i i?iw|g|i' i^iei^i 193

Nach RESET ( datei ); R EAD ( d a te i , a ); R EAD ( d a te i , b ); wuerde a = 'Eine ' sein und b — 'Zeile'; d.h. jeweils 5 Zeichen lang. READ ( datei, a ) hat das Fenster auf 'Z' stehen l a s s e n . Vo n d o r t h a t d a n n R E A D ( b ) w e i t e r g e l e s e n .

Nach
RESET ( datei ); READLN ( datei, a ); READLN ( datei, b ); wuerde a - 'Eine ' sein, b wuerde aber 'Die z' enthalten! READLN ( datei, a ) haette naemlich das Fenster auf den naechsten Zeilenanfang gestellt! Im Zusammenhang mit dem Zeilenendzeichen gibt es noch eine Standardfunkt ion: EOLN ( filevariable ) filevariable muss den Typ TEXT haben. EOLN kann TRUE od. FALSE liefern. TRUE wird geliefert, wenn das Zeilenende einer Zeile erreicht wurde (oder EOF auch TRUE ist/).

In diesem Sinne wollen wir einmal READLN ( datei ) simulieren: WHILE NOT EOLN ( datei ) DO READ ( datei ); READ ( datei ); Das Fenster steht jetzt auch auf dem ersten Zeichen nach dem Zeilenendzeichen. L i e s t m a n e i n z e l n e B u c h s t a b e n v o n d e r Ta s t a t u r e i n , s o i s t e s auch moeglich zu schreiben: V AR ch : CHAR;

REPEAT READ ( KBD, ch ); WRITE ( ch ); UNTIL EOLN; E s w i r d d a n n s o l a n g e g e l e s e n , b i s d i e Ta s t e " R E T U R N " o d . "ENTER" gedrueckt wurde. EOLN ohne eine Filevariable dahinter, b e z i e h t s i c h a l s o i m m e r a u f d i e Ta s t a t u r a l s E i n g a b e r n e d i u r n . Diese neue Funktion nicht oft benoetigen. ist nicht so sehr wichtig. Ihr werdet sie

A l s A u s k l a n g z u m T h e m a " Te x t d a t e i e n " r n o e c h t e n w i r e i n P r o g r a m m liefern, welches uns einen Brief, Programmtext oder sonst ein Te x t fi l e a u f d e m S c h i r m l i s t e t . D a b e i w i r d i m m e r g e s t o p p t , w e n n einmal der Bildschirm gefuellt wurde. 184

PROGRAM 1iestextfile;
CONST

zazeigendezeilen - 23; (it Zahl der Zeilen, die bis zum naechsten Stop angezeigt werden sollen *)
V AR d a t e i : T E X T;

zeile : STRING (.255.); (it maximal 255 Zeichen pro Zeile, muss reichen #,' nr : INTEGER; zeigenr : BOOLEAN; name ; STRING (.20.);
ch ; CHAR;

BEGIN WRITE ( 'Dateinamen des zu listenden Textfiles angeben: ' ); READLN ( name ); WRITE ( 'Sollen Zeilennummern angezeigt werden (J/N) ; ' ); READ ( KBD, ch ); WRITELN ( ch ); zeigenr := ch IN (.'J', 'j'.); ASSIGN ( datei, name ); RESET ( datei ); nr ;1; ch := 'X'; dt ch auf 'X' setzen, damit in die Schleife gegangen wird #)

WHILE NOT ( EOF ( datei ) OR (ch IN (.'E', 'e'.)) ) DO BEGIN READLN ( datei, zeile ); dt Zeile aus Datei holen it) IF zeigenr
THEN WRITE ( nr:6, ' ' );

WRITELN ( zeile ); dt und auf Schirm zeigen *) IF nr MOD zuzeigendezeilen = 0 (n wenn noetig, dann stoppen #) THEN BEGIN WRITE ( > £(nde des Listens, andere Tasten setzen das Listen fort; ' );
READ ( KBD, ch ); WRITELN; END;

nr

:=

nr

+

1;

dt

naechste

Zeilennummer

u)

END; dt WHILE *) END.

185

3. 19.5.

Ende ohne Schrecken

Hallo, seid gegruesst! Willkommen im letzten Kapitel. Alles frisch? Ausgeschlafen, gute Laune'"' Zum Abschluss noch einige Kleinigkeiten, mit denen ihr bei Freunden Eindruck schinden koennt. Wir koennen uns nur zu gut eure Gesichter vorstellen, wenn ihr eines der tollsten Datei programme habt laufen lassen und mit RESET eine nicht existierende Datei oeffnen wolltet. Schade eigentlich, dass der Rechner sofort abgestuerzt ist.

0 Ö j?

"Ja, aber..." Kein aber. Entweder man weiss, welche Dateien man h a t , o d e r. . . t j a , o d e r m a n m u s s d i e e n t s p r e c h e n d e n S i c h e r u n g e n einbauen. Da man nun nicht von allen Leuten erwarten kann, dass sie profundes Wissen ueber die vorhandenen Files mitbringen, helfen nur idiotensichere Programme. Will man irgendwann einmal Software verkaufen, so muss sie sowieso aeusserst benutzerfreundlich sein! Die Frage der Stunde lautet: Wie verhindere ich solcherlei Maleurs. Die Fehler (engl. error) treten nun auf, waehrend die Prozedur RESET oder CLOSE oder WRITE oder oder ausgefuehrt wird. Da sollte es doch ein Leichtes sein, dem Rechner zu sagen: "Junge, pass mal auf. Wenn jetzt gleich 'n Fehler bei der Einoder Ausgabe auftritt, dann drueckste mal 'n Auge zu. Wer wird denn da in die Luft gehen? Also... alles klar?" (#*!-#) wenn es im Prograrnrntext auftaucht, laesst den Rechner solange ein Auge zudruecken (nur bei Ein-/Ausgabeoperabionen) , bis (#$!+*) geschrieben wird. Die Schreibweise kennen wir ja noch vorn E r w e r b d e r R e k u r s i o n s e r l a u b n i s . K l a r, h i e r a u c h w i e d e r e i n e TURBO-PASCAL-Besonderheit. Zwischen diesen Schaltern (so werden sie genannt, genauer: Compiler Switches) koennt ihr Dateien oeffnen, loeschen, umbenen nen usw. wie es euch gefaellt, ohne dass ein Fehler das Programm abbrechen liesse. Die Fehler werden I/Q-Error genannt, weil sie bei Input— oder Out put-Oper at ionen auftreten; Input == Eingabe, Output = Ausgabe. F'robiert mal folgendes F'rogramm: 186

PROGRAM test; V A R d : FILE OF INTEGER; i : I N T E G E R ; ( a a u c h d i e s e Va r i a b l e . F u e r spaeteren Gebrauch // it) BEGIN
A S S I G N ( d , ' Q U AT S C H ' ) ; RESET ( d );

END.

Ve r g e w i s s e r t e u c h v o r h e r, d a s s K E I N E D a t e - i m i t d e m N a m e n 'QUATSCH' existiert. Dann lasst das Programm laufen. Ok, ein I/O-Error ist aufgetreten. Das war beabsichtigt. Jetzt setzt vor ASSIGN dies ein: (#$!-*)
u n d h i n t e r R E S E T s e t z t i : = I 0 R E S U L T; ( * $ ! + * ) e i n .

Jetzt lasst das Programm nochmal laufen. Na, welch Unterschied! Wenn (*$!-*) benutzt wird, kann man trotzdem pruefen, ob ein Fehler aufgetreten ist -vielleicht, um eine sehr sinnige Fehlermeldung auszugeben und das Programm fortzusetzen.
IORESULT

ist die vordefinierte Funktion, die uns sagt, ob ein Fehler aufgetreten ist (ihr habt sie oben schon in action gesehen). Sie liefert einen Wert UNGLEICH 0, wenn ein I/O-Fehler vorliegt. Wenn nicht, dann 0. D e r Tr i c k i s t , m a n k a n n s i e n u r e i n m a l n a c h j e d e m F e h l e r befragen. Tut man es mehrmals, ohne dazwischen eine andere Einoder Ausgabeoperation auszufuehren, so liefert sie beim 2. usw. Mal nur 0. Wird {$!-} usw. verwandt, so muss vor der naechsten I/O-Operation IORESULT einmal aufgerufen werden, ob ihr's noetig habt oder nicht/

Damit laesst sich also leicht eine Funktion schreiben, mit der wir angstfrei feststellen koennen, ob ein bestimmtes File existiert:

187

TYPE

tstring = STRING (.15.); FUNCTION dateivorhanden ( name : tstring ) : BOOLEAN; V A R datei : FILE OF INTEGER; dt Elementtyp ist egal it) BEGIN (it$I-it) dt Auge zudruecken it)

ASSIGN ( datei, name ); R E S E T ( d a t e i ) ; d t Ve r s u c h e n D a t e i z u o e ff n e n # ) dateivorhanden := IORESULT - 0; (it$I+*) (it Auge wieder aufmachen a)

END; dt dateivorhanden *) Sie liefert TRUE, wenn die Datei vorhanden ist. Bevor wir dann zu dem Abschlussprograrnm kommen, noch zwei nuetzliche vordefinierte Prozeduren. Beide gehoeren nicht (!) zum Standard! Nur in TURBO-PASCAL! ERASE ( filevariable ) loescht das File, dessen Name der Filevariablen mit ASSIGN zu geordnet worden ist. Fuer immer/ Also Vorsicht/ Beispiel: ASSIGN ( datei, 'datei.dat' ); ERASE ( datei ); Loescht die Datei 'datei.dat' auf dem Massenspeicher.

RENAME ( filevariable, neuername ) benennt die Datei, deren Name filevariable zugeordnet wurde um. Der neue Name steht in dem String neuername. Beispiel: ASSIGN ( datei, 'datei.dat' ); RENAME ( datei, 'groove.dat' ); Die Datei, welche den Namen 'datei.dat' hatte, heisst jetzt 'groove.dat'.

In den Faellen, wo ihr einen der beiden zuletzt angesprochenen Befehle benutzt, schliesst bitte vorher die Datei, auf welche er angewandt wird. That's good programming habit. Ihr wollt doch nichts dem Zufall ueberlassen, oder? Immer an Murphy's law denken!
188

Noch einmal tief Luft holen, dann zum letzten F'rogramrnbei spi el. In ihm kommen so ziemlich alle sinnvollen oder sinnlosen D a t e i O p e r a t i o n e n v o r. A u c h d i e g e w i s s e B e n u t z e r f r e u n d l i c h k e i t sollte nicht uebersehen werden! Vi e l S p a s s u n d a l l e s G u t e . . .
PROGRAM dateiverarbeitung; (*+++++++++++++++++++++++++++^ Dieses Programm soll beispielhaft die wichtigsten Operationen eines DateiverarbeitungsProgramms verdeutlichen. Folgende grundlegenden Funktionen sind enthalten: Aendern einer Dateikomponente Loeschen einer Dateikomponente Anfuegen von Komponenten an eine Datei Auflisten der Elemente in einer Datei Kopieren einer Datei Erzeugen einer neuen Datei

Das Sortieren der Dateikomponenten nach einem bestimmten Kriterium (z.B. alphabetisch) wird NICHT gezeigt, da eine Erlaeuterung des Problems 'Sortieren' den Rahmen des Buches sprengte und der Algo rithmus nicht selbsterklaerend genug waere. Es sei auf die im Anhang aufgefuehrte Literatur verwiesen. Die vorzufuehrenden Dateioperationen beziehen sich alle auf ein File, in dem Daten einer Person gespeichert sind; Name, Vorname, Alter sollen uns genuegen. Soll die Datei eine andere Struktur haben (z.B. jede Komponente soll noch Angaben zum Wohnort enthalten o.ae.), so muessen lediglich die strukturabhaengigen Prozeduren des Programms geaendert werden; dies sind die Unterprogramme zum Einlesen einer Komponente und zum Ausge ben einer solchen. Alle anderen Prozeduren sind strukturunabhaengig, weil sie nie den genauen Aufbau eines Dateielementes beruecksichtigen. Eine solche Programmierweise ist sehr aenderungsfreundlich und sollte verinnerlicht werden/

CONST

fehlerzeile - 23; ueberschriftzeile -4; menuezeile = 20; namenslaenge = 20-, dt strukturabhaengig n)

189

TYPE tzeile charmenge tname telement

STRING (.80.); SET OF CHAR;

STRING (.namenslaenge.); (* strukturabhaengig *) RECORD (a strukturabhaengig nane, vorname : tname;
alter : INTEGER; END;

a)

tdatei

= FILE OF telement;

dt und schon beginnt die Strukturunabhaengigkeit *)

V AR

datei dateiname
ch

: tdatei;
: STRING (.20.); : CHAR;

(it++++++++-f-++++-f-++-f-++-f-+++-f-+-t-+-t+++++^

Eine Fehlermeldung auf den Schirm und auf einen Tastendruck warten

PROCEDURE fehler ( meldung : tzeile ); V A R
ch : CHAR;

BEGIN
GOTOXY ( 1, fehl erzeile ); CLREOL;

WRITE ( ' > ', meidung, ' Eine Taste druecken: ' ); READ ( KBD, ch );
GOTOXY ( 1, fehlerzeile ); CLREOL; END; dt fehler *)

190

(#++++++++++-fi+++++++++++++++++-f-+-f-++++^^

Ueberschrift fuer einen Menuepunkt setzen Die Ueberschrift wird zentriert in die Mitte einer Zeile gesetzt/

PROCEDURE ueberschrift ( zeile ; tzeile ); BEGIN
CLRSCR;

GOTOXY ( (80 - LENGTH ( zeile )) DIV 2, uebersehr iftzeile ); WRITE ( zeile ); END; dt ueberschrift if)

(it-f-++++++++-fi+++++++++-f-++++++++++++^

Ein Menue auf den Sehr im bringen und den Wunsch einlesen. Da die Menge der gueltigen Wahlmoeglichkeiten uebergeben wird, werden nur zulaessige Eingaben von der Prozedur zurueckgegeben/
+++++++++++-fi++++++++++++++-f++++-f-+++^

FUNCTION menue ( zeile : tzeile; zulaessig : charmenge ) : CHAR; V A R
ch : CHAR;

FUNCTION grossbuchstabe ( ch : CHAR ) ; CHAR; dt Aus ch wird der entsprechende grosse Buchstabe gemacht. Aus 'a' wird 'A'. Diese Funktion existiert vordefiniert in der selben Weise in TURBO-PASCAL unter dem Namen UPCASE.*) BEGIN IF ch IN (.'a' ..'z> .) THEN ch := CHR ( ORD ( ch ) - 32 ); grossbuchstabe := ch; END; dt grossbuchstabe *) BEGIN df menue it) GOTOXY ( 1, menuezeile ); CLREOL; GOTOXY ( (80 - LENGTH ( zeile) * 1) DIV 2, menuezeile ); WRITE ( CHR ( 7 ), zeile, ': ' ); dt mit Glocke// *)
REPEAT

READ ( KBD, ch ); ch :- grossbuchstabe ( ch ); UNTIL ch IN zulaessig; menue := ch; END; dt menue a)

191

(it++-f+ +++++++++++++++++++++++-J-+++++++^

Auflisten der Attribute einer Filekomponente //// strukturabhaengig //// geraet ist das Textfile, in welches die Auflistung der Filekomponentenelemente geschehen soll. Zur Wahl stehen der Drucker und der Bildschirm/ MERKE: Dateien koennen nur als cal1-by-reference Parameter uebergeben werden/
•f-+++-f-++-f-+++++-h++++-/-+++++++++-f-++++^

PROCEDURE listekomponente ( komponente : telement; VAR geraet : TEXT ); BEGIN WRITELN ( geraet, komponente.vorname, ' ' : namenslaenge - LENGTH ( komponente.vorname ) -f- 5, komponente.name, ' ' : namenslaenge - LENGTH ( komponente.name ) + 10, komponente.alter:2 ); END; dt 1istkomponente #>

(it+++++++++-t++++++++++++++++++++++++^

Auflisten aller Komponente im File mit Nummern /// Ueberschrift beim Listen ist strukturabhaengig ff/

PROCEDURE listen; V A R geraetename : tname;
geraet : T E X T;

k

:

telement;

i, io : INTEGER; ch, ch2 : CHAR;

BEGIN geraetename := 'Bildschirm';
REPEAT

ueberschrift ( 'Listen der Dateikomponenten' ); ch := menue ( CONCAT ( 'Ausgabe auf; ', geraetename, ' / W(echsle geraet; L(iste erstellen; E(nde' ), (.'W', 'L', 'E'.) );

192

CASE ch OF

'W' : IF geraetename - 'Drucker' THEN geraetename := 'Bildschirm' ELSE geraetename := 'Drucker'; 'U : BEGIN

(#

Ausgabegeraet
IF geraetename THEN ASSIGN ( ELSE ASSIGN ( RESET ( geraet ); 'Drucker' geraet, 'LST:' ) geraet, 'CON:' ); io := IORESULT;

oeffnen

»)

dt

Versuchen

die

Datei

zu

oeffnen

*)

(*$!-*) RESET ( datei ); IF IORESULT = 0 THEN BEGIN i := 1; dt Nummer der Dateikomponente a) ch2 := '3'; io := 0; uebersehrift ( 'Die gewuenschte Liste kommt...' ); WRITELN; WRITELN ( geraet ); WRITELN ( geraet ); WRITELN ( geraet, Vorname; Name: Alter;' WRITELN ( geraet );

'

Nr.

);

(* Jetzt die Komponente ausgeben. Nach jeweils 20 stoppen. it) WHILE NOT EOF ( datei ) AND (io ~ 0) AND NOT (ch2 IN (.'£', 'e'.)) DO BEGIN READ ( datei, k ); io := IORESULT; WRITE ( geraet, i:5, ' ' ); 1 iste komponente ( k, geraet ); i :- i -f- 1; IF i MOD 20 = 0 THEN BEGIN WRITE ( ' > E ( n d e d e s L i s t e n s , s o n s t e i n e a n d e r e Ta s t e ; ' ) ; READ ( KBD, ch2 ); END; END; WRITE ( 'Eine Taste druecken: ' ); READ ( KBD, ch2 ); E N D ELSE fehler ( CONCAT ( 'Kann Datei ', dateiname, ' nicht zum Listen oeffnen/' ) ); (#$1+*) END; END; (it CASE *) UNTIL ch IN (.'E', 'e'.); END; dt listen *)

193

(it++++++++++++++++++++++++++++++++++++++++^

Elemente einer Filekomponente einlesen /// strukturabhaengig ///

PROCEDURE einlesen ( VAR k : telement; neu : BOOLEAN ); V AR komponente, alte ; (vorname, name, alter); BEGIN ueberschrift ( 'Aendern eines Filekomponenteninhaltes' ); IF neu
THEN BEGIN

k.name := ''; k.vorname := "; k.alter ;= 0; END;

dt

Auflisten

des

bisherigen

Inhaltes

#)

GOTOXY ( 10, 10 ); WRITE ( 'Vorname; ', k.vorname ); GOTOXY ( 10, 13 ); WRITE ( 'Name : ', k.name );
GOTOXY ( 10, 16 );

WRITE ( 'Alter : ', k.alter:2 );

dt

Jetzt

einlesen

der

neuen

Inhalte

*)

komponente := vorname; alte := komponente;
REPEAT

GOTOXY ( 2, ORD ( alte ) # 3 + 10 ); WRITE ( ' ' ); GOTOXY ( 2, ORD ( komponente ) * 3 + 10 ); WRITE ( '-->' ); ch := menue ( 'S - eine Komponente nach oben; D - ... nach unten; A(endern; E(nde', (.'E','A','S','D'.) );

194

CASE ch OF

'S' : IF komponente <> vorname THEN BEGIN alte := komponente; komponente ;- PRED ( komponente ); END; 'D' : IF komponente <> alter THEN BEGIN alte := komponente; komponente := SUCC ( komponente ); END;
'A' : BEGIN GOTOXY ( 19, ORD ( komponente ) a 3 -f- 10 ); CLREOL;

CASE komponente OF
n a m e : R E A D L N ( k .n a m e ) ; vorname : READLN ( k.vorname ); alter : READLN ( k.alter ); END; IF komponente <> alter THEN BEGIN

alte := komponente; komponente := SUCC ( komponente ); END; END;
END; (it CASE a) UNTIL ch = '£';

END; dt einlesen *)

195

Anfuegen von Datensaetzen an die Datei

PROCEDURE anfuegen; V A R io : INTEGER; k ; telement; PROCEDURE sucheende; dt stellt das Fenster hinter die letzte Komponente in der Datei #) BEGIN
dt$I-it)

RESET ( datei ); io :- IORESULT; WHILE NOT EOF ( datei ) AND (io = 0) DO BEGIN READ ( datei, k ); io :- IORESULT; END;
dt$I+it)

END; dt sucheende *) BEGIN dt anfuegen it) ueberschrift ( 'Einen kleinen Moment bitte...' ); sucheende;
(it$l-it)

IF io = 0 THEN REPEAT einlesen ( k, TRUE ); WRITE ( datei, k ); io := IORESULT; ueberschrift ( 'Anfuegen von Datensaetzen' ); UNTIL (menue ( 'A(nfuegen eines weiteren Datensatz; E(nde', (.'A'..'z'.) ) = 'E') OR (io <> 0) ELSE fehler ( CONCAT ( 'Datei ', dateiname, ' nicht vorhanden." ) ); CLOSE ( datei ); io := IORESULT; dt damit die neuen Datensaetze auch garantiert eingetragen sind/ #) ASSIGN ( datei, dateiname ); dt ist nach CLOSE noetig it)
(it$I+ii)

ch :- '-T; dt war bei Austesten des Programms noetig, warum wissen wir nicht *) END; dt anfuegen #)

196

Das Fenster auf den n-ten Eintrag in der Datei stellen. Der kann dann gelesen oder geschrieben werden/
+++-f-+-f-+++++++++++++-f+++-fi++++++++^

FUNCTION Suchekomponente ( n : INTEGER ) : INTEGER; V A R io : INTEGER; k : telement; BEGIN ueberschrift ( 'Einen Moment bitte...' ); dt$I-*) RESET ( datei ); io :- IORESULT; n := n - 1; IF io - 0 THEN WHILE NOT EOF ( datei ) AND (n > 0) DO BEGIN READ ( datei, k ); io := IORESULT; n := n - 1; END; suchekomponente := io; (#$1+*) END; Of suchekomponente it)

(*+++++++++-t-+++++++++-f++++++++-h++^

Aendern von Filekomponenten

PROCEDURE aendern; V A R ch : CHAR; io, nr : INTEGER; k BEGIN nr := 1;
REPEAT

:

telement;

ueberschrift ( 'Aendern von Datensaetzen' ); ch :~ menue ( 'L(isten aller Datensaetze; A(endern; N(aechsten aendern; E(nde', (.'L', 'A', 'N', 'E'.) ); 197

CASE ch OF

■' L ' ; l i s t e n ; ( * f a l l s m a n d i e N u m m e r v e r g e s s e n h a t a )
'N',

'A' : BEGIN IF ch = 'N'
THEN nr ;= nr + 1 ELSE REPEAT

GOTOXY ( 1, menuezeile ); CLREOL; WRITE ( 'Datensatznummer (>0>; ' ); READLN ( nr ); UNTIL nr > 0; IF (suchekomponente ( nr ) = 0) AND NOT EOF ( datei ) THEN BEGIN
READ ( datei, k );

IF IORESULT = 0 THEN BEGIN einlesen ( k, FALSE ); IF suchekomponente ( nr ) = 0 THEN BEGIN WRITE ( datei, k ); io := IORESULT; E N D ELSE fehler ( 'Lesefehler/' ); E N D ELSE fehler ( 'Fehler beim Lesen aus Datei." ); E N D ELSE fehler ( CONCAT ( 'Finde ', dateiname, ' nicht oder EOF erreicht." ) ); dttl-f-it) END;
END; (a CASE a) UNTIL ch - 'E';

END; (it aendern #)

198

()i++++++++++++-f--f-++++++++++++++++++^

Loeschen eines oder mehrerer Datensaetze
++++-f-++++-t++++++-f-++++++++++f-++++++^

PROCEDURE loeschen; V A R
ch ; CHAR;

e r s t e r, l e t z t e r, d u m m y, i o , n r : I N T E G E R ; hdatei k : : tdatei; dt eine telement; Hilfsdatei *)

PROCEDURE liesnummer ( nr : INTEGER; VAR nummer : INTEGER ); BEGIN
REPEAT

GOTOXY ( 1, menuezeile ); CLREOL; WRITE ( nr, '. Datensatznummer: ' ); READLN ( nummer ); UNTIL (nummer > 0) AND (nummer > erster); END; dt liesnummer *)

BEGIN
REPEAT

ueberschrift ( 'Loeschen von Datensaetzen' ); ch := menue ( 'Ldste aller Datensaetze; 1 ( datensatzl M(ehrere loeschen; E(nde', ( . ' U , ' V, ' M ' , ' E ' . ) ) ; CASE ch O F >U : l i s t e n ; 'i', 'M> : BEGIN erster ;- -1; liesnummer ( 1, dummy ); erster ;- dummy; letzter ;= erster; IF ch - 'M' THEN liesnummer ( 2, letzter ); dt Jetzt erstmal dt$I-it) ASSIGN ( hdatei, dateiname-f-'H' ); dt dies ist etwas proble matisch, da nicht alle Dateinamen einfach um einen Buchstaben erwei tert werden koennen it) eine neue leere Datei eroeffnen #)

199

R E W R I T E ( h d a t e i ) ; i o : - I O R E S U L T; R E S E T ( d a t e i ) ; i o : = I O R E S U LT; (* jetzt alle Datensaetze vor dem ersten zu loeschenden kopieren x) ueberschrift ( 'Datensaetze vor zu Loeschendem kopieren...' ); nr := 1; WHILE NOT EOF ( datei ) AND (io = 0) AND (nr < erster) DO BEGIN READ ( datei, k ); io := IORESULT; WRITE ( hdatei, k ); io := IORESULT; nr := nr ■/■ 1; END; (» jetzt die zu loeschenden Datensaetze ueber lesen, sie werden NICHT — it) dt in die Hilfsdatei uebernommen, also geloescht #) ueberschrift ( 'Ueberlesen der zu loeschenden Datensaetze...' ); WHILE NOT EOF ( datei ) AND (nr <= letzter) AND (io = 0) DO BEGIN READ ( datei, k ); io :- IORESULT; nr :- nr * 1; END; (* — jetzt die Datensaetze hinter dem letzten zu Loeschenden kopieren #) ueberschrift ( 'Dateirest kopieren...' ); WHILE NOT EOF ( datei ) AND (io - 0) DO BEGIN READ ( datei, k ); io := IORESULT; WRITE ( hdatei, k ); io := IORESULT; END; dt jetzt die alte Datei loeschen und die Hilfsdatei umbenennen it) C L O S E ( d a t e i ) ; i o : = I O R E S U LT; C L O S E ( h d a t e i ) ; i o : = I O R E S U LT; IF io = 0 THEN BEGIN E R A S E ( d a t e i ) ; i o : = I O R E S U LT; RENAME ( hdatei, dateiname ); io := IORESULT; ASSIGN ( datei, dateiname ); E N D ELSE BEGIN ERASE ( hdatei ); fehler ( 'I/O-Fehler, konnte nicht loeschen/ Alte Datei intakt.' ); END; (itfl-f-it) END;
END; Of CASE it) UNTIL ch - 'E';

END; Of loeschen *) 200

(ii++++-f-++++++++++++-f-++++++++++f-++++^

Eroeffnung einer neuen (noch leeren) Datei

PROCEDURE neuedatei; V AR
ch : CHAR;

BEGIN ueberschrift ( 'Eroeffnen einer neuen Datei' ); C# Pruefen, ob eine Datei vom selben Namen schon existiert *)
dttl-it) RESET ( datei ); ch := 'J'; IF IORESULT - 0

THEN ch := menue ( 'Es existiert schon eine Datei mit diesem Namen. Loeschen (J/N): ', (.'A',.'z'.) ); IF ch - 'J' THEN REWRITE ( datei );
IF (IORESULT - 0) AND (ch = 'J')

THEN anfuegen; dt$I+it) END; dt neuedatei #)

BEGIN dateiname := ";
REPEAT

ueberschrift ( 'Ein schoenes Dateiprogramm' ); dt -f-f-f-f-f-f-f- Dies Menue ist leider in Englisch, da so die Bezeichnungen -f-f-f-f-f- n) (# -f-f-f-f-f- fuer die Menuepunkte kuerzer wurden und in eine Zeile passten -t-f-t-f- ») ch :- menue ( 'Ldst; Fdlename; N(ew file; A(ppend; C(hange; D(elete; E(nd',
(.'L', 'F', 'N', 'A'r 'C, 'D', 'E'.) );

201

IF (ch - 'F') OR (ch <> 'E') AND (dateiname = ") THEN BEGIN REPEAT GOTOXY ( 1, menuezeile ); CLREOL; WRITE ( 'Der gewuenschte Dateiname; ' ); READLN ( dateiname ); UNTIL dateiname <> "; ASSIGN ( datei, dateiname ); END; CASE <?h O F

>U

m

listen;

' N ' • neuedatei; 'A' ' C
m a

anfuegen; aendern;

a

' D ' ■ loeschen;
END;

UNTIL ch -r ,£,. END.

Man koennte sich fragen, wie es moeglich ist, aus einer Muecke einen ca. 650 Zeilen Programrnelefanten zu machen, aber... Benutzerfreundlichkeit und Uebersicht haben ihren Preis.

>02

> Appendix

<

In den Kapiteln des Appendix wollen wir den ganz ganz Interes s i e r t e n u n t e r e u c h n o c h e i n i g e b i s h e r v e r s c h w i e g e n e PA S C A L - F e a tLires vorstellen. An ihre Benutzung solltet ihr allerdings erst denken, wenn euch das bis hier Gesagte in Fleisch und Blut uebergegangen ist. Aus diesem Grunde fallen die folgenden Ausfuehrungen sehr knapp aus. Unsere Absicht ist nur, einen Ueberblick ueber weitere M o e g l i c h k e i t e n PA S C A L S z u g e b e n . We r s i c h g e n a u e r m i t Z e i g e r n u s w. . a u s e i n a n d e r s e t z e n m o e c h t e , d e r s o l l t e w e i t e r e F a c h l i t e r a t u r heranziehen, die genauer in den Urngang mit ihnen einfuehrt. Der Rahmen unserer Einfuehrung in F'ASCAL wuerde unweigerlich ge sprengt werden.

203

1.

Die WITH—Anweisung

A r b e i t e t m a n v i e l m i t Ve r b u n d e n , s o k a n n e s m a n c h m a l z u r L a s t w e r d e n , m u s s m a n i m m e r w i e d e r a l l e f u e h r e n d e n Ve r b u n d v a r i a b l e n auffuehren, wenn man eine Komponente tief unten in der Struktur anspechen will:

TYPE tbeispiel = RECORD nummer : INTEGER;
person : RECORD name : STRING (.20.); RECORD geb tag, monat, jähr ;INTEGER; END;

END;
END; V AR

mitglied ; tbeispiel; mitglieder : ARRAY (.1..100.) OF tbeispiel;

READLN ( mitglied.person.geb.tag ); READLN ( mitglied.person.geb.monat ); READLN ( mitglied.per son.geb.jähr );

Eine echte Arbeit, diese Leseanweisungen zu schreiben, unterscheiden sie si :h nur in den letzten Komponenten.

Dabei

PA S C A L b i e t e t u n s n u n d i e M o e g l i c h k e i t , R E C O R D - Va r i a b l e n g u a s i auszuklammern, wenn sie mehrmals auftauchen. So koennen wir vereinfacht schreiben: WITH mitglied.person.geb DO BEGIN
READLN ( tag ); READLN ( monat ); READLN ( jähr ); END;

mitgl ied .person .geb denkt sich CPU einfach immer vor die Kom ponenten. Haetten wir nur mitgl ied .person hinter WITH angefuehrt, so haette immer geschrieben werden muessen:
READLN ( geb.tag ); u s w.

?04

Formal lautet die neue Anweisung in dieser Weise:
uith-anueisung: ^ — 1_ ^ + /'~^ ' + __ + +

—>—^HITH >—>—7—! recordvariable !--—>—(DO)—>—! anweisung !—> —" 7 + 1 V + +
\ i T

Durch bedachte Verwendung von WITH gewinnt man U e b e r s i c h t l i c h k e i t , s p a r t S c h r e i b a r b e i t u n d - b e i A R R AY O F R E C O R D auch Rechenzeit, siehe folgenden Fall:

WITH mitglieder(.i.).person DO ...
Auf Zweideutigkeiten ist acht zu geben, der Rechner weiss dann n i c h t , w e l c h e K o m p o n e n t e n , w e l c h e r Va r i a b l e n i h r m e i n t :

WITH mitglieder(,i.).person, mitglied.person DO BEGIN name := name; dt soll he issen: mitglied(.i.).person.name := mitglied,person.name »)
END;

Man ueberlege sich also immer genau, was der Rechner vor jede Komponente vorsetzen wird, was man ausklammert.

Zeiger Bisher haben wir nur statische Datenstrukturen kennengelernt, d.h. solche, die waehrend der Programmlaufzeit nicht mehr veraendert werden konnten. Wir muessen vor Programmstart alle Va r i a b l e n v e r e i n b a r e n , d i e w i r s p a e t e r b e n u t z e n w o l l t e n . Dies legt dem Profi bei ganz kniffligen Problemen aber Fesseln a n , d i e PA S C A L z u e i n e r d u r c h s c h n i t t l i c h e n D u r c h s c h n i t t s s p r a c h e degradieren wuerden. Aus diesem Grunde kann man auch dynamisch Va r i a b l e n e r z e u g e n , d . h . w e n n d a s P r o g r a m m s c h o n l a e u f t . Da man aber nicht weiss, ob, wann, wo usw. das geschieht, kann m a n d i e s e n d y n a m i s c h e n Va r i a b l e n v o r a b k e i n e n N a m e n g e b e n . S i e w e r d e n d a h e r u e b e r Z e i g e r a n g e s p r o c h e n , d . h . Va r i a b l e n , d i e d o r t h i n w e i s e n , w o w i r i m S p e i c h e r d i e n a g e l n e u e n Va r i a b l e n z u r Progr arnml auf zeit erschaffen haben.

zeigertyp:

4

4

—>-~(£>">—' ~ 4 typ"*!« I—> 4
i s t d e r n e u e Ty p d a f u e r. B e i s p i e l :
TYPE

zeiger - ^Objekt; dt man beachte das A *)
VAR

p, q : zeiger; p, q sind Zeigervariablen: ueber sie koennen wir die neu zu e r z e u g e n d e n , n a m e n l o s e n Va r i a b l e n a n s p r e c h e n . D i e s e s i n d i m m e r vom Typ objektl
ff Bezuas variable. V"' die$rgeschaffen hqben. Ist ohne
4 4 4 4

bezugsvariable:

—>—! zeiger var iable !—>—(^-->

Namen

We n n p , q v o m Ty p ' - o b j e k t s i n d , d a n n s i n d / j a , c / A v o r n Ty p obejkt. Sie sind die Bezugsvariablen! Jedes •"• will jetzt korrekt gesetzt werden!
TYPE

Objekt - (kreis, quadrat); dt Ergaenzung zu oben *) D i e e t w a s v e r z w i c k t e n Ve r h a e l t n i s s e v e r d e u t l i c h e n w i r ' m a l m i t einigen Grafiken:

206

Zeigervariable

Va r i a b l e

von

Typ

°objekt°

p
q

x
,

>
>

o

pA

=
qA=

O
a

p p :=
q

j q

4 >

o
,

Nach der Zuweisung ZEI6T p i auf dieselbe dynamische (-] Va r i a b l e wie q !
>

Man denke sich jetzt wieder den selben Zustand hergestellt vie in der ersten 6rafik, dann ergibt die naechste Operation folgendes:

p p* := q

| qA

>

Q Nach Va r i a b l e , >

der auf Q

j

Zuweisung hat die welche p zeigt, den selben WERT, wie die, aufdieqzeigt!

Im Zusammenhang mit Zeigern (oder engl.: pointer) gibt es auch eine neue Konstante: NIL.

p

:-

NIL

p

* p auf nichts zeigt also auf keine

bewirkt dann, dass d y n a m i s c h e Va r i a b l e .

J e t z t h a b e n w i r s o v i e l v o n d i e s e n t o l l e n n e u e n Va r i a b l e n erzaehlt, dann wollen wir doch mal sehen, wie man sie eigentlich erzeugen kann:

NEW ( zeigervariable ) erzeugt eine neue Variable vom Typ der Bezugsvariablen der Zeigervariable. Der Zeiger auf sie wird zeigervariable zugewiesen. DISPOSE ( zeigervariable ) gibt den Platz, welchen die zugehoerige Bezugsvariable im Speicher belegt, wieder frei, zeigervariable hat hinterher den Wert NIL.
Zu diesen beiden Standardprozeduren gibt es in den meisten PA S C A L - D i a l e k t e n n o c h d i e P r o z e d u r e n M A R K u n d R E L E A S E ; d a f u e r fehlt meist DISPOSE. Schlagt diesbezueglich doch mal in eurem H a n d b u c h z u m U e b e r S e t z u n g s p r o g r a m m n a c h . T U R B O - PA S C A L e n t h a e l t alle 4 Routinen.
207

Z u r Ve r d e u t l i c h u n g :
TYPE

zeiger - ^element; element - RECORD naechster : zeiger; da ten END; V AR wurzel, p, q : zeiger; datentyp; dt hier z.B. CHAR a)

NEW ( p )

pA.naechster := NIL

wurzel :■

wurzel ** !

p*.da ten

4

NEW ( p'-.naechster )

pA.naechster

t
4

•A' i
4

p*.naechster

P

* J

> 4
1

4

+- V -+
I
I

wurzel t >

4

'A' !
4

DISPOSE ( wurzel )

wuerde jetzt die Bezugsvariable mit Dateninhalt 'A' vernichten.

>08

Wie in der Grafik angedeutet, werden Pointer zum Aufbau von Listen benutzt, bei denen vorher nicht bekannt ist, wieviele Elemente sie enthalten werden. Z e i g e r e i g n e n s i c h f u e r d e n v e r s i e r t e n P r o g r a m m i e r e r, u m b e l i e big komplexe Datenstrukturen zu schaffen und leicht zu handhaben. Der Anfaenger sollte erst nach gehoeriger Programmierpraxis d i e s e n n e u e n Ty p b e n u t z e n u n d z u v o r v e r t i e f e n d e L i t e r a t u r z u m Thema waelzen.

209

Literatur1i ste Bauer, F.L. et al . : Comp i1 er Con st r uc t i on " S p r i n g e r s t u d y e d i t i o n " , S p r i n g e r - Ve r l a g B e r l i n H e i d e l b e r g N e w Yo r k To k i o
> Fuer denjenigen geeignet, der sich Einblick in den Aufbau und Arbeitsweise der UeberSetzungsprogramme beschaffen moechte. B o r l a n d I n t e r n a t i o n a l , I n e ( H e r a u s g e b e r ) : T U R B O PA S C A L Reference Manual Hei msoeth-Software, Muenchen > Hier sind alle Eigenheiten des in unserem Buche verwendeten PASCAL-Dialektes genau (aber knapp) beschrieben. Eyssen. Remy: Ich hasse Computer Droernersche Verlagsanstalt Th. Knaur Mach f. Muenc hen 198E > Als Ausgleichslektuere zu dieser Einfuehrung sehr zu empfehlen. Her sc hei, Rudolf u. Pi eper , Fr _i e d r_ic_h: PASCAL R . O l d e n b o u r g Ve r l a g M u e n c h e n W i e n ( 1 9 7 9 ) > Auch eine Einfuehrung in PASCAL, 'mal mit anderen Worten aus einer anderen Sicht. S c h a u e r, H e l m u t : PA S C A L f u e r A n f a e n g e r R . O l d e n b o u r g Ve r l a g M u e n c h e n W i e n ( 1 9 7 9 ) > dito Wirth, Niki aus: Algorithmen und Datenstrukturen Te u b n e r S t u d i e n b u e c h e r I n f o r m a t i k B d . 3 1 , S t u t t g a r t ( 1 9 7 9 ) > Ein Muss fuer jeden, der sich naeher mit Programmiertechniken und Algorithmen auseinandersetzen moechte. Hier wird auch der Umgang mit Dateien und Zeigern noch ausfuehrlicher und auf hoher Ebene behandelt. Auch sehr komplexe Sortieralgorithmen werden besprochen. Wirth, N.: Systematisches Programmieren Te u b n e r S t u d i e n b u e c h e r I n f o r m a t i k B d . 1 7 , S t u t t g a r t ( 1 9 7 2 ) > Eine Einfuehrung in den systematischen Entwurf von Programmen allgemein und PASCAL-Programmen im Besonderen. W i r t h , N . u . J e n s e n , - K a t h l e e n : PA S C A L U s e r M a n u a l a n d R e p o r t " S p r i n g e r s t u d y e d i t i o n . " , S p r i n g e r - V e r l a g N e w Yo r k ( 1 9 7 5 ) > Hier ist niedergelegt, wie PASCAL urspruenglich aussehen sollte, gaebe es nicht all die unterschied!ichen Dialekte. Sozusagen DAS Standartwerk vom Erfinder der Sprache. Wi rth, N. : Cornpilerbau Te u b n e r S t u d i e n b u e c h e r I n f o r m a t i k , S t u t t g a r t > siehe Bemerkungen zu "Compiler Construction"

:io

St i chwortVerzeichnis Begri ff Algorithmus ASCII Ausdruecke Ausgabeanwei sung Auswahl Bedingungen Bezeichner BOTTOM-UP Datei Dynamische Variablen Central Processing Unit (CPU) Character Endlosschlei fe Fehler Compi1 er-Switch fuer I/O I/O Felder - mehrdimensional - vorn Komponententyp CHAR File Funktionen Globale Objekte Grammati k Gueltigkeitsbereich Hardware Hexadez i malsyst em Identi f ier Initialisierung Kommentar Konstanten Lesen Lokale Objekte Maschinencode Massenspeicher Mathematische Operatoren / Funktionen Mengen Menu Nassi-Schnei dermann—Diagramm Optische Gliederung
S e i t e ni 5 7 58 55 siehe Schreiben 79f f 41 13 128 167f f 206 ff
^ i

14

16 78 186 186f 94ff 102ff 105f f 167ff 151f f 137 8 137ff 2 3

56ff

siehe Bezeichner 63 13 20ff 23f f 134 167 30 ff 11 4 f f 79f f 6, 7 170f f

69ff

F'arameter aktuelle formale C a l l - b y - Va l u e Call-by—Reference Programm -aufbau (formal) Prozedur Rechnen Rekursion Compiler Switch fuer Direkte Indirekte Schachtelung Schlei fen Schreiben S c h r i t t w e i s e s Ve r f e i n e r n Software
Struktogramrn String

143ff 144 144 144 145 7 13 131f f 30f f 161f f 164f 161 164 43 60 ff 15f f 5
_ * »

136ff 66ff 174ff

73ff

- funktionen in TURBO-PASCAL - vergleiche Symbol Syntax -diagramm Te x t d a t e i e n TOP-DOWN Typen Funkt ions - implizit - selbst definieren Skalar Strukturierte Unterbereichs - vordefiniert Unterprogramme Va r i a b l e Verbünde Ve r g l e i c h s o p e r a t o r e n Verzweigung Wa h r h e i t s w e r t e Wertzuwei sung Zahl ganze gebrochene groessete ganze -

6, 7 16 107f 113 12 8 8 lSlff 128 86 92 f 87ff 94ff 90 f 57 130ff

105ff

11 4 f f 1 2 3 f f

23f f l^of f 41 48 116 37ff 46ff 34ff 24 27 26 27

113

Verzeichnis der Syntaxdiagramme: Bezeichnung Additionsoperator Aktueller Parameter Anweisung Anweisungstei1 A R R AY- K o m p o n e n t e A R R AY- Ty p Ausdruck Ausgabeanweisung Bedingte Bedingung Bezeichner Bezugsvariable Block CASE-AnWeisung Eingabeanweisung Einfache Anweisung Einfacher Typ Faktor FILE-Typ FOR—Anweisung F Linkt ionsauf ruf Funktionsvereinbarung IF-AnWeisung Leere Anweisung Anweisung (...name) Seite 55 146 40 14 97 96 55 17 40 55 14 206 13 81 24 40 86 153 167 73 153 152 40 40 124 21 21 11 6 55 14 144 13 13 146 144 125 124 61 11 5 87 18 106 74 167

Komponenten1iste Konstantendefinition Konstante Menge Multiplikationsoperator Name Parameter 1iste Programm Programkopf Prozeduranweisung Prozedurvereinbarung RECORD-Komponente RECORD-Typ R E P E AT- A n w e i s u n g SET-Typ Skalar-Typ String STRING-Typ Strukturierte Strukturierter

Anweisung Typ

Te r m Typ Typdefinition Unterbereichstyp Va r i a b l e Va r i a b l e n v e r e i n b a r u n g Verbundanweisung Vereinbarungsteil Vergleichsoperator Vorzeichenlose Konstante Wiederholungsanweisung WITH-Anweisung WHILE-AnWeisung Wertzuweisung Zeigertyp

55 47 92 90 34 25 40 132 11 8 55 74 205 66 153 206

You're Reading a Free Preview

Download
scribd
/*********** DO NOT ALTER ANYTHING BELOW THIS LINE ! ************/ var s_code=s.t();if(s_code)document.write(s_code)//-->