From 04e68443040c7abad84d66477e98f93bed701760 Mon Sep 17 00:00:00 2001 From: Lars-Dominik Braun Date: Mon, 4 Feb 2019 13:09:03 +0100 Subject: Initial import --- doc/user-manual/1.7.3-pd/doc/pd.Handbuch.Teil6a | 1590 +++++++++++++++++++++++ 1 file changed, 1590 insertions(+) create mode 100644 doc/user-manual/1.7.3-pd/doc/pd.Handbuch.Teil6a (limited to 'doc/user-manual/1.7.3-pd/doc/pd.Handbuch.Teil6a') diff --git a/doc/user-manual/1.7.3-pd/doc/pd.Handbuch.Teil6a b/doc/user-manual/1.7.3-pd/doc/pd.Handbuch.Teil6a new file mode 100644 index 0000000..1ee80ec --- /dev/null +++ b/doc/user-manual/1.7.3-pd/doc/pd.Handbuch.Teil6a @@ -0,0 +1,1590 @@ + EUMEL-Benutzerhandbuch + + + TEIL 6: Erste Hilfe in ELAN + + +Vorwort + +Dieser Teil des EUMEL-Handbuchs ist keine "Einführung in die Programmierung +mit ELAN", sondern ist als Begleitmaterial für einen ELAN-Kurs gedacht. +Zudem beschreibt das Skript nicht die vollständige Sprache; dafür ist die +Sprachbeschreibung und das Handbuch vorgesehen. Folgende ELAN-Bücher sind +z.Zt. erhältlich: + +Klingen / Liedtke: +Programmieren mit ELAN +Teubner, Stuttgart, 1982 + +Jähnichen u.a.: +Systematisches Programmieren mit ELAN +W. de Gruyter, 1982 + +Wir haben in dieses Skript auch einige Aufgaben mit aufgenommen, die An- +fänger auf jeden Fall lösen sollten. Die Aufgaben dienen aber nur dazu, das +erlernte Wissen über ELAN zu überprüfen und sind keine eigentlichen Program- +mieraufgaben, die es im begleitenden Kurs geben sollte. Es gibt zwei Arten +von Aufgaben: + +a) HSG (Hätten Sie's gewußt?): Aufgaben, die das bis dahin Gelernte über- + prüfen sollen. +b) TSW (Trau', Schau', wem!): Aufgaben mit Programmen, die Fehler enthalten + können. Alle Programme dieses Skripts sind übrigens von der Art TSW. + +Es ist auch sinnvoll und notwendig, möglichst viele Programme dieses Skripts +direkt auf dem Terminal zu probieren und zu verändern. Auf diese Weise wird +ein Anfänger auch mit den Fehlermeldungen des ELAN-Compilers vertraut. + + + +Das erste Programm + +Gleich am Anfang einer Programmierlaufbahn haben Anfänger eine schwierige +Hürde zu nehmen: das erste Programm "zum Laufen" zu bringen. Das wird einem +Anfänger meist nicht leicht gemacht: schließlich hat er mit dem Betriebs- +system eines Computers zu kämpfen. Ein #ib#Betriebssystem#ie# sorgt u.a. für +die Steuerung so unterschiedlicher Peripheriegeräte wie Drucker, Lochkarten- +leser, Magnetplatten und -bänder usw. Zusätzlich hat es dafür Sorge zu +tragen, daß Informationen sicher gespeichert werden und nicht unbeabsichtigt +verändert werden können. Letztendlich hat ein Betriebsystem die Aufgabe, die +Aufträge von Benutzern ("jobs") - und das können mehrere auf einmal sein - +sicher und effizient bearbeiten zu lassen. Um mit einem Betriebsystem +"sprechen" zu können, ist meist eine eigene Sprache vorhanden, die Kommando- +sprache ("job control language", abgekürzt: JCL). + +Eine Kommandosprache kann - auf Grund der vielfältigen Aufgaben, die mit +ihrer Hilfe formuliert werden müssen - mehr oder weniger kompliziert sein. +Zusätzlich sind Kommandosprachen sehr unterschiedlich: aus leicht einsichti- +gen Gründen wollen sich Hersteller nicht auf eine Kommandosprache einigen. +Deshalb können wir die Anweisungen in einer speziellen Kommandosprache hier +nicht angeben; man erfragt diese am besten. Auf jeden Fall muß etwas getan +werden, um ein Programm auf einem Rechner "zum Laufen" zu bringen. + +Wie bereits erwähnt, beschränken wir uns hier auf die eigentlichen Programme. +Um den Mechanismus mit den Anweisungen an das Betriebsystem von Anfang +an kennen zu lernen, denken wir uns ein sehr einfaches Programm aus, das wir +bearbeiten lassen wollen. + +Programm 1: + + put ("Hallo: mein erstes Programm") + +Dieses Programm muß nun dem Rechner zur Bearbeitung übergeben werden. +Auch hier treffen wir auf Unterschiede bei den verschiedenen Rechensystemen: +bei einigen Rechnern muß ein solches Programm (mit Anweisungen der +Kommandosprache) auf Lochkarten übertragen werden, bei anderen dagegen +tippt man das Programm direkt an einem Sichtgerät ("Terminal") ein. Die +Ausgabe erfolgt dann über einen Schnelldrucker oder auch über das Sichtgerät. +Um von Geräten bestimmter Installationen zu abstrahieren, nennen wir im +folgenden das Eingabemedium #ib#Eingabegerät#ie# und das Gerät, auf dem die +Resultate erscheinen, dementsprechend Ausgabegerät. + +Aufgabe (TSW): + + Versuchen Sie, Programm 1 auf dem Rechner Ihrer Installation zu "rechnen". +Übungsziel: Umgang mit dem Betriebsystem + + +Das Ergebnis unseres ersten Programms ist nun das Erscheinen des Textes: +'Hallo: mein erstes Programm'. Was ist hier passiert? Da ein Rechner ein +ELAN-Programm meist nicht direkt ausführen kann, muß es in eine Form +gebracht werden, die der Rechner "versteht". Diese Form ist wiederum eine +(sehr andersartige und - für Menschen - nicht leicht verständliche) Sprache, +die Maschinensprache. Man muß also ein ELAN-Programm übersetzen. Dies wird +von einem Programm (und nicht etwa einer festverdrahteten Schaltung) vorge- +nommen, einem Übersetzer. Eine bestimmte Art von Übersetzer heißt Compiler; +er übersetzt ein Programm als Ganzes (im Gegensatz zu einem Interpreter, der +nur einzelne Anweisungen übersetzt und anschließend ausführt). Darum sind +bei ELAN-Programmen, die meist durch Compiler übersetzt ("kompiliert") +werden, zwei Phasen zu unterscheiden: + +a) Übersetzungsphase: + + In dieser Phase wird ein ELAN-Programm (man spricht von Quellprogramm + bzw. "source program") in ein äquivalentes Maschinenprogramm (Objektpro- + gramm) transformiert. Dabei überprüft der Übersetzer das Quellprogramm + auf eventuelle Fehler (Anweisungen, die nicht der ELAN-Sprachbeschreibung + entsprechen). Bei solchen Fehlern, die ein Compiler entdecken kann, + spricht man von syntaktischen Fehlern oder von Fehlern zur Übersetzungs- + zeit. + +b) Bearbeitungsphase: + + In dieser Phase ("run time") wird das übersetzte (Maschinen-) Programm + abgearbeitet. Auch hier können Fehler auftreten (z.B. wenn auf einen Wert + vom Programm zugegriffen wird, der noch gar nicht berechnet wurde). + Solche Fehler nennt man Laufzeitfehler. + +Haben wir das erste Programm so geschrieben, wie oben angegeben, dürften +keine Fehler entdeckt werden und das Programm wird (hoffentlich korrekt, d.h. +mit den geforderten Ergebnissen) beendet. Was für ein Programm haben wir nun +geschrieben bzw. was haben wir vom Rechner verlangt? + +Das Wort 'put' bezeichnet eine Prozedur. Eine Prozedur ist ein Algorithmus +(hier mit Parametern): eine bestimmte Sammlung von Anweisungen und unter +Umständen Daten. Eine solche Prozedur können wir in einem Programm unter +einem Namen (nämlich 'put') ansprechen und ausführen lassen. Man spricht +dann von dem Aufruf einer Prozedur, wenn ein Prozedurname geschrieben wird. +Von einer Prozedur brauchen wir nur zu wissen, was die Prozedur macht, aber +gottseidank nicht, wie sie es macht. + +Eine Prozedur wie 'put' ist vorgefertigt und einfach benutzbar, wobei wir +später sehen werden, wie man solche Prozeduren selber schreiben kann. Die +Prozedur 'put' hat einen Parameter, nämlich den in Klammern geschriebenen +Text, der auf dem Ausgabegerät ausgegeben werden soll. Wir können eine +solche Prozedur auch mit anderen Parametern versehen und mehrmals aufrufen: + +Programm 2: + + put ("Programm:"); + put (2) + +Mit dem zweiten Programm ist es uns gelungen, ein Programm mit zwei Anwei- +sungen zu schreiben (dabei ist der Parameter bei dem ersten Aufruf der +'put'-Prozedur ein Text, beim zweiten Parameter eine ganze Zahl). + +ELAN ist eine formatfreie Sprache, d.h. Anweisungen können so auf eine Zeile +verteilt werden, wie es uns gefällt und zweckmäßig erscheint. + +Programm 3: + + put ("mein"); put (3); put (".Programm") + +Man kann also eine oder mehrere Anweisungen auf eine Zeile schreiben oder +eine Anweisung über mehrere Zeilen. Das setzt jedoch voraus, daß die Anwei- +sungen voneinander getrennt werden (schließlich muß der Übersetzer erkennen +können, wo eine Anweisung anfängt und aufhört). Das ist besonders notwendig, +weil man in Namen in ELAN beliebig Leerzeichen zur besseren Lesbarkeit +verwenden kann. + + +Programm 4: + + p u t ( "aha"); + put ("aha") + +Beide Anweisungen bewirken also das Gleiche. + +Die Trennung von Anweisungen erfolgt in ELAN durch das Trennsymbol +Semikolon. Es bedeutet soviel wie: "führe die nächste Anweisung aus". Aus +diesem Grund darf hinter der letzten Anweisung eines Programms kein Semiko- +lon geschrieben werden (es folgt ja auch keine Anweisung mehr). + +Der Aufruf einer Prozedur (wie z.B. 'put') verlangt von unserem Rechner im- +mer eine Leistung. Wollen wir aber in einem Programm eine Bemerkung schrei- +ben (z.B. um uns etwas zu merken), dann können wir einen Kommentar schrei- +ben, der vom Übersetzer überlesen und somit keinen Einfluß auf die Aus- +führung eines Programms hat. Ein Kommentar in ELAN wird durch die Zeichen +(* und *) eingeschlossen und darf über mehrere Zeilen gehen. Kommentare sind +in ELAN aber nur in wenigen Fällen notwendig, weil wir Programme durch +andere Mittel gut lesbar machen können. + + + +Ziel der Programmierung + +Was wollen wir eigentlich mit dem Programmieren von Computern erreichen? +Häufig wiederkehrende und somit oft langweilige Tätigkeiten oder solche, die +besonders schnell erledigt werden müssen, sollen von dem "Werkzeug Computer +erledigt werden. Gehaltsberechnungen, Unterstützung beim Schreiben von +Texten, Katalogsysteme für Bibliotheken, Steuerung von Walzstraßen usw. sind +typische Aufgaben für Computer. + +Bei der Programmierung wird also versucht, Objekte (wie z.B. Geld bei einer +Gehaltsberechnung) und Prozesse (wie z.B. die Simulation von Wirtschaftsab- +läufen) der realen Welt mit Hilfe von Programmen in einem Computer nachzu- +bilden und nach bestimmten Vorstellungen so zu verändern, daß man "brauch- +bare" Ergebnisse erlangt. In einem Programm sind Befehle an einen Rechner +für eine solche Abbildung enthalten. Die Befehle in einem Programm werden +Anweisungen genannt. Ein Programmierer muß also folgendes tun: + +1. Abbilden von Objekten und Prozessen der realen Welt in ein Programm. + Dabei müssen die Bedingungen der Aufgabe beachtet werden. Was das Pro- + gramm Programm leisten soll, wird darum in einer Spezifikation festgelegt. + +2. Einbringen des Programms in einen Rechner und Bearbeitung desselben. Die + Formulierung von Anweisungen in einem Programm erfolgt in einer bestimmten + Sprache, nämlich einer Programmiersprache. + +3. Interpretation der Ergebnisse. + + + +Das Konzept des Datentyps + +Befassen wir uns vorerst nur mit Objekten. Sicherlich gibt es sehr viele Ob- +jekte in unserer Welt. Einige von ihnen haben aber gleiche Eigenschaften: + +- Fahrzeuge (Autos, Mofas, Dreiräder) bringen uns von Ort A nach Ort B. + +- Geld (Münzen, Geldscheine, Murmeln, Franc, DM) erlaubt es, etwas zu kaufen. + +- Schreibgeräte (Bleistift, Kugelschreiber, Schreibmaschine) sind die Werk- + zeuge von Leuten, die etwas zu schreiben haben. + +- ... + +Es ist also möglich, einige Objekte der realen Welt in Klassen zusammenzu- +fassen. Eine solche Zusammenfassung kann hinsichtlich gleicher Eigenschaften +bzw. gleicher Operationen, die für solche Objekte zugelassen sind, erfolgen. +Eine Klasse von Objekten mit gleichen Eigenschaften wird in Programmier- +sprachen Datentyp genannt. Dabei hat ein Datentyp immer einen Namen, der die +Klasse von Objekten sinnvoll kennzeichnet. Als ein Datenobjekt wird ein +Exemplar eines Datentyps (also ein spez. Objekt einer Klasse) bezeichnet. + +Datentypen sind in ELAN ein zentrales Konzept. Jedes der in einem ELAN- +Programm verwandten Datenobjekte hat einen Datentyp; somit kann man Daten- +typen auch als Eigenschaften von Datenobjekten ansehen. Für jeden Datentyp +sind nur spezielle Operationen sinnvoll. Z.B. sind für einen Datentyp +"UBoot" die Operationen "erstellen", "tauchen", "auftauchen", "versenken" +und "lieber nicht verwenden" sinnvoll, aber nicht die Operation "+" wie bei +ganzen Zahlen. Man kann nun Übersetzern die Aufgabe überlassen zu überprüfen, +ob stets die richtige Operation auf einen Datentyp angewandt wird. + +Aufgabe (HSG): + + Was ist ein Datentyp? Welche Funktion erfüllen Datentypen? +Übungsziel: Datentyp-Konzept + +Einige Datentypen spielen bei der Programmierung eine besondere Rolle, weil +sie häufig benötigt werden. In ELAN sind das die Datentypen für + +- ganze Zahlen. Dieser Datentyp wird INT (für "integer") genannt. + +- reelle Zahlen (REAL). + +- Zeichen und Zeichenfolgen (TEXT). + +- Wahrheitswerte (BOOL). + +Diese Typen werden in ELAN elementare Datentypen genannt. Für effiziente +Rechnungen mit elementaren Datentypen gibt es in den meisten Rechnern +spezielle Schaltungen, so daß die Hervorhebung und besondere Rolle, die +sie in Programmiersprachen spielen, gerechtfertigt ist. Zudem hat man +Werte-Darstellungen innerhalb von Programmen für die elementaren Datentypen +vorgesehen, was wir im nächsten Abschnitt erklären wollen. + +Im weiteren Teil dieses Skripts werden wir uns zunächst auf die Behandlung +der elementaren Datentypen beschränken. Das bedeutet für den Programmierer, +daß er alle Objekte der realen Welt mit Hilfe der elementaren Datentypen in +den Computer abbilden muß. Das kann manchmal sehr schwierig sein (wie bilden +wir z.B. Personen oder UBoote mit den elementaren Datentypen ab?). Später +werden wir dann Möglichkeiten kennenlernen, neue - problemgerechte - +Datentypen in ELAN zu formulieren. + + + +Denoter (Werte-Repräsentationen) elementarer Datentypen + +Wenn wir mit Objekten elementarer Datentypen arbeiten, müssen wir die +Möglichkeit haben, Werte in ein Programm zu schreiben. Leider kann man einen +Wert "an sich" in einem Programm nicht direkt angeben. Schreiben wir z.B. +4711, dann meinen wir zwar einen INT-Wert, haben aber die Ziffern 4, 7, 1 und +1 geschrieben. Der eigentliche Wert wird in unserem Kopf oder - für unsere +Zwecke - in einem Rechner gebildet. + +Die Werte-Darstellungen oder Werte-Repräsentationen, die in ELAN "Denoter" +genannt werden, sind für jeden Datentyp unterschiedlich. Wie bereits erwähnt, +haben alle Datenobjekte in ELAN (also auch Denoter) nur einen - vom Über­ +setzer feststellbaren - Datentyp. Aus der Form eines Denoters ist also der +Datentyp erkennbar: + +- INT-Denoter: + Bestehen aus einer Aneinanderreihung von Ziffern. Beispiele: + + 17, 007, 32767, 0 + + Führende Nullen spielen bei der Bildung des Wertes keine Rolle (sie werden + vom ELAN-Compiler überlesen). Negative INT-Denoter gibt es nicht (wie + negative Werte-Darstellungen in einem Programm geschrieben werden, lernen + wir bei den Ausdrücken). + +- REAL-Denoter: + Hier gibt es zwei Formen. Die erste besteht aus zwei INT-Denotern, die + durch einen Dezimalpunkt getrennt werden. Beispiele: + + 0.314159, 17.28 + + Der Dezimalpunkt wird analog der deutschen Schreibweise als Komma + verwendet. Negative REAL-Denoter gibt es wiederum nicht. + + Eine zweite Form wird kurioserweise als "wissenschaftliche Notation" be- + zeichnet. Sie findet dann Verwendung, wenn sehr große oder Zahlen, die + nahe bei Null liegen, dargestellt werden müssen. Beispiele: + + 3.0 e5, 3.0e-5 + + Der (INT-) Denoter hinter dem Buchstaben e gibt an, wie viele Stellen der + Dezimalpunkt nach rechts (positive Werte) oder nach links zu verschieben + ist. Dieser Wert wird Exponent, der Teil vor dem Buchstaben e Mantisse + genannt. + +- TEXT-Denoter: + TEXT-Denoter werden in Anführungszeichen eingeschlossen. Beispiele: + + "Das ist ein TEXT-Denoter" + "Jetzt ein Text-Denoter ohne ein Zeichen: ein leerer Text" + "" + + Beachte, daß das Leerzeichen ebenfalls ein Zeichen ist. Soll ein An- + führungszeichen in einem TEXT erscheinen (also gerade das Zeichen, welches + einen TEXT-Denoter beendet), so muß es doppelt geschrieben werden: + + "Ein TEXT mit dem ""-Zeichen" + "Ein TEXT-Denoter nur mit dem ""-Zeichen:" + """" + + Manchmal sollen Zeichen in einem TEXT-Denoter enthalten sein, die auf dem + Eingabegerät nicht zur Verfügung stehen. In diesem Fall kann der Code- + Wert des Zeichens angegeben werden: + + ""32"" + + bedeutet z.B. das (ASCII-) Leerzeichen. Der Code-Wert eines Zeichens er- + gibt sich aus einer Code-Tabelle (installationsspezifisch), in der jedem + Zeichen eine ganze Zahl zugeordnet ist. + +- BOOL-Denoter: + Es gibt nur zwei BOOL-Denoter: TRUE (für "wahr") und FALSE (für "falsch"). + +Nun wird auch klar, was für Parameter wir in den obigen Programmen verwandt +haben. Es waren natürlich TEXT- bzw. INT-Denoter. + + +Aufgabe (TSW): + + Welche der folgenden Denotationen ist falsch? + + a) 1. e) 1 . 0 i) 007 + b) -1 f) "" j) "Ein "Getuem" stellt sich vor" + c) """ g) """" + d) "das ist ein text" h) TRUE k) 1.0 e 37 + +Übungsziel: Lernen von Denotationen + + + +ELAN-Datenobjekte + +Wie bereits erwähnt, wollen wir mit Hilfe von Programmen Datenobjekte so +verändern, daß wir erwünschte Ergebnisse erhalten. Meist wird zu dieser Ver- +änderung von Datenobjekten "Rechnen" gesagt, obwohl - wie wir gleich sehen +werden - nicht nur numerische Objekte manipuliert werden. Die Veränderung +der Datenobjekte findet zur "Laufzeit" (nicht zur Übersetzungszeit) im +Rechner statt. Die Darstellung eines Werts in einem Rechner zur Laufzeit +eines Programms wird #ib#Repräsentation#ie# genannt. Wenn es eindeutig ist, +daß es sich nur um die Repräsentation im Rechner handelt, sprechen wir kurz +von Werten. +Da also ein Datenobjekt wechselnde Werte annehmen kann, brauchen wir eine +Möglichkeit, es in einem Programm anzusprechen, egal welchen Wert das Objekt +zu einem Zeitpunkt beinhaltet. Zu diesem Zweck können wir einem Datenobjekt +einen Namen geben (wie z.B. einen Personennamen, hinter dem sich eine wirk­ +liche Person "verbirgt"). Wenn wir also den Namen des Datenobjekts in ein +Programm schreiben, dann meinen wir (meist) den Wert des Datenobjekts, den +es zu diesem Zeitpunkt besitzt. + +Nun sollen die zu behandelnden Datenobjekte ja auch neue Werte erhalten. In +diesem Fall müssen wir die Speicherstelle finden, in die der neue Wert ge- +bracht werden soll. Für diesen Zweck benutzen wir ebenfalls den Namen, zu- +sätzlich zu der Angabe einer Operation, durch die das Objekt einen neuen +Wert erhalten soll. Diese Operation (Wert "schreiben") nennen wir Zuweisung. +Der Zuweisungs-Befehl wird ':=' geschrieben. Beispiel: + + a := 5 + +Bedeutet, daß das Datenobjekt mit dem Namen 'a' den Wert '5' erhält. + +Von manchen Datenobjekten wissen wir, daß wir ihnen nur einmal einen Wert +geben wollen. Sie sollen also nicht verändert werden. Oder wir wissen, daß +in einem Programmbereich ein Datenobjekt nicht verändert werden soll. Um ein +unbeabsichtigtes Verändern zu verhindern, wird in ELAN dem Namen eines +Datenobjekts ein zusätzlicher Schutz mitgegeben: das Zugriffsrecht oder +Accessrecht. Es besteht aus der Angabe der Worte VAR (für Lesen und Ver- +ändern) oder CONST (für ausschließliches Lesen). + + + +Die Deklaration (Vereinbarung) von Datenobjekten + +Wollen wir ein Datenobjekt in einem Programm verwenden, so müssen wir dem +Übersetzer mitteilen, welchen Datentyp und welches Accessrecht das Objekt +haben soll. Das dient u.a. dazu, nicht vereinbarte Namen (z.B. verschriebene) +vom Übersetzer entdecken zu lassen. Weiterhin ist aus dem bei der Deklaration +angegebenen Datentyp zu entnehmen, wieviel Speicherplatz für das Objekt zur +Laufzeit zu reservieren ist. Beispiel: + +INT VAR mein datenobjekt + +Zuerst wird der Datentyp, dann das Accessrecht und schließlich der Name des +Datenobjekts angegeben. Wie werden nun Namen in ELAN formuliert? + +Das erste Zeichen eines Namens muß immer ein kleiner Buchstabe sein. Danach +dürfen beliebig viele kleine Buchstaben, aber auch Ziffern folgen. Zur bes- +seren Lesbarkeit können (wie bei den obigen Prozedurnamen) Leerzeichen in +einem Namen erscheinen, die aber nicht zum Namen zählen. Beispiele: + + name1 + n a m e 1 + x27 + gehalts konto + das ist ein langer name + +Verschiedene Datenobjekte mit gleichem Datentyp und Accessrecht dürfen in +einer Deklaration angegeben werden (durch Kommata trennen). Mehrere Dekla- +rationen werden - genauso wie Anweisungen - durch das Trennsymbol +voneinander getrennt. Beispiele: + + INT VAR mein wert, dein wert, unser wert; + BOOL VAR listen ende; + TEXT VAR zeile, wort + + + +Die Initialisierung von Datenobjekten + +Um mit den so vereinbarten Datenobjekten arbeiten zu können, muß man ihnen +eine Wert geben. Hat ein Datenobjekt noch keinen Wert erhalten, so sagt man, +sein Wert sei undefiniert. Das versehentliche Arbeiten mit undefinierten +Werten ist eine beliebte Fehlerquelle. Deshalb wird von Programmierern +streng darauf geachtet, diese Fehlerquelle zu vermeiden. Eine Wertgebung an +ein Datenobjekt kann (muß aber nicht) bereits bei der Deklaration erfolgen, +was man in ELAN Initialisierung nennt. Beispiele: + + INT CONST gewuenschtes gehalt :: 12 000; + TEXT VAR zeile :: ""; + REAL CONST pi :: 3.14159; + BOOL VAR bereits sortiert :: TRUE + +Allerdings: für mit CONST vereinbarte Datenobjekte ist die Initialisierung +die einzige Möglichkeit, ihnen einen Wert zu geben. + +Die Initialisierung erfolgt mit Hilfe des '::'-Symbols. Anschließend folgt +der Wert, den das Datenobjekt erhalten soll. (In den Beispielen haben wir +nur Denoter geschrieben. Es sind aber auch allgemeinere Ausdrücke erlaubt.). +Es ist nun möglich, mit der oben erwähnten 'put'-Prozedur auch den Wert von +Datenobjekten ausgeben zu lassen. + + +Programm 5: + + INT VAR nummer :: 5; + TEXT CONST bemerkung :: ".Programm"; + put (nummer); + put (bemerkung) + +Beachte dabei, daß bei der Aufführung eines Namens in diesem Fall immer der +Wert des Datenobjekts gemeint ist. Auch die 'put'-Prozedur druckt nicht etwa +den Namen des Datenobjekts oder die Adresse der Speicherstelle, sondern +ebenfalls den Wert. + + +Aufgabe (HSG): + + Welche Aufgabe erfüllen Deklarationen? Was heißt: "Eine Variable hat + einen undefinierten Wert"? Was ist eine Initialisierung? Was ist ein + CONST-Datenobjekt? Warum müssen CONST-Datenobjekte initialisiert + werden? +Übungsziel: Verständnis von Deklarationen und Accessrecht + + + +Schlüsselworte + +Einige Worte haben in ELAN eine feste Bedeutung und können somit nicht - +wie etwa Namen - frei gewählt werden. Solche Worte werden bei den meisten +ELAN-Übersetzern mit großen Buchstaben geschrieben, wie z.B. VAR, CONST, +INT oder REAL u.a.m. Wie wir später sehen werden, besteht die Möglichkeit, +neue Schlüsselworte einzuführen. Halten wir vorläufig fest, daß feste +Bestandteile der Sprache (wie z.B. CONST oder VAR) und Datentypen (wie INT +oder REAL) Schlüsselworte sind, also mit großen Buchstaben geschrieben +werden. + + + +Ausdrücke + +Nun wäre es natürlich schlecht, wenn Programmierer nicht mehr machen könnten, +als Werte ausgeben. Als erste Stufe von etwas komplexeren "Rechnungen" +dürfen Ausdrücke gebildet werden. Ausdrücke sind eine Zusammenstellung von +Datenobjekten (Denoter, VAR- oder CONST-Objekte) und Operatoren. Schauen wir +uns dazu erst ein Programm an: + + +Programm 6: + + INT CONST wert 1 :: 1, + wert 2 :: 2, + wert 3 :: 3; + + put (wert1 + wert2); + put (wert2 - wert1); + put (wert2 * wert3); + put (wert3 DIV wert2); + put (wert2 ** wert3) + +In diesem Programm werden drei Datenobjekte initialisiert. Anschließend +werden jeweils die Werte von zwei Objekten addiert (Operatorzeichen: '+'), +subtrahiert ('-'), multipliziert ('*'), dividiert (ganzzahlige Division ohne +Rest: 'DIV') und potenziert ('**'). Dies sind Operatoren, die zwei Operanden +haben: man nennt sie dyadische Operatoren. Die monadischen Operatoren da- +gegen haben nur einen Operanden. Beispiel: + + put ( - wert1) + +Operatoren in ELAN werden - wie wir an den obigen Beispielen sehen - durch +ein oder zwei spezielle Zeichen oder durch große Buchstaben (in den Fällen, +in denen kein "vernünftiges" Zeichen mehr zur Verfügung steht) als Schlüssel- +wort dargestellt. + +Als Operanden (also die Datenobjekte, auf die ein Operator "wirken" soll) +eines Operators darf ein VAR- oder CONST-Datenobjekt, aber auch ein Denoter +verwendet werden. Das Resultat eines Operators (also das Ergebnis einer +Berechnung) ist bei den obigen Ausdrücken wieder vom Datentyp INT mit dem +Accessrecht CONST. Darum ist es erlaubt, solch einen Ausdruck wiederum als +Operanden zu verwenden. Praktisch bedeutet dies, daß wir mehrere Operatoren +und Datenobjekte zusammen in einem Ausdruck haben dürfen. + + +Programm 7: + + INT CONST wert 1 :: 1, + wert 2 :: 2, + wert 3 :: 3; + + put (wert2 + 3 - wert2 * wert3); + put (- wert2 * wert3) + +Nun haben wir eine Schwierigkeit: Der Ausdruck in der ersten 'put'-Anweisung +ist mehrdeutig, d.h. kann - je nach Reihenfolge der Auswertung - unter- +schiedliche Ergebnisse als Resultat liefern. Beispiel: + + a) (wert2 + 3 = 5) - (wert2 * wert3 = 6) = -1 + b) ((wert2 + 3 = 5) - wert2 = 3) * 3 = 9 + +Es kommt also auf die Reihenfolge der Auswertung von Operatoren an. Diese +kann man durch die Angabe von Klammern steuern. Beispiel: + + (a + b) * (a + b) + +Es wird jeweils erst 'a + b' ausgewertet und dann erst die Multiplikation +durchgeführt. In ELAN ist es erlaubt, beliebig viel Klammernpaare zu ver- +wenden (Regel: die innerste Klammer wird zuerst ausgeführt). Es ist sogar +zulässig, Klammern zu verwenden, wo keine notwendig sind, denn überflüssige +Klammernpaare werden überlesen. Beispiel: + + ((a - b)) * 3 * ((c + d) * (c - d)) + +Somit können wir beliebig komplizierte Ausdrücke formulieren. (Was man aber +vermeiden sollte, weil sie leicht zu Fehlern führen. Stattdessen kann man +einen komplizierten Ausdrücke in mehrere (einfachere) zerlegen.) + +Um solche Ausdrücke einfacher zu behandeln und sie so ähnlich schreiben zu +können, wie man es in der Mathematik gewohnt ist, wird in Programmiersprachen +die Reihenfolge der Auswertung von Operatoren festgelegt. In ELAN wurden +neun Ebenen, Prioritäten genannt, festgelegt: + + +Priorität Operatoren + + 9 alle monadischen Operatoren + 8 ** + 7 *, /, DIV, MOD + 6 +, - + 5 =, <>, <, <=, >, >= + 4 AND + 3 OR + 2 alle übrigen, nicht in dieser Tabelle aufgeführten + dyadischen Operatoren + 1 := + + +(Die bis jetzt noch nicht erwähnten Operatoren in der Tabelle werden wir in +den weiteren Abschnitten besprechen.) + +Operatoren mit der höchsten Priorität werden zuerst ausgeführt, dann die mit +der nächst höheren Priorität usw. Operatoren mit gleicher Priorität werden +von links nach rechts ausgeführt. Dadurch ergibt sich die gewohnte Abarbei- +tungsfolge wie beim Rechnen. Beispiel: + + -2 + 3 * 2 ** 3 + + a) -2 + b) 2 ** 3 + c) 3 * (2 ** 3) + d) ((-2)) + (3 * (2 ** 3)) + +Wie bereits erwähnt, ist es immer erlaubt, Klammern zu setzen. Ist man sich +also über die genaue Abarbeitungsfolge nicht im Klaren, so kann man Klammern +verwenden. + + +Aufgabe (HSG): + + Welche INT-Werte ergeben sich? + + a) 14 DIV 4 e) -14 DIV -4 + b) + 14 DIV 4 f) 2 * 3 DIV 2 ** 2 * 4 + c) -14 DIV 4 g) 2 ** 3 ** 4 + d) 14 DIV -4 h) 3 + 4 * 2 + 3 + +Übungsziel: Arithmetische Ausdrücke + + +Aufgabe (HSG): + + Bilden Sie für folgende mathematische Formeln entsprechende ELAN- + Ausdrücke: + + a b a+b + a) - c d) a g) - --- + b c + + + a+b b a c + b) --- e) -a h) - * - + c+d b d + + + a+b -b c + c) --- e f) a i) (a*b) + c+d + +Übungsziel: Arithmetische Ausdrücke formulieren + + + +Generische Operatoren und Prozeduren + +Bis jetzt wurden nur Ausdrücke mit INT-Operanden verwendet. Wie sieht es +jetzt mit REALs aus? + + +Programm 8: + + put (1.0 + 2.0); + put (2.0 - 1.0); + put (2.0 * 3.0); + put (3.0 / 2.0); + put (2.0 ** 3.0) + +Man beachte die Unterschiede zum Programm 7: Wir müssen nun REAL-Denoter +verwenden (mit INT-Denotern zu arbeiten wäre ein Fehler). Der Divisions- +Operator hat sich nun von 'DIV' zu '/' gewandelt. Die Ergebnisse sind nun +nicht INT-, sondern REAL-Werte. Für die Reihenfolge der Auswertung der +Operatoren sowie die Verwendung von Klammern gilt das für INT-Ausdrücke +gesagte. + +Wir haben den '+'-Operator in zwei verschiedenen Formen gesehen: in Programm +7 mit Operanden vom Datentyp INT, ein INT-Resultat liefernd, und in Programm +8 das gleiche mit REALs. Es liegen also zwei verschiedene Operatoren vor, +die aber den gleichen Namen (Zeichen: '+') haben. + +In ELAN ist es somit möglich, unterschiedlichen Operatoren (aber auch Proze- +duren) gleiche Namen zu geben. Solche Operatoren werden generische Opera- +toren genannt. Ein ELAN-Compiler wählt den richtigen Operator aufgrund der +Datentypen der Operanden aus. Oft werden die verfügbaren Operatoren wie folgt +dokumentiert: + + INT OP + (INT CONST links, rechts) + +Diese Form nennt man einen "Operator-Kopf". Sie wird in ELAN-Programmen bei +der Definition von Operatoren benötigt. Dabei steht OP für "OPERATOR". Die +Angabe des Datentyps davor gibt den Datentyp des Resultats des Operators an. +Zwischen 'OP' und der öffnenden Klammer steht der Name des Operators (hier: +'+'). In den Klammern werden die Datentypen und das Accessrecht der +Operanden angegeben. CONST bedeutet hier: der Operand darf vom Operator +nicht verändert werden, während bei VAR (was normalerweise ja nicht sein +sollte!) ein Operand bei der Abarbeitung eines Operators verändert werden +kann. + +Damit wir solche Definitionen besser beherrschen, geben wir noch weitere +Beispiele an: + + INT OP - (INT CONST operand) + REAL OP / (INT CONST l, r) + +Bei dem ersten Operator handelt es sich um den monadischen Operator '-' für +INT-Operanden (z.B.: 'INT VAR a :: 1; put (-a)'), während es sich bei dem +zweiten Operator um eine Divisions-Operator handelt, der jedoch ein REAL- +Resultat liefert (z.B.: 'put (3 / 2)' liefert 1.5). Der MOD-Operator liefert +den Rest einer Division: + + INT OP MOD (INT CONST l, r) + REAL OP MOD (REAL CONST l, r) + +Die Beschreibung von generischen Prozeduren verläuft analog. Beispiele: + + PROC put (INT CONST wert) + PROC put (REAL CONST wert) + +Hier wird das Wort 'OP' durch 'PROC' (für 'PROCEDURE') ersetzt. Die Angaben +in Klammern bezeichnen nun nicht Operanden, sondern Parameter. + +Über die verfügbaren Operatoren und Prozeduren für INT- und REAL-Datenob- +jekte kann man sich im ELAN-Handbuch oder im EUMEL-Benutzerhandbuch infor- +mieren. Einige - aber nicht alle - der Operatoren und Prozeduren (auch für +andere Datentypen) werden wir erklären, wenn wir sie in Programmen benötigen. + + + +Die Zuweisung + +Ein spezieller Operator ist die Zuweisung (Zeichen: ':='). Dieser Operator +hat immer die geringste Priorität, wird also immer als letzter eines Aus- +drucks ausgeführt. Die Zuweisung wird verwendet, um einer Variablen einen +neuen Wert zu geben. Beispiel: + + a := b + +Hier wird der Wert von 'b' der Variablen 'a' zugewiesen. Der vorher vor- +handene Wert von 'a' geht dabei verloren. Man sagt auch, der Wert wird über- +schrieben. Auf der rechten Seite (also als rechter Operand) des ':=' +Operators darf auch ein Ausdruck stehen. Beispiel: + + a := b + c + +Hier wird das Resultat von 'b + c' an die Variable 'a' zugewiesen. Man be- +achte dabei die Prioritäten der Operatoren '+' (Priorität 6) und ':=' (Pri- +orität 1): die Addition wird vor der Zuweisung ausgeführt. Die Auswertung +von Zuweisungen mit Ausdrücken muß immer so verlaufen, da die Zuweisung +stets die niedrigste Priorität aller Operatoren hat. + +Schauen wir uns zum besseren Verständnis die Definitionen des (natürlich +auch generischen) Operators ':=' an: + + OP := (INT VAR ziel, INT CONST quelle) + OP := (REAL VAR ziel, REAL CONST quelle) + OP := (TEXT VAR ziel, TEXT CONST quelle) + OP := (BOOL VAR ziel, BOOL CONST quelle) + +Der Operator ':=' liefert also kein Resultat (man sagt auch, er liefert +keinen Wert) und verlangt als linken Operanden ein VAR-Datenobjekt (an den +der Wert der rechten Seite zugewiesen werden soll). Der Wert des linken +Operanden wird also verändert. Für den rechten Operanden ist durch CONST +sichergestellt, daß er nur gelesen wird. + +Oft kommt es vor, daß ein Objekt auf der linken und rechten Seite des Zuwei- +sungsoperators erscheint, z.B. wenn ein Wert erhöht werden soll. Beispiele: + + a := a + 1; + a := a + 17 + +Hier wird der "alte", aktuelle Wert von 'a' genommen, um '1' erhöht und dem +Objekt 'a' zugewiesen. Man beachte, daß hier in einer Anweisung ein Datenob- +jekt unterschiedliche Werte zu unterschiedlichen Zeitpunkten haben kann. + +In solchen Fällen darf man den Operator INCR verwenden: + + a INCR 1; + a INCR 17 + +Analoges gilt für den Operator DECR, bei dem ein Wert von einer Variable +subtrahiert wird. Also: + + OP INCR (INT VAR ziel, INT CONST dazu) + OP INCR (REAL VAR ziel, REAL CONST dazu) + + OP DECR (INT VAR ziel, INT CONST abzug) + OP DECR (REAL VAR ziel, REAL CONST abzug) + +Schauen wir uns folgendes Programm an, bei dem zwei Werte vertauscht werden: + + +Programm 9: + + INT VAR a, b, x; + + get (a); + get (b); + x := a; + a := b; + b := x; + put (a); + put (b) + +Wie wir an diesem Beispiel sehen, existieren nicht nur 'put'-Prozeduren, +sondern auch 'get'-Prozeduren, die einen Wert vom Eingabemedium einlesen. +Es gibt folgende 'get'- Prozeduren (die 'put'-Prozeduren führen wir der +Vollständigkeit halber auch mit auf): + + PROC get (INT VAR wert) + PROC get (REAL VAR wert) + PROC get (TEXT VAR wert) + + PROC put (INT CONST wert) + PROC put (REAL CONST wert) + PROC put (TEXT CONST wert) + + +Aufgabe (HSG): + + Was versteht man unter Generizität? + Übungsziel: Generizitäts-Begriff + + + +Refinements + +Bevor wir die Operationen für TEXTe und BOOLs besprechen, wollen wir eine +weitere wichtige Eigenschaft von ELAN diskutieren, nämlich die Namensgebung. +Namen für Datenobjekte haben wir bereits kennengelernt. In ELAN ist es eben- +falls möglich, Namen für Ausdrücke oder eine bzw. mehrere Anweisungen zu +vergeben. + + +Programm 10: + + INT VAR a, b, x; + einlesen von a und b; + vertauschen von a und b; + vertauschte werte ausgeben. + + einlesen von a und b: + get (a); + get (b). + + vertauschen von a und b: + x := a; + a := b; + b := x. + + vertauschte werte ausgeben: + put (a); + put (b). + +Dies ist das gleiche Programm wie das 9. Beispielprogramm. Für den Namen +'einlesen von a und b' werden die Anweisungen 'get (a); get (b)' vom +ELAN-Übersetzer eingesetzt. Man kann also die ersten vier Zeilen des +Programms als eigentliches Programm ansehen, wobei die Namen durch die +betreffenden Anweisungen ersetzt werden. Eine solche Konstruktion wird in +ELAN Refinement genannt. Was wird dadurch erreicht? + +Durch die sinnvolle Verwendung von Refinements wird ein Programm im Programm +und nicht in einer separaten Beschreibung dokumentiert. Weiterhin kann ein +Programm "von oben nach unten" ("top down") entwickelt werden: wir haben das +obige - zugegeben einfache - Beispielprogramm in drei Teile zerlegt und +diese durch Namen beschrieben. Bei der Beschreibung von Aktionen durch Namen +sagen wir, was wir machen wollen und nicht wie, denn wir brauchen uns auf +dieser Stufe der Programmentwicklung um die Realisierung der Refinements +(noch) keine Sorgen zu machen. Das erfolgt erst, wenn wir genauer definieren +müssen, wie das Refinement programmiert werden muß. Dabei können wir +wiederum Refinements verwenden usw., bis wir auf eine Ebene "herunterge- +stiegen" sind, bei dem eine (jetzt: Teil-) Problemlösung sehr einfach ist +und wir sie direkt hinschreiben können. Wir beschäftigen uns also an jedem +Punkt der Problemlösung nur mit einem Teilaspekt des gesamten Problems. +Zudem sieht man - wenn die Refinements einigermaßen vernünftig verwendet +werden - dem Programm an, wie die Problemlösung entstanden ist. + +Die Verwendung von Refinements hat also eine Anzahl von Vorteilen. Schauen +wir uns deshalb an, wie die Refinements formal verwandt werden müssen. Das +"Hauptprogramm" wird durch einen Punkt abgeschlossen, falls ein Refinement +folgt. Ein Refinement besteht aus der Nennung des Refinement-Namens, der +von einem Doppelpunkt gefolgt sein muß. In einem Refinement kann eine +Anweisung oder mehrere - durch Semikolon getrennt - stehen. Das Refinement +wird durch einen Punkt abgeschlossen. + +Refinements können auch dort verwendet werden, wo ein Wert erwartet wird, +z.B. in einem Ausdruck oder einer 'put'-Anweisung. In diesem Fall muß das +Refinement natürlich einen Wert liefern. Wie macht man das? Eine Möglichkeit +ist, daß im Refinement ein Ausdruck geschrieben wird, der einen Wert als +Resultat liefert. + + +Programm 11: + + INT VAR a :: 1, b :: 2, c :: 3; + put (resultat). + + resultat: + (a * b + c) ** 3. + +Eine Zuweisung liefert - wie bereits erwähnt - kein Resultat. Es ist auch +erlaubt, ein Refinement mit mehreren Anweisungen zu schreiben, das einen Wert +liefert. Allgemeine Regel: die letzte Anweisung eines Refinements bestimmt, +ob ein Refinement einen Wert liefert - und wenn ja, von welchen Datentyp. + + + +BOOLesche Operationen + +Für BOOLesche Datenobjekte gibt es einige Operatoren: + + BOOL OP AND (BOOL CONST links, rechts) + BOOL OP OR (BOOL CONST links, rechts) + BOOL OP NOT (BOOL CONST operand) + +Der Operator AND liefert als Resultat die logische "und"-Verknüpfung (nur +wenn beide Operanden den Wert TRUE haben ist das Resultat TRUE, sonst FALSE), +OR ist das logische "oder" (nur wenn beide Operanden FALSE liefern, ist das +Resultat FALSE, sonst TRUE) und die logische Negation NOT (als Resultat wird +das "Gegenteil" geliefert). + +Ebenfalls wichtig sind die Vergleichs-Operatoren, die zwar keine BOOLeschen +Operanden erwarten, aber ein BOOLesches Resultat liefern: + + BOOL OP = (INT CONST links, rechts) + BOOL OP <> (INT CONST links, rechts) + BOOL OP < (INT CONST links, rechts) + BOOL OP <= (INT CONST links, rechts) + BOOL OP > (INT CONST links, rechts) + BOOL OP >= (INT CONST links, rechts) + +Diese Operatoren: = (gleich), <> (ungleich), < (kleiner), <= (kleiner +gleich), > (größer), >= (größer gleich) gibt es auch noch für Operanden vom +Datentyp REAL und TEXT. Da die Vergleichs-Operatoren ein BOOLesches Resultat +liefern, kann man sie in BOOLeschen Ausdrücken verwenden. Zu beachten ist +dabei die Priorität der Operatoren: die Vergleiche werden immer vor den +Operatoren AND bzw. OR ausgeführt. + + +Programm 12: + + BOOL CONST kaufen; + kaufen := will ich AND NOT zu teuer. + + will ich: + TEXT VAR produktname; + get (produktname); + produktname = "muesli" OR produktname = "vollkornbrot". + + zu teuer: + INT VAR preis; + get (preis); + preis > 20. + + + +Aufgabe (HSG): + + Welche BOOL-Werte ergeben sich? + + a) TRUE AND FALSE e) TRUE AND TRUE OR TRUE + b) TRUE OR FALSE f) 10 < 3 AND 17 > 4 + c) TRUE AND NOT FALSE g) 17 + 4 = 21 OR TRUE + d) NOT TRUE AND FALSE h) TRUE AND FALSE OR TRUE + + Übungsziel: Boolesche Ausdrücke + + + +Abfragen + +BOOLesche Ausdrücke werden in einer speziellen Anweisung verwandt, der +Abfrage: + + +Programm 13: + + INT VAR a, b; + get (a); get (b); + IF a > b + THEN vertausche a und b + END IF; + put (a); put (b). + + vertausche a und b: + INT CONST x :: a; + a := b; + b := x. + +Das Refinement im THEN-Teil der bedingten Anweisung wird nur durchgeführt, +wenn der BOOLesche Ausdruck ('a > b') den Wert TRUE liefert. Liefert er den +Wert FALSE, wird die Anweisung, die der bedingten Anweisung folgt (nach END +IF), ausgeführt. Programm 13 kann etwas anders geschrieben werden: + + +Programm 14: + + INT VAR a, b; + get (a); get (b); + IF a > b + THEN put (a); + put (b) + ELSE put (b); + put (a) + END IF. + +Der THEN-Teil wird wiederum ausgeführt, wenn die BOOLesche Bedingung +erfüllt ist. Liefert sie dagegen FALSE, wird der ELSE-Teil ausgeführt. + +Die bedingte Anweisung gibt uns also die Möglichkeit, abhängig von einer +Bedingung eine oder mehrere Anweisungen ausführen zu lassen. Dabei können +im THEN- bzw. ELSE-Teil wiederum bedingte Anweisungen enthalten sein usw. +Solche geschachtelten bedingten Anweisungen sollte man jedoch vermeiden, +weil sie leicht zu Fehlern führen können (statt dessen durch Refinements +realisieren). Man beachte auch die Einrückungen, die man machen sollte, um +die "Zweige" besonders kenntlich zu machen. + + +Aufgabe (HSG): + + a) In welcher Reihenfolge werden Operatoren ausgewertet? + b) Reihenfolge der Auswertung von: a + b + c + c) INT VAR a, b, c; + ... + IF NOT a = 0 AND b = 0 THEN... + ergibt einen syntaktischen Fehler. Welchen? + d) Wie wird der BOOLesche Ausdruck ausgewertet? + INT VAR a :: 0, b :: 4; + ... + IF a = 0 AND b DIV a > 0 + e) Warum ist + BOOL VAR ende :: TRUE; + ... + IF ende = TRUE + THEN... + Unsinn? + + Übungsziel: Reihenfolge der Auswertung von Ausdrücken + +Bei Abfrageketten kann das ELIF-Konstrukt eingesetzt werden. (ELIF ist eine +Zusammenziehung der Worte ELSE und IF). Anstatt + + ... + IF bedingung1 + THEN aktion1 + ELSE IF bedingung2 + THEN aktion2 + ELSE aktion3 + END IF + END IF; + ... + +kann man besser + + ... + IF bedingung1 + THEN aktion1 + ELIF bedingung2 + THEN aktion2 + ELSE aktion3 END IF; + ... + +schreiben. + +Die bedingte Anweisung kann auch einen Wert liefern. In diesem Fall muß der +ELSE-Teil vorhanden sein und jeder Zweig den gleichen Datentyp liefern +(jeweils die letzte Anweisung muß einen Wert liefern). + + +Aufgabe (HSG): + + Was berechnen folgende (Teil-) Programme? + + a) INT VAR a; + get (a); + put (wert). + + wert: + IF a < 0 + THEN -a + ELSE a + END IF. + + b) INT VAR brutto, netto; + get (brutto); + berechne gehalt; + put ("mein gehalt:"); + put (netto). + + berechne gehalt: + IF jahresverdienst > 30 000 (* zu wenig? *) + THEN sonderabgabe + END IF; + netto := brutto - brutto DIV 100 * 20. + + jahresverdienst: + brutto * 12. + + sonderabgabe: + brutto := brutto - brutto DIV 100 * 30 + + c) INT VAR x; + ... + put (signum). + + signum: + IF x > 0 + THEN 1 + ELSE kleiner gleich + END IF. + + kleiner gleich: + IF x = 0 + THEN 0 + ELSE -1 + END IF. + + + +TEXTe + +TEXT-Denoter haben wir bereits kennengelernt. Im folgenden Programm stellen +wir die Wirkung einiger TEXT-Operationen vor. + + +Programm 15: + + TEXT VAR a, b, c; + a := "ELAN"; + b := "-Programm"; + c := a + b; + put (c) + +Der Operator + + TEXT OP + (TEXT CONST links, rechts) + +liefert als Ergebnis einen TEXT, bei dem an den linken der rechte Operand +angefügt wurde (Fachausdruck: "Konkatenation"). Weitere Operatoren: + + TEXT OP CAT (TEXT VAR ziel, TEXT CONST dazu) + TEXT OP * (INT CONST i, TEXT CONST a) + TEXT OP SUB (TEXT CONST t, INT CONST pos) + +Der Operator CAT fügt an einen TEXT einen zweiten an ('a CAT b' wirkt wie +'a := a + b'). Mit dem '*'-Operator kann man einen TEXT vervielfältigen +(Beispiel: 17 * "--"), während man mit SUB ein Zeichen aus einem TEXT her- +ausholen kann (Beispiel: "ELAN" SUB 3 liefert "A"). + +Die meisten TEXT-Operationen sind als Prozeduren realisiert, weil mehr als +zwei Operanden benötigt werden. Die Wirkung einiger Operationen geben wir in +kurzen Kommentaren an: + + TEXT PROC subtext (TEXT CONST t, INT CONST von) + (* rechter Teiltext von 't' von der Position 'von' bis Ende *) + + TEXT PROC subtext (TEXT CONST t, INT CONST von, bis) + (* Teiltext von 't' von der Position 'von' bis 'bis' *) + + PROC change (TEXT VAR t, TEXT CONST old, new) + (* Ersetzung von 'old' in 'new' im TEXT 't' *) + + INT PROC length (TEXT CONST t) + (* Anzahl Zeichen von 't' *) + + INT PROC pos (TEXT CONST t, muster) + (* Die Position des ersten Auftretens von 'muster' in 't' *) + +Die Vergleichs-Operatoren für TEXTe arbeiten bei dem Vergleich nach der +alphabetischen Reihenfolge ('"a" < "b"' liefert TRUE). Dabei definiert ELAN +nur die Reihenfolge innerhalb der kleinen und großen Buchstaben und Ziffern. +Das Leerzeichen ("#ib#blank#ie#") ist jedoch stets das "kleinste" Zeichen. +Wie diese "Zeichenblöcke" und die restlichen Zeichen angeordnet sind, wurde +nicht spezifiziert. Ob '"a" < "Z"' TRUE oder FALSE liefert, wurde also nicht +festgelegt und ist somit rechnerspezifisch. Anmerkung: Im EUMEL-Betriebs- +system wird der ASCII-Zeichencode, DIN 66 003 mit Erweiterungen verwandt. +Die folgenden Vergleiche sind alle TRUE: + + "otto" = "otto" + "a" < "z" + "Adam" < "Eva" + "hallo" < "hallu" + "hallo" < "hallo " + length ("ha") = 2 + subtext ("ELAN-Programmierung", 14) = "ierung" + + +Aufgabe (HSG): + + Gib die Realisierung von folgenden vorgegebenen Prozeduren und Opera- + toren an: + a) TEXT PROC subtext (TEXT CONST t, INT CONST von) durch + TEXT PROC subtext (TEXT CONST t, INT CONST von, bis) + b) OP CAT (TEXT VAR a, TEXT CONST b) durch ':=' und '+' + c) TEXT OP SUB (TEXT CONST t, INT CONST p) durch 'subtext' + + Übungsziel: Lernen einiger vorgegebener TEXT-Operationen + + + +Die Wiederholungs-Anweisung + +Wiederholungs-Anweisungen ermöglichen es uns, Anweisungen wiederholt - meist +in Abhängigkeit von einer Bedingung - ausführen zu lassen. Darum wird die +Wiederholungs-Anweisung oft auch #ib#Schleife#ie# genannt, die in ihr ent- +haltenen Anweisungen #ib#Schleifenrumpf#ie#. Die Schleife von ELAN baut auf +einem Basis-Konstrukt auf: + + REP + anweisungen + END REP + +Diese Anweisungsfolge realisiert eine sogenannte "Endlosschleife", weil nicht +spezifiziert wird, wann die Schleife beendet werden soll. + +Bei der abweisenden Schleife wird die Abbruchbedingung an den Anfang der +Schleife geschrieben: + + WHILE boolesche bedingung REP + anweisungen + END REP + +Bei jedem erneuten Durchlauf durch die Schleife wird überprüft, ob der +BOOLesche Ausdruck den Wert TRUE liefert. Ist das nicht der Fall, wird mit +der nächsten, auf die Schleife folgenden Anweisung mit der Bearbeitung fort- +gefahren. Die Schleife wird abweisende Schleife genannt, weil der Schleifen- +rumpf nicht ausgeführt wird, wenn die Bedingung vor Eintritt in die Schleife +bereits FALSE liefert. + +Anders verhält es bei der nicht abweisenden Schleife: + + REP + anweisungen + UNTIL boolesche Bedingung END REP + +Hier wird der Schleifenrumpf auf jeden Fall einmal bearbeitet. Am Ende des +Rumpfes wird die BOOLesche Bedingung abgefragt. Liefert diese den Wert FALSE, +wird die Schleife erneut abgearbeitet. Liefert die Bedingung den Wert TRUE, +wird die Schleife abgebrochen und mit der ersten Anweisung hinter der +Schleife in der Bearbeitung fortgefahren. + +Bei beiden Arten der Wiederholungs-Anweisung ist es wichtig, daß Elemente +der BOOLeschen Bedingung in der Schleife verändert werden, damit das +Programm terminieren kann, d.h. die Schleife abgebrochen wird. + +Eine Endlos-Schleife wird bei der Zählschleife meist nicht vorkommen: + + FOR i FROM anfangswert UPTO endwert REP + anweisungen + END REP + +Zählschleifen werden eingesetzt, wenn die genaue Anzahl der Schleifendurch- +läufe bekannt ist. Hier wird eine Laufvariable verwendet (in unserem Bei- +spiel 'i': sie muß mit INT VAR deklariert werden), die die INT-Werte von +'anfangswert' bis 'endwert' in Schritten von '1' durchläuft. Diese Schleife +zählt "aufwärts". Wird anstatt UPTO das Schlüsselwort DOWNTO verwendet, wird +mit Schritten von -1 "abwärts" gezählt. Beispiel: + + FOR i FROM endwert DOWNTO anfangswert REP + ... + +Für ein Beispielprogramm stellen wir uns die Aufgabe, aus TEXTen das Auf- +treten des Buchstabens "e" herauszufinden. Die TEXTe sollen vom Eingabe- +medium solange eingelesen werden, bis wir den TEXT "00" eingeben. + + +Programm 16: + + INT VAR anzahl e :: 0; + TEXT VAR wort; + REP + get (wort); + zaehle e im wort + UNTIL wort = "00" END REP; + put (anzahl e). + + zaehle e im wort: + INT VAR i; + FOR i FROM 1 UPTO length (wort) REP + IF das i te zeichen ist e + THEN anzahl e INCR 1 + END IF + END REP. + + das i te zeichen ist e: + (wort SUB i) = "e". + + +Aufgabe (HSG): + + Die Klammern in dem letzten Refinement sind notwendig. Warum? + +Bevor wir ein Programm einem Rechner zur Bearbeitung übergeben, sollten wir +uns davon überzeugen, daß das Programm wirklich das leistet, was es soll. +Eine der wichtigsten Bedingungen ist die Terminierung eines Programms, d.h. +das Programm darf nicht in eine Endlosschleife geraten. Unser Beispielpro- +gramm terminiert, wenn beide Schleifen terminieren: die obere Schleife +terminiert durch das Endekriterium, während die zweite Schleife automatisch +durch die Zählschleife begrenzt wird. Das Programm wird also auf jeden Fall +beendet (kann in keine Endlosschleife geraten), falls das Endekriterium ein- +gegeben wird. +Interessant sind dabei immer "Grenzfälle", wie z.B. die Eingabe eines +"leeren Textes", sehr lange TEXTe usw. + + +Aufgabe (HSG): + + Welche Fehler befinden sich in den folgenden Programmteilen? + a) INT VAR i; + FOR i FROM 1 UPTO i REP + tue irgendwas + END REP + + b) BOOL CONST noch werte :: TRUE; + INT VAR i; + WHILE noch werte REP + get (i); + ... + IF i = O + THEN noch werte := FALSE + END IF + END REP + + c) INT VAR anz berechnungen :: 1; + REP + lies eingabe wert; + berechnung; + drucke ausgabewert + UNTIL anz berechnungen > 10 END REP. + + d) INT VAR anz berechnungen; + WHILE anz berechnungen <= 10 REP + lies eingabewert; + berechnung; + drucke ausgabewert; + anz berechnungen INCR 1 + END REP. + + e) INT VAR n := 1, summe; + summe der ersten 100 zahlen. + + summe der ersten 100 zahlen: + WHILE n < 100 REP + summe := summe + n; + n INCR 1 + END REP. + (* Achtung: 2 Fehler! (Vorwarnen ist feige) *) + + f) INT VAR n := 1; + REP + INT VAR summe := 0; + summe := summe + n; + n INCR 1 + UNTIL n = 100 END REP + (* Achtung: 2 Fehler! *) + + Übungsziel: Arbeiten mit Schleifen + + +Das Programm 16 können wir etwas besser formulieren. Dazu wollen wir uns +aber eine etwas andere Aufgabe stellen: wie viele Leerzeichen sind in einem +Text? Zur Lösung dieser Aufgabe sollten wir den Text nicht wortweise ein- +lesen, sondern zeilenweise. Dazu verwenden wir die Prozedur + + PROC get (TEXT VAR t, INT CONST max length) + +die einen TEXT 't' mit maximal 'max length' Zeichen einliest. Auf dem +EUMEL-System gibt es dafür auch die Prozedur 'getline'. + + +Programm 17: + + INT VAR anzahl blanks :: 0; + REP + lies zeile ein; + zaehle blanks + UNTIL zeile hat endekriterium END REP. + + lies zeile ein: + TEXT VAR zeile; + get (zeile, 80). + + zaehle blanks: + INT VAR von :: 1; + WHILE zeile hat ab von ein blank REP + anzahl blanks INCR 1; + von auf blank position setzen + END REP. + + zeile hat ab von ein blank: + pos (zeile, " ", von) > 0. + + von auf blank position setzen: + von := pos (zeile, " ", von). + + zeile hat endekriterium: + pos (zeile, "00") > 0. + + +Aufgabe (TSW): + + Das Programm 17 enthält (mindestens) zwei Fehler. Finden Sie diese bitte + heraus. + + Übungsziel: Finden von Programmierfehlern. + + +Aufgabe (HSG): + + a) Welche Werte liefern folgende Ausdrücke für die Textvariable + TEXT VAR t :: "Das ist mein Text" + a1) pos (t, "ist") + a2) pos (t, "ist", 5) + a3) length (t) + a4) subtext (t, 14) + a5) subtext (t, 14, 17) + + b) Welche Werte liefern folgende Ausdrücke für die Textkonstanten + TEXT CONST text :: "ELAN-Programm", + alphabet :: "abcde...xyz" + b1) 3 * text + b2) length ("mein" + text + 3 * "ha") + b3) 3 * "ha" < text + b4) pos (text, alphabet SUB 1) + b5) pos (text, subtext (alphabet, 7, 7)) + + c) Schreibe in anderer Form: + c1) subtext (text, 7, 7) + c2) change (text, "alt", "neu") + c3) INT VAR laenge :: length (text); + IF subtext (text, laenge, laenge) =... + c4) IF NOT (text = "aha") + THEN aktion 1 + ELSE aktion 2 + END IF + + Übungsziel: TEXT-Ausdrücke und Prozeduren + + + +Die Repräsentation von Datentypen + +Wie bereits erwähnt, sind Datentypen Klassen von Objekten der realen Umwelt. +Die Objekte eines Datentyps müssen in den Speicher eines Rechners abgebildet +werden. Die Darstellung eines Objekts im Rechner wird Repräsentation genannt. +Aus organisatorischen Gründen versucht man, immer feste, gleich große Ein- +heiten für die Objekte eines Datentyps zu verwenden. Durch die Begrenzung auf +feste Speicherplatzeinheiten ist der Wertebereich beschränkt. Diese Grenzen +hat man beim Programmieren zu beachten. + +Beim Datentyp BOOL spielt die Repräsentation nur insoweit eine Rolle, daß +man die zwei möglichen Werte mehr oder weniger speicheraufwendig realisieren +kann. Eine Einschränkung des Wertebereichs gibt es nicht. + +Bei INTs ist jedoch eine Einschränkung des Wertebereichs gegeben. Für die +Repräsentation von INTs sind Einheiten von 16, 32 Bit u.a.m. gebräuchlich. +Es existiert die Möglichkeit, den größten INT-Wert mit Hilfe von + + maxint + +zu erfragen. Z.B. ist 'maxint' für EUMEL-Systeme z.Zt. 32 767. Der kleinste +INT-Wert ist oft nicht ' - maxint' (im EUMEL-System kann er unter 'minint' +angesprochen werden). Übersteigt ein Wert 'maxint', gibt es eine Fehler- +meldung 'overflow', im andern Fall 'underflow'. + +REALs sind noch schwieriger. Durch die endliche Darstellung der Mantisse +treten "Lücken" zwischen zwei benachbarten REALs auf. Deshalb ist bei Ver- +wendung von REALs immer mit Repräsentationsfehlern zu rechnen. Dieses Thema +der "Rundungsfehler" wollen wir hier jedoch nicht weiter vertiefen. Auf +jeden Fall gibt es aber auch einen größten REAL-Wert + + maxreal + +Bei TEXTen gibt es zwei Repräsentations-Schwierigkeiten. Einerseits werden +TEXTe durch "irgendeinen" Code im Rechner repräsentiert, der z.B. bei Ver- +gleichen verwendet wird. ELAN-Compiler auf Rechenanlagen mit unterschied- +lichen Zeichencodes können daher unterschiedliche Ergebnisse liefern. +Andererseits ist in ELAN nicht definiert, wie viele Zeichen maximal in einen +TEXT passen, was ebenfalls vom Rechner bzw. von einem ELAN-Compiler abhängt. +Auf dem EUMEL-System kann die maximale Anzahl Zeichen eines TEXTs durch +'maxtext length' erfragt werden. Sie ist z.Z. '32 000'. + + + +Ein- und Ausgabe + +Wie Datenobjekte - auf einfache Weise - auf einem Ausgabemedium ausgegeben +werden können, haben wir bereits geschildert (Prozedur 'put'). Die Ausgabe +erfolgt solange auf einer Zeile, bis ein auszugebender Wert nicht mehr auf +eine Zeile paßt. In diesem Fall wird die Ausgabe in die nächste Zeile pla- +ziert. Zwischen den einzelnen Werten auf einer Zeile wird jeweils ein Blank +Zwischenraum gelassen, um die Ausgaben voneinander zu trennen. Mit folgenden +Prozeduren kann man die Ausgabe flexibel gestalten: + + PROC line (* bewirkt einen Zeilenvorschub *) + + PROC line (INT CONST anzahl) (* bewirkt 'anzahl' Zeilenvorschübe *) + + PROC page (* bewirkt einen Seitenvorschub auf + einem Drucker oder löscht den Bild- + schirm und positioniert in die linke + obere Ecke *) + + PROC putline (TEXT CONST zeile) (* gibt 'zeile' auf dem Bildschirm aus + und positioniert auf die nächste + neue Zeile *) + + PROC cursor (INT CONST reihe, spalte) (* Positioniert die Schreibmarke + auf dem Bildschirm in die an- + gegebene Position *) + +Die Prozedur 'get' holt Eingaben vom Eingabemedium. Ein Element der Eingabe +wird dabei durch ein Blank vom nächsten getrennt. Einige weitere Eingabe- +Prozeduren: + + PROC get (TEXT VAR t, TEXT CONST delimiter) (* die nächste Eingabe wird + nicht von einem Blank + begrenzt, sondern durch + 'delimiter' *) + + TEXT PROC get (* dient zum Initialisieren *) + + PROC inchar (TEXT VAR zeichen) (* wartet solange, bis ein Zeichen vom + Bildschirm eingegeben wird *) + + TEXT PROC incharety (* Versucht ein Zeichen vom Bildschirm + zu lesen. Ist kein Zeichen vor- + handen, wird "" geliefert *) + + PROC editget (TEXT VAR line) (* Bei der Eingabe kann 'line' editiert + werden *) + + PROC get cursor (INT VAR zeile, spalte) (* Informationsprozedur, wo die + Schreibmarke aktuell steht *) + + + +Konvertierungen + +Manchmal ist es notwendig, eine Datentyp-Wandlung für ein Objekt vorzunehmen. +Die Wandlungen von einem INT- bzw. einen REAL-Wert in einen TEXT und umge- +kehrt sind relativ unkritisch: + + TEXT PROC text (INT CONST value) + TEXT PROC text (REAL CONST value) + INT PROC int (TEXT CONST number) + REAL PROC real (TEXT CONST number) + +Aber bei der folgenden Prozedur 'int' gehen im allgemeinen Fall Informationen +verloren (es wird abgeschnitten): + + INT PROC int (REAL CONST value) + REAL PROC real (INT CONST value) + +Zusätzlich steht eine Informationsprozedur 'last conversion ok' zur Ver- +fügung, die den Wert TRUE liefert, falls die letzte Konversion fehlerfrei +war: + + BOOL PROC last conversion ok + +Solche Abfragen sind notwendig, weil die Konversionsroutinen bei falschen +Parameterwerten (z.B. 'int (maxreal)') nicht mit einer Fehlermeldung ab- +brechen. Als Beispiel zeigen wir ein Programm zum Einlesen von Werten, von +denen man nicht weiß, ob sie INT oder REAL sind. Darum kann auch nicht die +'get'-Prozedur für INT oder REAL verwandt werden: + + +Programm 18: + + TEXT VAR eingabe element; + REP + get (eingabe element); + wert nach intwert oder realwert bringen; + berechnung + UNTIL ende ENDREP. + + wert nach intwert oder realwert bringen: + IF pos (eingabe element, ".") > 0 + THEN REAL VAR realwert :: real (eingabe element) + ELSE INT VAR intwert :: int (eingabe element) + END IF; + IF NOT last conversion ok + THEN put ("Fehler bei Konvertierung:" + eingabe element); + line + END IF. + + berechnung: + ... + + -- cgit v1.2.3