224 58 22MB
German Pages 332 [336] Year 1984
de Gruyter Lehrbuch Schulz • Einführung in das Programmieren in PL/1
Arno Schulz
Einführung in das Programmieren in PL/1 2., bearbeitete und erweiterte Auflage
W DE
C_
Walter de Gruyter • Berlin • New York 1984
Dr. techn. A r n o Schulz o. Universitätsprofessor Institut für Informatik der J o h a n n e s K e p l e r U n i v e r s i t ä t Linz
Schulz, Arno: Einführung in das Programmieren in PL 1/Arno Schulz. - 2., bearb. u. erw. Aufl. - Berlin; New York: de Gruyter, 1984. ISBN 3 - 1 1 - 0 0 9 9 8 8 - 8
© Copyright 1984 by Walter de Gruyter & Co., Berlin 30. Alle Rechte, insbesondere das Recht der Vervielfältigung und Verbreitung sowie der Übersetzung, vorbehalten. Kein Teil des Werkes darf in irgendeiner Form (durch Photokopie, Mikrofilm oder ein anderes Verfahren) ohne schriftliche Genehmigung des Verlages reproduziert oder unter Verwendung elektronischer Systeme verarbeitet, vervielfältigt oder verbreitet werden. Satz: Frohberg, 6463 Freigericht. - Druck: Gerike GmbH, Berlin. - Bindearbeiten: Dieter Mikolai, Berlin. Printed in Germany
Vorwort zur 1. Auflage
Dieses Buch wendet sich sowohl an den Anfänger, der keinerlei Programmierkenntnisse besitzt, als auch an denjenigen, der bereits höhere Programmiersprachen beherrscht. Es ist entstanden aus Einführungsvorlesungen und Praktika in höherer Programmierung, insbesondere PL/1, die der Verfasser seit längerer Zeit vor Studenten anwendungsorientierter Informatikstudienrichtungen hält. Es hat sich gezeigt, daß diese Studenten das Erkenntnisobjekt der Informatik dann schnell erfassen, wenn die Vorlesungen des Gegenstandes „Grundlagen der Informatik" durch Programmieren in einer problemorientierten Sprache unterstützt und vertieft werden. Insofern ist diese Veröffentlichung auch als Ergänzung zu meiner „Informatik für Anwender" [12] zu verstehen. Sie kann ebenso als Textbuch für begleitende Übungen und Praktika verwendet werden. In der Informatik-Ausbildung wird heutzutage manchmal die Auswahl der zu lehrenden Programmiersprache zu einem Dogma erhoben. Wenn wir unterstellen, daß akademische Bildungsstätten weitgehend zu Ausbildungsstätten geworden sind, die junge Menschen für das Leben und Arbeiten in einer hochindustrialisierten Welt zurüsten sollen, dann kann die Wahl einer Programmiersprache nur vom Lehrziel eines Studienganges ausgehen. Für den anwendungsbezogenen Informatiker genügt es nicht, daß er lernt, ganz allgemein mit Algorithmen umzugehen. Er muß in der Lage sein, die ganze Breite der Anwendungen von EDV-Anlagen, die nach wie vor ihren Schwerpunkt in der betrieblichen Datenverarbeitung hat, algorithmisch zu erfassen. Hierzu muß sich der Studierende auch handwerkliche Fähigkeiten im Programmieren aneignen, wobei man von ihm bei Eintritt in das Berufsleben durchaus auch eine gewisse Perfektion in dieser Materie erwartet. PL/1 ist wegen der Breite des Sprachumfangs, die Gebiete wie Dateiverarbeitung, Programmierung simultan ablaufender Prozesse, rekursive Prozeduren, Listenverarbeitung und zahlreiche andere abdeckt, für eine anwendungsorientierte Informatik-Ausbildung vorzüglich geeignet. Alle Diskussionen darüber, daß bisher nur ein Hersteller PL/l-Kompilierer anbietet, scheinen dadurch gegenstandslos zu sein, daß seit Jahren Normungsgremien, wie die E C M A , an einer Vereinheitlichung dieser Sprache arbeiten. Der hier vorgelegte erste Band führt in die elementaren Teile der Programmiersprache PL/1 ein, einschließlich der gesamten Dateiverarbeitung, die vor allem in Form des direkten Zugriffs in der modernen betrieblichen Datenverarbeitung eine entscheidende Rolle spielt. Um eine Sprachsyntax eindeutig beschreiben zu können, ist es üblich, auf formale Methoden zurückzugreifen.
6
Vorwort zur 1. A u f l a g e
Für diesen Zweck wird eine einfache Darstellungsweise benutzt, die im ersten E M C A Bericht über PL/1 zu finden ist [6, 8] und die auch der Anwender leicht beherrschen kann. Der später erscheinende Band [13] wird dann den höheren Programmiertechniken von PL/1 gewidmet sein und auch auf Spracherweiterungen eingehen. Zur Vertiefung des Stoffes sind den Texten Programmierbeispiele* und kleine Aufgaben beigegeben. Sie können und sollen natürlich nicht ein Programmierpraktikum ersetzen, zumal sich nur dort moderne Methoden wie die Technik der „strukturierten Programmierung" üben lassen. Ich hoffe, daß auch dieses Lehrbuch zur Kritik anregt und damit einen Lernprozeß durchlaufen wird. Für Verbesserungsvorschläge bin ich wiederum jederzeit sehr dankbar. Zu danken habe ich schließlich dem Verlag für die äußere Gestaltung des Buches und die gute Zusammenarbeit. Im September 1974
Arno
Schulz
Alle Programmierbeispiele und technische Einzelheiten beziehen sich auf den PL/l-Optimizing Compiler (Release 3.1).
Vorwort zur 2. Auflage
In den letzten Jahren hat sich die strukturierte Programmierung in voller Breite in der Praxis durchgesetzt und wird nicht mehr ausschließlich in akademischen Zirkeln gepflegt. Obwohl neben PL/1 jetzt eine ganze Reihe neuer Programmiersprachen zur Verfügung stehen, die das strukturierte Programmieren unterstützen, hat PL/1 wegen seiner Universalität, z.B. in der Dateiverarbeitung, bisher nicht an Bedeutung verloren. Allerdings ist es notwendig, diese Eigenschaft systematisch und nicht willkürlich anzuwenden. Für diese Forderung hat Software-Engineering in den letzten Jahren Erkenntnisse und Beiträge geliefert. Dieser Entwicklung mußte die 2. Auflage angepaßt werden, indem nicht nur die Syntax von PL/1 dargestellt wird, sondern auch Regeln, wie diese Syntax in einem gut strukturierten Programm anzuwenden ist. Darüber hinaus hat das Release 3.0 des PL/l-Optimizing Compilers neue Sprachelemente zur strukturierten Programmierung eingeführt. In dieser 2. Auflage wurden auch auf Anregungen vieler Leser eine Reihe von Einzelheiten didaktisch verbessert. Ich hoffe, daß auch diese Neuauflage wieder einen Lernprozeß durchlaufen wird und bin für Anregungen zu einer weiteren Verbesserung dankbar. Im August 1983
Arno
Schulz
Inhalt
1. Einführung 1.1 Grundlegende Begriffe der höheren Programmierung 1.2 Prinzipien der strukturierten Programmierung 1.3 Entstehung und Merkmale der problemorientierten Programmiersprache PL/1
2. Grundelemente der problemorientierten Programmiersprache PL/1 2.1 2.2 2.3 2.4
Der Zeichenvorrat Syntax-Notation Anweisungen und Vereinbarungen Arbeitsobjekte in PL/1
3. Der elementare Teil der problemorientierten Programmiersprache PL/1 3.1 3.2 3.3 3.4
Verarbeitungsanweisungen Die Verarbeitung von Kettendaten Anweisungen zur Programmsteuerung Transportanweisungen 3.4.1 Die Zuordnungsanweisung 3.4.2 Eingabe-und Ausgabeanweisungen 3.4.2.1 Das Modell der Eingabe und Ausgabe in PL/1 3.4.2.2 Der zeichenweise Datenverkehr 3.4.2.2.1 Der EDIT-gesteuerte Datenverkehr 3.4.2.2.2 Der LIST-und DATA-gesteuerte Datenverkehr 3.4.2.3 Dateien 3.4.2.4 Ein Programmierbeispiel zum zeichenweisen Datenverkehr und der Dateiverarbeitung 3.4.2.5 Der satzweise Datenverkehr 3.5 Die Ablaufstruktur von PL/1 Programmen 3.5.1 Prozeduren 3.5.2 Der Aufruf von Prozeduren 3.5.3 Blockstruktur, Speicherplatzzuordnung und Gültigkeitsbereich von Vereinbarungen
4. Nichtelementare Dateiorganisation und Dateiverarbeitung 4.1 Magnetbanddateien 4.2 Magnetplattendateien 4.2.1 Sequentielle Verarbeitung 4.2.2 Vereinbarung von Magnetplattendateien
11 11 18 23
27 27 30 33 39
59 59 81 86 106 106 113 113 115 115 133 137 143 151 161 161 165 180
191 191 209 209 214
Inhalt
10
4.2.3 Verarbeitung von Magnetplattendateien im direkten und indirekten Zugriff 4.2.4 Sequentielle Verarbeitung von regionalen Magnetplattendateien 4.2.5 Die indexsequentielle Speicherungs- und Verarbeitungsform
5. Schlußbemerkungen Anhang A I Ausnahmebedingungen A2 Mathematische Funktionen A3 Eingefügte Funktionen für die Bereichsverarbeitung A4 Eingefügte Funktionen für die Kettenverarbeitung A5 Eingefügte Bedingungsfunktionen A6 Pseudovariable
. . .
228 243 245
255 257 257 259 276 279 287 290
Lösungen der Übungsaufgaben
290
Literaturverzeichnis
321
Sach- und Personenregister
323
1. Einführung
1.1 Grundlegende Begriffe der höheren Programmierung Die funktionelle Struktur eines modernen Datenverarbeitungssystems entspricht im großen und ganzen noch immer der Organisation des klassischen Universalrechenautomaten, wie sie der Pionier des elektronischen Rechnens, der Mathematiker John von Neumann, in den Jahren 1945 bis 1947 konzipiert hat. Ein datenverarbeitendes System besteht danach aus fünf Hauptfunktionseinheiten, nämlich dem Eingabewerk zusammen mit einer Reihe von Eingabeeinheiten, dem Speicher als dem Mittelpunkt des ganzen Systems, dem Rechenwerk, dem Ausgabewerk zusammen mit Ausgabeeinheiten und dem Leitwerk. Informationelle Arbeitsprozesse, in denen durch Verknüpfung von Eingangs- und Zustandsinformationen neue Informationen entstehen, laufen im Rechenwerk ab. Ihre Steuerung übernimmt das Leitwerk, wobei die Steuerungsanweisungen nicht ein für allemal fest im Automaten verschaltet sind, sondern als binäre Information codiert im Speicher stehen. Dieses „gespeicherte" Programm als konstituierendes Merkmal des Computers stellt ein informationelles Fertigungsverfahren dar, das aus einer Folge von Befehlen besteht, die der Computer in der Reihenfolge ihrer Notation ausführt. Er kann aber in Abhängigkeit eines erreichten Programmzustandes bei der Programmausführung von dieser linearen Notationsfolge abweichen, so daß sich eine große Mannigfaltigkeit in den möglichen Wegen durch ein Programm ergibt, die einerseits zu begrüßen ist, andererseits das Programm testen erschwert. Den Benutzer eines Datenverarbeitungssystems interessiert vor allem die Frage, wie das Sprachsystem beschaffen sein muß, durch das er mit dieser Maschine kommunizieren kann, damit sie ihm bei der Lösung seiner Probleme hilft. Wir kommen damit zu den „Programmiersprachen", als zum Abfassen von informationellen Arbeitsvorschriften geschaffenen Notationskonventionen. Es ist naheliegend, daß sich die Sprache, in der ein in der Datenverarbeitungsanlage gespeichertes Programm niedergelegt wird, an der Struktur und der Funktion des maschinellen Arbeitsmittels orientiert, das Aufgaben informationeller Natur lösen soll. Eine solche „Maschinensprache" besteht deshalb aus einfachen Befehlen, die unmittelbar informationsverarbeitende Prozesse steuern. Ein Beispiel ist die Addition von zwei natürlichen Zahlen. In der Regel schreiben aber heute Programmierer ihre Programme nicht mehr in dieser Form nieder, sondern sie benutzen „Anweisungen", die in ihrer Ausdrucksform möglichst stark der Sprache ähneln, die der Programmierer selbst spricht. Diese Konzeption, die vom zu lösenden Problem ausgeht und nicht vom maschinellen Hilfsmittel, das später dieses Problem bearbeitet, dient der besseren Kommunikation zwischen Mensch und Maschine.
12
1. Einführung
Um solche, in einer „problemorientierten" Programmiersprache abgefaßte Programme ausführen zu können, ist es allerdings notwendig, die benutzerfreundlichen Anweisungen in einem Übersetzungsprozeß in die Sprache zu übertragen, die von der Datenverarbeitungsanlage unmittelbar verstanden wird. Obwohl eigentlich trivial, war es doch eine bahnbrechende Erfindung, als Zuse 1948 und Rutishauser 1951 vorschlugen, für diesen Übersetzungsprozeß dieselbe Maschine heranzuziehen, die später das Maschinenprogramm ausführen soll. Vom Standpunkt des Benutzers aus gesehen verschmelzen damit Übersetzungsprozeß und informationeller Arbeitsprozeß zu einer Einheit, so daß es für ihn irrelevant ist, daß die Maschine problemorientierte Programme gar nicht unmittelbar verstehen kann. Im Gegensatz zur syntaktisch armen Maschinensprache sind problemorientierte Programmiersprachen also Ausdrucksformen einer höheren Programmierung, die in abstrakter Form Arbeitsprozesse und Arbeitsobjekte beschreibt. Damit ergibt sich der in Abbildung 1 — 1 dargestellte schematische Ablauf moderner Programmiertätigkeit.
Abb. 1 — 1. Prinzip der höheren Programmierung.
Die Programmierungsterminologie versteht also unter problemorientierter Programmiersprache eine formale Sprache, „die dazu dient, Programme aus einem bestimmten Anwendungsbereich unabhängig von einer bestimmten digitalen Rechenanlage abzufassen, und die diesem Anwendungsbereich besonders angemessen ist" [4, S. 6]. Demgegenüber ist eine maschinenorientierte Programmiersprache in der Weise definiert, daß ihre Anweisungen, „die gleiche oder eine ähnliche Struktur wie die Befehle einer bestimmten digitalen Rechenanlage haben" [4, S. 6]. Ein Sonderfall ist dabei die Maschinensprache, die zum Abfassen informationeller Arbeitsvorschriften „nur Befehle zuläßt und zwar solche, die Befehlswörter einer bestimmten digitalen Rechenanlage sind" [4, S. 6]. Auf der Seite der Übersetzer heißen Programme, die „in einer problemorientierten Programmiersprache abgefaßte Quellanweisungen in Zielanweisungen einer maschinenorientierten Programmiersprache" umwandeln, Kompilierer und Übersetzer, die „in einer maschinenorientierten Programmiersprache abgefaßte Quellanweisungen in Zielanweisungen der zugehörigen Maschinensprache umwandeln", Assemblierer [4, S. 6]. Diese genormte Begriffsterminologie liegt den folgenden Ausführungen zugrunde.
1.1 Grundlegende Begriffe der höheren Programmierung
13
Wir müssen uns nun den Elementen höherer Programmiersprachen zuwenden. Eine solche Sprache muß in der Lage sein, sowohl Arbeitsvorschriften als auch Arbeitsobjekte eindeutig beschreiben zu können. Arbeitsvorschriften werden in Form von Anweisungen abgefaßt, „die im gegebenen Zusammenhang wie auch im Sinne der benutzten Sprache abgeschlossen sind" [4, S. 6], Arbeitsobjekte beschreibt der Programmierer mit Hilfe von Vereinbarungen. Die Syntax höherer Programmiersprachen geht dabei so vor, daß sie Klassen von Arbeitsobjekten bildet, die durch gemeinsame Eigenschaften (Attribute) gekennzeichnet sind. Als Beispiel seien genannt: die natürlichen Zahlen, die rationalen Zahlen oder boolesche Arbeitsobjekte, die nur den Wert „wahr" oder „falsch" annehmen können. Eine Klasse von Arbeitsobjekten ist eine Menge M im mathematischen Sinn und durch ein gemeinsames Attribut A definiert: M = {xlA(x)}. Damit kann man nun für die höhere Programmierung folgenden Programmbegriff definieren: „eine zur Lösung einer Aufgabe vollständige Anweisung zusammen mit allen erforderlichen Vereinbarungen" [4, S. 5]. Dabei wird der Begriff „Anweisung" rekursiv gebraucht. Die Fachterminologie versteht darunter eine Technik des Definierens, bei der durch wiederholte Anwendung eines schon definierten Begriffs, wie hier der „Anweisung", quasi durch sich selbst Oberbegriffe erzeugt werden, die den definierten Grundbegriff enthalten. Diese „vollständige Anweisung" führt in dem Augenblick, in dem eine Datenverarbeitungsanlage sie ausführt, zu Tätigkeiten, deren Gesamtheit einen informationsverarbeitenden Prozeß bilden. Oder in anderen Worten: Ein Programm gibt an, welche Operationsfolge einen solchen Prozeß charakterisiert. Auf eine weitere Eigenschaft von Programmen ist noch hinzuweisen. Obwohl eine Datenverarbeitungsanlage für die Durchführung jeder Aufgabe ein Programm benötigt, der Programmierer also auch dann ein Programm erstellen muß, wenn die Aufgabe nur einmal zu lösen ist, wird aus ökonomischen Gründen ein Programm in der Regel so abgefaßt, daß es eine Arbeitsvorschrift für eine bestimmte Klasse von Aufgaben darstellt. Diese zunächst sehr abstrakten Ausführungen sollen an einem kleinen, ersten Programmierbeispiel in PL/1 erläutert werden. Nehmen wir an, es sei der größte gemeinsame Teiler zweier ganzer rationaler Zahlen zu bestimmen, wobei als Operationen nur die Addition und die Subtraktion zur Verfügung stehen [6b]. Abbildung 1 - 2 zeigt den Programmablaufplan, der die Lösung dieser Aufgabe in allen Details beschreibt. In der Technik des Programmierens nimmt diese schematische Darstellung eines Programms einen wichtigen Platz ein, so daß sie kurz erläutert werden muß. Ein Programmablaufplan stellt die zeitlichen Beziehungen zwischen den Teilvorgängen, aus denen sich die Ausführung eines Programmes zusammensetzt,
14
1. Einführung
Zahlen b«ispiel 1 Durchg ¡2 Durchgj 3
(stört )
ZI - 21 Z2.28
c-
A-B >
Zl.c Z2. B
O-
Z1 gröOt. gemein: Ttilcr
(Ende )
B .21 B . 7
A • 28 A -21
A .14 B• 7
C . 7 C .14
C. 7
ZI« 7 Z1 .14 Z2.21 Z2» 7
ZI.7 Z2-7
Ergebnis 7
Abb. 1—2. Programmablaufplan zur Bestimmung des größten gemeinsamen Teilers*
mit Hilfe von genormten Sinnbildern (s. [5]) dar. Für komplexe Aufgaben wird dadurch die Programmierung übersichtlicher und damit auch sicherer. Jedes Programm beginnt mit einem Startbefehl, im Beispiel der Abbildung 1—2 durch „Start" gekennzeichnet. Anschließend sind die beiden rationalen Zahlen ZI und Z2 in die Datenverarbeitungsanlage einzugeben, wobei man sich hinsichtlich des Eingabemittels häufig nicht festlegen will, so daß es der Programmierer im Programmablaufplan nicht näher spezifiziert. Es folgt im Programmablauf der Vergleich der beiden Zahlen ZI und Z2. Ist die Zahl ZI nicht größer als Z2, so wird weiter geprüft, ob ZI gleich Z2 ist. Falls diese Frage bejaht wird, hat das Programm den größten gemeinsamen Teiler gefunden und ZI wird ausgegeben. Ist dies nicht der Fall, dann wird die größere der beiden Zahlen zum Minuenden, die kleinere zum Subtrahenden der nachfolgenden Subtraktion. Im nächsten Schritt bildet das Programm die Differenz aus *
Symbole, s. [5].
15
1.1 Grundlegende Begriffe der höheren Programmierung
den beiden Zahlen. Von diesem Punkt ab arbeitet es nur noch mit dem Subtrahenden und der Differenz weiter und verzweigt zurück zur ersten logischen Entscheidung. Diese „Programmschleife" wird so lange durchlaufen, bis der größte gemeinsame Teiler gefunden ist. Im folgenden wird das zu diesem Programmablaufplan gehörende PL/l-Programm angegeben. BEISP1 :
PROCEDURE
OPTIONS(MAIN);
DECLARE(Z1,Z2,A,B,C)DECIMAL
FIXED(10);
ON E N D F I L E ( S Y S I N ) G O TO SCHLUSS; START : SCHLEIFE:
GET DATA( Z 1 , Z 2 ) ; IF
Z1
> Z2 THEN GO TO J A ;
ELSE I F
Z1 = Z2 THEN GO TO ENDE ;
B = Z1 ; A = SUBTRAKTION:
Z2;
C = A-B; Z1 = C ; Z2 = B ; GO TO SCHLEIFE;
JA:
A = Z1 ; B = Z2; GO TO SUBTRAKTION;
ENDE:
PUT
DATA(Z1);
GO TO START; SCHLUSS:
END B E I S P 1 ;
In der Regel besteht ein größeres PL/l-Programm aus mehreren Programmteilen, die Prozeduren oder auch Blöcke genannt werden.* Durch diese Blockstruktur, die von der problemorientierten Programmiersprache ALGOL übernommen wurde, wird Speicherplatz gespart; denn die Zuordnung von Speicherplätzen zu Arbeitsobjekten, die der Übersetzer automatisch vornimmt, gilt nur für einen Block. Nachdem er ausgeführt wurde, wird derselbe Speicherplatz automatisch für andere Blöcke freigegeben. Daraus folgt, daß in PL/1 Vereinbarungen in der Regel nur innerhalb eines Blocks gelten. Diese Sprache verfügt über zwei Arten von Programmblöcken, die PROCEDUREBlocke und die BEGIN-Blöcke. Innerhalb der Klasse der PROCEDUREBlöcke gibt es noch die Hauptprozedur, die als Anfangsprozedur eines Programmes vom Betriebssystem als erste Prozedur aktiviert wird. Sie ist gekennzeichnet durch die beiden Schlüsselwörter OPTIONS (MAIN). Sie erhält auch einen Namen, der links vom Schlüsselwort PROCEDURE erscheint und Wir gehen zunächst auf den Unterschied in diesen beiden Begriffen nicht ein.
16
1. Einführung
durch einen Doppelpunkt von diesem abgetrennt wird (im vorliegenden Fall „BEISP1"). Jede Prozedur besteht aus Vereinbarungen und Anweisungen, die beliebig aufeinander folgen können. Aus Übersichtlichkeitsgründen sollte sie der Programmierer allerdings getrennt notieren, indem er nach der Kopfzeile einer Prozedur zunächst die Vereinbarungen niederschreibt. Im vorliegenden Beispiel sind fünf Arbeitsobjekte zu definieren, die mit den Bezeichnern Z I , Z2, A, B und C belegt und durch die beiden Schlüsselwörter D E C I M A L FIXED als Typ „Festpunktzahlen" ausgewiesen werden. Anschließend folgt eine Angabe ihrer Datenlänge, gerechnet in Zeichen und in Klammern notiert. Die erste Zahl spezifiziert dabei die Gesamtlänge eines Arbeitsobjektes, die zweite, falls notwendig, die Anzahl der Stellen hinter dem Radixpunkt. Vereinbarungen und Anweisungen werden durch ein Semikolon beendet. Um ein Programm ordnungsgemäß abschließen zu können, verfügt PL/1 über die Anweisung „ON E N D F I L E " . Sie spezifiziert Maßnahmen, die das Programm selbständig vornehmen soll, wenn im Programmablauf diese Bedingung auftritt, d.h. daß beim Lesen einer Datei (SYSIN) der letzte Datensatz eingegeben wurde. Häufig sind am Ende der Ausführung eines Programms eine Reihe von Endroutinen durchzuführen, indem etwa Endsummen zu berechnen und zu drucken sind. Im vorliegenden Beispiel soll in diesem Fall allerdings das Programm nur zur Anweisung mit dem Namen „SCHLUSS" verzweigen, um dort mit Hilfe des Schlüsselwortes „ E N D " das Programm abzuschließen. Auf den Vereinbarungsteil folgt der Anweisungsteil, der das später auszuführende Maschinenprogramm repräsentiert. Er beginnt in diesem Beispiel mit der Eingabeanweisung „ G E T D A T A (Z1,Z2)", die den Namen „START" trägt. Dieser Name entspricht der Maschinenadresse, unter der diese Anweisung später im Hauptspeicher zu finden ist. Die Anweisung selbst veranlaßt, die beiden Arbeitsobjekte Z I und Z2 von einem Datenträger zu lesen. Die Art des Trägermediums ist auf dieser Stufe der Programmierung irrelevant, eine typische Eigenschaft problemorientierter Programmiersprachen. Auf die Eingabeanweisung folgt eine Anweisung, die der Programmverzweigung dient und zwei Ausgänge hat. Ist der Wert des Arbeitsobjektes ZI größer als Z2, dann soll das Programm zur Anweisung mit dem Namen „JA" verzweigen. Ist dies nicht der Fall, dann kommt das Programm durch das Schlüsselwort „EL SE" zu einer nächsten Programmverzweigung, in der abgefragt wird, ob Z I gleich Z2 ist. Falls diese Frage zu bejahen ist, hat das Programm den größten gemeinsamen Teiler gefunden, der durch die Anweisung mit dem Namen „ E N D E " ausgegeben wird. In diesem Fall beginnt eine neue „Programmschleife", in der zwei neue Arbeitsobjekte gelesen werden. Falls der größte gemeinsame Teiler noch nicht gefunden wurde, kommt das Programm zu zwei Transportanweisungen, in denen die beiden Arbeitsobjekte Z I und Z2 den beiden „Speicherplätzen" B und A zugeordnet werden. Es folgt eine arithmetische Anweisung zur Berechnung der Differenz aus A und B. PL/1 geht hierbei, wie A L G O L und F O R T R A N , von der Symbolik der Mathematik aus, be-
1.1 Grundlegende Begriffe der höheren Programmierung
17
nutzt aber eine eigene Grammatik für die Niederschrift arithmetischer Ausdrücke, die bedingt ist durch die sequentielle Verarbeitung von Arbeitsobjekten. Der Unterschied zwischen einer mathematischen Formel und der arithmetischen Anweisung zeigt sich besonders deutlich an der Funktion des Gleichheitszeichens. Wenn problemorientierte Programmiersprachen dieses Zeichen verwenden, dann wird dadurch das Ergebnis der rechts von diesem Zeichen stehenden Operationen dem Speicherplatz mit dem links von diesem Zeichen stehenden Namen zugeordnet. Diese Zuweisung von Werten, die keine funktionale Beziehung im mathematischen Sinn schafft, hat dazu geführt, daß man diese Anweisungsklasse auch als Ergibtanweisung bezeichnet. Sie ist, wie spätere Beispiele zeigen werden, aber nicht nur auf skalare Arbeitsobjekte beschränkt, sondern läßt sich auch in eleganter Weise auf mehrdimensionale Arbeitsobjekte anwenden. Innerhalb des arithmetischen Ausdrucks, der rechts von der Wertzuweisung steht, werden dann die einzelnen Operationen von links nach rechts abgearbeitet, allerdings unter der Beachtung von Vorrangregeln. Im Programm folgen auf die arithmetische Anweisung „C = A — B" wiederum zwei Transportanweisungen, um die Differenz „C" weiter verarbeiten zu können, und anschließend die Programmsteuerungsanweisung „GO TO". Sie weist das Leitwerk bei der Ausführung des Programms an, vom normalen Ablauf, der durch die sequentielle Notation der Anweisungen gegeben ist, abzuweichen und zur Anweisung, deren Namen durch GO TO aufgerufen wird, zu verzweigen. Im vorliegenden Beispiel wird dadurch ein weiterer Durchlauf der „SCHLEIFE" veranlaßt. Der „JA-Zweig" der ersten IF-Anweisung arbeitet in gleicher Weise wie die bereits diskutierten Anweisungen, nur mit dem Unterschied, daß jetzt die beiden Arbeitsobjekte ZI und 72 invers den Arbeitsobjekten A und B zugewiesen werden. Anschließend mündet auch dieser Programmzweig, durch die Anweisung „GO TO SUBTRAKTION" ausgelöst, in die Anweisung „SUBTRAKTION" ein. Dieses kleine Programmierbeispiel läßt schon die wichtigsten Sprachelemente der problemorientierten Programmiersprache PL/1, die im folgenden weiter zu untersuchen sein werden, zutage treten, nämlich: Vereinbarungen und Anweisungen mit den Hauptklassen: 1. Verarbeitungsanweisungen, hier nur vertreten durch eine einfache arithmetische Anweisung, die aus einem Operator (Subtraktion) und zwei Operanden besteht, 2. Anweisungen zur Verarbeitung von Dateien, hier durch einfache Eingabeund Ausgabeanweisungen verkörpert (GET DATA, PUT DATA) und 3. Anweisungen zur Steuerung des Programms (IF-Anweisung, GOTO-Anweisung).
18
1. Einführung
1.2 Prinzipien der strukturierten Programmierung
EOF-Teil
SCHLUSS:
Abb. 1 - 3 . Schematische Darstellung der Ausführung des Programms „BEISP1".
Abbildung 1—3 zeigt schematisch dargestellt sämtliche Wege, die das Programm „BEISP1" während seiner Ausführung durchläuft. Schon diese einfache Aufgabe ist geprägt durch eine verwirrende Programmstruktur, die sich in überschneidenden Programmwegen niederschlägt und deshalb schwer nachzuvollziehen ist. Die Ursache, daß dieser Programmablauf so unübersichtlich wird, liegt in den sechs GOTO-Anweisungen, die Programmteile, die der Programmierer an verschiedenen Stellen notiert hat, in der Programmausführung zu einem gemeinsamen Weg verbinden (Beispiel: „JA-Teil" und „ S U B T R A K TION")- Man kann erwarten, daß bei größeren Aufgaben, in denen die Anzahl der GOTO-Anweisungen noch größer ist, die Programmstruktur noch
1.2 Prinzipien der strukturierten Programmierung
19
unklarer wird (s. Abb. 1—4), scherzhaft auch Spaghetti-Programmierung genannt.
Dijkstra hat bereits 1968 gezeigt, daß die Fehlerdichte in einem Programm proportional ist zur Anzahl der GOTO-Anweisungen dieses Programms [3a]; denn viele Programmierer sind überfordert, wenn sie genau alle möglichen Programmzustände an dem Punkt untersuchen sollen, zu dem der Programmablauf mit einer GOTO-Anweisung verzweigt. Kritisch sind also im Grunde genommen nicht die Programmverzweigungen, sondern die Programmzusam-
20
1. Einführung
menführungen. Um die Fehlerwahrscheinlichkeit und damit auch den Testaufwand zu reduzieren, fordert Dijkstra die GOTO-Anweisung abzuschaffen, so daß eine Programmstruktur entsteht, die in der Programmausführung nicht von der linearen Notationsfolge der Programmbausteine abweicht. Um dieses Ziel zu erreichen, benötigt man eine eigene Anweisung, die Programmschleifen zu steuert. Ein Beispiel ist in PL/1 die DO WHILE-Anweisung. Hierbei wird hinter dem Schlüsselwort WHILE in einer Klammer durch einen Elementausdruck die Bedingung notiert, bis zu deren Eintreten die Schleife wiederholt abgearbeitet wird. Das Ende der Schleife markiert eine END-Anweisung. Abbildung 1—5 zeigt den modifizierten Programmablaufplan, der ohne GO TO-Anweisungen auskommt. Im linearen Anfangsteil werden alle Vorbereitungsarbeiten für die Programmausführung, wie der Start des Programms, die Vereinbarung der Arbeitsobjekte und das Lesen der ersten beiden rationalen Zahlen ZI und Z2 zusammengefaßt. Anschließend tritt die Programmausführung in eine erste Schleife ein, die solange durchlaufen wird, bis die Eingabedatei ihr Ende (£nd oi File) erreicht hat. In dieser ersten Programmschleife liegt eine zweite, die von der Programmausführung solange durchlaufen wird, bis die beiden Zahlen ZI und Z2 gleich sind, so daß das Programm den größten gemeinsamen Teiler (ZI) ausgeben kann. In diese Schleife sind noch einmal zwei Schleifen eingebettet, wodurch die beiden Fälle ZI < 72 oder ZI > Z2 abgedeckt werden. Im Folgenden wird das zu diesem Programmablauf gehörende PL/l-Programm angegeben („BEISP1_STRUKTURIERT"). Es fällt sofort auf, daß dort keine einzige Anweisung mehr einen Namen trägt, ein Indiz dafür, daß keine GOTO-Anweisung verwendet wird. Um die äußerste Schleife steuern zu können, muß zusätzlich eine binäre Variable „EOF" eingeführt werden, die mit dem Attribut INIT den Ausgangswert 'O'B erhält. Sobald die ON END FILE-Anweisung anspricht, wird dieser binären Variablen der Wert T B zugeordnet. Er wird von der ersten DO WHILE-Schleife abgefragt. Die zweite wird gesteuert durch den Vergleich von ZI mit Z2, der bei dem Ergebnis „gleich", in PL/1 ausgedrückt durch —1 = , zum Abbruch dieser Schleife führt. Wir werden im Abschnitt 3.3 auf Programmschleifen wieder zurückkommen. Hier soll nur schon jetzt darauf hingewiesen werden, daß es verschiedene Formen von Schleifen gibt. Bei der DO WHILE-Schleife wird am Beginn einer Schleife abgefragt, ob die Bedingung, die zum Abbruch der Schleife führt, erfüllt ist. Lautet die Antwort „ja", dann durchläuft die Programmausführung diese Schleife nicht mehr (abweisende Schleife).
1.2 Prinzipien der strukturierten Programmierung
linearer
/
'
21
Anfangstell
DO WHLE — E)F
^
DO WHILE ZI + 12
N
DO WHILE ZI < 12 B - ZI A = Z2; C = A - B ZI = C; 12 = B; END ZI < Z2 DO WHILE ZI > 17 A - 11: B - 12: C = - B 11 = C; 12 = B: END ZI > Z2 ~
r
Ausg. ZI
END
ZI 4 12 Lesen ZI, Z2 END "•EOF
Abb. 1 - 5 . Strukturierter Programmablaufplan* zur Bestimmung des größten gemeinsamen Teilers. * Symbole, s. [5],
22
1. Einführung
BEISP1_STRUKTURIERT: PROCEDURE OPTIONS(MAIN); DECLARE ( Z 1 , Z 2 , A , B , C ) DECIMAL FIXED(10), EOF BIT (1) I N I T ( ' O ' B ) ; ON ENDFILE(SYSIN) EOF = ' 1 ' B ; GET DATA(Z1,Z2); DO WHILE(EOF = ' O ' B ) ; DO WHILE (Z1 Z2) ; DO WHILE (Z1 < Z 2) ; B = Z1 ; A = Z2 ; C = A-B; Z1 = C; Z2 = B; END; DO WHILE (Z1 > Z2) ; A = Z1 ; B = Z2 ; C = A-B; Z1 = C ; Z2 = B; END; PUT DATA(Z1); END; GET DATA (Z1 , Z 2) ; END; END BEISP1_STRUKTURIERT; Zusammenfassend soll gesagt werden, daß die strukturierte Programmierung durch folgende Merkmale gekennzeichnet ist: • Vermeidung der GOTO-Anweisung • Verwendung von drei Grundbausteinen für die Strukturierung von Programmen. nämlich: — Sequenz als Folge von Programmbausteinen (z.B. Anweisungen, Prozeduren), die in der Reihenfolge ihrer Niederschrift ausgeführt werden; — Programmverzweigung, Selektion, von der aus einer und nur einer von mehreren möglichen Programmzweigen ausgeführt wird (z.B. IF-Anweisung) — Programmschleife, Iteration, als ein Programmbaustein, der null-, einoder mehrmals durchlaufen wird.
1.3 Entstehung und Merkmale der problemorientierten Programmiersprache PL/1
23
• Die äußere Form der Programmnotation unterscheidet sich von der herkömmlichen Programmierung durch Einrückungen, um die Strukturelemente eines Programms besser erkennen zu können. In den folgenden Programmen werden wir soweit wie möglich die strukturierte Programmierung verwenden.
1.3 Entstehung und Merkmale der problemorientierten Programmiersprache PL/1 Lange Zeit hindurch war es üblich, in der Datenverarbeitung zwischen einem technisch-wissenschaftlichen Anwendungsbereich und einem betriebswirtschaftlich orientierten zu unterscheiden. Ohne daß man eine scharfe Grenze zwischen diesen beiden Problemkreisen definieren konnte, sollte eine betriebswirtschaftliche Datenverarbeitung dadurch gekennzeichnet sein, daß die Datenverarbeitungsanlage relativ einfache Rechenoperationen an großen Datenmengen zu vollziehen hatte, hingegen im technisch-wissenschaftlichen Bereich komplexe Rechenverfahren im Vordergrund standen. Diese ziemlich willkürliche Begriffsbestimmung war spätestens zu dem Zeitpunkt überholt, an dem Betriebswirte begannen, mathematische Verfahren der Statistik und des Operations Research einzusetzen. Andererseits wünschen technisch-wissenschaftlich orientierte Anwender seit längerem sowohl Berichte, die von Menschen lesbar sind, als auch die Verarbeitung größerer Dateien, eine Funktion, die früher nur in der kommerziellen Datenverarbeitung anzutreffen war. Hinzu kommt, daß aus Gründen der Wirtschaftlichkeit in vielen Betrieben Wissenschaftler und Kaufleute gemeinsam dieselbe Datenverarbeitungsanlage benutzen. Wenn aber schon der Ingenieur, der Naturwissenschaftler und der Betriebswirt für informationelle Aufgaben dasselbe Arbeitsmittel einsetzen, dann ist es naheliegend, daß sich auch alle Anwender derselben Programmiersprache bedienen, um Programme, Programmiererfahrung und wenn notwendig auch Programmierer austauschen zu können. Damit ist aber eine spezielle Ausrichtung von Programmiersprachen auf technisch-wissenschaftliche Zwekke, wie sie sich in ALGOL und FORTRAN manifestierte, und auf kommerzielle Zwecke, wie es bei COBOL der Fall war, überholt. Diese Erfahrungen, die viele FORTRAN-Benutzer Anfang der Sechzigerjähre gesammelt hatten, führten dazu, daß die Share-Organisation (Society for Help to Avert Redundant Effort) gemeinsam mit der Firma IBM im Jahr 1963 ein Komitee gründete, um eine Verbesserung von FORTRAN in Richtung einer universellen Programmiersprache zu entwerfen. Dabei ist auch noch zu berücksichtigen, daß zur selben Zeit IBM an der Entwicklung ihres Systems /360 arbeitete, das neue Funktionen brachte, die in herkömmlichen Programmiersprachen nicht auszudrücken waren. Der Parallelbetrieb soll in diesem Zusammenhang erwähnt werden.
24
1. Einführung
Dieses Komitee, von dem drei Mitglieder aus Anwenderkreisen kamen und drei Mitglieder aus dem Hause IBM, begann seine Arbeit im Oktober 1963. Es zeigte sich jedoch sehr bald, daß es sinnvoller ist, von Zeit zu Zeit eine neue Programmiersprache zu entwickeln, als eine bestehende immer wieder zu erweitern. Im Fall von FORTRAN wirkte sich insbesondere die dort verwendete Technik der Datenvereinbarung, die noch aus der Zeit des Lochkartenverfahrens stammt, sehr hemmend für eine Weiterentwicklung aus. Im Frühjahr 1964 veröffentlichte dieses Komitee einen ersten Bericht über eine neue problemorientierte Programmiersprache, für die von Seiten der IBM der Name NPL (New Programming Language) vorgeschlagen wurde, der allerdings, wie sich später herausstellte, als Warenzeichen geschützt war. Für die erste volle Sprachbeschreibung prägte dann die Firma IBM 1965 den Namen PL/1, als Abkürzung für Programming Language 1. Der erste Kompilierer (FCompiler) war dann im August 1966 verfügbar und damit die Sprache von dort an für die Anwender greifbar. Wie in der Geschichte von FORTRAN, so blieb auch die Programmiersprache PL/1 zunächst auf IBM-Anlagen beschränkt und zwar vor allem auf die Systemfamilie /360 bzw. /370. Wegen der weltweiten wirtschaftlichen Verflechtung auf dem Gebiet der Datenverarbeitung und aus dem Wunsch der Anwender nach einem internationalen Daten- und Programmaustausch heraus, wollten sie die weitere Entwicklung dieser Sprache aber nicht den Herstellern, insbesondere der Firma IBM, allein überlassen und bildeten deshalb in einem früheren Entwicklungsstadium, als es bei FORTRAN und COBOL der Fall war, Normungsgremien für PL/1. So widmete sich der deutsche Normenausschuß für Informationsverarbeitung (NI) bereits seit dem Jahr 1966 dieser Aufgabe. Auch trägt jetzt die internationale Zusammenarbeit auf dem Gebiet der Normung von Programmiersprachen erste Früchte, indem im Frühjahr 1972 ein erstes ISO-Dokument über PL/1 erschien [6, 8]. 1976 wurde von der ISO die amerikanische Norm ANSI X3.53—1976 als eigene Norm übernommen und damit PL/1 weltweit anerkannt [la]. Dieser Entwicklung schloß sich 1980 der deutsche Normenausschuß mit der Norm DIN 66 255 an [5a]. Auch zeichnet sich schon ab, daß auf der Grundlage dieser Sprache spezielle Programmiersprachen entstehen, wie Simulationssprachen [3, S. 227—235] und Prozeßrechnersprachen (Beispiel: PAS 1 von der Firma BBC). Es sollen nun im folgenden die wichtigsten Eigenschaften dieser neuen und wohl auch breitesten, problemorientierten Programmiersprache aufgezeigt werden. 1. Im Gegensatz zu COBOL, wo versucht wurde, eine natürliche Sprachstruktur zu simulieren, ist die Anweisungsstruktur von PL/1 wie bei FORTRAN formal und damit mathematisch orientiert. 2. Die einzige Gemeinsamkeit mit einer natürlichen Sprache besteht darin, daß PL/1, um dem Anwender entgegenzukommen, viele Varianten zuläßt, die natürlich bei der Syntaxbeschreibung Schwierigkeiten bereiten.
1.3 Entstehung und Merkmale der problemorientierten Programmiersprache PL/1
25
3. Aus Punkt 2 folgt, daß derjenige Benutzer, der über wenig Programmiererfahrung verfügt, relativ viel Zeit aufwenden muß, um PL/1 zu erlernen. Andererseits arbeitet sich der erfahrene FORTRAN-Programmierer schnell in diese Sprache ein [11, S. 534] und auch umgekehrt; denn die ANSI-Norm FORTRAN 78 besitzt jetzt auch viele Sprachelemente, die von PL/1 herrühren. 4. PL/1 ist grundsätzlich in der Lage, sowohl COBOL als auch FORTRAN zu ersetzen, ähnelt aber mehr FORTRAN als COBOL. 5. Im Gegensatz zu COBOL und FORTRAN ist PL/1 tatsächlich weitgehendst maschinenunabhängig, dafür allerdings im Sprachumfang durch die verschiedenen Kompilierer begrenzt [11, S. 543], 6. Die wichtigsten programmtechnischen Eigenschaften lassen sich wie folgt zusammenfassen: Modularität der Sprache: PL/1 besteht aus verschiedenen Teilmengen, die sich aus dem Umfang der Kompilierer ergeben. Der wenig versierte Programmierer bekommt damit die Möglichkeit, sich sukzessive in die volle Sprache einzuarbeiten. Standardinterpretationen: Versäumt der Programmierer, Arbeitsobjekte explizit zu vereinbaren, so ordnet ihnen die Grammatik der PL/l-Sprache von selbst eine Standardvereinbarung zu. Es gibt kein festes Programmschema. Der Programmierer darf die einzelnen Anweisungen nacheinander in freiem Format wie Text niederschreiben. Jede Anweisung wird durch ein Semikolon beendet, wodurch der Übersetzer weiß, wo eine Anweisung beginnt und aufhört. Blockstruktur: Die Anweisungen werden zu Programmblöcken zusammengefaßt, die Prozeduren* heißen. Ein Programm kann aus einem oder mehreren Blöcken bestehen. Dadurch wird, wie bereits im Abschnitt 1.1 herausgearbeitet, Speicherplatz gespart. In der strukturierten Programmierung sind Programmblöcke ein Mittel, um Programme zu strukturieren und zu modularisieren. Insofern kommt PL/1 den Anforderungen moderner Software-Entwurfstechniken entgegen. Mannigfache Datenkonversionen sind möglich. Echte Textverarbeitung: Durch einen speziellen Verknüpfungsoperator und Funktionen kann Text erzeugt werden. Mehrdimensionale Arbeitsobjekte: Es sind verschiedenartig strukturierte mehrdimensionale Datenanordnungen zugelassen. Listenverarbeitung: Unter einer Liste versteht die Fachterminologie eine Datenanordnung, die in einem logisch fortlaufenden Zusammenhang steht. Jeder Datensatz enthält dabei die Adresse des nächsten Datensatzes, der in einer logischen Beziehung zu diesem Datensatz steht (Pointer). Die Opera* Nicht mit dem Prozedurbegriff von ALGOL zu verwechseln, wo Prozeduren Unterprogramme sind.
26
1. Einführung
tionen, die auf Listen anzuwenden sind, bestehen darin, daß neue Datensätze in eine Liste einzufügen sind oder daß man überholte Datensätze stornieren muß. PL/1 enthält in rudimentärer Form die Möglichkeit einer Listenverarbeitung und zwar mit Hilfe von Zeigervariablen. Übersetzungszeitanweisungen: PL/1 läßt im Gegensatz zu F O R T R A N zu, daß noch während des Kompilier-Vorganges, genauer gesagt kurz vor der Übersetzung, durch einen Preprozessor das Quellprogramm modifiziert werden kann. Diese Anweisungsklasse wird durch ein spezielles Zeichen (Prozentzeichen) vor dem Schlüsselwort gekennzeichnet. Die moderne Softwaretechnologie bedient sich häufig dieser Eigenschaft, um neue Erkenntnisse, die von der Syntax einer Programmiersprache nicht unterstützt werden, zu realisieren. Bei Dateien, die unter direktem Speicherzugriff stehen, ist eine wahlweise direkte oder indirekte Adressierung der gespeicherten Datensätze üblich. Beide Formen sind in PL/1 leicht zu beschreiben und damit mit relativ wenig Programmieraufwand zu verarbeiten (REGIONAL-Modell). Simultanverarbeitung: PL/1 läßt zu, daß Programmteile, die simultan ablaufen können, als Unterprogramme in verschiedenen Tasks des Betriebssystems aufgenommen werden können.
2. Grundelemente der problemorientierten Programmiersprache PU1
2.1 Der Zeichenvorrat
Wie in jeder natürlichen Sprache so ist auch in einer Programmiersprache zunächst der Zeichenvorrat zu definieren, den diese Sprache benutzt. Um problemorientierte Programme notieren zu können, verfügt die Programmiersprache PL/1 über zwei Zeichensätze, den vollen Zeichensatz, der aus 60 Elementen besteht, und einen reduzierten Zeichensatz mit 48 Zeichen. Theoretisch kann ein Programmierer wahlweise den einen oder den anderen Zeichenvorrat verwenden. In der Praxis wird er dabei von der vorgegebenen Konfiguration der Datenverarbeitungsanlage, auf der sein Programm laufen soll, eingeengt. Um Zeichen Vorräte der Datenverarbeitung formal beschreiben zu können, benötigt man eine Metasprache. Dafür sind zwei Methoden bekannt geworden: 1. die Notation der Mengenlehre 2. die Backus Normalform. Die Notation der Mengenlehre als Metasprache verwendet geht davon aus, daß die Fachterminologie der Informatik den Begriff Zeichen versteht als „ein Element aus einer zur Darstellung von Information vereinbarten endlichen Menge von verschiedenen Elementen", genannt Zeichenvorrat [4, S. 2]. Man kann deshalb die übliche mengentheoretische Symbolik verwenden, um Zeichenvorräte von Programmiersprachen darzustellen. Ihre Elemente werden dabei in geschweifte Klammern gesetzt und die Mengen mit Großbuchstaben bezeichnet. Zeichenvorräte von Programmiersprachen weisen allerdings wie natürliche Sprachen eine Ordnung auf, die durch die Stellung der Zeichen in einer Codetabelle gegeben ist. In Analogie zur geschriebenen Sprache nennt die Terminologie der Datenverarbeitung jeden geordneten Zeichenvorrat ein Alphabet [4, S. 2], Die Reihenfolge im Alphabet muß wie der Zeichenvorrat selbst von den einzelnen Benutzern gemeinsam vereinbart werden. Mengentheoretisch gesehen wird diese Reihenfolge durch den Begriff der linearen Ordnung erfaßt, der besagt, daß sich für je zwei verschiedene Elemente eine Reihenfolge dieser beiden Elemente angeben läßt und daß es dabei ein erstes und ein letztes Element der Menge gibt. Greift man zur Beschreibung von Alphabeten der Datenverarbei-
28
2. Grundelemente der problemorientierten Programmiersprache PL/1
tung auf die Notation der Mengenlehre zurück, dann lassen sich die Axiome über die lineare Ordnung ohne weiteres dabei verwenden. Von einer ganz anderen Seite kommt die Metasprache der „Backus Normalform" her, die sich für diese Aufgabe bisher am stärksten durchgesetzt hat. Sie wurde speziell für die Beschreibung der Syntax von Programmiersprachen entworfen und zwar im Zusammenhang mit der Beschreibung von A L G O L [1], Diese Metasprache benutzt drei Symbole, um Zeichenvorräte zu definieren. Metalinguistische Variable, die Namen für Untermengen darstellen, werden in Metaklammern ( ) gesetzt. Als zweites Symbol tritt eine metalinguistische Wertzuweisung auf, die zur Definition metalinguistischer Aussagen dient. Sie wird dargestellt durch das Symbol :: = . Die Elemente, die eine Untermenge bilden, werden durch ein Oder-Symbol getrennt. Allerdings läßt diese Art der Notation die Ordnung eines Zeichenvorrats nicht unmittelbar erkennen, sondern gibt nur die Klassenbesetzung an. Im folgenden soll in dieser Weise nun der volle Zeichenvorrat der Programmiersprache PL/1 beschrieben werden. (PL/l-Zeichen-60) :: = (Alphanumerisches Zeichen) :: =
(Alphanumerisches Zeichen) I (Sonderzeichen) (Dezimalziffer) I (Buchstabenzeichen) I (Binärzeichen)
(Dezimalziffer) :: =
0|1|2|3|4|5|6|7|8|9
(Binärzeichen) :: =
Oll
(Buchstabenzeichen) :: =
A l B l C l D l E l F l G l H l I l J l K l L l M l N l O l P l Q l R l S l T l U l V l W l X l Y l Z l $ l @ l #
(Sonderzeichen) :: =
(Zwischenraum) I (Grundoperator) I (boolescher Operator) I (Interpunktion) I (Dezimalpunkt) I (Sonstiges)
( Zwischenraum) ::
b
(Grundoperator) :: =
+ |-|*|/| = |
(boolescher Operator) :: =
&I1H*
(Interpunktion) :: = (Sonstiges) :: =
( I ) I' I, I: I; I. %l?l_
* Bedeutung in der Reihenfolge der Niederschrift: Konjunktion, Disjunktion, Negation.
29
2.1 Der Zeichenvorrat
Die Notation „PL/l-Zeichen-60" deutet an, daß der volle Zeichenvorrat aus 60 Elementen besteht, wobei Doppelbelegungen, wie die Untermenge „Binärzeichen", nicht mitgezählt werden. Diese Darstellung läßt, wenn man von der Klasse der Binärzeichen absieht, allerdings nicht erkennen, daß einige Zeichen in verschiedener Bedeutung benutzt werden. So kann ein Programmierer beispielsweise die beiden arithmetischen Operatoren Minuszeichen und Stern auch für andere Zwecke, wie etwa zur Darstellung von Text, verwenden. Aus diesen Grundelementen der Programmiersprache PL/1 entstehen wie in einer natürlichen Sprache durch Aneinanderreihung von Zeichen Wörter, wobei eine endliche Menge von Regeln (Grammatik) angibt, welche Permutationen sinnvolle Wörter erzeugen. Diese Regeln darzustellen, wird Gegenstand der weiteren Ausführungen sein. Hier sollen nur einige Bemerkungen zur Verwendung des PL/l-Zeichenvorrats vorausgeschickt werden. Zur Klasse der alphanumerischen Zeichen ist an dieser Stelle zu sagen, daß sie Arbeitsobjekte definieren, indem sie die Arbeitsobjekte mit einem Namen bezeichnen („Bezeichner"). Als Beispiel seien genannt: DATEI5
#123
ADAM_1
$BETRAG
Der Zwischenraum, das Leerzeichen, trennt wie in der natürlichen Sprache die einzelnen PL/l-Wörter. Grundsätzlich kann dabei eine beliebige Anzahl von Leerzeichen erscheinen. Innerhalb von Wörtern sind allerdings im Unterschied zur problemorientierten Programmiersprache FORTRAN Leerzeichen verboten. Besonders hinzuweisen ist noch auf die Klasse der Interpunktionszeichen. Sie dienen nicht nur zur Textdarstellung, sondern vor allem auch der Strukturierung von Anweisungen und Vereinbarungen. So trennt der Doppelpunkt den Namen einer Anweisung (Markenpräfix) von der eigentlichen Arbeitsvorschrift. Das Semikolon beendet Anweisungen und Vereinbarungen. In ähnlicher Weise wird das Prozentzeichen benutzt. Anweisungen, die mit diesem Zeichen beginnen, sind ÜbersetzungszeitanWeisungen. Um zu den oben dargestellten Operationen noch weitere zu erhalten wie das Wort ** als Symbol der Potenzierung oder ~i = als Vergleichsoperator, wird die Funktion der Wortbildung auch auf Operatoren angewendet. Da sich Dezimalziffern und Binärzeichen nicht unterscheiden, werden Worte aus Binärzeichen durch den Buchstaben „B" abgeschlossen. So stellt das Wort 0010B die Dualzahl „0010" dar. Der reduzierte Zeichenvorrat von PL/1 unterscheidet sich vom vollen Zeichenvorrat in der Klasse der Buchstabenzeichen und der Sonderzeichen. Bei den Buchstabenzeichen fällt das Nummernzeichen und das kommerzielle A weg. Als Sonderzeichen sind verfügbar: (Sonderzeichen PL/1 - 4 8 ) ::= bl = I + I - 1*1/1 (1)1,1.1' Mit Ausnahme von zwei Sonderzeichen können alle anderen Zeichen des vol-
30
2. Grundelemente'der problemorientierten Programmiersprache PL/1
len Zeichenvorrats im kleineren entweder als Zweizeichenfolgen oder als Buchstabenfolgen dargestellt werden. Dabei gilt folgende Zuordnung: 60er Zeichensatz /o >
—
1 & 1 > < 1
48er Zeichensatz // 5 • NOT AND OR GT LT kein Äquivalent kein Äquivalent
2.2 Syntax-Notation Die im vorangegangenen Abschnitt 2.1 beschriebenen Zeichen der Programmiersprache PL/1 sind im Sinne dieser Sprache nicht weiter zerlegbar und werden deshalb auch „Terminals" genannt. Erst wenn man die Ebene der problemorientierten Programmiersprachen verläßt und sich auf die Ebene der Codes begibt, sind diese Grundzeichen in Bits zerlegbar. Aus diesen Terminals bildet nun die Syntax von PL/1 durch Zeichenfolgen „Zeichen aus Zeichen", denen eine Bedeutung zugeordnet wird. Dieser Vorgang wird häufig in der Programmierungsliteratur rein verbal beschrieben. Um zu konsistenten Aussagen zu kommen, ist es auch hier wieder besser, eine eigene formale Metasprache einzuführen. Sie muß insbesondere in der Lage sein, die von der Syntax zugelassenen Wortfolgen eindeutig darzustellen. Die Backus Notation ist dazu grundsätzlich in der Lage, aber die metalinguistischen Aussagen werden sehr lang und für die Darstellung der Syntax benötigt man mehrere einhundert Formeln [16]. Die „Spracharchitekten" von PL/1 griffen deshalb zusätzlich zur Backus Notation auf Sprachelemente zurück, die sich bei der Beschreibung der problemorientierten Programmiersprache C O B O L bewährt haben. So wurde in dem von der E C M A zusammen mit dem US-Normenausschuß ANSI vorgelegten ersten Entwurf für eine international genormte PL/1Sprache [6, 8] folgende Metasprache* eingeführt, die wir in dieser Darstellung benutzen werden. *
In diesem Entwurf wird zwischen einer abstrakten und einer konkreten Syntax von PL/1 unterschieden, eine Differenzierung, die hier vernachlässigt wird.
2.2 Syntax-Notation
31
metalinguistisches Zeichen
Bedeutung
Beispiele
Kleinbuchstabe
metalinguistische Variable (Klassenname) für Sprachelemente von PL/1
bezeichner operator arithmetischer ausdruck
PL/l-Zeichen
metalinguistische Konstante (tritt in derselben Form in PL/1 auf)
Schlüsselwörter wie: DECLARE A (als Formatspezifikation)
Wahlmöglichkeiten zwischen syntaktischen Einheiten, aber auch Klammerung
{DECIMAL BINARY} [DECIMAL] [BINARY
D E C I M A L 1 BINARY
1
Wahlmöglichkeit notiert mit Oder-Symbol (kein sprachlicher Unterschied zur darüberstehenden Zeile)
[]
Zusätze (Options)
[genauigkeit]
metalinguistische Wertzuweisung
genauigkeit
einmalige oder mehrmalige Wiederholung der unmittelbar davor angegebenen syntaktischen Einheit
programm :: = prozedur ...
{}
;;
=
•:=(p[,Hq])
Die Wörter dieser Metasprache sind metalinguistische Variable und Konstante. Variable spezifizieren Klassen problemorientierter Sprachelemente. Sie haben damit dieselbe Funktion wie die in Metaklammern gesetzten Bezeichnungen von Unterklassen eines Zeichen Vorrats. Metalinguistische Sätze, die syntaktische Einheiten einer problemorientierten Programmiersprache wie Vereinbarungen und Anweisungen beschreiben, werden gebildet, indem man metalinguistische Variable und Konstante mit Hilfe von fünf Konnektoren verbindet, nämlich den geschweiften Klammern, den eckigen Klammern, dem Oder-Symbol, dem Wiederholungssymbol und der Wertzuweisung. Dabei ha-
32
2. Grundelemente der problemorientierten Programmiersprache PL/1
ben die geschweiften Klammern und das Oder-Symbol dieselbe Funktion. Sie dienen nur der übersichtlicheren Darstellung metalinguistischer Sätze. Dafür soll als Beispiel an dieser Stelle schon als Vorgriff auf den nächsten Abschnitt, die einfachste Form der Vereinbarung skalarer arithmetischer Arbeitsobjekte beschrieben werden, die allerdings später verfeinert werden muß: D E C L A R E bezeichner
[genauigkeit];
Das Schlüsselwort für Vereinbarungen in PL/1 ist „ D E C L A R E " . Jedes Arbeitsobjekt wird durch einen „bezeichner" identifiziert, der verschiedene „Werte" annehmen kann und deshalb eine metalinguistische Variable darstellt. Es sind zwei Gruppen arithmetischer Arbeitsobjekte zu unterscheiden, nämlich Dezimalzahlen, definiert durch das Wort „DECIMAL", das der Programmierer auch als „ D E C " abkürzen darf, und Dualzahlen, vereinbart mit „BINARY" bzw. BIN. PL/1 zwingt aber den Programmierer nicht, explizit diese Attribute zu notieren. Falls er dies nicht tut, was in der obigen metalinguistischen Aussage durch die eckigen Klammern bezeichnet wird, unterstellt der Übersetzer, daß Arbeitsobjekte, deren Bezeichner mit den Anfangsbuchstaben A bis H, O bis Z, dem Dollarzeichen, dem kommerziellen A oder dem Nummernzeichen beginnen, implizit als dezimale Gleitpunktzahlen vereinbart werden sollen. Im Fall der Anfangsbuchstaben I bis N werden duale Festpunktzahlen unterstellt. Fordert der Programmierer eine andere Darstellung, dann muß er sie explizit durch die Schlüsselwörter „FIXED" oder „ F L O A T " definieren. Hat der Programmierer allerdings in der Vereinbarung nur eines dieser beiden Schlüsselwörter angegeben, dann unterstellt der Kompilierer, daß es sich um eine Dezimalzahl handelt. Auch für die „genauigkeit", durch die man die Länge der Arbeitsobjekte festlegt, gibt es Standardannahmen, so daß auch hier der Programmierer nicht gezwungen ist, sie explizit zu definieren. Zum besseren Verständnis dieser formalen Syntax soll noch der Fall diskutiert werden, daß im letzten metalinguistischen Satz innerhalb der geschweiften Klammern alle eckigen Klammern fehlen würden. Dies hätte zur Folge, daß keine impliziten Definitionen zugelassen seien, ein Programmierer also entweder das Attribut D E C I M A L bzw. D E C oder BINARY bzw. BIN und genauso FIXED oder F L O A T notieren müßte. Abschließend ist zu dieser Syntax-Notation nur noch zu bemerken, daß das Oder-Symbol sowohl als metalinguistische Konstante als auch als metalinguistisches Zeichen auftreten kann. In diesem Fall wird das Zeichen, das nicht Bestandteil der Metasprache ist, unterstrichen. Dafür wieder ein Beispiel: boolesche anweisung ::= Operand { & 11} Operand; Diese metalinguistische Aussage definiert, daß eine boolesche Anweisung aus zwei Operanden bestehen kann, die konjunktiv oder disjunktiv verknüpft sein können.
2.3 Anweisungen und Vereinbarungen
33
2.3 Anweisungen und Vereinbarungen Bevor mit der Darstellung der einzelnen Anweisungs- und Vereinbarungsklassen begonnen wird, soll in diesem Abschnitt zunächst der strukturelle A u f b a u von Anweisungen und Vereinbarungen mit dem im letzten Abschnitt beschriebenen Instrumentarium untersucht werden. Anweisungen und Vereinbarungen sind die kleinsten Bausteine eines PL/l-Programmes* und stellen damit die unterste Stufe der Begriffsleiter von PL/1-Programmbausteinen dar. D a f ü r ein Beispiel: BEISP2 :
PROCEDURE OPTIONS(MAIN) ; DECLARE A DEC FIXED (5)
INITIAL
(12345);
PUT DATA (A); END BEISP2; Ein PL/l-Programm kann definiert werden als eine Folge von Prozeduren. Im einfachsten Fall umfaßt es nur eine Prozedur, formal dargestellt: Programm :: = prozedur ... Prozedur :: = präfix Prozeduranweisung [prozedurkörper] ... endanweisung Im obigen Beispiel besteht das Programm aus einer einzigen Prozedur, die deshalb das Attribut „ O P T I O N S ( M A I N ) " bekommt, das Prozedurelement „präfix" aus der Zeichenfolge „ B E I S P 2 : " , die „Prozeduranweisung" aus dem Wort P R O C E D U R E und der „prozedurkörper" aus einer Vereinbarung und einer Anweisung. Die Vereinbarung definiert explizit ein Arbeitsobjekt A als fünfstellige Dezimalzahl und legt zugleich für dieses Objekt durch das Schlüsselwort I N I T I A L auch noch den Anfangswert "12345" fest. Die Anweisung P U T D A T A veranlaßt, daß, wie im ersten Programmbeispiel des Abschnitts 1.1., der Wert dieses Arbeitsobjektes ausgegeben wird. In der Regel nimmt in einer problemorientierten Programmiersprache ein Arbeitsobjekt während der Ausführung eines Programms verschiedene Werte an, so daß obiges Beispiel einen selten auftretenden Sonderfall darstellt. Es ist deshalb in der Fachterminologie üblich, solche Arbeitsobjekte wie in unserem Beispiel die G r ö ß e „ A " als Variable zu bezeichnen. Vereinbarungen legen explizit oder implizit die Bezeichner für variable Größen fest und definieren ihren Typ, z.B. Dezimalzahl, sowie ihre Ausdehnung im Speicher (Genauigkeit). Es soll an dieser Stelle auch schon erwähnt werden, daß in PL/l-Programmen häufig eine Vereinbarung mehrere Variable definiert, wobei gleichartige Arbeitsobjekte in runden Klammern zusammengefaßt werden können, um Schreibarbeit zu sparen (s. Programm „BEISP3"). *
In [8] „Unit" genannt.
34
2. Grundelemente der problemorientierten Programmiersprache PL/1
D a m i t k o m m e n wir jetzt zur Struktur des Programmbausteins „ A n w e i s u n g " in PL/1. I m allgemeinsten Fall besteht sie aus drei Teilen: 1. der eigentlichen ausführbaren A n w e i s u n g , 2. einem M a r k e n p r ä f i x und 3. einem Bedingungspräfix. Es ergibt sich damit f o l g e n d e f o r m a l e Struktur einer PL/1-Anweisung: anweisung :: =
[bedingungspräfix] [markenpräfix] ausführbare anweisung
E i n e A n w e i s u n g wird i m m e r durch ein Semikolon beendet. Ein P r o g r a m m i e rer kann ein P L / l - P r o g r a m m wie fortlaufenden Text notieren. Durch das Semikolon wird j e w e i l s das E n d e einer A n w e i s u n g o d e r auch einer Vereinbarung angezeigt. I m einfachsten Fall, der Nullanweisung, besteht eine A n w e i s u n g nur aus d e m E n d e s y m b o l . Es gehört zur metalinguistischen Variablen „ausführbare anweisung" und schließt diese ab. D a s Markenpräfix,
das unmittelbar v o r der ausführbaren A n w e i s u n g steht, ist
ein N a m e , durch den v o n irgendeiner anderen Stelle im P r o g r a m m aus auf diese A n w e i s u n g B e z u g g e n o m m e n w e r d e n kann. Beispiele dafür waren in der A u f g a b e „ B E I S P 1 " die M a r k e n : S T A R T ,
SCHLEIFE,
J A , E N D E und S C H L U S S . D a s Bedingungspräfix
SUBTRAKTION,
gibt an, o b beim A u f t r e t e n
der in dieser „ V o r s i l b e " genannten Bedingung eine Programmunterbrechung e r f o l g e n soll o d e r nicht. Typisches Beispiel ist die Division durch N u l l , bei der, wenn sie im P r o g r a m m auftritt, normalerweise das P r o g r a m m anhält und eine entsprechende Nachricht herausschreibt. D i e Bedingungen w e r d e n durch in K l a m m e r n gesetzte Schlüsselwörter angegeben. W e n n das P r o g r a m m beim A u f t r e t e n einer solchen Bedingung nicht unterbrechen soll, dann muß der P r o g r a m m i e r e r d e m Bedingungsnamen das W o r t N O voranstellen. W i e ein solches Bedingungspräfix arbeitet, soll noch an einem kleinen Beispiel d e m o n striert w e r d e n , das eine Erweiterung des P r o g r a m m s „ B E I S P 2 " darstellt: BEISP3
:
PROCEDURE
OPTIONS(MAIN);
DECLARE A DEC FIXED (B,C) (NOSIZE):
T1
: T2
:
(12345),
(1 ) ;
(B);
C =
PUT DATA END
INITIAL
: B = A;
PUT DATA (SIZE)
(5)
DEC FIXED
A;
(C);
BEISP3;
D i e Datenverarbeitungsanlage gibt als Ergebnis der Transportanweisung T 1 mit H i l f e v o n P U T D A T A ( B ) aus: B = 5;
2.3 Anweisungen und Vereinbarungen
35
denn das Arbeitsobjekt B wurde einstellig definiert. Bei der Zuordnung des Wertes von A („12345") zu B gehen deshalb vier signifikante Stellen verloren. Normalerweise wird dieser Fehler durch eine Meldung angezeigt, die aber durch das Bedingungspräfix NOSIZE abgeschaltet wurde. Im Fall der Transportanweisung T2 löst das Bedingungspräfix SIZE diese Fehlermeldung wieder aus, so daß die zweite PUT-Anweisung nicht ausgeführt wird. Im Anhang 1 sind sämtliche in der Syntax der Programmiersprache PL/1 zugelassenen Bedingungspräfixe zusammengestellt worden. Sowohl das Markenpräfix als auch das Bedingungspräfix lassen sich in der formalen Syntax-Notation wie folgt beschreiben: markenpräfix : : = {markenkonstante [b...] : [b...]} ... bedingungspräfix : : = {(bedingungsname) [b...] : [b...]} ... Das Bedingungspräfix unterscheidet sich also vom Markenpräfix dadurch, daß es in runde Klammern gesetzt wird. Zwischen der Markenkonstanten und dem Doppelpunkt bzw. dem Doppelpunkt und den nachfolgenden Strukturelementen der Anweisung können beliebig viele Leerzeichen stehen. Die Syntax fordert aber kein einziges Leerzeichen. Die drei Punkte am Ende jeder der beiden metalinguistischen Sätze besagen, daß die entsprechende syntaktische Einheit, d.h. das Markenpräfix in Form der Markenkonstanten bzw. der Bedingungsname, hinter dem Doppelpunkt wiederholt auftreten kann. Dies bedeutet, daß eine Anweisung durch mehrere Marken identifiziert werden darf, die durch Doppelpunkte getrennt werden. Eine Marke kann eine Markenkonstante oder eine Markenvariable („markenvariable") sein. Eine Markenkonstante ist fest mit einer Anweisung verbunden. Dies gilt nicht für die Markenvariable, die durch eine Zuweisung mit einer Markenkonstanten verknüpft wird. Dafür wieder ein Beispiel: M A R K E B : M A R K E C : M A R K E D : C = X + Y; MARKEZ = MARKEB; Durch die letzte Anweisung wird die Markenkonstante „ M A R K E B " der Markenvariablen „ M A R K E Z " zugeordnet, so daß beispielsweise durch die G O TO-Anweisung" G O T O M A R K E Z das Programm zur Addition X + Y verzweigt. Eine Markenvariable muß speziell mit Hilfe des Attributs L A B E L vereinbart werden. Im letzten Beispiel würde dafür die Vereinbarung zu notieren sein: D E C L A R E M A R K E Z LABEL; Bei der Bildung von Marken sind folgende drei Regeln zu beachten: 1. Es sind in Marken nicht sämtliche PL/l-Zeichen zugelassen. Formal läßt sich diese Regel wie folgt darstellen: imarkenkonstante markenvariable
36
2. Grundelemente der problemorientierten Programmiersprache PL/1 b £ (Buchstabenzeichen) c G (Alphanumerisches Zeichen) A C E (Unterstreichung) (Unterstreichung) : : = _ Diese der Mengenlehre entlehnte Notation besagt, daß das erste Zeichen einer Marke immer ein Buchstabenzeichen sein muß, die darauf folgenden aber auch Dezimalziffern oder Unterstreichungen sein können. Beispiele für gültige Marken sind: ENDSUMMEN
# DATEI 1
$BETRAG
2. Ein Zwischenraumzeichen innerhalb einer Marke ist nicht zugelassen. 3. Länge der Marke: Hier ist zwischen internen und externen Marken zu unterscheiden. Interne Marken werden innerhalb einer Prozedur verwendet. Mit externen Marken werden sowohl Prozeduren selbst als auch Dateien identifiziert. Interne Marken dürfen bis zu 31 der zugelassenen Zeichen lang sein, externe nur bis zu sieben Zeichen. Dafür wieder ein Beispiel. Die Kopfzeile einer Prozedur hat ein Programmierer wie folgt notiert: HAUPTPROGRAMM:
P R O C E D U R E OPTIONS (MAIN);
Sie ist syntaktisch falsch; denn die externe Marke G R A M M " ist länger als sieben Zeichen. Richtig wäre: HAUPTPR:
„HAUPTPRO
P R O C E D U R E OPTIONS (MAIN);
Moderne Kompilierer lassen allerdings aus Gründen der Benutzerfreundlichkeit auch längere Marken zu und begrenzen sie automatisch auf die maximal zugelassene Wortlänge, drucken aber in den Programmlisten die vom Programmierer verwendeten Namen in ihrer vollen Länge aus. Um die formale Sprachbeschreibung abzukürzen, fassen wir noch zusammen: präfix :: = [bedingungspräfix] [markenpräfix] Zum Kern einer Anweisung, der den ausführbaren Teil repräsentiert, formal dargestellt: ausführbare anweisung wäre an dieser Stelle nur zu sagen, daß eine ausführbare Anweisung wiederum mehrere Anweisungen enthalten kann. Ein typisches Beispiel dafür ist die IFAnweisung, die in der Regel aus zwei Anweisungen besteht (s. Abschnitt 3.3). Als nächstes ist an dieser Stelle die Struktur der Vereinbarung zu untersuchen. Dieses Sprachelement beschreibt explizit zu verarbeitende informationelle Objekte. In der PL/l-Literatur gilt allerdings die Vereinbarung häufig als eine spezielle Form der Anweisung, was zu beachten ist, wenn man auf die Literatur der Computerhersteller zurückgreift. Es liegt nahe, ein Arbeitsobjekt in der Form zu definieren, daß man ihm einen Namen zuordnet — in PL/1 Bezeichner genannt — und daß man bei diesem Prozeß auch die Attribute angibt, die dieses Arbeitsobjekt charakterisieren. Eine Vereinbarung beginnt deshalb
2 . 3 A n w e i s u n g e n und V e r e i n b a r u n g e n
37
mit dem Schlüsselwort D E C L A R E , abgekürzt auch DCL geschrieben, das darauf hinweist, daß zu vereinbarende Arbeitsobjekte folgen. Die allgemeinste Form einer Vereinbarung lautet deshalb: Vereinbarung :: = rDECLARE] r 1 DCL j[vanable] • • Arbeitsobjekte einer problemorientierten Programmiersprache können grundsätzlich variable Werte annehmen - Variable — oder während der Laufzeit eines Programms denselben Wert behalten — Konstante. In PL/1 kann nur die erste Form mit einem Namen belegt werden*. Um Programmieraufwand zu sparen, läßt die Syntax von PL/1 zu, daß eine Vereinbarung mehrere Variable gemeinsam definiert. Damit ist es theoretisch möglich, daß der Programmierer alle Variable eines Programms in einer einzigen Vereinbarung zusammenfaßt. Aus praktischen Gründen ist allerdings davon abzuraten. Wenn ein Programm zu ändern ist, dann wird häufig auch der Vereinbarungsteil davon betroffen sein. Es ist deshalb sinnvoll, nur Variable des gleichen Typs in einer Vereinbarung zusammenzufassen, so daß gilt: variable :: = [(] bezeichner [.bezeichner] ... [)] [attribut] ... variable :: = bezeichnerteil [attribut] ... bezeichnerteil : : = [(] bezeichner [,bezeichner] ...[)] „bezeichner" ist der Name eines Arbeitsobjektes (englisch: Identifier). Im Gegensatz zur PL/l-Literatur, in der auch Marken als Bezeichner gelten, wird hier dieser Begriff ausschließlich für zu verarbeitende Objekte verwendet. Für die Notation von Bezeichnern gelten dieselben Regeln, die bereits für die Notation von Marken angegeben wurden, und zwar entspricht ein Bezeichner einer internen Marke. Da man ihn nicht mit dem Schlüsselwort „Label" vereinbaren darf, kommen hierbei allerdings nur die Regeln für die Markenkonstante in Frage. Ein Bezeichner darf also aus maximal 31 Zeichen bestehen. Werden mehrere Variable gemeinsam notiert, so faßt man sie in runden Klammern zusammen und nennt anschließend den Typ, der aus einem oder mehreren Attributen besteht. Beispiel: D C L (A,B) (C D (E F
DEC DEC BIN INIT INIT
FIXED (8,2), F L O A T (10), FLOAT) INIT (98765), (543.12), (222.999)) BIN FIXED (20,8);
Natürlich ist es möglich, eine Variable zu vereinbaren und dieser einen Anfangswert zuzuweisen, der sich während der Laufzeit eines Programms nicht verändert.
38
2. Grundelemente der problemorientierten Programmiersprache PL/1
Diese Vereinbarung definiert gemeinsam sechs Variable. A und B sind Festpunktzahlen und zwar mit insgesamt acht Stellen, von denen zwei Dezimalstellen sind. Anschließend hat der Programmierer mit derselben Vereinbarung zwei Variable C und D vereinbart, die durch denselben Anfangswert „98765" charakterisiert sind. Die Variablen E und F sind vom gleichen Typ, nämlich duale Festpunktzahlen, unterscheiden sich aber in ihren Anfangswerten. Dieses Beispiel zeigt, daß hinsichtlich der Reihenfolge der Attribute in einer Vereinbarung eine große Freizügigkeit besteht, so daß der Programmierer seinen Schreibaufwand minimieren kann. Darunter leidet aber die Übersichtlichkeit. Vom Standpunkt einer guten Dokumentation wäre deshalb folgende andere Form der Vereinbarung der eben genannten sechs Variablen anzustreben: DCL (A,B) C D E F
DEC DEC BIN BIN BIN
FIXED FLOAT FLOAT FIXED FIXED
( 8,2), (10) INIT INIT (20,8) INIT (20,8) INIT
(98765), (98765), (543.12), (222.99);
In jeder problemorientierten Programmiersprache ist die Benutzung des Zwischenraumzeichens immer eine besondere Frage. Für PL/1 kann man generell sagen, daß (wie in einer natürlichen Sprache) Wörter durch ein Zwischenraumzeichen voneinander zu trennen sind. Es kann dann entfallen, wenn ein anderes Begrenzungszeichen, wie beispielsweise ein Operator oder Interpunktionszeichen, an dieser Stelle in einer Vereinbarung oder Anweisung auftritt. In der Praxis der Programmierung schadet es aber nicht, wenn der Programmierer schon aus Übersichtlichkeitsgründen Zwischenraumzeichen großzügig verwendet. Nachfolgend noch einige Beispiele für die Verwendung des Zwischenraumzeichens: A D E C FIXED (5) syntaktisch identisch mit: A D E C FIXED(5) INITIAL (12345) INITIAL( 12345) C = A + B; C=A+B;
Übungsaufgaben Welche der folgenden Zeichenketten sind keine gültigen Bezeichner in PL/1 (Antwort mit Begründung)? 1. l . Z A E H L E R 2. R E C H N U N G - 1 3. $ - B E T R A G 4. LINZER T O R T E 5. SUMME—l 6. PL/1_VARIABLE
2.4 Arbeitsobjekte in PL/1
39
7. Q U E R S U M M E N Z A E H L E R 8. A,B,C 9. % Z A H L Welche der folgenden Zeichenketten sind als interne Marken in PL/1 nicht zugelassen? 10. A N F A N G S AN WEIS. 11. A N W E I S U N G _ 1 12. START 13. H A U P T P R O G R A M M 14. G O T O _ l Welche der folgenden Zeichenketten sind als externe Marken in PL/1 nicht zugelassen? 15. l . P R O C 16. A U F G A B E _ 1 17. SINUS 18. PTEIL1 19. H A U P T P R .
2.4 Arbeitsobjekte in PL/1 Fassen wir die bisherigen Ausführungen zusammen: Problemorientierte Programmiersprachen haben die Aufgabe, Objekte, die von Datenverarbeitungsanlagen zu verarbeiten sind (Arbeitsobjekte), unabhängig von den Eigenschaften bestimmter Maschinentypen zu beschreiben. Wie in natürlichen Sprachen, in denen Sprachelemente mit Hilfe ihrer distributionalen Eigenschaften klassifiziert werden, so bildet auch die Syntax höherer Programmiersprachen mit Hilfe charakteristischer Merkmale der Arbeitsobjekte, Attribute genannt, Klassen (Typen), die Mengen im mathematischen Sinn darstellen. Eine Klasse von Arbeitsobjekten 0j, ist also gegeben durch die Beziehung: x E O , A, (x) (x ist Element der Menge 0,, genau dann, wenn es die Eigenschaft A, besitzt) Die Mächtigkeit dieser Klassen kann unendlich sein (Beispiel: Klasse der natürlichen Zahlen); allerdings darf ein Arbeitsobjekt nur aus einer endlichen Anzahl von Zeichen bestehen. Über diesen Klassen ist eine endliche Menge von Operationen zugelassen. Die Klassifizierung der Arbeitsobjekte mit Hilfe von Aussagen über ihre Attribute geschieht explizit oder implizit. Die explizite Klassenbildung erfolgt in einer Vereinbarung, in der eine Zuordnung zwischen den Namen von Arbeitsobjekten, den Bezeichnern, und ihren Attribu-
2. Grundelemente der problemorientierten Programmiersprache P L / 1
40
ten erfolgt. So können wir uns unter einem Bezeichner B die Menge B von Arbeitsobjekten vorstellen, für die eine bestimmte Aussage zutrifft, etwa die Eigenschaft „dezimale Gleitpunktzahl". Eine implizite Klassifizierung geht von standardisierten Annahmen über die Attribute von Arbeitsobjekten aus. So unterstellte beispielsweise schon FORTRAN, daß Variable, die mit den Buchstaben A bis H und O bis Z beginnen, Gleitpunktzahlen sind. Attribute
q>p
Bruch
von
,
-q
Arbeitsobjekten
Anzahl
def
(Variable)
Nullen recht» « n
der
letzten
sigmtitianten
Zitier
Abb. 2 - 1 . Attribute von Variablen in PL/1.
In der Regel bilden höhere Programmiersprachen mittels weiterer Attribute A', beispielsweise dem Merkmal, wie viele Stellen eine Gleitpunktzahl lang ist, ein Klassifizierungssystem für zu verarbeitende Objekte. Dadurch erhält man eine hierarchische Gliederung aller von der Syntax einer höheren Programmiersprache zugelassenen Arbeitsobjekte, die sich formal in der Form darstellen läßt:
o e p, ^
A; (0) (die Menge 0 ist Element einer Menge Pj mit Hilfe der Eigenschaft AJ)
Es ist üblich, ein solches Klassifizierungssystem durch einen Baum darzustellen (s. Abb. 2—1). In der Regel bildet man zunächst die beiden Hauptgruppen Variable und Konstante. Wir wenden uns zunächst der Klasse der Variablen zu. Ein solches Arbeitsobjekt wird dadurch charakterisiert, daß sein Inhalt — sein Wert — variiert und damit bei der Notation des Programmes nicht bekannt ist. Er läßt sich zu diesem Zeitpunkt nur als Element einer Menge angeben. Als Beispiel nennen wir eine Variable aus der Menge der natürlichen Zahlen. Natürlich muß im Zeitpunkt der Ausführung einer Anweisung durch
2.4 Arbeitsobjekte in PL/1
41
eine Datenverarbeitungsanlage der Wert einer Variablen bekannt sein. Dies erfolgt durch eine Wertzuweisung, die im Programmablauf erfolgen muß, bevor die entsprechende Anweisung zur Ausführung kommt. Hingegen wird eine Konstante bereits vom Programmierer durch eine endliche Folge von Zeichen aus dem Zeichenvorrat der vorgegebenen Programmiersprache eindeutig definiert. Damit werden auch ihre Attribute implizit festgelegt. Wir wenden uns zunächst der expliziten Vereinbarung von Variablen zu und beschränken uns an dieser Stelle auf skalare Arbeitsobjekte (Elementvariable). Die Syntax von PL/1 unterscheidet zwei Hauptklassen von Arbeitsobjekten, nämlich Kettendaten und arithmetische Daten. Kettendaten, die dadurch entstehen, daß, wie beim Prozeß der Wortbildung natürlicher Sprachen, Zeichen aus einem vorgegebenen Zeichenvorrat aneinander gereiht werden, sind noch einmal unterteilt in Zeichenketten und Bitketten. Der Begriff „Zeichenkette", der vielleicht etwas unglücklich gewählt wurde*, besagt, daß die Arbeitsobjekte aus einer zusammenhängenden Folge von Zeichen (Zeichenreihen) bestehen, die dem vollen PL/l-Zeichenvorrat angehören, formal dargestellt: zeichenkette : : = aaa...
a G (PL/l-Zeichen-60)
Ein typisches Beispiel für eine Zeichenkette stellt Text in einer natürlichen Sprache dar, der durch Interpunktionszeichen und Zwischenraumzeichen strukturiert ist, wobei in PL/1 ein Arbeitsobjekt auch nur aus Zwischenraumzeichen bestehen darf. Bitketten hingegen sind eingeschränkt auf die Untermenge der Binärzeichen. bitkette : : = bbb...
b G (Binärzeichen)
Kettendaten werden wie alle Arbeitsobjekte mit einem Bezeichner belegt und im Fall der Zeichenkette durch das Attribut CH A R A C T E R (abgekürzt: C H A R ) und im Fall der Bitkette durch das Attribut BIT ausgewiesen. Die maximale Kettenlänge ist ebenfalls zu vereinbaren und wird in Klammern gesetzt angegeben. Jeder in einer Zeichenkette enthaltene Zwischenraum gilt dabei als ein Zeichen und ist deshalb bei der Längenangabe mitzuzählen. Falls das Längenattribut fehlt, wird die Kettenlänge „1" implizit vereinbart. Damit ergibt sich folgende formale Struktur einer Kettenvereinbarung für skalare Arbeitsobjekte: kettenvariable :: = bezeichnerteil CHARACTER I CHAR BIT
[(maximale länge | *)] •
[VARYING I VAR] • [anfangswert] * Jede Kette besteht aus Zeichen.
2. Grundelemente der problemorientierten Programmiersprache PL/1
42
Beispiel: DCL TEXT TEXT—l TEXT_2 TEXT_3 TEXT_4
CHAR (20) VAR INIT ('BERLIN'), INIT ('BREMEN') VAR CHAR (20), CHAR (I = B + C), CHAR , CHAR (0) ;
Die Kettenlänge wird entweder durch eine ganzzahlige dezimale Konstante oder durch einen arithmetischen Ausdruck vereinbart* (s. z.B. TEXT_2). Die maximale Länge einer so vereinbarten Kette beträgt 32767 Zeichen, die minimale Länge null Zeichen (s. TEXT_4). Um Speicherplatz zu sparen, sollte eine Kettenvariable im Speicher nur so viel Platz belegen, wie ihrem augenblicklichen Wert entspricht. Dies wird in der Vereinbarung durch das Attribut „VA RYING" erreicht. Die Aufeinanderfolge der drei metalinguistischen Variablen Längenattribut, VARYING und Anfangswert ist wiederum frei (s. auch S. 38). Diese metasprachliche Aussage wird jetzt explizit durch das Permutationssymbol „ • " ausgedrückt. Schließlich können Kettenvariable wiederum mit einem Anfangswert versehen werden (s. TEXT und TEXT_1). In der betriebwirtschaftlich orientierten Datenverarbeitung werden im allgemeinen Textdaten nicht nur aus alphabetischen Angaben bestehen, sondern auch Werte enthalten, die textlich darzustellen sind. Es sind beispielsweise Rechnungen zu schreiben mit Preisen oder Aufträge mit Stückzahlen. Um diese Aufgabe lösen zu können, verfügt PL/1 über eine zweite Form, Kettendaten zu definieren, nämlich das Picture-Attribut. Es wird hierbei der Wert einer Kette Stelle für Stelle auf spezielle Zeichen abgebildet, nämlich die Abbildungszeichen, und dadurch bildlich beschrieben. Jedes Abbildungszeichen gibt an, welcher Untermenge des PL/l-Zeichenvorrats das entsprechende Kettenzeichen angehört. Diese Abbildungszeichen sind vergleichbar mit den Feldspezifikationen bei der Ein- und Ausgabe in FORTRAN. Die formale Darstellung lautet in diesem Fall: abbildungskettenvariable :: = bezeichnerteil PICTURE PIC
'numerische abbildungsspezifikation' 'zeichenabbildungsspezifikation' [anfangswert]
Die Zeichen-Abbildungsspezifikation hat dieselbe Funktion wie das CHA RACTER-Attribut. Sie benutzt drei Abbildungszeichen: A : für die Untermengen (Buchstabenzeichen)und (Zwischenraum) X: für (PL/1 -Zeichen-60) 9: für (Dezimalziffer) und (Zwischenraum). *
In Unterprogrammen auch durch einen Stern.
2.4 Arbeitsobjekte in PL/1
43
Da jedes Zeichen der Zeichenkette durch ein Abbildungszeichen beschrieben wird, ist es nicht mehr notwendig, in der Abbildungskettenvereinbarung anzugeben, wie lang die Zeichenkette ist. Das Längenattribut ist deshalb im Gegensatz zur Kettenvereinbarung nicht zugelassen. Dasselbe gilt für den Zusatz VARYING. Dafür ein Beispiel: Es ist eine Ortsangabe, die aus der Postleitzahl und dem Ortsnamen besteht, zu vereinbaren. Eine erste Form dieser Vereinbarung lautet: D C L O R T PICTURE'(30)X'; Die in Klammern gesetzte Zahl Dreißig ist eine Wiederholungsspezifikation, wie sie in F O R T R A N auch vorkommt und Schreibarbeit erspart. Im Gegensatz zu F O R T R A N ist aber darauf zu achten, daß die Syntax von PL/1 vorschreibt, die Wiederholungsspezifikation in Klammern zu setzen. Wenn man bedenkt, daß eine Ortsangabe in der Regel mit der Postleitzahl beginnt, bei der im Fall des Auslands die ersten Stellen Buchstaben sein können, dann gibt es folgende weitere Möglichkeit einer Vereinbarung des Datums „ORT": DCL O R T PICTURE'AA(4)9(24)A'; Diese Vereinbarung besagt, daß in den ersten beiden Stellen einer Ortsangabe ein Buchstabenzeichen oder ein Zwischenraum erscheint, je nachdem ob es sich um eine ausländische oder eine inländische Postleitzahl handelt. Danach folgen maximal vier Dezimalziffern. Sind es weniger, wie es bei deutschen Postleitzahlen der Fall sein kann, dann erscheint an der betreffenden Stelle wiederum ein Blank. Anschließend folgen maximal 24 Buchstabenzeichen. Ist die Ortsangabe kürzer, dann wird an den betreffenden Stellen auch hier wieder ein Blank eingesetzt. Es ist noch zu beachten, daß die Zeichen-Abbildungsspezifikation mindestens ein „A" oder „X" enthalten muß; denn der Kompilierer erkennt nur an diesen beiden Zeichen, daß es sich um diese Art der Abbildungsspezifikation handelt. In der numerischen Abbildungsspezifikation dürfen deshalb auch diese beiden Zeichen nicht verwendet werden. Um den Unterschied zwischen der Abbildungskettenvereinbarung und der Kettenvereinbarung noch einmal herauszustellen, soll das letzte Beispiel noch in Form einer Kettenvereinbarung programmiert werden: D C L O R T C H A R (30); Aber nicht immer sind diese beiden Formen, Ketten zu vereinbaren, identisch. Dies gilt insbesondere für die numerische Abbildungsspezifikation, zu der wir jetzt kommen. Obwohl sie auch für die Vereinbarung der maschineninternen Speicherung numerischer Daten verwendet werden kann, hat sie vor allem die Aufgabe, dezimale Festpunkt- oder Gleitpunktwerte für eine Datenausgabe im Speicher aufzubereiten. Um Programmierarbeit zu sparen, fordert hierfür der Programmierer von einer problemorientierten Programmiersprache folgende Aufbereitungsfunktionen:
44
2. Grundelemente der problemorientierten Programmiersprache PL/1
1. Einfügung des Radixpunktes in Dezimalzahlen; 2. Unterdrückung führender Nullen in Dezimalzahlen; 3. Ergänzung des numerischen Wertes einer Variablen durch Vorzeichen und Währungssymbole; 4. Strukturierung des Druckbildes einer Variablen durch Einfügung von Zwischenraumzeichen oder Kommata, um beispielsweise die Tausenderstelle von der Hunderterstelle zu trennen; 5. Angaben über die Art der Gleitpunktdarstellung in der Datenausgabe. Für diese Aufgaben bietet PL/1 für die numerische Abbildungsspezifikation folgende Abbildungszeichen an: 9: nur noch für die Untermenge (Dezimalziffer), aber nicht mehr für den Zwischenraum; V: zur Markierung der Stellung des Radixpunktes, ohne ihn selbst darzustellen. Dies muß durch die Angabe des Radixpunktes im PICTURE-Attribut selbst erfolgen. Da in einem Datenwort nur ein Radixpunkt auftreten kann, darf dieses Abbildungszeichen je aufzubereitendes Datenwort nur einmal erscheinen; Z: zur Markierung, daß eine führende Null an dieser Stelle eines Datenwortes unterdrückt werden soll; dieses Zeichen darf nicht rechts vom Abbildungszeichen „9" in demselben Datenwort notiert werden; Y: zur Markierung der Unterdrückung jeder Null, führend oder nichtführend; *: in derselben Funktion wie Z mit dem Unterschied, daß anstelle der führenden Null ein Stern in das Datenwort eingesetzt wird; S: zur Markierung der Vorzeichenstelle ( + oder - wird eingesetzt); falls dieses Abbildungszeichen mehrmals in derselben Abbildungsspezifikation erscheint, wird das Vorzeichen links von der höchsten signifikanten Ziffer gesetzt; dieselben Abbildungszeichen links davon haben dann die Funktion des Abbildungszeichens Z. + : zur Spezifizierung des positiven Vorzeichens, falls der Zahlenwert der Variablen > 0 ist; ist der Wert negativ, erscheint ein Blank; —: in der inversen Funktion des Pluszeichens ( < 0 ) ; $: definiert ein vorgegebenes Währungssymbol (in der Regel Dollarzeichen); falls dieses Zeichen mehrmals in derselben Abbildungsspezifikation auftritt, wirkt es analog zum Abbildungszeichen Z. Die letzten vier Abbildungszeichen (S,+ , — ,$) können in der Abbildungsspezifikation sowohl statisch als auch „driftend" wirken. Eine statische Verwendung liegt dann vor, wenn ein Abbildungszeichen immer an der markierten Stelle im ausgegebenen Datenwort erscheint. Bei der Verwendung als Driftzeichen notiert der Programmierer mehrere gleichartige Zeichen („Driftkette"). Alle Abbildungszeichen, die links von dem Driftzeichen stehen, das
2.4 Arbeitsobjekte in PL/1
45
statisch wirkt, haben die Funktion des Abbildungszeichens „Z" (z.B. die Funktion des Abbildungszeichens „S"). Weitere Abbildungszeichen für die numerische Abbildungsspezifikation sind: B: Kennzeichnung einer Zeichenstelle, die immer Zwischenraum sein soll; CR: zur Kennzeichnung negativer Beträge von Festpunktwerten in kommerziellen Auswertungen; diese Zweizeichenfolge kann nur rechts von einem Zahlenwert erscheinen. Ist der Wert nicht negativ, werden zwei Blanks eingesetzt; DB: in derselben Funktion wie CR; E: zur Markierung des Beginns eines Exponentenfeldes bei der Gleitpunktdarstellung (E erscheint im Druckbild); K: zur Markierung des Beginns eines Exponentenfeldes bei der Gleitpunktdarstellung (K erscheint nicht im Druckbild); F: zur Kennzeichnung eines Skalenfaktors (Scaling Factor) in der Festpunktdarstellung. Darüber hinaus verfügt PL/1 noch über einige Zeichen, die eingefügt werden, wenn sie im Picture-Attribut erscheinen: •
, /
Die Verwendung dieser Abbildungszeichen zusammen mit den Einfügungszeichen soll jetzt noch an einem kleinen Programmierbeispiel demonstriert werden: BEISP4:
PROCEDURE OPTIONS(MAIN); DCL PREIS_1 PICTURE'Z/ZZZ.ZZ9V,YYBCR', PREIS_2 PICTURE'+++9V99', GLTPKTZAHL_1 P I C T U R E ' S . * * 9 V , 9 9 E S 9 9 ' , GLTPKTZAHL_2 PICTURE'S.ZZ9V,99K+99', A DEC FIXED ( 9 , 2 ) , B DEC FLOAT(5); A = -123.40; B = 98.00E-05; PREIS_1 = A; PREIS_2 = A; GLTPKTZAHL_1 = B; GLTPKTZAHL_2 = B; PUT DATA(PREIS_1, PREIS_2, GLTPKTZAHL_1, GLTPKTZAHL_2); END BEISP4;
46
2. Grundelemente der problemorientierten Programmiersprache PL/1
E r g e b n i s PREIS_1=
: 123,4
CR
GLTPKTZAHL_1= +.979,99E-06
PREIS_2=
12340
GLTPKTZAHL_2= +.979,99
06
Damit ist der linke Teil der Abbildung 2—1 so weit erschöpfend dargestellt worden, wie es zum Schreiben einfacher PL/l-Programme notwendig ist. Bevor wir zum rechten Teil, den arithmetischen Attributen, weitergehen, soll zunächst noch kurz auf die Kettenkonstanten eingegangen werden, zu deren Notierung nach den vorangegangenen Ausführungen nur noch wenige Ergänzungen notwendig sind. Kettenkonstanten werden wie alle Konstanten in einem Programm dadurch vereinbart, daß der Programmierer sie unmittelbar notiert. Damit der Kompilierer sie von der Klasse der arithmetischen Konstanten unterscheiden kann, wird jede Kettenkonstante von einem ApostrophZeichen am Anfang und E n d e der Kette eingeschlossen. Da natürlich in der Zeichenkette selbst auch ein Apostroph oder ein Hochkomma als Bestandteil eines Anführungszeichens auftreten kann, sind für diesen Fall bestimmte Vereinbarungen zu treffen. U m sie vom Apostroph-Zeichen als Begrenzungszeichen der Kette unterscheiden zu können, verlangt die Syntax von PL/1, daß diese Zeichen ohne Einfügung eines Zwischenraums innerhalb der Kette zu verdoppeln sind. Z u r Darstellung von Zeichenketten-Konstanten ist wie bei den entsprechenden Variablen der gesamte Zeichenvorrat der PL/l-Sprache zugelassen. Leerzeichen werden jeweils als eigenes Zeichen interpretiert. Dafür noch einige Beispiele: 'LINZER TORTE' 'PL/l_PROGRAMM' ' Z I T A T A U S " " E I N F U E H R U N G IN D I E P L / 1 _ S P R A C H E " ' V 'GOETHE"S""FAUST'"" Das letzte Beispiel — Goethe's „Faust" — besteht aus neunzehn Zeichen. Soll eine Zeichen-Konstante mehrmals hintereinander in einer Zeichenkette erscheinen, so kann dies der Programmierer, um sich Programmierarbeit zu sparen, durch einen Wiederholungsfaktor ausdrücken, der aus einer in runde Klammern gesetzten ganzzahligen Dezimalzahl besteht. Soll beispielsweise in einem Text eine Unterstreichung aus der Aneinanderreihung von 115 Unterstreichungszeichen bestehen, dann kann dies in folgender Weise vereinbart werden: D C L U N T E R S T R E I C H U N G C H A R (115) I N I T I A L ((115)'_'); D e r Sonderfall einer Zeichenkettenkonstante sind Kommentare, die Programmierer bei ihrer Arbeit in Programme einfügen, um die Aussagefähigkeit ihrer Niederschrift zu erhöhen und damit auch eine bessere Programmdokumentation zu erreichen. D a diese Kommentare vom Übersetzungsprozeß nicht verändert werden dürfen, müssen sie durch spezielle Zeichen gekennzeichnet sein. PL/1 verwendet dafür eine Zweizeichenfolge, bestehend aus einem Schrägstrich und einem Stern:
2.4 Arbeitsobjekte in PL/1
47
kommentar :: = /*zeichenkette*/ Der Programmierer darf Kommentare überall in einem Programm einfügen, wo Zwischenraumzeichen erlaubt sind. Allerdings wird in einer Kette ein Kommentar nicht als Kommentar interpretiert. Da dort sämtliche Zeichen zugelassen sind, gibt es für den Kompilierer keine Möglichkeit, den Kommentar als solchen zu erkennen. Sowohl der Kommentar als auch seine Begrenzungszeichen werden als Teil der Zeichenkette aufgefaßt. Wie bei Variablen, so kann auch eine Kettenkonstante eine Bitkette sein. Um sie von einer Zeichenketten-Konstanten unterscheiden zu können, muß der Programmierer unmittelbar nach dem abschließenden Apostroph den Buchstaben „B" notieren. Er wird genauso wie die beiden Apostroph-Zeichen am Anfang und Ende der Kette nicht mitgespeichert. Beispiel: ' 00 1 1 0 1 0 1 'B Nach diesem Exkurs über die Vereinbarung von Kettenkonstanten sollen nun die Regeln für die Vereinbarung arithmetischer Daten durch Attribute (s. Abb. 2—1) dargestellt werden. Skalare arithmetische Daten, auch einfache Variable genannt, sind in PL/1 durch vier Attribute gekennzeichnet, nämlich die Zahlenbasis (dezimal oder dual), die Schreibweise (Festpunktdarstellung oder Gleitpunktdarstellung), den Modus (reel oder komplex) und die Genauigkeit (Größe des Arbeitsobjektes). Die Zahlenbasis eines arithmetischen Datenelements wird explizit durch das Attribut D E C I M A L , abgekürzt durch D E C , oder BINARY, abgekürzt durch BIN, vereinbart. Hinsichtlich der Zahlendarstellung, auch Schreibweise genannt, ist wie in F O R T R A N zwischen der Festpunktdarstellung und der Gleitpunktdarstellung zu unterscheiden. Die Festpunktdarstellung, die die Grundlage für die Festpunktrechnung ist, wird durch das Attribut FIXED vereinbart, die Gleitpunktdarstellung durch FLOAT. Sie bedient sich einer halblogarithmischen Zahlendarstellung: Z G P = M • Be (M: Mantisse, e: Exponent, B: Basis der Zahlendarstellung) Es ist allgemein üblich, in der Datenverarbeitung Mantisse und Exponent seriell zu speichern, wobei für die Dateneingabe zur Abgrenzung beider Teile in PL/1 der Buchstabe E verwendet wird. Da die Speicherwortlänge jeder Datenverarbeitungsanlage begrenzt ist, ist auch der Wertebereich für die Mantisse M und den Exponenten e begrenzt. Es gelten folgende Regeln: M ^ 1016 - 1 - 7 8 ^ e ^ +75 Neben dieser expliziten Vereinbarung von Festpunkt- oder Gleitpunktvariablen gibt es, ähnlich wie in F O R T R A N , auch die implizite Form. Variable, für die keine externen Vereinbarungen getroffen wurden, werden vom Übersetzer als dezimale Gleitpunktvariable interpretiert, wenn ihre Bezeichner mit den
48
2. Grundelemente der problemorientierten Programmiersprache PL/1
Buchstaben A bis H, O bis Z oder dem Dollarzeichen, dem Nummernzeichen oder dem kommerziellen A beginnen. Für Bezeichner, die mit einem der Buchstaben I bis N beginnen, wird, wie in F O R T R A N , eine Festpunktdarstellung angenommen, allerdings jetzt mit der Zahlenbasis „dual". Natürlich können auch Dualzahlen in halblogarithmischer Darstellung verarbeitet werden. Auch hier ist die Mantissenlänge und Exponentenlänge beschränkt. Sie betragen: M dual 53 Bits - 2 6 0 « e dual « +252 Der Einfachheit halber soll auch hier gleich wieder die Vereinbarung von arithmetischen Konstanten eingefügt werden. Eine dezimale Festpunktkonstante wird mit oder ohne Vorzeichen zusammen mit einem Dezimalpunkt notiert. Wenn kein Radixpunkt angegeben wurde, wird er als unmittelbar rechts von der niedrigsten Dezimalziffer stehend angenommen. Dasselbe gilt für Dualzahlen, nur daß auch hier wieder der Buchstabe B notiert werden muß. Beispiele: +3.141593 -98765 101010(Dezimalzahl!) —000.IIB 101010B Die letzten beiden Festpunktkonstanten könnten durch folgende Vereinbarung definiert und Variablen zugeordnet werden: D C L A BIN F I X E D (5,2) INITIAL (-000.11B), B BIN F I X E D (6) INITIAL (101010B); Konstante in Gleitpunktdarstellung müssen, wie bereits angegeben, den Buchstaben E zur Markierung des Exponententeils enthalten. Beispiele: — 1234.56E+10
+9.321E—2
-101010.111E2B
Als nächstes Datenattribut arithmetischer Arbeitsobjekte erscheint im Entscheidungsbaum der Abbildung 2—1 der Modus, der reell oder komplex sein kann. Die Vereinbarung muß in diesem Fall explizit erfolgen und zwar entweder durch das volle Schlüsselwort COMPLEX oder die Abkürzung CPLX. Eine als komplexe Zahl definierte Variable kann sowohl die Zahlenbasis dezimal oder dual und die Schreibweise Festpunktzahl oder Gleitpunktzahl annehmen. Die maschineninterne Speicherung von komplexen Zahlen erfolgt in Form von zwei Datenworten. Das erste Datenwort interpretiert das Programm als Realteil, das zweite als Imaginärteil. Die Attribute Zahlenbasis und Schreibweise beziehen sich dabei natürlich auf beide Datenworte gemeinsam. Analog zu dieser Form der Vereinbarung ist eine komplexe Konstante in Form von zwei Konstanten zu definieren, von denen die erste den Realteil darstellt und die zweite den Imaginärteil. Zusätzlich muß der Imaginärteil durch den Buchstaben I gekennzeichnet sein. Beispiel:
2.4 Arbeitsobjekte in PL/1
49
— 12.34E10+1010.10BI* Der Realteil ist in diesem Beispiel die Gleitpunktzahl: — 12.34E10 Der Imaginärteil wurde in Form einer dualen Festpunktzahl notiert: + 1010.10B Als weiteres Attribut bei der Vereinbarung arithmetischer Variablen ist die Genauigkeit zu notieren. Bei einer Festpunktdarstellung versteht die Syntax von PL/1 darunter die Anzahl p aller Ziffern, die eine Variable enthalten kann. Dazu kommt noch eine Angabe q über die angenommene Stellung des Radixpunktes, wobei p und q in Form von dezimalen ganzzahligen Konstanten anzugeben sind. Im Fall der Gleitpunktdarstellung entfällt natürlich die zweite Angabe (q) und die Konstante p definiert die Mindestanzahl der signifikanten Ziffern, die bei dieser Darstellung zu berücksichtigen sind. Wenn ein Arbeitsobjekt mehr Ziffern enthält, als diese Angabe zuläßt, werden die niedrigsten Stellen bei einer Wertzuweisung vernachlässigt. Wird im Datenverarbeitungsprozeß ein Ergebnis einer Festpunktvariablen zugewiesen, so bleibt die für diese Zielvariable vereinbarte Genauigkeit erhalten. Diese Wertzuweisung erfolgt stellengerecht unter Beachtung des angenommenen Radixpunktes im Zielfeld. Dabei werden führende Nullen eingefügt, wenn das zugewiesene dezimale oder duale Datenwort weniger signifikante Ziffern enthält, als für das Ergebnis vereinbart wurden. Dasselbe gilt für den gebrochenen Datenteil. Auch hier nimmt der Übersetzer eine Verlängerung nach rechts vor, indem er Nullen hinzufügt. Der Skalenfaktor q einer Festpunktzahl muß im Zahlenbereich zwischen —128 und +127 liegen. Wie Abbildung 2—1 zeigt, kann er sowohl größer als p sein, als auch einen negativen Wert annehmen. Ist q > p, dann liegt ein Bruch vor, bei dem der Radixpunkt so viele Stellen links von der am weitesten rechts stehenden Ziffer angenommen wird, wie in der Vereinbarung angegeben wurde. Die Differenz von q und p sind Stellen, welche Nullen enthalten, die nicht gespeichert sind. Beispiel: D C L A D E C FIXED(2,3); A = 0.098; In diesem Fall werden nur die beiden Ziffern Neun und Acht gespeichert, wodurch Speicherplatz für Arbeitsobjekte eingespart wird. Ein negativer Skalenfaktor hat die inverse Funktion, indem Nullen, die rechts von einer signifikanten Ziffer stehen, unterdrückt werden. Beispiel: D C L A D E C F I X E D ( 2 , - 3 ) INITIAL (98000); Es werden wieder nur die beiden Ziffern Neun und Acht gespeichert. * Es gibt in Wirklichkeit keine komplexe Konstante in PL/1; sondern diese Funktion wird erreicht, indem der Programmierer zwei Konstante notiert, wobei er jetzt sowohl verschiedene Zahlenbasen als auch Schreibweisen verwenden darf.
2. G r u n d e l e m e n t e der p r o b l e m o r i e n t i e r t e n Programmiersprache PL/1
50
Die Aufeinanderfolge der in Abbildung 2—1 als Entscheidungsbaum dargestellten arithmetischen Attribute in einer Vereinbarung ist bis auf die Einschränkung frei, daß die Genauigkeitsangabe immer nach einem der drei Attribute Zahlenbasis, Schreibweise und Modus folgen muß. Beispiel: D C L A D E C F I X E D (10,3),B F L O A T D E C (16),C FIXED (20,5)BIN; Im Abschnitt 1.3 wurde als eine typische Eigenschaft von PL/1 die Annahme von Standardinterpretationen angeführt, die immer dann wirksam werden, wenn der Programmierer gewollt oder ungewollt Attribute von Arbeitsobjekten nicht explizit definiert. Dies gilt nun inbesondere für die Vereinbarung von arithmetischen Variablen. Die Standardinterpretationen, die hier gelten, zeigt Tabelle 2—1 zusammen mit der maximal zulässigen Ausdehnung eines Arbeitsobjektes. Tabelle 2 - 1 . Standardinterpretationen von arithmetischen Variablen und ihre maximale Ausdehnung
implizite Vereinbarung
Standardannahme
Anfangsbuchstabe des Bezeichners: A—H, O—Z, $, @, #
D E C F L O A T (6)
Anfangsbuchstabe des Bezeichners: I—N
BIN F I X E D (15)
FIXED
D E C (5,0)
FLOAT
D E C (6)
DEC
F L O A T (6)
BIN
F L O A T (21)
DEC FIXED
(5,0)
15 signifikante Ziffern
BIN F I X E D
(15)
31 Dualstellen
BIN F L O A T
(21)
53 Dualstellen
DEC FLOAT
(6)
16 signifikante Ziffern
REAL
DEC
F L O A T (6)
jede Variable, die nicht explizit als C O M P L E X definiert
REAL
maximale Ausdehnung
2.4 Arbeitsobjekte in PL/1
51
Um eine leicht lesbare und damit änderungsfreundliche Programmdokumentation zu erhalten, sollte der Programmierer allerdings von der Freizügigkeit, die die Sprachsyntax von PL/1 zuläßt, nur in Ausnahmefällen Gebrauch machen. Folgende Dokumentationsregeln haben sich bewährt: • Vereinbare jedes Arbeitsobjekt soweit wie möglich explizit; • vereinbare jedes Arbeitsobjekt für sich; • gebe für jedes Arbeitsobjekt den Anfangswert in der Vereinbarung mit an, um zu verhindern, daß ein Programm versucht Variable ohne eine Wertzuweisung zu verarbeiten. Die Programme „BEISP7" und BEISP8" zeigen Beispiele für eine gute Programmdokumentation . Es wurde bisher nur über skalare Arbeitsobjekte berichtet. Alle Vereinbarungen bezogen sich auf diesen Fall. In der modernen Datenverarbeitung nehmen jedoch Datengruppierungen, insbesondere in Form von Dateien, eine zentrale Stellung ein. Es muß deshalb zum Abschluß dieses Kapitels noch auf nichtskalare Arbeitsobjekte, ihre Art und Definition, eingegangen werden. Die Syntax von PL/1 unterscheidet zwei Arten von Datengruppierungen: 1. den Bereich, in dem die Arbeitsobjekte gewisse gemeinsame Eigenschaften aufweisen. Da alle Datenelemente gleiche Attribute besitzen, ist es nur notwendig, den Bereich als Ganzes zu vereinbaren. 2. Sind die Attribute der einzelnen Datenelemente verschieden, stehen jedoch die Arbeitsobjekte in einem organisatorischen Zusammenhang, der sich als Baum der Graphentheorie darstellen läßt, so wird diese Gruppierung eine Struktur genannt. Ein typisches Beispiel für einen Bereich sind Verbrauchszahlen eines Energieversorgungsunternehmens, die dieser Betrieb quartalsmäßig speichert. Der Bereich, der begrifflich dem des Feldes in F O R T R A N entspricht, erhält als Ganzes wiederum einen Namen,beispielsweise „ E N E R G I E V E R B R A U C H " , unter dem sämtliche Elemente des Bereichs identifiziert werden können. Es ist naheliegend, das einzelne Element dann durch diesen Namen zusammen mit einem Index anzusprechen. In der Bereichsvereinbarung folgt deshalb auf den Bezeichner ein in Klammern gesetztes Dimensionsattribut, das die Ausdehnung des Bereichs definiert, gefolgt vom Datenattribut, das wiederum die Zahlenbasis, die Schreibweise, den Modus und die Genauigkeit der Datenelemente des Bereichs beschreibt, wobei auch Standardinterpretationen zugelassen sind. Anfangswerte dürfen für den Bereich mit angegeben werden. Damit ergibt sich folgende formale Bereichsvereinbarung: bereichsvariable
:: = bezeichnerteil (dimensionsattribut [,dimensionsattribut] ...) fattribut] ...
52
2. Grundelemente der problemorientierten Programmiersprache PL/1
dimensionsattribut ::= [untere grenze :] obere grenze I * untere grenze obere grenze
:: = ganzzahliger elementausdruck :: = ganzzahliger elementausdruck
Beispiel: DCL MATRIX (3,2), FELD (6) DEC FIXED (5,2) INITIAL (123.45,987.65); Der zweidimensionale Bereich „MATRIX" besteht aus drei Zeilen und zwei Spalten, wobei die Datenelemente vom Typ duale Festpunktzahl sind und aus 15 Stellen bestehen. Den ersten beiden Elementen des eindimensionalen Bereichs „FELD" werden in der Vereinbarung Anfangswerte zugewiesen. In diesem Beispiel wurde die einfachste Form des Dimensionsattributes ohne explizite Angabe der unteren Grenze benutzt. Im Gegensatz zur Programmiersprache FORTRAN, bei der ein Feld aus maximal drei Dimensionen bestehen durfte, sind in PL/1 bis zu 15 Dimensionen zugelassen. Im allgemeinsten Fall kann der Programmierer für jede Dimension die untere Grenze und die obere Grenze angeben. Jede Grenze ist eine dezimale ganzzahlige Konstante, intern dargestellt als BIN FIXED (15), die entweder direkt notiert oder durch einen arithmetischen Prozeß bestimmt wird. Wurde keine untere Grenze festgelegt, dann unterstellt der Übersetzer dafür die Konstante Eins. Fernerhin muß der Wert der unteren Grenze kleiner oder gleich dem Wert der oberen Grenze sein; beide dürfen aber ein negatives Vorzeichen aufweisen. Diese sehr allgemein gehaltenen Regeln für die Bestimmung der Bereichsgrenzen kommen dem Anwender entgegen, indem er in der Wahl der Grenzen frei ist und beispielsweise für Tabellen auch Jahreszahlen als Indizes einsetzen kann. Die zugelassene Ausdehnung der Bereiche zeigt Tabelle 2—2. Tabelle 2 - 2 . Dimensionsattribute für Bereiche
untere grenze
obere grenze
Dimension
Standard: 1 sonst 3= - 32768
« + 32767
15
Die allgemeine Form einer Bereichsvereinbarung soll wiederum an einem Beispiel demonstriert werden: DCL BEREICH (-25:+24,10,5,0:3) DEC FIXED (10,2) INITIAL (0,15,18,(10)0,(20)1,(30)-12.34), FELD (A + B:C*D) FLOAT, KETTE (10) INITIAL((10)(1)TB)BIT(1); Diese Vereinbarung definiert nicht nur drei Bereiche mit den Bezeichnern „BEREICH", „FELD" und „KETTE", sondern ordnet ihnen auch noch
2.4 Arbeitsobjekte in PL/1
53
durch das Attribut INITIAL Anfangswerte zu. Die in Klammern stehenden Zahlen (10,20 und 30) sind Wiederholungsfaktoren und geben an, wie viele Elemente eines Bereichs mit dem Wert, der nach dieser Klammer notiert wurde, zu initialisieren sind. Dabei ist es nicht notwendig, einen ganzen Bereich mit Anfangswerten zu belegen. Bei Bereichen, die mit dem Kettenattribut belegt wurden (im Beispiel oben „KETTE"), ist zu beachten, daß neben den Bereichswiederholungsfaktoren auch noch Kettenwiederholungsfaktoren auftreten. So besteht „KETTE" aus zehn einstelligen Bitelementen, die alle mit dem Binärzeichen Eins initialisiert wurden. Dabei ist (1) der Kettenwiederholungsfaktor, der aus Gründen der Eindeutigkeit in diesem Beispiel nicht weggelassen werden darf. Der eindimensionale Bereich „FELD" benutzt für die Definition der Dimensionen arithmetische Ausdrücke. Dabei ist zu beachten, daß nur der ganzzahlige Anteil des Wertes dieser Ausdrücke für die Definition der Bereichsgrenzen verwendet wird. Dieses Beispiel zeigt auch deutlich, wie die einzelnen Datenelemente der Variablen „ B E R E I C H " dadurch identifiziert werden, daß der Bezeichner des Bereichs zusammen mit einem Index, der die Lage des einzelnen Elementes im Feld angibt, notiert wird. Dieser Sprachgebrauch entspricht der mathematischen Terminologie, die auch Elemente einer Matrix durch Indizes kennzeichnet. Initialisierung: 0 - * BEREICH(- -25,1,1,0) 15 —»BEREICH(- -25,1,1,1) 1 8 - » BEREICH(- -25,1,1,2) 0 - + BEREICH(- -25,1,1,3) 0 - > B E R E I C H ( - -25,1,2,0)
0 1
BEREICH(-25,1,4,0) BEREICH(-25,1,4,1)
Damit kommen wir jetzt zu den PL/l-Konventionen, die Strukturen vereinbaren. Es sei noch einmal erinnert, daß Strukturen nach der PL/1-Terminologie Datengruppierungen sind, die aus Datenelementen bestehen, die nicht gleiche Attribute besitzen. So sind in der Praxis häufig Dateien in Form von Strukturen organisiert. Als typisches Beispiel der betrieblichen Datenverarbeitung sei ein Teilenachweis genannt, in dem Textdaten wie Materialbeschreibungen und Anschriften der Lieferanten zusammen mit numerischen Daten wie Mengen und Preisen gespeichert sind. Die Attribute dieser Daten sind also nicht gleich-
54
2. Grundelemente der problemorientierten Programmiersprache PL/1
artig, sondern beschreiben in diesem Fall Zeichenketten und arithmetische Daten. Die hierarchischen Zuordnungen solcher Datengruppierungen lassen sich auf Graphen abbilden. Um Strukturen in einem Programm ansprechen zu können, ist es üblich, sie wie Bereiche mit Bezeichnern zu belegen. Mit einem Strukturbezeichner kann die gesamte Datenanordnung aufgerufen und verarbeitet werden. Falls es notwendig ist, einzelne Elemente einer Datenstruktur zu identifizieren, dann dienen dafür nicht mehr Indizes wie bei Bereichen, sondern es werden eigene Bezeichner verwendet. Dabei dürfen sich Bezeichner wiederholen. Auf diese Art entsteht eine Hierarchie von Datennamen, deren Stufung, mit Eins beginnend, durch die Menge der natürlichen Zahlen gekennzeichnet ist. Eine Strukturvereinbarung enthält also zusätzlich zu den Bezeichnern auch noch Angaben über die hierarchischen Stufen, wodurch sich folgende formale Notation ergibt: strukturvariable :: =
1 bezeichner [dimensionsattribut], [, stufe bezeichnerteil [dimensionsattribut] [attribut] . . . ] . . .
An dieser Strukturvereinbarung ist folgendes besonders zu beachten: 1. Die Hauptstruktur bekommt die Stufennummer Eins. Sie erhält kein Attribut. 2. Unterstrukturen sind mit Stufennummern zu vereinbaren, die größer als Eins sind. Sie müssen dezimale ganzzahlige Konstante sein. Die Aufeinanderfolge der Stufennummern ist beliebig, wobei Zahlenbereiche übersprungen werden dürfen. 3. Der Programmierer darf gleiche Bezeichner auf verschiedenen Stufen verwenden. 4. Ein Datenattribut wird erst dann vergeben, wenn die betreffende Unterstruktur nur noch aus nicht mehr weiter auflösbaren Datenelementen besteht (Elementvariable oder Bereich), wobei implizite Vereinbarungen zugelassen sind. 5. Die höchste Stufennummer, die PL/1 zuläßt, ist 255. Allerdings dürfen davon nur 15 Stufen mit Bezeichnern besetzt sein. 6. Der Zusatz INITIAL darf nur für Elementvariable vergeben werden. Diese Regeln für die Vereinbarung von Strukturen sollen wiederum an einem Beispiel demonstriert werden: DCL 1 TEILENACHWEIS, 4 TEILEDATEN, 6 NUMMER 6 BESCHREIBUNG 3 LAGERDATEN, 5 NUMMER
C H A R (3) INIT ('001'), C H A R (50), C H A R (3),
2.4 Arbeitsobjekte in PL/1
55
5 MENGE D E C F I X E D (4), 2 BESTELLDATEN, 6 ( B E S T E L L M E N G E , LOSGROESSE) D E C F I X E D (3); Die Hauptstruktur wird in diesem Fall mit dem Bezeichner „ T E I L E N A C H WEIS" angesprochen. Die Unterstrukturen mit den Stufennummern Fünf und Sechs sind Elementvariable und werden deshalb mit einem Attribut versehen. Die Unterstruktur L A G E R D A T E N könnte natürlich auch die Stufennummer Zwei bekommen. Zu dieser Unterstruktur gehört die Zeichenkette „ N U M M E R " und die dezimale Festpunktzahl „ M E N G E " , was noch einmal auf den heterogenen Aufbau von Strukturen hinweist. Eine Struktur oder eine Unterstruktur wird von einem Programm dadurch aufgerufen, daß der betreffende Bezeichner in einer Anweisung erscheint. Da es aber nun zulässig ist, in Strukturvereinbarungen in verschiedenen Unterstrukturen dieselben Namen zu verwenden, können dadurch Zweideutigkeiten entstehen. In solchen Fällen ist es notwendig, den Namen der übergeordneten Struktur mit aufzurufen. So wäre im obigen Beispiel die Teilnummer der Lagerdaten durch die Folge zweier Bezeichner zu identifizieren, die durch einen Punkt miteinander verbunden sind, also TEILEDATEN. NUMMER Der Lagerort wäre zu identifizieren durch die Angabe: LAGERDATEN.NUMMER Wir nennen diese Art der Bezeichnung einen gekennzeichneten Namen („gekennzeichnete bezeichner"). In der Praxis werden häufig Strukturen in Bereiche eingebettet sein. Um beim Beispiel des Teilenachweises zu bleiben, wird in der Regel in einem Betrieb nicht nur der Teilenachweis einer Teilnummer in einer Datenverarbeitungsanlage gespeichert sein, sondern alle Teilnummern, die dort vorkommen. Dies bedeutet, daß der Bereich T E I L E N A C H W E I S aus einer größeren Anzahl von Strukturen besteht. Deshalb lautet die Vereinbarung für die Hauptstruktur, die einen Bereich darstellt, unter der Annahme, daß 10000 Teilnummern vorkommen: D C L 1 T E I L E N A C H W E I S ( 10000), 4 TEILEDATEN, Beim Aufruf eines Datenwortes ist jetzt natürlich noch anzugeben, in welcher Struktur es steht. Dies erfolgt wiederum mit Hilfe eines Indizes. Beispiel: Y = MENGE(5); In diesem Fall würde das Programm die Lagermenge des fünften Teilesatzes innerhalb des strukturierten Bereiches aufrufen und in die Variable Y übertragen. Auch hier sind natürlich mehrdimensionale Bereiche zugelassen. Dies
56
2. Grundelemente der problemorientierten Programmiersprache PL/1
soll noch an einem anderen Beispiel, nämlich dem einer Energieverbrauchsstatistik, gezeigt werden. Gewünscht wird, den Verbrauch der einzelnen Abnehmer über zehn Jahre hinweg monatlich zu erfassen und zu speichern: DCL 1 VERB RAUCHSTATISTIK( 1000), 2 ABNEHMER-NUMMER CHAR(5), 2 ABNAHME(10,12) DEC FIXED(6,2); Es wird in diesem Fall der Verbrauch von jedem Abnehmer zehn Jahre lang monatlich als Festpunktzahl gespeichert. Soll der Verbrauch des 50. Abnehmers für das 5. Jahr und den 6. Monat aufgerufen werden, so lautet die entsprechende Anweisung: Y = VERB RAUCHSTATISTIK(50) .ABNAHME(5,6); Solange die Reihenfolge der Indizes der Strukturstufen unverändert bleibt, dürfen sie auch beliebig nach rechts oder links verschoben werden. Dies soll noch an einem Beispiel gezeigt werden. Folgende Anweisungen haben dieselbe Wirkung: Y = VERB RAUCHST ATISTIK.ABNAHME(50,5,6); Y = VERB RAUCHSTATISTIK(50,5,6). ABNAHME; In der betrieblichen Datenverarbeitung kommen die verschiedenartigsten Strukturen vor. Die Beispiele haben bereits gezeigt, daß es relativ viel Schreibaufwand verursacht, Strukturen zu definieren. Um diese Arbeit abzukürzen, verfügt PL/1 noch über eine spezielle Vereinbarung, nämlich „LIKE". Diese Vereinbarung gibt an, daß eine zu definierende Struktur in derselben Form aufgebaut sein soll wie eine bereits früher vereinbarte. Sie kopiert quasi diese Struktur, ohne sie neu zu beschreiben, wobei die verwendeten Bezeichner und ihre Attribute beibehalten werden. Um beim letzten Beispiel, der Verbrauchsstatistik zu bleiben, könnte ein Betrieb daran denken, das Auswertungsprogramm für diese Statistik auch für andere Auswertungen zu benutzen. So könnte man damit den Umsatz, den einzelne Verkäufer in einem Warenhaus erzielt haben, in derselben Form ermitteln. Die entsprechende LIKEVereinbarung würde dann lauten: DCL 1 UMSATZ LIKE VERBRAUCHSTATISTIK; Ein Dimensionsattribut hinter dem Bezeichner STIK" wäre falsch.
„VERBRAUCHSTATI
Die LIKE-Vereinbarung ist nicht nur auf die Hauptstruktur beschränkt, sondern kann auch Unterstrukturen umfassen. Allerdings verbietet die Syntax von PL/1 ihre Anwendung auf strukturierte Bereiche wie im Beispiel VER BRAUCHSTATISTIK(IOOO). Die obige Vereinbarung würde nur eine einzige Struktur „UMSATZ" anlegen. In diesem Fall lautet die vollständige Vereinbarung: DCL 1 UMSATZ (1000) LIKE VERBRAUCHSTATISTIK;
57
2.4 Arbeitsobjekte in PL/1
Die inverse Funktion von LIKE hat das DEFINED-Attribut. Es legt fest, daß die in einer Vereinbarung bezeichneten Element-, Struktur- oder Bereichsdaten den gleichen Speicherplatz belegen wie bereits vereinbarte. In dieser Weise kann Speicherkapazität eingespart werden. Dafür noch zwei Beispiele: DCL MATRIX(10,20,30),TABELLE(10,20,30) DEFINED MATRIX; DCL TEXT CHAR(50), TEXT_1 CHAR(10) DEFINED TEXT, TEXT_2 CHAR(10) DEFINED TEXT POSITION(ll), TEXT_3 CHAR(30) DEFINED TEXT POSITION(21); Im ersten Beispiel wird ein dreidimensionaler Bereich „TABELLE" definiert, der identisch ist mit dem Bereich „MATRIX". Die Elemente beider Bereiche entsprechen sich, so daß eine Veränderung eines Elements von MATRIX auch eine Veränderung des entsprechenden Elements im Bereich TABELLE zur Folge hat und umgekehrt. Diese Eins-zu-Eins-Zuordnung wird auch korrespondierendes Definieren genannt. Im zweiten Beispiel erfolgt ein überlagerndes Definieren, bei dem über eine schon definierte Datengruppierung, in diesem Fall einem Bereich, eine neue Datenorganisation gelegt wird. Dadurch wird der Bereich „TEXT" in drei Unterbereiche gruppiert. Der erste Unterbereich TEXT_1 beginnt bei der ersten Speicherstelle von TEXT und hat die Ausdehnung von zehn Zeichen. TEXT_2 beginnt beim 11. Zeichen von TEXT, was durch das Attribut POSITION markiert wird. In derselben Weise werden die letzten 30 Zeichen von TEXT_3 zugeordnet. Auf weitere Einzelheiten dieser sehr eleganten Technik, Datengruppierungen zu organisieren und zu verarbeiten, wird im zweiten Band näher eingegangen werden.
Übungsaufgaben 1. Geben Sie die durch das PICTURE-Attribut aufbereiteten Zeichenketten für folgende Vereinbarungen und Quelldaten an: lfd. Nr.
PICTUREVereinbarung
Vereinbarungen der Quelldaten
Quelldaten
1 2 3 4 5 6 7 8 9
99999 99999V 9999V99 9999V/99 9999. V99 ZZZ9V.99 ****V99 YYYYVYY ZZ,999V99
DEC DEC DEC DEC DEC DEC DEC DEC DEC
01234 01234 01234 01234 012.34 012.34 000.01 000.01 00012.34
FIXED(5) FIXED(5) FIXED(5) FIXED(5) FIXED(5,2) FIXED(5,2) FIXED(5,2) FIXED(5,2) FIXED(7,2)
2. Grundelemente der problemorientierten Programmiersprache PL/1
58
lfd. Nr.
PICTUREVereinbarung
Vereinbarungen der Quelldaten
Quelldaten
10 11 12 13 14 15
SZZ.999V99 $ZZZ.99CR ,V99999E99 ,V99999KS99 SZZ9.V99E+99 ZZZV.99ES99
DEC DEC DEC DEC DEC DEC
00012.34 1.23 .12345E10 .12345E10 001.23E—01 001.23E+04
FIXED(7,2) FIXED(5,2) FLOAT(5) FLOAT(5) FLOAT(5) FLOAT(5)
2. Geben Sie die Vereinbarung für folgende Datengruppierungen an: 1. Bezeichner: SPALTE
Spalte
Element
1 2 3 4 5
4.3 2.6 7.8 9.9 0.2
2. Bezeichner: TABELLE ^ ^ ^ S p a l t e 1 2 3 4 3. Bezeichner: TAFEL
1
2
3
9.IE—21 483E64 6.09E03 0.0098E19
0.8E19 2109E0 9E00 0.123E06
7.5E- 03 314E--45 5E01 2E00
^^Spalte Zeile^^^ 0 'IT' 'ME' 'AM' '12' '3%'
2
3
'-3' 'HE' 'AN' '34' '$4'
'GO' 'WE' 'AS' '56'
'4P BE' 'AT' oo r-
-2 -1 0 1 2
1
3. Esist folgende Struktur ohne Benutzungvon Bereichen neu zu vereinbaren: DCL 1 Q(2), 2 A CHAR(IO). 2 B(2), 3 C CHAR(20), 3 D CHAR(30); 4. Was definiert folgende Vereinbarung: DCL DATEN (1,2,3,4,5) FIXED;
3. Der elementare Teil der problemorientierten Programmiersprache PL/1
3.1 Verarbeitungsanweisungen Die PL/l-Anweisungen lassen sich in folgendes Klassifizierungsschema einordnen: Klassifizierung von Anweisungen Übersetzeranweisungen (z.B. E N D )
Ob j ektprogrammanweisungen Transportanweisungen
Verarbeitungsanweisungen
Programmsteuerungsanweisungen
Verarbeitungsanweisungen sind generell dadurch ausgezeichnet, daß Daten verschiedenen Ursprungs in der Weise verknüpft werden, daß „neue" Daten entstehen. Informationstheoretisch betrachtet, sind diese Anweisungen dadurch gekennzeichnet, daß im informationellen Arbeitsprozeß der mittlere Informationsgehalt der eingebrachten Informationen abnimmt. So steht in einem binären Verarbeitungselement ein Ausgangsbit zwei Eingangsbits gegenüber. D e r Entscheidungsgehalt am Ausgang dieses Arbeitsprozesses ist damit kleiner als am Eingang. Alle elementaren Verarbeitungsanweisungen haben die gleiche Struktur. D e r Wert eines arithmetischen, booleschen oder Vergleichsausdrucks wird einer Variablen, gekennzeichnet durch einen Bezeichner, zugeordnet. E s ist deshalb auch üblich, diese Anweisung als Ergibtanweisung zu bezeichnen [9, S. 37]. Allerdings gibt es auch Transportanweisungen, die in Form einer Ergibtanweisung programmiert werden. Man sollte deshalb um der begrifflichen Klarheit wegen genauer unterscheiden, welche Veränderungen die Arbeitsobjekte in einem informationellen Arbeitsprozeß erfahren, ob es Substanz- oder nur Lagenveränderungen sind. Formal ist die Verarbeitungsanweisung, wenn man den Bedingungspräfix und den Markenpräfix vernachlässigt, folgendermaßen definiert: ausführbare Verarbeitungsanweisung :: = ' elementvariable bereichsvariable strukturvariable . pseudovariable J
r[,elementvariable] " [,bereichsvariable] [,strukturvariable] l'[,pseudovariable] -
_
auscjrucj(.
'
60
3. Der elementare Teil der problemorientierten Programmiersprache PL/1
ausdruck
' arithmetischer ausdruck ' boolescher ausdruck vergleichsausdruck . Verkettungsausdruck
Die Ausführung jeder Verarbeitungsanweisung erfolgt in zwei Phasen. Zuerst wird ihr rechter Teil, das Strukturelement „ausdruck", der im allgemeinen aus mehreren Operanden besteht und durch Operatoren verknüpft ist, zahlenmäßig berechnet. Anschließend wird dieser Wert einer oder auch mehreren Variablen, die im linken Teil der Anweisung notiert wurden, zugewiesen. Beispiel: A,B,C = 2 * D * (E + F); Diese Anweisung addiert zunächst die beiden Variablen E und F, multipliziert die Summe mit 2D und übergibt den Wert dieses Ausdruckes an die drei Variablen A, B und C. In dieser mehrfachen Wertzuweisung unterscheidet sich PL/1 von FORTRAN, wo der Programmierer den Wert, beispielsweise eines arithmetischen Ausdrucks, nur einer Variablen zuweisen konnte. Zunächst soll eines der wichtigsten Programmelemente problemorientierter Programmiersprachen, die Unterklasse der arithmetischen Ausdrücke, in ihren verschiedenen Varianten untersucht werden. Analog der Unterteilung der Arbeitsobjekte unterscheiden wir arithmetische Elementausdrücke, Bereichsausdrücke und Strukturausdrücke: arithmetischer ausdruck
arithmetischer elementausdruck arithmetischer bereichsausdruck arithmetischer strukturausdruck
Es soll auch hier wieder zunächst die Verarbeitung skalarer Arbeitsobjekte verfolgt werden. Ein arithmetischer Elementausdruck ist, in Worte gefaßt, eine computerorientierte arithmetische Rechenregel, die aus Konstanten und Variablen besteht, welche wir Operanden nennen. Diese sind durch Operatoren oder vorprogrammierte Funktionen verbunden, wobei wegen der seriellen Arbeitsweise einer Datenverarbeitungsanlage Gliederungsmittel (Klammern) verwendet werden, um die Priorität der Auswertung innerhalb eines Ausdrucks steuern zu können. Ein solcher Elementausdruck liefert, nachdem sämtliche arithmetische Operatoren, die in ihm notiert wurden, abgearbeitet sind, einen und nur einen Wert als Ergebnis. Er wird in der „ausführbaren Verarbeitungsanweisung" einer oder auch mehreren Variablen zugewiesen, die nicht unbedingt „elementvariable" sein müssen. Die Strukturbeschreibung des arithmetischen Elementausdrucks lautet somit: arithmetischer elementausdruck :: = [arithmetischer präfixoperator] ... skalarer Operand [arithmetischer infixoperator [arithmetischer präfix-
operator...] skalarer Operand]
3.1 Verarbeitungsanweisungen
61
Im einfachsten Fall besteht ein arithmetischer Elementausdruck aus einem einzigen skalaren Operanden in Form einer Variablen oder Konstanten. Auf das obige Beispiel einer arithmetischen Anweisung bezogen, wäre nach dieser Strukturbeschreibung der erste Operand die Konstante Zwei, der arithmetische Präfixoperator das Multiplikationssymbol und der zweite Operand die Variable „D". U m den Ausdruck „ ( E + F ) " noch in die Strukturbeschreibung mit aufnehmen zu können, wird das Strukturelement „skalarer Operand" rekursiv definiert: skalarer Operand :: = skalares arbeitsobjekt I skalarer funktionsaufruf I [Qarithmetischer elementausdruckf)] skalares arbeitsobjekt :: = elementvariable I elementkonstante Die Schreibweise arithmetischer Operatoren entspricht in PL/1, wie auch in anderen problemorientierten Programmiersprachen, im großen und ganzen der Notation der Mathematik mit Ausnahme der Potenzierung (**) und der Division (/). Dabei ist noch zu berücksichtigen, daß der Operator Potenzierung als ein Symbol gilt und deshalb zwischen den beiden Sternen kein Zwischenraum vorkommen darf. Eine Besonderheit stellt dabei noch der Multiplikationsoperator (*) dar, der immer vorhanden sein muß, auch wenn die mathematische Notation es gestattet, ihn wegzulassen. Operatoren werden in PL/ 1 eingeteilt in Präfixoperatoren und Infixoperatoren. Unter einem Präfixoperator versteht die Syntax von PL/1 ein Operationssymbol, das vor einem Operanden steht (monadische Operation). Beispiel: + A Ein Infixoperator verbindet zwei Operanden (dyadische Operation), wie: A + B Z u r Klasse der Präfixoperatoren gehören drei Elemente, nämlich die Addition, die Subtraktion und die Negation (natürlich nur für boolesche Operationen anwendbar): präfixoperator :: = + I — I —i Zu beachten ist noch, daß vor einer Variablen mehr als ein Präfixoperator stehen darf. Beispiel: A Für die Infixoperationen stellt PL/1 die üblichen arithmetischen Operatoren zur Verfügung zuzüglich der wichtigsten Vergleichsoperatoren, booleschen Operatoren und einem Kettenoperator, der, obwohl er nicht in arithmetischen und booleschen Anweisungen Verwendung findet, trotzdem hier bereits erwähnt werden soll:
62
3. Der elementare Teil der problemorientierten Programmiersprache PL/1
a r i t h m e t i s c h e r i n f i x o p e r a t o r :: = + 1 — 1 * 1 / 1 * * V e r g l e i c h s o p e r a t o r :: = > I > = I = I —1= I < = I < I —1< I - i > b o o l e s c h e r o p e r a t o r :: = & 11 k e t t e n o p e r a t o r :: =
II
Innerhalb eines Ausdrucks arbeitet eine Datenverarbeitungsanlage die einzelnen Operationen von links nach rechts ab und zwar unter der Beachtung einer hierarchischen Stufung der Operatoren: Stufe 1: präfixoperator I** 2: * 1/ 3: + 1 4: k e t t e n o p e r a t o r 5: V e r g l e i c h s o p e r a t o r 6: &
7: I Ranggleiche Operatoren werden wie in A L G O L und in F O R T R A N von links nach rechts fortschreitend ausgeführt. Beispiel: A * X/C
entspricht:
— c
Es wird zunächst das Produkt ax gebildet und dann der Quotient berechnet. Eine Ausnahme von dieser Regel bietet die höchste Prioritätsstufe, deren Operatoren von rechts nach links abgearbeitet werden. Beispiel: —A ** 2 In diesem Fall wird zunächst das Quadrat von A gebildet und anschließend mit einem negativen Vorzeichen versehen. Der Ausdruck: - A ** 2/3 * 4 + B entspricht der mathematischen Notation: a2 -4— + b 3 Denn es werden als erstes die beiden Operationen der höchsten Prioritätsstufe von rechts nach links abgearbeitet und anschließend der Quotient mit der Konstanten Vier multipliziert, um am Ende der Ausführung dieses Ausdrucks die Addition durchzuführen. Die Syntax von PL/1 verlangt nicht, daß zwischen den Operanden und den Operatoren Zwischenraumzeichen eingefügt werden. Aus Gründen der Übersichtlichkeit wird es der Programmierer trotzdem häufig tun. Sollen die Vorrangregeln aufgehoben werden, dann dienen dazu runde Klammern. In einem solchen Fall gelten die Vorrangregeln nur noch für den Ausdruck innerhalb der Klammer. Beispiel: -(A + B)**2
63
3.1 Verarbeitungsanweisungen
Es führt die Datenverarbeitungsanlage in diesem Fall zunächst die Addition durch, quadriert anschließend die Summe, um als letztes die Präfixoperation auszuführen. Weiteres Beispiel: ( - A ) ** 2
entspricht
(-a)2
In der bisherigen Darstellung arithmetischer Ausdrücke wurde stillschweigend unterstellt, daß die Attribute der Operanden gleich sind. In der Regel wird diese Annahme nicht erfüllt sein. Dann tritt eine spezielle Eigenschaft von PL/1 in Kraft, die ältere problemorientierte Programmiersprachen wie FORT R A N nur in rudimentärer Form besaßen, nämlich die Datenkonvertierung. Beispielsweise kann im obigen Beispiel der Summand A eine Festpunktzahl und B eine Gleitpunktzahl sein. In diesem Fall ist das Ergebnis nach den für die Datenkonversion aufgestellten Regeln ebenfalls eine Gleitpunktzahl. Allerdings soll im Rahmen des elementaren Teils von PL/1 nicht weiter auf diese Eigenschaft eingegangen werden. Wir unterstellen im folgenden, daß in arithmetischen Ausdrücken die Attribute der Operanden irrelevant sind. Die Regeln für arithmetische Ausdrücke wollen wir noch in einem etwas größeren Beispiel zusammengefaßt darstellen. Es sei die Aufgabe gegeben, folgende Formel so zu programmieren, daß eine Datenverarbeitungsanlage zu ihrer Lösung möglichst wenig Rechenprozesse aufwenden muß. y =
~
a +
bx+cx 2 + dx 3 + f (5b — f) 2
, " e
r-c + V ? X
In dieser Gleichung sei e die Basis der natürlichen Logarithmen. Als PL/1Anweisung lautet diese Formel: Y = - A + (X*(B + C * X + D*X**2) + F)/(5*B - F)**2 * EXP (X) + SQRT (F*X); In dieser Anweisung wurde an zwei Stellen ein skalarer Funktionsaufruf als Operand benutzt, nämlich: EXP und SQRT. Wir kommen damit zum Strukturelement „skalarer funktionsaufruf" des arithmetischen Elementausdrucks. Es handelt sich dabei um häufig benötigte Funktionen. Um Programmierarbeit zu sparen, werden sie vorprogrammiert als Bestandteil der Programmiersprache angeboten. Ein typisches Beispiel sind die Winkelfunktionen, die viele technisch orientierte Anwender benötigen. Es ist nicht einzusehen, warum jeder Anwender eine solche Funktion immer wieder neu programmieren soll. PL/1 bietet auch in dieser Hinsicht einen besonderen Komfort, indem es ein großes Repertoire von Funktionen dem Anwender zur Verfügung stellt. Eine solche standardisierte Funktion wird durch Nennung ihres Namens zusammen mit einer in Klammern stehenden Liste von Argumenten aktiviert. An dieser Stelle interessieren uns nur die in der PL/l-Literatur als arithmetische und mathematische Funktionen klassifizier-
64
3. Der elementare Teil der problemorientierten Programmiersprache PL/1
ten Unterprogramme. Die Namen dieser Funktionen wurden in der Tabelle 3— la zusammengestellt. Tabelle 3—la. Namen der eingefügten Funktionen für arithmetische Ausdrücke (Klassifizierung nach PL/l-Literatur)
arithmetische Funktionen ABS ADD BINARY CEIL COMPLEX CONJG DECIMAL DIVIDE FIXED FLOAT FLOOR
IMAG MAX MIN MOD MULTIPLY PRECISION REAL ROUND SIGN TRUNC
mathematische Funktionen ACOS ASIN ATAN ATAND ATANH COS COSD COSH ERF ERFC EXP
LOG LOGIO LOG2 SIN SIND SINH SORT TAN TAND TANH
Eine vollständige Beschreibung dieser Funktionen findet sich im Anhang 2. Hier sollen nur einige charakteristische Beispiele zitiert werden. Häufig wünscht sich der Programmierer, die Genauigkeit eines Rechenergebnisses bestimmen zu können. Für diesen Zweck stellt PL/1 drei Funktionen zur Verfügung: ADD
DIVIDE
MULTIPLY.
Die Arbeitsweise dieser Funktionen soll am Beispiel von ADD demonstriert werden. Die formale Beschreibung dieser Funktion lautet: ADD (x,y,p[,q]) Beim Aufruf dieser Funktion in einem arithmetischen Ausdruck wird die Summe aus den beiden Summanden x und y in der Genauigkeit p,q errechnet. Handelt es sich um eine Gleitpunktaddition, dann wird „q" nicht spezifiziert. Bei der Ausführung eines Objektprogramms wird zunächst der Wert dieser Funktion berechnet und anschließend entsprechend dem arithmetischen Ausdruck, in dem er vorkommt, weiter verarbeitet. Analog arbeiten die beiden Funktionen DIVIDE und MULTIPLY, die in ihrer Struktur ADD entsprechen. Von großer praktischer Bedeutung sind auch noch die drei arithmetischen Funktionen: MAX (x 1; x 2 ,...x n ) MIN (x!,x 2 ,...x n ) MOD (x,,x2)
65
3.1 Verarbeitungsanweisungen
Die Funktionen MAX und MIN entnehmen einer vorgegebenen Anzahl von n Ausdrücken den Ausdruck mit dem maximalen bzw. minimalen Wert und geben diesen Wert an die Stelle des Funktionsaufrufes zurück. Leider wird dabei nicht vermerkt, von welchem Ausdruck der Wert übernommen wurde. Die Funktion MOD gibt den Rest der Division xj/x2 an. Bei den „mathematischen" Funktionen ist an erster Stelle die Funktion zur Berechnung der Quadratwurzel (SQRT) zu nennen. Weiterhin sind in dieser Funktionsklasse die Winkelfunktionen wie SIN(x), COS(x), TAN(x) erwähnenswert, wobei das Argument x im Bogenmaß anzugeben ist, und SIND(x), COSD(x), TAND(x), falls das Argument x im Gradmaß ausgedrückt wurde. Um den Logarithmus einer Variablen bestimmen zu können, bietet PL/1 drei Funktionen an: den natürlichen Logarithmus: LOG(x) den dekadischen Logarithmus: LOGlO(x) den Logarithmus zur Basis Zwei: LOG2(x). Im begrifflichen Zusammenhang mit den Funktionsaufrufen steht der Begriff der Pseudovariablen (s. Anhang 6). Wie die formale Strukturbeschreibung der arithmetischen Anweisung zeigt, sind Pseudovariable Empfangsfelder einer Ergibtanweisung. Der Wortteil „Pseudo" soll andeuten, daß es sich dabei um keine echte Variable, sondern um eine Funktion als Empfangsfeld handelt. Der Programmierer darf Pseudovariable an den Stellen des Programms verwenden, wo auch andere Variable zugelassen sind, um Werte aufzunehmen. Nicht alle Funktionen sind als Pseudovariable verwendbar. Von den in Tabelle 3 - l a aufgelisteten Namen läßt die Syntax von PL/1 nur drei Funktionen als Pseudovariable zu, nämlich: COMPLEX
IMAG
REAL.
Die Pseudovariable COMPLEX(a,b) beispielsweise ordnet den Realteil eines komplexes Ergebnisses der Variablen „a" zu und den Imaginärteil der Variablen „b", so daß jede für sich allein weiter verarbeitet werden kann. Wir wollen die arithmetischen Ausdrücke abschließen, indem wir noch ihre Verwendung an zwei größeren Programmierbeispielen darstellen. Im ersten sollen die vier Grundrechenarten auf mehrstellige Dualzahlen angewendet werden. In diesem Programmierbeispiel (BEISP5) definieren wir zunächst zwei vierstellige Festpunktdualzahlen „A" und „B" mit den beiden Anfangswerten 1 1 0 0 und 1 0 10. Anschließend bilden wir Summe, Differenz und Produkt dieser beiden Zahlen. In der letzten arithmetischen Anweisung wird das Produkt durch die Dualzahl „B" dividiert, so daß der Quotient der Ausgangswert „A" sein muß. Die Ergebnisse dieser vier arithmetischen Anweisungen sollen natürlich als Dualzahlen gedruckt werden, was leider die Syntax von PL/1 nicht unmittelbar zuläßt. Wir helfen uns in der Weise, daß wir die Ergebnisse C, D, E und F in Bitketten C _ l , D _ l , E_1 und F_1 konvertieren und sie in dieser Form mit PUT DATA ausdrucken lassen.
66
3. Der elementare Teil der problemorientierten Programmiersprache PL/1
BEISP5
:
PROCEDURE OPTIONS(MAIN); DCL(A I N I T I A L ( 1 1 0 0 B ) , (C,D) E (C 1 , D 1)
B INITIAL(1O1OB),F)
BINARY FIXED
(4),
BINARY FIXED
(5),
BINARY FIXED
(7),
BIT
(5),
E_1
BIT
(7),
F_1
BIT
(4);
C=
A+B;
D = A-B; E = A*B ; F = E/B; C_1 = C; D_1 = D; E_1 = E; F 1 = PUT
F;
DATA(C_1,D_1,E_1,F_1); END B E I S P 5 ;
Ergebnis: C_1='10110'B
D_1='00010'B
E_1='1111000'B
F_1='1100'B;
Im zweiten Programmierbeispiel wollen wir den Umgang mit komplexen Größen an einem Beispiel aus dem Fachgebiet der Elektrotechnik demonstrieren. Es ist dort üblich, Wechselstromschaltungen, die aus Wirkwiderständen (ohmsche Widerstände) und Blindwiderständen (Kapazitäten und Induktivitäten) bestehen, als komplexe Größen zu interpretieren, um auf sie die Regeln für das Rechnen mit komplexen Zahlen anwenden zu können. So soll ein PL/1Programm geschrieben werden, das den Betrag des komplexen Widerstandes und den Phasenwinkel folgender elektrischer Schaltung berechnet: Hintereinanderschaltung eines ohmschen Widerstandes R! (Leitungswiderstand) mit einer Parallelschaltung, bestehend aus einer verlustbehafteten Induktivität (Reihenschaltung ohmscher Widerstand R2 mit reiner Induktivität L) und einer verlustbehafteten Kapazität (Parallelschaltung: ohmscher Widerstand R 3 mit reiner Kapazität C). Der induktive Blindwiderstand beträgt jcoL (w: Kreisfrequenz 2ni) und der kapazitive 1/jcuC. Wir führen ein: Z L = R2 + jcoL
67
3.1 V e r a r b e i t u n g s a n w e i s u n g e n
Zfff8 ic — R, Yl = ¿-L
YL+YC YC =
K
+ jcuC 3
Dabei ist Z ges der gesamte Widerstand dieser Schaltung und Y L der Leitwert der Reihenschaltung: ohmscher Widerstand R 2 mit der Induktivität L, und Y c der Leitwert der verlustbehafteten Kapazität. Unter Verwendung dieser Symbolik entsteht das nachfolgende Programm: BEISP6
:
PROCEDURE DCL P I L
OPTIONS(MAIN);
INITIAL DEC
FLOAT,
(ZGES,YC) EOF B I T ON E N D F I L E
(3.14159),
COMPLEX, (1)
INIT
(SYSIN)
('O'B);
EOF =
'1'B;
GET DATA
(FREQ,R1,R2,L,R3,C)
DO WHILE
(EOF =
OMEGA
=
REAL
(YC)
IMAG
(YC)
ZGES
=
2
* PI
= OMEGA * = R1
BETRAG
*
FREQ;
1/R3;
+
= ABS
C;
1/(1/COMPLEX
* L)
/*
(R2,
OMEGA
+ YC) ; (ZGES);
BETRAG GESAMTWIDERSTAND
SUMME QUADRATE R E A L PHASWI
COPY;
'O'B);
= ATAND
ALS
2.
WURZEL AUS
UND I M A G I N Ä R T E I L (IMAG
(ZGES),
*/
REAL
(ZGES)) ; /*
PHASENWINKEL
PUT DATA PUT S K I P GET DATA
IM GRADMASS
(BETRAG,
PHASWI)
*/
SKIP;
(4); (FREQ,R1,R2,L,R3,C)
COPY;
END; END
BEISP6;
Um eine eindeutige Zuordnung zwischen den Eingabewerten und den Ergebnissen zu haben, ist es notwendig, die Eingabewerte auszudrucken. Natürlich könnte man sie in der PUT-Anweisung zusammen mit den Ergebnissen notieren. Um Programmierarbeit zu sparen, stellt die Sprachsyntax für die GETAnweisung den Zusatz „COPY" zur Verfügung, durch den diese unmittelbar
68
3. Der elementare Teil der problemorientierten Programmiersprache PL/1
nach dem Leseprozeß automatisch gedruckt werden. Um die Funktionsweise der Pseudovariablen zu demonstrieren, haben wir die komplexe Größe „YC" unter Verwendung der beiden Funktionen R E A L und IMAG als Pseudovariable aufgebaut. Natürlich wäre es auch möglich, sie direkt in die Berechnung von „ Z G E S " aufzunehmen, wobei diese arithmetische Anweisung dann lauten würde: Z G E S = R1 + l/(l/COMPLEX(R2,OMEGA*L) + C O M P L E X (1/R3, O M E G A * C ) ) ; Um im Listenbild der Ausgabe die durch COPY gedruckten Anfangswerte von den Ergebnissen „ B E T R A G " und „PHASWI" abzuheben, soll der Drukker einen einzeiligen Vorschub vor dem Drucken der Ergebniszeile ausführen, was durch den Zusatz „SKIP" in der PUT-Anweisung ausgedrückt wird. Dabei ist zu beachten, daß dieser Anweisungszusatz schon vor der Ausführung der PUT-An Weisung zum Tragen kommt. In gleicher Weise wird nach dem Drucken der Ergebniszeile durch die nächste PUT-SKIP-Anweisung ein vierzeiliger Vorschub ausgelöst. Wir wenden uns nun der Struktur boolescher Ausdrücke zu, um anschließend gemeinsam für die arithmetischen und booleschen Ausdrücke die Frage der Bereichs- und Strukturverarbeitung zu diskutieren. Analog zum arithmetischen Ausdruck definiert die Syntax von PL/1: boolescher ausdruck : : =
boolescher elementausdruck | boolescher bereichsausdruck > boolescher strukturausdruck J
Auch die Struktur des booleschen Elementausdruckes ist analog zum arithmetischen Elementausdruck aufgebaut: boolescher elementausdruck:: = [boolescher präfixoperator]... skalarer boolescher Operand [boolescher infixoperator[boolescher präfixoperator...] skalarer boolescher Operand] boolescher präfixoperator:: = —i skalarer boolescher Operand:: = skalares boolesches arbeitsobjekt I skalarer boolescher funktionsaufruf I [(] boolescher elementausdruck [)] skalares boolesches arbeitsobjekt:: = boolesche elementvariable Iboolesche elementkonstante Boolesche Arbeitsobjekte sind Bitketten. Es hat sich in der PL/l-Literatur für boolesche Ausdrücke auch die Bezeichnung Bitkettenausdrücke bzw. „Bitkettenoperationen" eingebürgert [7, S. 35]. Beispiel: DCL (A INITIAL ('0101'B), B INITIAL ( ' l l l l ' B ) , C) BIT(4); C = A&B;
69
3.1 Verarbeitungsanweisungen
Das Ergebnis C lautet nach den Regeln der booleschen Algebra*: C = '0101'B; Falls die Operanden eines booleschen Ausdrucks nicht in Form von Bitketten vorliegen, werden sie vor der Ausführung boolescher Operationen in Bitketten konvertiert. Sind die beiden Operanden einer Infixoperation nicht gleich lang, wird der kürzere nach rechts mit binären Nullen aufgefüllt, so daß beide Operanden die gleiche Kettenlänge haben. Auch das Ergebnis weist dieselbe Länge auf. Die Regeln der booleschen Algebra lassen sich für den Sprachumfang von PL/ 1, unter der Annahme, daß die beiden Variablen X und Y die Kettenlänge Eins haben, wie folgt zusammenfassen: ^~\Operanden: X Y
0 0 11 0 10 1
Name
0 0 0 1 O l l i 110 0
Konjunktion, UND-Verknüpfung Disjunktion, ODER-Verknüpfung Negation Negation
Operation: Z=X&Y Z = Xl Y
z=-x Z = —i Y
10 10
Die restlichen booleschen Funktionen, von denen insbesondere für den Entwurf von Datenverarbeitungsanlagen die NAND- und die NOR-Funktion von Bedeutung sind, lassen sich durch den Funktionsaufruf „BOOL" realisieren. Da die Eingabe und Ausgabe boolescher Arbeitsobjekte in PL/1 in Form von Bitketten erfolgt, wird diese Funktion in der Regel unter den Funktionen für die Kettenverarbeitung subsumiert (s. Anhang 4). Mit dieser Funktion lassen sich alle 16 dyadischen booleschen Operationen in PL/1 realisieren. Die vier möglichen Ausgangssignale einer booleschen Funktion muß dabei der Programmierer als drittes Argument in den Funktionsaufruf mit aufnehmen. So lautet beispielsweise für den Fall der NAND-Verknüpfung (Shefferfunktion) der boolesche Funktionsaufruf: BOOL('0011'B,'0101'B,'1110'B) Die ersten beiden Bitketten sind die vier möglichen Kombinationen von Eingangssignalen X] und x2 der NAND-Verknüpfung und die Bitkette '1110'B die dazugehörigen Ausgangssignale. So hat beispielsweise für X] = 0 und x2 = 0 die NAND-Verknüpfung den Wert '1'. Um die Wirkungsweise dieser 16 Funk*
Es wird unterstellt, daß eine Datenverarbeitungsanlage dieses Ergebnis mit PUT D A T A ausgibt; denn die interne Datenspeicherung erfolgt ohne Hochkommata und den Buchstaben „B".
70
3. Der elementare Teil der problemorientierten Programmiersprache PL/1
tionen darzustellen, soll ein Programm geschrieben werden, das eine Tabelle sämtlicher dyadischer boolescher Funktionen ausdruckt. Zu diesem Zweck ist es allerdings notwendig, dem Stoff dieses Buches wieder etwas vorzugreifen und schon auf die DO-Anweisung, die im Abschnitt 3.3 zur Diskussion steht, einzugehen, weil sich mit dieser Anweisung ein solches Programm sehr kurz formulieren läßt. Im einfachsten Fall besteht eine DO-Anweisung aus einer Laufvariablen, beispielsweise I, und einem Variablenbereich, den diese Laufvariable durchlaufen soll. In unserem Fall lautet die DO-Anweisung: D O 1 = 0 T O 15; Diese Anweisung besagt, daß die Laufvariable „I" den Wertebereich null bis fünfzehn durchlaufen soll und zwar mit der Schrittweite „1". Dadurch werden die nach der DO-Anweisung notierten Anweisungen insgesamt 16mal durchlaufen. Jeder Durchlauf wird beendet durch eine END-Anweisung. Das Programm zur Lösung dieser Aufgabe lautet: BEISP7
:
PROCEDURE DCL A B I T
(4),
X BIT
(4)
INIT
('0011'B),
Y BIT
(4)
INIT
('0101'B),
I DO
OPTIONS(MAIN);
B I N FIXED
(4);
I = 0 TO
15;
A = BOOL
(X,Y,I);
PUT S K I P
(2)
DATA
(X,Y,I,A);
END; END B E I S P 7 ;
Der Drucker gibt folgende Ergebnisse aus: Druckerausgabe
Name boolesche Funktion
x= '001 l ' B x= '001 l ' B
Y = '0101'B Y = '0101'B
1= 0 1= 1
x= '0011'B x= '001 l ' B x= '0011'B x= '0011'B x= '0011'B x= '0011'B
Y= Y= Y= Y= Y= Y=
1= 1= 1= 1= 1= 1=
'0101'B '0101'B '0101'B '0101'B '0101'B '0101'B
2 3 4 5 6 7
A = '0000'B; Nullfunktion (nie) A = '0001'B; Konjunktion (UND-Verknüpfung) A = '0010'B A = '0011'B A = '0100'B A = '0101'B A = '0110'B Antivalenz; Exklusives Oder A = ' O l l l ' B Disjunktion; Inklusives Oder (ODER-Verknüpfung)
3.1 Verarbeitungsanweisungen
71
X='0011'B
Y='0101'B
1= 8
A='1000'B;
weder noch, Peircefunktion (NOR-Verknüpfung) Äquivalenz; Gleichheit
X='0011'B X='0011'B X='0011'B X='0011'B X='0011'B X='0011'B
Y='0101'B Y='0101'B Y='0101'B Y='0101'B Y='0101'B Y='0101'B
1= 9 1=10 1=11 1=12 1=13 1=14
X='0011'B
Y='0101'B
1=15
A='1001'B; A='1010'B; A='1011'B; Implikation; wenn, dann A='1100'B; A='1101'B; Implikation; wenn, dann A='1110'B; Shefferfunktion (NAND-Verknüpfung) A='1111'B; Einsfunktion (immer)
Wir haben in diese Ausgabe noch die Namen der entsprechenden Funktionen mit aufgenommen. In der vorletzten Zeile findet sich die schon erwähnte NAND-Verknüpfung. Boolesche Ausdrücke treten häufig in Verbindung mit Anweisungen zur Programmsteuerung auf, nämlich der noch zu behandelnden IF-Anweisung. Dasselbe gilt für die jetzt noch zu diskutierende dritte Klasse skalarer Operationen, den Vergleichselementausdruck. Er sagt mit Hilfe eines Vergleichsoperators (s. Klasse „Vergleichsoperator") aus, ob der Vergleich wahr (Bit:l) oder falsch (Bit.O) ist. Jede Vergleichsoperation liefert also als Ergebnis eine einstellige Bitkette ( T B oder 'O'B). In PL/1 gibt es drei Arten von Vergleichen: 1. den arithmetischen Vergleich 2. den Vergleich von Zeichenketten 3. den Vergleich von Bitketten. Beispiel: Unter der Voraussetzung, daß die Variablen X und Y dezimale Festpunktzahlen mit den Werten X = 1 und Y = 2 sind, liefern sämtliche möglichen Vergleichsoperationen folgende Ergebnisse: Vergleichselementausdruck
Ergebnis
X> Y X >= Y X = Y X-i= Y X Y
'O'B 'O'B 'O'B TB TB TB 'O'B TB
Besondere Beachtung verdient in diesem Zusammenhang das Gleichheitszeichen, das in PL/1 in zweifacher Bedeutung verwendet wird, nämlich als Ver-
72
3. D e r elementare Teil der problemorientierten Programmiersprache PL/1
gleichsoperator und zur Wertzuweisung in dem Sprachelement „ausführbare Verarbeitungsanweisung". So würde, um beim letzten Beispiel zu bleiben, die Anweisung: Z = X = Y; der Variablen „Z" den Wert 'O'B zuweisen*. Wenn die Operanden eines Vergleichs nicht derselben Klasse von Arbeitsobjekten angehören, beispielsweise der eine Operand eine Bitkette ist und der andere in die Klasse der arithmetischen Daten fällt, dann erfolgt eine Datenkonvertierung, wobei die Syntax von PL/1 wiederum Prioritätsstufen einführt. Arithmetische Arbeitsobjekte bekommen die höchste Priorität. Ihnen folgen die Zeichenketten und die Bitketten mit der niedrigsten Priorität. Soll beispielsweise ein Vergleichsausdruck eine Bitkette mit einem dezimalen Festpunktwert vergleichen, dann würde zuerst der Übersetzer beide Operanden in duale Festpunktzahlen konvertieren und anschließend einen arithmetischen Vergleich durchführen. Zu beachten ist noch, daß auf komplexe Zahlen nur die Vergleichsoperatoren = und —1 = angewendet werden dürfen. An dieser Stelle soll uns nur der arithmetische Vergleich und der Vergleich von Bitketten interessieren. Eine bitweise Vergleichsoperation wird in den beiden Operanden von links nach rechts ausgeführt. Notfalls ergänzt der Übersetzer einen kürzeren Operanden rechts mit dem Binärzeichen Null, um gleiche Operandenlänge zu erreichen. Beispiel: Die Variable A sei die Bitkette '0001'B und die Variable B '001'B. Dann sind folgende Vergleichsoperationen möglich:
*
Vergleichselementausdruck
Ergebnis
A > B A >= B A = B A-i=B A B
'0'B '0'B '0'B TB TB TB '0'B TB
Z ist dabei als BIT (1) vereinbart worden.
3.1 Verarbeitungsanweisungen
73
Für Vergleichsausdrücke und zwar unter Berücksichtigung der Datenkonversion* gelten folgende formale Definitionen: vergleichselementausdruck Vergleichsausdruck:: = • vergleichsbereichsausdruck vergleichsstrukturausdruck vergleichselementausdruck:: = skalarer Vergleichsoperand Vergleichsoperator skalarer Vergleichsoperand skalarer Vergleichsoperand:: = skalares vergleichsobjekt I
skalares vergleichsobjekt:: = vergleichselementvariable I vergleichselementkonstante Sollen Vergleiche zwischen Vergleichselementausdrücken ausgeführt werden, dann sind sie in runde Klammern zu setzen. Dasselbe gilt für boolesche Elementausdrücke, die boolesche Operatoren enthalten. Beispiel: DCL (U,V,W,Z,Y) BIT(l); Z = (U & V) = ( W l Y ) ; D a arithmetische Operatoren vor Vergleichsoperatoren ausgeführt werden, ist es in diesem Fall nicht notwendig, arithmetische Elementausdrücke, die Vergleichsobjekte sind, in Klammern zu setzen. Als weiteres Beispiel für diese Notation sollen noch arithmetische Vergleiche gebracht werden: A > B In diesem Fall gehören die beiden Vergleichsoperanden der Klasse „arithmetischer elementausdruck" an und zwar in Form des skalaren Arbeitsobjektes „elementvariable". Wie aus der formalen Definition hervorgeht, sind aber als Operanden in Vergleichselementausdrücken, wie generell in PL/1 üblich, auch wieder Elementausdrücke zugelassen. Beispiel: X = —A + B > = ( C < D ) ; Unter der Voraussetzung, daß die Variablen A , B, C und D dezimale Festpunktzahlen mit den Werten A = 1, B = 2, C = 3, D = 4 sind, wird unter Berücksichtigung der hierarchischen Stufung der Operatoren der Variablen X als Ergebnis die Bitkette ' l ' B zugewiesen; denn sowohl der arithmetische Elementausdruck — A + B als auch der Vergleich C < D liefert als Ergebnis den Wert Eins. Als letztes wird der arithmetische Vergleich > = durchgeführt, der, Sie wurden bei der formalen Definition des arithmetischen und booleschen Ausdrucks nicht berücksichtigt.
3. Der elementare Teil der problemorientierten Programmiersprache PL/1
74
da beide Operanden den Wert Eins haben, wahr ausfällt. Aus dieser Eigenschaft von Vergleichsausdrücken, wonach sie mehrere Vergleichsoperatoren haben können, darf allerdings nicht geschlossen werden, daß die in der Mathematik üblichen mehrfachen Vergleiche direkt für PL/1 übernommen werden dürfen. Beispiel: Der arithmetische Vergleich mit den obigen Zahlenwerten A < B < C < D, der das Ergebnis wahr liefert, darf nicht unmittelbar in derselben Form in PL/ 1 notiert werden, weil die beiden Operanden „B" und „C" gleichzeitig zwei Vergleichsoperationen angehören. Eine gültige PL/l-Anweisung zur Lösung dieser Aufgabe wäre: X = (A < B) = (B < C) = (C < D); Nur wenn sämtliche drei Vergleiche wahr ausfallen, bekommt auch die Variable X den Wert Eins zugewiesen. Der Programmierer kann die letzte Aufgabe auch in der Form lösen, daß er auf boolesche Operatoren zurückgreift: X = A Y T H E N A = 1; E L S E A = 2; C = A + B; Nach der Ausführung der IF-Anweisung fährt das Programm mit der näch-
3.3 Anweisungen zur Programmsteuerung
89
sten, sequentiell auf die IF-Anweisung folgenden Anweisung oder Vereinbarung fort. So wird im obigen Beispiel nach der IF-Anweisung die arithmetische Anweisung „C = A + B;" ausgeführt. Wurde die ELSE-Klausel nicht notiert und kam auch die „einheit eins" nicht zur Ausführung, weil die dort notierte Bedingung nicht erfüllt war, dann wird sofort die nächste hinter der IFAnweisung stehende Anweisung abgearbeitet. In der Regel wird die Struktur einer IF-Anweisung symbolisch folgendermaßen dargestellt, wobei wir uns auf das obige Beispiel beziehen:
Ohne den ELSE-Zweig ergibt sich folgende schematische Darstellung:
Falls die „einheit eins" eine GOTO-Anweisung enthält, wird in dem Fall, daß die von der IF-Anweisung abgefragte Bedingung erfüllt ist, nicht mehr zur nächsten, sequentiell auf die IF-Anweisung notierte Anweisung zurückgekehrt. Diesen Sonderfall zeigt die nächste schematische Darstellung:
90
3. Der elementare Teil der problemorientierten Programmiersprache PL/1
Es muß noch betont werden, daß sowohl in „einheit eins" als auch in „einheit zwei" der IF-Anweisung eine und nur eine Anweisung vorkommen darf. Diese Regel ist natürlich eine sehr praxisferne Einschränkung; denn häufig wird es so sein, daß eine Gruppe von Anweisungen in Abhängigkeit von einer Bedingung zu durchlaufen ist. Man denke dabei nur an die Durchführung eines größeren Rechenprozesses, der mehrere arithmetische Anweisungen umfaßt. Für diese Aufgabe stellt die Syntax von PL/1 eine Sonderform der DO-Anweisung, die DO-Gruppe, zur Verfügung, die mehrere Anweisungen funktionell zu einer Anweisung zusammenfaßt. Diese DO-Gruppe beginnt mit dem Schlüsselwort „DO". Der Ablauf dieser IF-Anweisung läßt sich schematisch folgendermaßen darstellen:
3.3 Anweisungen zur Programmsteuerung
91
Bevor wir auf die in der praktischen Programmierung relevante Frage der geschachtelten IF-Anweisungen eingehen, muß zunächst noch der interne Ablauf dieser Anweisung vertieft werden. Es wurde schon herausgearbeitet, daß bei ihrer Ausführung geprüft wird, ob im „elementausdruck", der in eine Bitkette konvertiert wird, eine binäre Eins vorkommt. Dieser Ablauf soll noch am Beispiel eines Ausschnitts aus einem Programm dargestellt werden: DCL (A,B) BIT (4); A = '0010'B; B = '0000'B; IF A + B T H E N G O T O EINS; ELSE G O T O ZWEI;
In diesem Beispiel würde das Programm bei der Marke „EINS" weitergehen; denn die Summe „A + B" enthält eine binäre Eins. IF-Anweisungen dürfen geschachtelt verwendet werden. Dies bedeutet, daß sowohl einheit eins als auch einheit zwei selbst wieder eine IF-Anweisung sein kann. Beispiel: IF A = B T H E N IF A = C T H E N D = E; ELSE F = G; ELSE F = A ; X = Y/2; Dieses letzte Beispiel der ineinandergeschachtelten IF-Anweisung soll noch schematisch dargestellt werden:
92
3. Der elementare Teil der problemorientierten Programmiersprache PL/1
Es wurden bisher in der IF-Anweisung nur Vergleichsausdrücke benutzt. Zusammen mit booleschen Elementausdrücken lassen sich vielfältige und tief verschachtelte IF-Anweisungen aufbauen. Beispiel: I F X > Y & Y — 1 = Z T H E N A = 1; ELSE A = 2; Schematisch dargestellt läßt sich diese einzige IF-Anweisung in zwei Bedingungen auflösen:
Verschachtelte IF-Bedingungen lassen sich häufig durch die SELECT-Anweisung eleganter programmieren als durch IF-Anweisungen. Wir wollen deshalb jetzt diese Anweisung darstellen und obige Aussage zunächst mit einem Beispiel belegen. In einem Programm soll der momentane Wert einer Variablen „A" in Stufen abgefragt werden. Dazu könnten folgende IF-Anweisungen dienen: IF A > 1000 THEN DO . . ELSE IF A > 100 THEN DO . . ELSE IF A > 10 THEN DO . . ELSE IF A > 0THEN DO . . ELSE DO . .
.END END .END .END .END
Mit Hilfe einer SELECT-Anweisung läßt sich dasselbe Problem in folgender Form eleganter lösen: SELECT; WHEN (A > 1000) WHEN (A > 100) WHEN (A > 10) WHEN (A > 0) OTHERWISE END;
DO DO DO DO DO
. . . . .
END END .END .END END
3.3 Anweisungen zur Programmsteuerung
93
Diese Form, Auswahlbedingungen zu unterscheiden, ist zweifellos übersichtlicher als mehrfach verschachtelte IF-Anweisungen. Damit kommen wir zur formalen Notation der SELECT-Anweisung: SELECT [(elementausdruck eins)]; {[bedingungpräfix] WHEN (elementausdruck [,elementausdruck]...) ausführbare anweisung}... [{OTHERWISE | OTHER} ausführbare anweisung] END [markenpräfix]; Im allgemeinsten Fall wird der „elementausdruck eins", den der Programmierer nach der metalinguistischen Konstanten „SELECT" notiert hat, ausgewertet und mit den „elementausdrücken" nach „WHEN" verglichen. Wenn dabei ein Wert gefunden wird, der dem „elementausdruck eins" entspricht, dann wird der betreffende WHEN-Zweig ausgeführt und die WHEN-Bedingungen, die anschließend notiert wurden, ignoriert. Führt keine der WHEN-Bedingungen zu einer „ausführbaren anweisung", so wird der OTHERWISE-Zweig ausgeführt, sofern der Programmierer ihn notiert hat.
Übungsaufgaben Die folgenden IF-Anweisungen sind schematisch als Programmablaufplan darzustellen: 1. I F A > B | C - i = D THEN G O T O X; ELSE GOTO Y; 2. I F A > B & B > C | A > D THEN G O T O X; ELSE G O T O Y; 3. IF A > B & (B > C | A > D) THEN GOTO X; ELSE G O T O Y; 4. IF A > B & -i(B > C) | A > D THEN GOTO X; ELSE G O T O Y; 5. IF A > B & -i(B > C) | -i(A > B) & B > C THEN G O T O X; ELSE G O T O Y; 6. IF —i(A > B & B > C | ~i(A > B) & ~i(B > C)) THEN G O T O X; ELSE G O T O Y; Welche dieser sechs Anweisungen führen zum gleichen Programmablauf? (Antwort mit Beweis) 7. In einer IF-Anweisung (IF-Bedingung „A < B") ist im THEN-Zweig die Vereinbarung „DCL A DEC" und im ELSE-Zweig die Vereinbarung „DCL B BIN" zu notieren. Geben Sie bitte die IF-Anweisung an, die den gestellten Bedingungen entspricht.
94
3. Der elementare Teil der problemorientierten Programmiersprache PL/1
8. Es sollen unter Benutzung der IF-Anweisung folgende Aufgaben programmiert werden: a) Es sind mit Hilfe des Hornerschen Schemas die Werte folgenden Polynoms zu berechnen: y = a n • xn + a n _, • x"" 1 + a n _ 2 • x n ~ 2 + ... + ao Annahmen:
1. n ^ 10 2. x = 0 bis x = b mit einer Abszissendifferenz Ax = c 3. Die Variablen a, b, c und x sollen als Festpunktzahl mit der Genauigkeit "(7,2)" vereinbart werden. 4. Die Werte a 0 bis a„, b und c werden mit Hilfe der Anweisung G E T D A T A über Lochkarten in die Datenverarbeitungsanlage eingegeben und das Ergebnis zur Kontrolle zusammen mit den eingegebenen Werten durch die Anweisung PUT D A T A gedruckt. 5. Das Programm soll mit der Anweisung „ON E N D F I L E (SYSIN)" abgeschlossen werden (s. „BEISP1" im Kapitel 1.1).
Als Testwerte sind die beiden Zahlenbeispiele zu benutzen: 1. a 0 = 10, a, = 9, a 2 = 8, a 3 = 7, a 4 = 6, a 5 = 5, a 6 = 4, a 7 = 3, a 8 = 2, a 9 = 1, a 10 = 0, b = 10, c = 1; 2. a 0 = 10, a, = 1, a 2 = - 2 0 , a 3 = 3, b = 10, c = 0,5. b) Es ist die Inhaltsformel für Dreiecke in PL/1 zu programmieren, und zwar unter der Annahme, daß zwei Seiten (a und b) und der von ihnen eingeschlossene Winkel (y) vorgegeben sind. Der Winkel kann sowohl im Bogenmaß als auch im Gradmaß eingegeben werden. Zur Kennzeichnung dienen die beiden Worte „Gradmaß" oder „Bogenmaß" bei der Eingabe. Es bedeutet also: G = 30.5, I D E N T = ' G R A D M A S S ' daß dieser Winkel im Gradmaß vorgegeben ist und 30,5° beträgt. Die Eingabe und Ausgabe soll wiederum mit G E T D A T A und PUT D A T A erfolgen. Als weitere Anweisung zur Programmsteuerung stellt die Syntax von PL/1 die DO-Anweisung zur Verfügung. Bevor die Struktur dieser Anweisung formal beschrieben wird, ist es zunächst notwendig, auf Programmschleifen, die bereits generell definiert wurden, einzugehen; denn Programmschleifen sind das primäre Anwendungsgebiet dieser Anweisung, nicht die DO-Gruppe als THEN-Klausel oder ELSE-Klausel der IF-Anweisung. Es sind zwei Grundtypen von Schleifen in der Programmiertechnik zu unterscheiden: 1. Schleifen mit konstanter Durchlaufzahl, die durch einen Schleifenzähler gesteuert werden,
95
3.3 Anweisungen zur Programmsteuerung
2. Schleifen mit variabler Durchlaufzahl, deren Durchlauf durch eine vorgegebene Endbedingung beendet wird. Hierbei unterscheidet man noch einmal sukzessive Schleifen und iterative Schleifen. D i e Struktur der Schleife mit konstanter Durchlaufzahl ist dadurch charakterisiert, daß vor Eintritt in die Schleife die Anzahl der Schleifendurchläufe bekannt ist und deshalb in einem Schleifenzähler eingestellt werden kann. Diese Schleife
heißt
„Zählschleife".
Ein
typisches
Anwendungsgebiet
solcher
Schleifen sind Summenbildungen, wie sie vor allem in der betrieblichen Datenverarbeitung häufig vorkommen. Abbildung 3—3 zeigt die
allgemeine
Struktur der Zählschleife, dargestellt am Beispiel der Akkumulierung von zehn beliebigen, in einem eindimensionalen Bereich gespeicherten Zahlen, gesteuert durch die IF-Anweisung oder die D O - A n w e i s u n g . Vor dem Eintritt in die Schleife ist zunächst das Summenfeld „ S " auf Null zu stellen. Erfolgt die Schleifensteuerung mit Hilfe der IF-Anweisung, dann muß anschließend das Programm den Schleifenzähler auf einen Anfangswert einstellen, in diesem Fall die Zahl Eins. Im Verarbeitungsteil erfolgt die Addition der indizierten Variablen A ( I ) , beim ersten Durchlauf also die Verarbeitung des Summanden A ( l ) . Danach ist der Zähler um eine Einheit zu erhöhen und anschließend abzufragen, ob die vorgegebene Zählgrenze bereits erreicht wurde. Ist dies nicht der Fall, dann wird die Schleife erneut durchlaufen.
mit 1F - Anw.
mit DO - Anw.
A b b . 3 - 3 . Struktur der Zählschleife in PL/1 (Addition von zehn Zahlen).
96
3. Der elementare Teil der problemorientierten Programmiersprache PL/1
Der Programmierer benötigt bei Verwendung der IF-Anweisung zur Schleifensteuerung drei Anweisungen, in unserem Fall: 1 . 1 = 1; 2. I = I + 1; 3. die IF-Anweisung. Die DO-Anweisung ersetzt diese drei Anweisungen zur Schleifensteuerung. Sie enthält sowohl die Grundstellung des Zählers (die erste Zahl rechts vom Gleichheitszeichen) als auch seinen Endwert (die Zahl nach dem Schlüsselwort „TO") und die Schrittweite (durch das Schlüsselwort „BY" notiert). Ist die Schrittweite Eins, wie in unserem Beispiel, dann ist es nicht notwendig, sie explizit anzugeben. Das Ende der Schleife ist durch die END-Anweisung zu markieren. Für Schleifen mit variabler Durchlaufzahl, und zwar sowohl für sukzessive Schleifen als auch für iterative Schleifen, stellt PL/1 drei Sonderformen der DO-Anweisung zur Verfügung, nämlich die DO-WHILE-Anweisung, die DO-UNTIL und die DO-REPEAT-Anweisung. In der DO-WHILE-Anweisung wird hinter dem Schlüsselwort W H I L E in einer Klammer durch einen Elementausdruck die Bedingung notiert, unter der die Schleife wiederholt werden soll. Ein einfaches, aber typisches Beispiel für solche Schleifen mit variabler Durchlaufzahl ist die Verarbeitung der Sätze einer Eingabedatei, bis die ON-ENDFILE-Anweisung anspricht (s. z.B. Programm „BEISP6"). In gleicher Weise lassen sich iterative Schleifen programmieren, bei denen die Endbedingung in Form eines Konvergenzkriteriums gestellt wird: I Xn - Xn-1 I
' 1 0 1 100'B D C L A BIT(6)VAR, B CHAR(4); A = B; '1011' '1011'B
Generell läßt sich sagen, daß bei den Kettenkonversionen aus einer Zeichenkette eine gleichlange Bitkette wird und umgekehrt. Schwierigkeiten können nur dann entstehen, wenn eine Zeichenkette, die in eine Bitkette konvertiert werden soll, auch andere Zeichen als Binärzeichen enthält. Obwohl man sich vorstellen könnte, daß diese Zeichen in ihrer Darstellung als Binärcode in die Bitkette eingehen, läßt die Syntax von PL/1 dies nicht zu und löst in solchen
110
3. Der elementare Teil der problemorientierten Programmiersprache PL/1
Fällen die „CONVERSION-Bedingung" aus. Problematischer ist die Konvertierung arithmetischer Daten in Kettendaten und umgekehrt (s. Tabelle 3—3b und 3—3c). Hierbei treten Zwischenergebnisse auf. So erfolgt die Konvertierung arithmetischer Daten in Bitketten über die Umsetzung in eine ganzzahlige Dualzahl und die Konvertierung von arithmetischen Daten in Zeichenketten über eine dezimale Konstante, auch wenn der Ausgangswert eine Dualzahl ist. Wie schon oben betont, ist fernerhin bei der Konvertierung in Kettendaten zu beachten, daß die Zuordnung entsprechend den Regeln der Kettenzuweisung von links nach rechts im Zielfeld abläuft. Es wurden in die Tabellen 3—3b und 3—3c die Umrechnungsformeln für die Berechnung der Längen von Zwischenergebnissen mit aufgenommen. Werden diese Längen nicht beachtet, dann können bei der Kettenzuweisung Stellen verloren gehen (s. 3. Beispiel der Konvertierung arithmetischer Daten nach Zeichenketten). Diese Umrechnungsformeln sind keineswegs so undurchsichtig, wie es auf den ersten Blick aussieht. So verhalten sich die Längen von ein und derselben Zahl in zwei verschiedenen Zahlensystemen umgekehrt wie die Logarithmen der Basen der beiden Zahlensysteme. Deshalb haben Dualzahlen ld 10 = 3,32mal mehr Stellen als Dezimalzahlen, womit der Umrechnungsfaktor 3,32 für die Konvertierung arithmetischer Daten in Bitketten begründet ist. Die Konvertierung in Zeichenketten, die als Zwischenergebnis eine dezimale Konstante erzeugt, muß dabei maximal drei Zeichen einfügen, nämlich ein negatives Vorzeichen (positive Werte erhalten kein Vorzeichen), den Radixpunkt und den Buchstaben „F" zur Kennzeichnung eines Skalenfaktors*. Deshalb erscheint in der Umrechnungsformel für die Konvertierung arithmetischer Daten in Zeichenketten die Konstante Drei (p + 3 bzw. p + 3 + k).
*
Dieser Faktor, der in Form einer ganzzahligen Konstanten mit positivem oder negativem Vorzeichen nach dem Buchstaben F in einer Zeichenkette notiert wird, gibt an, daß der Radixpunkt um diese Anzahl von Stellen rechts (bei positiver Konstanten) oder links (bei negativer Konstanten) von seiner angenommenen Position im Zeichenkettenwert liegt (s. auch Abschnitt 2.4, Abbildungszeichen für numerische Abbildungsspezifikation).
111
3.4 Transportanweisungen
oa h
Q o. •• Eu s •â +1
1 2 4
3.
D e r
e l e m e n t a r e
O .
i-
cfi
ci
• Si 60 1
e
i
S
I
60
60
o [fa
e CO
~ -O
u T3 C
a i .
u
e (U I-.
£ o
C
e u
re Q
Q C/3 U 73 C 1 THEN RETURN
(N * FAK
ELSE RETURN
(N -
1)) ;
(1);
END FAK; END B E I S P 1 8 ; Programmstort
Programmanti*
Abb. 3—6. Schematische Darstellung der Prozeduraufruftechnik.
Der rekursive Prozeduraufruf liegt in diesem Beispiel im THEN-Zweig der IFAnweisung. Es wurde schon angedeutet, daß der Programmierer anstelle einer Rekursion auch eine Schleife, d.h. eine Iteration, verwenden kann. Rechenberg hat darauf hingewiesen, daß sich grundsätzlich jeder rekursive Algorithmus durch einen iterativen ersetzen läßt und vice versa [10a]. Diese Aussage wollen wir am Beispiel des Programms „BEISP12" demonstrieren. Dort soll ein rekursiver Prozeduraufruf die DO WHILE-Schleife ersetzen. Das modifizierte Programm „BEISP12_RECURSIVE" zeigt die Lösung dieser Aufgabe. BEISP12_RECURSIVE DCL
:
PROCEDURE
(NAME,ORT,STR)
OPTIONS(MAIN); CHAR
(20),
PLZ
CHAR
(
REST
CHAR
(16),
EOF
BIT
( 1)
5), INIT
('0'B);
3.5 D i e Ablaufstruktur von PL/1 Programmen
ON ENDFILE CALL VERARBEIT
(SYSIN)
179
EOF =
' 1'B;
VERARBEIT; :
GET E D I T
PROCEDURE
(A I F EOF =
RECURSIVE;
(NAME,PLZ,ORT,STR,REST) ( 2 0 ) ,A
'1'B
THEN
(4) , 2
(A
(20) ) ,A
(16) ;
RETURN;
PUT E D I T
(NAME)
(X
PUT E D I T
(PLZ,ORT)
(5), (X
A) ; (5),A,X
(2),A)
SKIP; PUT E D I T
(STR)
PUT S K I P
(4);
CALL
(X
(5),
A)
SKIP;
VERARBEIT; END V E R A R B E I T ; END
BEISP12_RECURSIVE;
Dieses Beispiel ist zu klein, um die Vorteile und die Nachteile rekursiver Prozeduren deutlich zutage treten zu lassen. Bei größeren Programmen führt die Transformation einer Iteration in eine Rekursion zu einer Verkleinerung des Programms (statische Länge), aber auch zu größeren Durchlaufzeiten und vice versa [10a]. So haben wir selbst bei Zeitmessungen mit Hilfe des Softwarewerkzeugs PRT7 (s. auch [13a]) am Beispiel der beiden Programme „BEI SP12" und „BEISP12_RECURSIVE" bei 250 Eingabelochkarten eine Vergrößerung der Durchlaufzeit von ca. 30% gemessen. Diese Verschlechterung der Effektivität ist einer der Gründe, daß sich bis jetzt rekursive Prozeduren in der betrieblichen Datenverarbeitung nicht durchsetzen konnten [13b]. Abschließend sollen die Ergebnisse dieses Abschnitts in einer Abbildung zusammengefaßt werden, wobei insbesondere noch einmal die Aufeinanderfolge von Hauptprozedur und Unterprogrammen verdeutlicht werden soll (Abb. 3-6). Übungsaufgaben 1. Es ist unter dem Namen WI ein Funktionsunterprogramm mit zwei Eingängen zu schreiben, das entweder nach dem Sinussatz oder dem Cosinussatz Winkel (im Bogenmaß) in einem Dreieck berechnet. 2. Man erstelle unter dem Namen „HALB" ein Unterprogramm, das Dezimalziffern in vierstelle Dualzahlen konvertiert und dabei auf die Halbierungsmethode zurückgreift. Die Rückgabe der Dualzahl an die aufrufende Prozedur erfolgt durch den Parameter A. Dieses Unterprogramm soll zusammen mit einem Hauptprogramm, das auch zu entwerfen ist, zur Simulation einstelliger dualer Addierwerke verwendet werden. In dieses Haupt-
180
3. Der elementare Teil der problemorientierten Programmiersprache PL/1
programm sind zum Testen die fünf dezimalen Additionen fest einzubauen: 1 + 8, 2 + 6, 3 + 4, 4 + 2, 5 + 0. Die Ergebnisse sind als Dualzahl auszudrucken. 3. Das Programm „BEISP11" im Abschnitt 3.3 soll in der Weise verändert werden, daß die Matrizenmultiplikation separiert und als Unterprogramm (unter dem Namen MAMU) ausgeführt wird. Es ist das Unterprogramm zu notieren und das geänderte Hauptprogramm anzugeben.
3.5.3 Blockstruktur, Speicherplatzzuordnung und Gültigkeitsbereich von Vereinbarungen Es wurde schon als ein Vorteil der blockweisen Unterteilung eines Programmes herausgearbeitet, daß dadurch der Bedarf an Speicherplatz zurückgeht, weil der Kompilierer nur für aktive Blöcke Speicherplatz reserviert. Er wird wieder freigegeben, sobald ein Block durch die END-Anweisung beendet wird. Damit sind natürlich auch die Werte der Arbeitsobjekte, die in diesem Block vorkamen, verloren. Falls es notwendig ist, diese Werte für einen weiteren Aufruf des Blocks, der später noch einmal erfolgt, zu erhalten, müssen die Werte an die aufrufende Prozedur zurückgegeben werden (s. BEISP14_1) oder der Speicherplatz eines Blocks ist für die gesamte Programmausführung zu sperren. Wir kommen damit zu einer Unterteilung der Speicherplatzzuordnung in zwei Klassen, nämlich die dynamische und die statische Zuordnung. Das nächste Schema zeigt stichwortartig die wichtigsten Merkmale dieser beiden Zuordnungsverfahren. Zuordnung von Speicherplatz zu Arbeitsobjekten in PL/1
dynamisch: Normalfall, beim Eintritt in einen Block wird automatisch Speicherplatz zugeordnet und beim Verlassen wieder freigegeben, explizit vereinbart durch AUTOMATIC.
statisch: vereinbart durch STATIC, Speicherplatzzuordnung erfolgt beim Beginn einer Programmausführung und bleibt während der gesamten Zeit der Programmausführung erhalten.
Der Begriff statische Speicherplatzzuordnung kennzeichnet die Möglichkeit, daß der Programmierer einem Arbeitsobjekt vor der Programmausführung einen Speicherplatz fest zuordnet und daß sich daran während der gesamten Ausführungszeit des Programms nichts ändert. Dies hat zur Folge, daß Variable mit ihrem letzten Wert in einen neuen Verarbeitungsprozeß eingehen, wenn eine Prozedur mehrmals aufgerufen wird, in der mit dem Attribut STA TIC vereinbarte Variablen vorkommen.
3.5 Die Ablaufstruktur von PL/1 Programmen
181
Beispiel: U: P R O C E D U R E ; DCL X FIXED(3) STATIC INITIAL(l);
PUT DATA(X);
X=X+1; ENDU; Wenn die Prozedur U das erste Mal aufgerufen wird, dann hat das Arbeitsobjekt X auf Grund der Initialisierung durch „INITIAL(l)" den Wert Eins und mit der PUT-Anweisung wird das Element X = 1 gedruckt. Danach erhöht die Verarbeitungsanweisung X um Eins. Wenn ein Hauptprogramm die Prozedur U ein zweites Mal aufruft, dann hat X noch immer den Wert Zwei und wird wegen des Attributes „STATIC" nicht durch die aufrufende Prozedur neu mit dem Wert Eins initialisiert. Die PUT-Anweisung gibt also jetzt X = 2 aus. Wir kommen damit zu einer weiteren Klasse von Attributen, die Arbeitsobjekte beschreiben, nämlich den Speicherklassenattributen, wofür STATIC und A U T O M A T I C nur zwei Beispiele sind. Der Programmierer darf diese Attribute nicht für Eingangsnamen von Prozeduren, Dateibezeichner, Unterstrukturen oder mit „ D E F I N E D " vereinbarte Daten verwenden. Fernerhin dürfen sich die beiden Attribute STATIC und A U T O M A T I C nicht auf Parameter beziehen. Weiter ist zu beachten, daß bei der Verarbeitung von Strukturen ein Speicherklassenattribut nur für die Hauptstruktur vergeben werden kann und sich dieses Attribut dann automatisch auf alle Elemente der Struktur bezieht. Im Normalfall wird Variablen aber nicht statisch, sondern erst beim Aktivieren einer Prozedur Speicherplatz automatisch zugewiesen. Er bleibt auch nur so lange zugeordnet, wie die Prozedur aktiv ist. Damit sind beim Verlassen einer Prozedur die Werte ihrer Arbeitsobjekte im allgemeinen verloren. Ein Sonderfall liegt hierbei allerdings dann vor, wenn durch das Attribut E X T E R N A L der Gültigkeitsbereich von Bezeichnern auf alle jene Prozeduren ausgedehnt wird, die eine externe Vereinbarung des gleichen Bezeichners enthalten. Auf diese Weise ist es möglich, Werte von Arbeitsobjekten zwischen Prozeduren auszutauschen, ohne die CALL-Anweisung zu benutzen, eine Möglichkeit die zu einer engen Prozedurkopplung und damit änderungsfeindlichen und fehleranfälligen Programmen führt. Den inversen Effekt zu E X T E R N A L hat das Speicherklassenattribut CON T R O L L E D . Es handelt sich dabei um eine Sonderform der dynamischen Speicherplatzzuordnung, indem einem Arbeitsobjekt, das mit diesem Attribut ver-
182
3. Der elementare Teil der problemorientierten Programmiersprache PL/1
einbart wurde, erst durch eine spezielle Anweisung, nämlich A L L O C A T E , in einem Block Speicherplatz zugeordnet wird. Der Programmierer kann diese Zuordnung wiederum durch eine spezielle Anweisung aufheben, nämlich FREE. Beispiel: Z: P R O C E D U R E , DCL (A,B,C) C O N T R O L L E D ; A L L O C A T E A,B,C; A = B + C; PUT D A T A (A); F R E E A,B,C; E N D Z; Speicherplatz für die drei Arbeitsobjekte A, B und C wird jetzt innerhalb der Prozedur Z nur von der Anweisung A L L O C A T E bis zur Anweisung F R E E reserviert. In einem solchen Fall übernimmt der Programmierer die Speicherplatzzuordnung, eine Funktion, die sonst im Kompilierer liegt. Es gibt schließlich noch ein viertes Speicherklassenattribut, nämlich BASED, das allerdings nur für die Listenverarbeitung relevant ist und deshalb hier nur der Vollständigkeit halber erwähnt wird. Mit der Blockstruktur von Programmen inhärent verbunden ist die Frage nach dem Gültigkeitsbereich expliziter und impliziter Vereinbarungen. Das Grundprinzip von PL/1 ist, daß alle Vereinbarungen intern in einem Block gelten. Da aber Blöcke geschachtelt notiert werden dürfen, muß diese einfache Regel verfeinert werden. Zu diesem Zweck ist es sinnvoll, eine Unterteilung von Blöcken bzw. Prozeduren in externe Blöcke und interne Blöcke einzuführen. Als interne Prozedur wird eine Prozedur bezeichnet, die in einer anderen Prozedur (externe Prozedur) enthalten ist. Nach dieser Definition sind BEGINBlöcke immer interne Blöcke. In jedem PL/l-Programm muß mindestens eine externe Prozedur vorhanden sein. Interne Prozeduren können als geschachtelte Blöcke interpretiert werden. Beispiel: A: P R O C OPTIONS(MAIN); B: B E G I N ; E N D B; C: P R O C ;
3.5 Die Ablaufstruktur von PL/1 Programmen
183
D: BEGIN; E: P R O C ; E N D E; E N D D; E N D C; E N D A; Im obigen Beispiel ist die Prozedur A als Hauptprozedur eine externe Prozedur. Der BEGIN-Block B ist, wie gefordert, ganz in der Prozedur A eingebettet und definitionsgemäß intern zu A. Prozedur C ist ebenfalls intern zu A und enthält außerdem den BEGIN-Block D, der wiederum die interne Prozedur E umschließt. Dieses Beispiel enthält drei Schachtelungsstufen. Relativ zu A gehören die Blöcke B und C zur Stufe Eins. D liegt auf der zweiten Stufe relativ zu A, aber auf der ersten Stufe relativ zu C. Schließlich verkörpert die Prozedur E die dritte Stufe, wobei diese Prozedur relativ zu C auf der zweiten Stufe liegt und relativ zu D auf der ersten Stufe. Die maximale Schachtelungstiefe beträgt 49 Stufen. Sie ist gegeben durch die Anzahl der Prozeduranweisungen, der BEGIN-Blöcke und DO-Anweisungen ohne die dazugehörenden ENDAnweisungen. Fernerhin geht in diese Zahl die Anzahl der noch aktiven IFAnweisungen ein, die Anzahl der zu dieser Zeit nicht geschlossenen öffnenden Klammern, die Anzahl der Dimensionen in jedem aktiven Bereichsausdruck, die maximale Anzahl der Dimensionen jedes aktiven Bereichsausdrucks und die maximale Anzahl der Dimensionen jedes aktiven Strukturausdrucks. An dieser Stelle ist es naheliegend, die Syntax der END-Anweisung zusammenzustellen. Wenn in einer solchen Anweisung keine Marke notiert wurde, dann schließt sie die DO-Gruppe oder den Block ab, der am nächsten vor der END-Anweisung liegt und für den noch kein E N D aufgetreten ist. Wird eine Marke vergeben, dann schließt diese Anweisung, die DO-Gruppe oder den Block ab, zu dem diese Marke als Markenpräfix gehört. Alle noch nicht abgeschlossenen DO-Gruppen und alle Blöcke, die in eine solche DOGruppe oder diesen Block geschachtelt sind, werden automatisch dabei mit abgeschlossen. Es ist also zugelassen, mit einer einzelnen END-Anweisung mehrere Blöcke zu beenden. Die Syntax von PL/1 führt für verschachtelte Blöcke noch zwei weitere Begriffe ein, nämlich „im Block enthalten" und „intern zu einem Block". Es wird definiert: 1. Der gesamte Text einer Prozedur, mit Ausnahme ihrer Präfixe, heißt im Block enthalten.
184
3. Der elementare Teil der problemorientierten Programmiersprache PL/1
2. Als intern zu Block A wird derjenige Teil seines Textes bezeichnet, der a) im Block A enthalten ist, b) jedoch nicht zu einem Block gehört, der selbst wieder in A enthalten ist. 3. Der gesamte Text eines BEGIN-Blockes, außer den Marken, die vor der Anweisung BEGIN stehen, heißt im Block enthalten. 4. Die Eingangsnamen einer externen Prozedur sind in keinem Block enthalten und heißen deshalb externe Namen oder externer Prozedurmarkenpräfix. Beispiel: P:
P R O C E D U R E OPTIONS (MAIN);
E:
ENTRY; PROCEDURE;
Intern zu Block P und " enthalten in P
Intern zu Block A und 'enthalten in P
E N D A; B:
Intern zu Block B und " enthalten in P
E N D P; Das gesamte, innerhalb des Rechtecks notierte Programm ist im Block P enthalten, aber nicht insgesamt auch intern zu P. Die Blöcke A und B sind davon ausgenommen. Die beiden Marken P und E sind extern zum Block P und deshalb externe Namen. Wir kommen damit jetzt zum Gültigkeitsbereich von Vereinbarungen. Ein Name gilt als explizit vereinbart, wenn er unter einer der folgenden vier Bedingungen aufgetreten ist: 1. 2. 3. 4.
in der durch das Schlüsselwort D E C L A R E notierten Vereinbarung; in der Parameterliste einer Prozeduranweisung; als Markenpräfix einer Prozedur- oder ENTRY-Anweisung; als Markenpräfix einer Anweisung.
Nach dieser Aufstellung gelten also auch Parameter der Parameterliste einer Prozeduranweisung als explizit vereinbart, und zwar in der Weise, als ob eine Vereinbarung mit dem Schlüsselwort D E C L A R E unmittelbar nach der Proze-
185
3.5 Die Ablaufstruktur von PL/1 Programmen
duranweisung für diese Parameter notiert worden wäre. Für das Markenpräfix einer Prozedur- oder ENTRY-Anweisung gilt diese Regel in der Form, daß unterstellt wird, die DECLARE-Vereinbarung wäre unmittelbar vor der Prozedur- bzw. ENTRY-Anweisung notiert worden. Explizite Vereinbarungen gelten für den Block, zu welchem diese Vereinbarungen intern sind und für alle seine internen Blöcke mit Ausnahme der Blökke, für die eine andere Vereinbarung desselben Bezeichners erfolgte. Beispiel: B
Gültigkeitsbereich von Namen: Z:
] "
PROCEDURE; D C L ( A , B ) BIN; Y: PROCEDURE; DCL(B,C) DEC;
B'
END Y ;
] .
END Z;
Da der Name B sowohl in der Prozedur Z als auch in der Prozedur Y definiert wurde, kommt hier die oben gegebene Einschränkung zum Tragen, indem er in der Prozedur Z als BIN F L O A T mit 21 Stellen Genauigkeit definiert gilt und in der Prozedur Y als D E C F L O A T mit 6 Stellen (in obiger Skizze B ' ) . Für Variable, die nicht explizit vereinbart wurden, haben wir im Abschnitt 2.4 die implizite Form der Vereinbarung eingeführt. Ihr Gültigkeitsbereich ist in der Weise definiert, daß man sich diese Vereinbarung als eine explizite Vereinbarung vorstellt, die unmittelbar nach der ersten Prozeduranweisung der zugehörigen externen Prozedur notiert wurde. Beispiel: Gültigkeitsbereich: Z:
Z
PROCEDURE; implizite Vereinbarung C DCLBBIN; Y: PROCEDURE; DCL X DEC; X=B+C; END Y ; END Z;
B
Y
C
-i X
J
Der Bezeichner C wurde jetzt implizit vereinbart. Infolgedessen erstreckt sich sein Gültigkeitsbereich im Gegensatz zum letzten Beispiel auf die gesamte
186
3. Der elementare Teil der problemorientierten Programmiersprache PL/1
Prozedur Z. Sein Wert bleibt auch nach der Anweisung „END Y " erhalten. Die Syntax von PL/1 definiert noch eine dritte Form der Vereinbarung, die textabhängige Vereinbarung. Im Grunde genommen handelt es sich dabei um eine Sonderform der impliziten Vereinbarung, die wir bisher nicht besonders herausgestellt haben. Die wichtigsten Anwendungsfälle dieser textabhängigen Vereinbarung sind: 1. Der Bezeichner eines Übergabeargumentes in der CALL-Anweisung oder in einem Funktionsaufruf erhält die Attribute E N T R Y und E X T E R N A L zugeordnet. 2. Ein Dateibezeichner, der nicht explizit vereinbart wurde, bekommt das Attribut FILE. Als größeres Beispiel für den Gültigkeitsbereich von Bezeichnern wollen wir noch einmal das Programm „BEISP11" aus dem Abschnitt 3.3 aufgreifen. Zur Initialisierung des Bereichs „ M A T R A " haben wir dort im Hauptprogramm das Unterprogramm „ I N I T " aufgerufen, das in diesem Beispiel extern zur Hauptprozedur ist. Aus diesem Grund mußten wir auch im Unterprogramm den Bereich M A T R A neu vereinbaren, weil er dort nicht bekannt war. Wenn wir nun die Prozedur „ I N I T " zur internen Prozedur der Hauptprozedur deklarieren, indem wir ihr Markenpräfix jetzt hinter der letzten END-Anweisung dieses Programms notieren, dann ist M A T R A auch in der Prozedur INIT bekannt und braucht dort nicht mehr neu definiert zu werden. Es kann deshalb auch diese Prozedur aufgerufen werden, ohne daß ein Argument übergeben wird. Dies zeigt „BEISP19". BEISP19
:
PROCEDURE
OPTIONS(MAIN);
DCL MATRA
(2,3)
FIXED
(10)
INITIAL
MATRB
(3,2)
FIXED
(10)
INITIAL
MATRC
(2,2)
CALL
INIT,
( (2) 8 , ( 2 ) 1 12233,1 , 2 ) ,
PUT DATA PUT
FIXED
(10)
INITIAL
((4)0);
(MATRA,MATRB,MATRC);
PAGE;
DO I
=
1 TO HBOUND
(MATRA,1);
DO J =
1 TO HBOUND
(MATRB,2);
MATRC DO K =
(I,J)
=
0;
1 TO HBOUND
MATRC
(I,J)
(MATRA,2);
= MATRA + MATRC
(I,K) (I,J);
END; PUT DATA END; END;
(MATRC
(I,J));
* MATRB
(K,J)
3.5 Die Ablaufstruktur von PL/1 Programmen
INIT:
187
PROCEDURE; DCL K FIXED I N I T I A L DO I
=
DO J =
(0);
1,2; 1,2,3;
K = K + 1; MATRA
(I,J)
= K;
END; END; END
INIT;
END
BEISP19;
In größeren Programmsystemen, die aus mehreren Prozeduren bestehen, wünschen die Benutzer häufig, daß Schlüsselgrößen mit denselben Bezeichnern in allen Programmen desselben Systems auftreten. Als Beispiel nennen wir nur aus dem Bereich der betrieblichen Datenverarbeitung Variable wie ZWISCHENSUMME, ENDSUMME, RECHNUNGSNUMMER, ARTI KELNUMMER, LAGERMENGE usw. Der Gültigkeitsbereich eines Bezeichners kann in einem solchen Fall über die oben angegebenen Grenzen hinaus ausgedehnt werden, wenn der Programmierer diesem Bezeichner das Attribut EXTERNAL erteilt. Ein solcher Bezeichner ist dann in allen Prozeduren bekannt, in denen er mit dem gleichen Attribut und unter dem gleichen Namen definiert wurde. Eine Ausnahme bilden Hauptstrukturen. Wenn die Bezeichner von Hauptstrukturen in mehr als einem Block mit dem Attribut EXTERNAL vereinbart wurden, dann müssen nur die Strukturelemente gleich sein. Die Bezeichner der Unterstrukturen dürfen voneinander abweichen. So hätten wir im Programm „BEISP11" auch dem Bereich MATRA das Attribut EXTERNAL erteilen können, wodurch dieser Bereich dann auch in der Prozedur INIT unter demselben Namen bekannt wäre. Allerdings kommen wir in diesem Fall nicht um die erneute Vereinbarung dieses Bezeichners in der Prozedur INIT herum. Die Ausdehnung des Gültigkeitsbereichs eines Bezeichners durch das Attribut EXTERNAL soll noch an einem kleinen Beispiel demonstriert werden. Z:
PROCEDURE; DCL(A,B) BIN; Y: PROCEDURE; DCL C EXTERNAL DEC FLOAT(5); END Y;
X:
END Z; PROCEDURE;
188
3. Der elementare Teil der problemorientierten Programmiersprache PL/1
D C L C E X T E R N A L D E C FLOAT(5); E N D X; Mit diesem Attribut ist es also möglich, zwischen Prozeduren Daten auszutauschen, ohne dabei auf Parameterlisten zurückzugreifen. Diese Konzeption, Speicherbereiche gemeinsam vom Hauptprogramm und aufzurufenden Unterprogrammen zu benutzen und damit die Parameterübergabe einzusparen, bot schon F O R T R A N mit der COMMON-Anweisung. Die inverse Funktion zum Attribut E X T E R N A L hat das Attribut INTER NAL, das für Variable jeder Speicherklasse und für Eingangsnamen interner Prozeduren automatisch unterstellt wird. Der Gültigkeitsbereich eines Bezeichners, der mit diesem Attribut versehen wurde, ist der gleiche wie der Gültigkeitsbereich seiner Vereinbarung. Eine andere explizite Vereinbarung dieses Namens bezieht sich auf ein anderes Objekt mit einem unterschiedlichen, nicht überlappenden Gültigkeitsbereich. Eingangsnamen externer Prozeduren und Dateibezeichner haben, falls nicht explizit definiert, immer das Attribut E X T E R N A L . Nur so ist es möglich, daß sich externe Prozeduren gegenseitig aufrufen können. Da die Syntax von PL/1 zwischen externen und internen Prozeduren unterscheidet, müssen spezielle Regeln für den Prozeduraufruf aufgestellt werden. Jede Prozedur (extern oder intern) kann jederzeit eine externe Prozedur aufrufen, sofern es nicht die Hauptprozedur ist. Interne Prozeduren können jedoch nur von denjenigen externen Prozeduren aufgerufen werden, die sie unmittelbar umschließen. Andererseits können interne Prozeduren nur von denjenigen internen Prozeduren aufgerufen werden, die von der gleichen externen Prozedur umschlossen werden. Beispiel: P:
P R O C OPTIONS(MAIN); C A L L A;
A: P R O C ; CALL B; B:
PROC; END B , E N D A; C A L L C;
3.5 Die Ablaufstruktur von PL/1 Programmen
189
C: PROC; END C; CALL A; END P; Die externe Prozedur P umschließt die Prozeduren A, B und C, die also interne Prozeduren von P sind. Die Prozedur B ist zugleich interne Prozedur von A. Damit ergeben sich folgende Aufrufmöglichkeiten: Aufrufende Prozedur
Aufgerufene Prozedur Begründung
P
A C
unmittelbar intern zu P unmittelbar intern zu P
A
B C
unmittelbar intern zu A wie A von P umschlossen
C
A
wie C von P umschlossen
Aus dieser Aufstellung folgt, daß die Prozedur B nicht von P aufgerufen werden kann, weil dazwischen die interne Prozedur A steht.
Übungsaufgaben 1. Es sind aus dem Programm „ B E I S P l - S T R U K T U R I E R T " (s. Abbildung 1—5) zwei Funktionsunterprogramme mit dem Markenpräfix Kl und K2 abzuleiten. Das zweite Funktionsunterprogramm ist als rekursive Prozedur zu schreiben. Beide Unterprogramme sollen ihr Ergebnis an das aufrufende Programm in Form von DEC FIXED (10) zurückgeben. Das aufrufende Programm ist mit anzugeben. 2. Es ist das Programm „BEISP15" in ein Programm umzuschreiben, das die Iteration „HAUPTSL" durch eine Rekursion ersetzt. 3. Schreiben Sie bitte ein Programm P R O C E D U R E OPTIONS(MAIN), das für eine Matrix die Transponierte erzeugt. Die Ausdehnung der Matrix (m,n), m $ 999, n =£ 999 wird mit einer Lochkarte in die Datenverarbeitungsanlage mit der Anweisung GET LIST eingegeben und ebenso die Elemente der Ausgangsmatrix. Sie ist wie auch das Ergebnis mit PUT EDIT zu drucken, wobei in beiden Fällen dasselbe R-Formatelement benutzt werden soll. Im Druckbild sollen auf einer Druckzeile bis zu neun Elemente
190
3. Der elementare Teil der problemorientierten Programmiersprache PL/1
einer Zeile der Matrizen ausgegeben werden. Die Elemente der Matrizen sind mit D E C FIXED(5) zu vereinbaren. 4. Korrigieren Sie bitte die Fehler im folgenden Programm (mit Begründung): AUFGABE
PROC OPTIONS (MAIN); DCL TEXT CHAR (9); CALL DRUCKROUTINE (TEXT); CALL VERARBEITUNG;
DRUCKROUTINE
PROC (KETT); DCL LISTE FILE RECORD OUTPUT ENV (F(10) CTLASA), KETT CHAR (9); DCL 1 UEBERSCHRIFT, 2 VORSCHUBSTEUERUNG CHAR (1) INIT
Cl"),
2 KETTE CHAR (9) ; KETTE = KETT; EINGANG
ENTRY; WRITE FILE (LISTE) FROM (UEBERSCHRIFT); RETURN ; END DRUCKROUTINE;
VERARBEITUNG
PROC; DO I = 1 TO 10; PUT SKIP LIST CALL EINGANG; END; END VERARBEITUNG; END AUFGABE;
('VERARBEITUNG');
4. Nichtelementare Dateiorganisation und Datei Verarbeitung
4.1 Magnetbanddateien Der im Abschnitt 3.4.2.5 dargestellte satzweise Datenverkehr ist dadurch charakterisiert, daß Daten zwischen peripheren Einheiten und der Zentraleinheit in ihrer maschineninternen Darstellungsform ausgetauscht werden. Als Dateien im Sinne von PL/1 hatten wir auf der Eingabeseite einer Datenverarbeitungsanlage bisher ausschließlich in Stapeln zusammengefaßte und nach einem Ordnungskriterium seriell sortierte Lochkartenbestände unterstellt und auf der Ausgabeseite vor allem Listen, falls erforderlich, aber auch wieder Lochkarten. Dieser externe Datenträger war aber nicht nur das konstituierende Element des Datenflusses, sondern übte auch die Funktion eines permanenten Datenspeichers für Stammdaten aus. So stehen in einer lochkartenorientierten informationellen Ablauforganisation sämtliche Bestandsdaten wie Materialkonten, Kunden- und Lieferantendaten sowie Fertigungspläne auf Lochkarten. Obwohl als Vorteil dieser konventionellen Dateiform das leichte „Updaten" der Datei, das sich in Form eines Austausches der Datenträger vollzieht, zu vermerken ist, sind ihre Nachteile doch evident: 1. Da die Aufzeichnungsdichte auf Lochkarten nur gering ist, lassen sich keine großen Speicherkapazitäten erzielen. 2. Der Zugriff zu den in einer Lochkartendatei gespeicherten Daten erfolgt rein sequentiell. Da Lochkartenmaschinen relativ langsam arbeiten, sind die Zugriffszeiten groß. 3. Lochkartenspeicher sind reine Lesespeicher. Daten können nur gelesen, nicht geschrieben werden. Es läßt sich deshalb mit dem Leseprozeß nicht das Updaten überholter Daten verbinden, welches eine Grundforderung moderner Dateiverarbeitung ist. Diese Nachteile vermeiden Magnetband- und Magnetplattenspeicher, die heute weitgehend die Lochkarte als „peripheren Speicher" abgelöst haben. Es ist nicht die Aufgabe dieser Darstellung, Formen der Datenorganisation geschlossen darzustellen. Wir verweisen zu diesem Zweck auf die entsprechende Fachliteratur [10, 14], Wir können hier nur die Grundstrukturen aufzeigen, deren Kenntnis notwendig ist, um die Dateibeschreibung und Dateiverarbeitung in PL/1 zu verstehen. Den Ablauf einer Magnetbandverarbeitung zeigt Abbildung 4—1 in schematischer Form. Eine Stammdatei (in Abbildung 4 - 1 „Bestand alt") ist auf den neuesten Stand zu bringen. Die Bewegungsdaten, die die Änderungen darstel-
192
4. N i c h t e l e m e n t a r e D a t e i o r g a n i s a t i o n und D a t e i v e r a r b e i t u n g
2) BEWEGUNGSKARTEN. EBENFALLS AUFSTEIGEND SORTIERT
d
KONTO- BELEG- DATUM NR. NR.
AUSGABE
SOLL
320023.15
1140C.4C
KONTO-NR. 6 SPROSSEN
DAT UM SPROSSEN
9
[NXVJ SALDO SPROSSEN
Ìo^Ì
J101 ! 1030 2002 2
S25.34-« 12 5 0 0 . 0 0 « 0 357.12
31 01 2 2024 27 02 2
312554.01« 3 5 00.57-
2075.23
125001 0)25 0102 2 I I S M Ì O 125005
ALTER SALDO NEUER SALJ)^
1217.2«
1 0 » « 02 2
1] BESTANDSBAND (ALTE S A L D E N ) . AUFSTEIGEND SORTIERT N KONTO-NR.:
HABEN
31 012 0712 05.02 2
125003
/
BEWEGUNGSLISTE:
KTO.- BELDATUM NR. NR. 125001
/
BETRAG
• 357:12
0.00«
Abb. 4—1. Grundstruktur der Magnetbandverarbeitung.
len, können entweder, wie in diesem Bild angedeutet, in Form von Lochkarten vorliegen oder auch auf einem zweiten Eingabeband stehen. Magnetbanddateien sind sequentiell geordnete Datenmengen. Die Datensätze werden nach aufsteigenden oder absteigenden Ordnungsmerkmalen gespeichert, wobei das Speichermedium über keine fest aufgezeichneten Speicheradressen verfügt. Das Aufsuchen eines Datensatzes erfolgt in der Weise, daß ein Suchbegriff (Ordnungsmerkmal des Bewegungssatzes) mit gespeicherten Ordnungsmerkmalen so lange verglichen wird, bis Gleichheit besteht. Zu einem bestimmten Datensatz wird also zugegriffen, indem alle Ordnungsmerkmale starr fortlaufend bis zum gesuchten Datensatz angesprochen werden. Wegen der sequentiellen Organisation der Dateien muß dabei natürlich die Sortierfolge in der Stammdatei und der Bewegungsdatei die gleiche sein und auf demselben Ordnungsmerkmal beruhen. Wenn wir vom Sortieren einer Datei nach einem neuen Ordnungsmerkmal und dem Aufspalten einer Datei in zwei oder mehrere Dateien einmal absehen, dann besteht die Hauptfunktion der Magnetbandverarbeitung darin, die gespeicherten Stammdaten auf den neuesten Stand zu bringen (Updaten). Sie läßt sich in weitere Teilfunktionen aufspalten: 1. Verändern eines bestehenden Datensatzes (in unserem Beispiel Errechnen des neuen Saldos) und 2. Schreiben der veränderten Daten auf ein Ausgabeband; 3. Aufnehmen eines neuen Stammsatzes in die Datei, d.h. Einfügen in die vorgegebene Ordnung auf dem Ausgabeband; 4. Löschen eines Stammsatzes, was bedeutet, daß dieser Satz nicht auf das Ausgabeband übernommen wird. Mit diesen vier Funktionen ist inhärent das Aufsuchen eines Stammsatzes auf-
193
4.1 Magnetbanddateien
grund des vorgegebenen Ordnungsmerkmals des Bewegungssatzes verbunden, und das Lesen dieses Satzes, sobald er in der Datei gefunden wurde. Häufig gehört zu dieser Grundstruktur der Magnetbandverarbeitung auch noch, daß eine Bewegungsliste zu drucken ist. Der Datenfluß dieser Form der Magnetbandverarbeitung wurde in Abbildung 4 - 2 schematisch dargestellt, wobei Beispiele für Ordnungsmerkmale mit aufgenommen wurden. BESTAND ALI
001
002
00A
009
*
009
(Zugang (Veränderung
\Veronderung Veränderung
\
Emgobebond
fAbgang tfS^3
OK
003 002
002 OOI
BEST AMD NEU
(
l
I
j
001
1 l
002
\
I
2
\ 004
003
g
010
j
i
1 Ausgabeband
Abb. 4 - 2 . Datenfluß Magnetbandverarbeitung.
Ein wesentlicher Faktor dieser Organisationsform ist die Tatsache, daß die Datenverarbeitungsanlage Veränderungen nicht unmittelbar auf dem Eingabeband vornehmen kann. Es sprechen dagegen: 1. Um die Eingabesätze zu modifizieren, wäre es notwendig, das Eingabeband um einen Block zurückzusetzen und die veränderten Daten anstelle der alten Daten zu schreiben. Diese Forderung wäre nur dann technisch realisierbar, wenn das Magnetbandgerät beim Rücksetzen genau dieselben Sprossen auf dem Magnetband treffen würde wie beim vorangegangenen Leseprozeß. Aus Toleranzgründen zusammen mit der hohen Aufzeichnungsdichte auf dem Magnetband wäre diese Bedingung nur schwer zu erfüllen. 2. Es ist bei dieser Aufgabe häufig notwendig, neue Bestände in die vorgegebene Ordnung einzureihen. Es müßte deshalb möglich sein, von dieser Stelle ab alle Bestandsätze auf dem Magnetband nach rechts zu verschieben. 3. Beim inversen Vorgang, dem Löschen eines Bestandssatzes, wäre es unwirtschaftlich, den Speicherraum, den dieser Satz auf dem Magnetband ein-
194
4. Nichtelementare Dateiorganisation und Dateiverarbeitung
genommen hat, freizuhalten. Hier wäre eine Komprimierung nach links notwendig. Funktionell betrachtet sind aus der Sicht der Stammdatei in dieser Aufgabe drei oder vier Teilaufgaben zu erkennen: • Für einen Stammsatz liegen in der Bewegungsdatei ein oder mehrere gleichartige Datensätze vor, die zum Updaten des Stammsatzes herangezogen werden. In der Praxis hat sich für diese Teilaufgabe die Bezeichnung „bewegte Stammsätze" durchgesetzt. • Für einen Stammsatz gibt es in der Bewegungsdatei keinen analogen Bewegungssatz. Beispielsweise werden in einer Bank nicht täglich alle Konten bewegt. In diesem Fall wird der Stammsatz unverändert von der Datei „Bestand alt" in die Datei „Bestand neu" übernommen, Teilfunktion: „nichtbewegter Stammsatz". • Für einen Bewegungssatz existiert kein analoger Datensatz in der Stammdatei. In diesem Fall soll offensichtlich ein neuer Stammsatz mit Hilfe der Daten des Bewegungssatzes angelegt werden, Teilfunktion „Bewegungen ohne Stammsatz". • Schließlich sind Stammsätze, die längere Zeit nicht bewegt wurden, zu löschen. Wenn die Ordnungsmerkmale in aufsteigender Sortierfolge vorliegen, dann kann das Programm aus einem Vergleich des Ordnungsmerkmals eines Bewegungssatzes (B) mit dem Ordnungsmerkmal eines Stammsatzes (S) auf die auszuführende Teilfunktion schließen, indem folgende Vergleiche durchgeführt werden: B = S : bewegter Stammsatz (z.B. „001" in Abb. 4 - 2 ) B > S : nichtbewegter Stammsatz (z.B. „009" im Vergleich mit „004" in Abb. 4 - 2 ) . B < S : Bewegung ohne Stammsatz (z.B. „003" im Vergleich mit „004" in Abb. 4 - 2 ) . Im nachfolgenden Programm „BEISP20" beruht die Programmsteuerung auf diesen Vergleichen. Jede Form der Dateiverarbeitung besteht, wie schon ausgeführt, programmtechnisch aus vier Phasen: 1. der Vereinbarung von Dateien, die in diesem Programm benutzt werden sollen; 2. dem Eröffnen dieser Dateien, wobei Komponenten der Dateivereinbarung mit übernommen werden können; 3. der eigentlichen Dateiverarbeitung; 4. dem Schließen der Dateien.
195
4.1 Magnetbanddateien
Für die Vereinbarung von Magnetbanddateien sind folgende Sprachelemente des satzweisen Datenverkehrs (s. Abschnitt 3.4.2.5) relevant: [DECLARE]
DCL
R
LR
dateibezeichner [FILE] [ R E C O R D ]
[SEQUENTIAL]
UNBUFFERED [BUFFERED]
ENVIRONMENT ENV
IIINPUT] 1 QUTPUT
[BACKWARDS]
(zusatzlistem)
Diese Vereinbarung definiert die typischen Eigenschaften einer Magnetbanddatei, nämlich: — satzweise Verarbeitung — eine Magnetbanddatei kann sowohl Eingabedatei als auch Ausgabedatei sein. — Die Magnetbanddatei wird sequentiell verarbeitet. — Die Verarbeitung kann gepuffert oder ungepuffert ablaufen. — Eine Magnetbanddatei kann auch rückwärts gelesen werden. Alle Attribute dieser Dateivereinbarung dürfen, bis auf „ E N V I R O N M E N T (zusatzlistem)", auch vom Programmierer in der OPEN-Anweisung notiert werden. Dieses Attribut, das die Zusatzliste „m" eröffnet, ist kein Bestandteil der Programmiersprache, sondern verbindet die abstrakte PL/l-Maschine mit den technischen Realitäten der Eingabe- und Ausgabegeräte. Die für Magnetbanddateien relevanten Teile der Zusatzliste lauten angedeutet durch den Buchstaben „m": zusatzlistem : : = [satzformat] [RECSIZE (satzlänge)] [BLKSIZE (blockgröße)] [BUFFERS(n)] CONSECUTIVE [LEA VE] 1 r [ R E R E A D ] [ [COBOL] [NCP (ganzzahlige dezimalkonstante)] Das Metasymbol „satzformat" beschreibt die Datenorganisation der Sätze in der Datei. Man unterscheidet vier Satzformen [12, S. 215]: 1. 2. 3. 4.
feste Sätzlänge (ungeblockt) : Fl FS* ID feste Satzlänge (geblockt) : FBIFBS* I DB variable Satzlänge (ungeblockt) : VlVS variable Satzlänge (geblockt) : VBIVBS
Diese Satzformen zeigt Abbildung 4—3 in schematischer Darstellung. Die einfachste Form einer Datenorganisation auf Magnetband ist die feste Satzlänge, ungeblockt. In diesem Fall entspricht der physische Satz in Gestalt eines * Der Buchstabe „S" steht für „Standard".
196
4. Nichtelementare Dateiorganisation und Dateiverarbeitung
Blocks dem logischen Satz. Die Ausnutzung der Speicherkapazität ist wegen der Blockabstände, die für die Aufzeichnung von Nutzdaten verloren gehen, relativ schlecht. Durch das Blocken mehrerer Datensätze wird diese Ausnutzung verbessert, die Organisation der Verarbeitung aber auch komplexer; denn die Datensätze, die nach ein und demselben Programm zu verarbeiten sind, stehen nach dem Einlesen eines Blocks von Magnetbandspeicher an verschiedenen Stellen des Hauptspeichers. Damit der Programmierer das „Entblocken" nicht selbst programmieren muß, wird im Satzformat die Blockgröße und die Satzlänge angegeben. In solchen Fällen muß die Blocklänge ein ganzzahliges Vielfaches der Satzlänge sein. Das Entblocken wird dann automatisch ausgeführt. Durch die Blockung wird auch die Übertragungsgeschwindigkeit von der peripheren Einheit zum Zentralspeicher erhöht, indem die Anzahl der Start-Stop-Zyklen reduziert wird. Stammsätze müssen nicht immer dieselbe Länge aufweisen. In diesem Fall ergibt sich eine variable Länge der logischen Sätze, wobei wiederum eine Blockung möglich ist. Werden Sätze dieser Art in einem Block zusammengefaßt, dann muß jeder Satz, um ihn von den nachfolgenden unterscheiden zu können, eine Angabe über seine Länge enthalten. Fernerhin muß am Beginn eines Blocks die gesamte Blocklänge aufgezeichnet werden, damit das Betriebssystem entsprechenden Speicherplatz im Hauptspeicher für den Lesevorgang reservieren kann. Vom Programmierer her muß in diesem Fall die maximale Blocklänge und die maximale Satzlänge, die in einer Datei vorkommen können, in der Zusatzliste notiert werden. Dabei treten als Sonderfall noch die „blockumspannenden" Sätze auf, deren Satzlänge die maximale Blocklänge überschreiten kann. Die Steuerungsinformationen am Beginn jedes Blocks (in Abbildung 4—3 „BL" und „SL") werden beim Schreiben von Magnetbändern automatisch durch das Betriebssystem aufgezeichnet. 1. feste Sotzlänqe.unqeblockt: Satz 1
?
Satz 2
Satz 3
H
Satz 4
| | Satz 5
2. feste Sotzlonqe.geblockt: Satz 1
Satz 2
Satz 3
Y6..
Satz 4
Satz 5
Satz 6
t
Satz 4
3. variable Sotzlänqe. unqeblockt Satz 1 BL SLI j« 4 Bytes
1
BL SU
Satz 2
Satz 3 BL SLI
i.variable Satzlänqe.qeblockt: Satz 1 BL SL|
SL|
Satz 2
B L ^ Blocklängenangabe
Satz 3 SL|
1
S l = Satzlängenangabe
Abb. 4 - 3 . Datenorganisation auf Magnetbandspeichern.
Satz i
1]
4.1 Magnetbanddateien
197
Die Satzlänge wird im ENVIRONMENT-Attribut durch den Zusatz „RECSI Z E " zusammen mit einer Längenangabe (in Bytes) und die maximale Blocklänge durch den Zusatz „BLKSIZE" definiert. Eine ältere Schreibweise, die hinter dem Metasymbol „satzformat" in runden Klammern ohne den Zusatz „RECSIZE" und „BLKSIZE" die Längenangaben vorsah, wird vom Optimizing Compiler auch noch akzeptiert. Damit ist die Schreibweise ,,F(100,50)" identisch mit „F BLKSIZE(IOO) RECSIZE(50)". Die Satzformate F,FB,FS und FBS entsprechen den beiden Organisationsformen der Abbildung 4 - 3 . Satzlänge und Blockgröße sind in Bytes anzugeben. Bei Sätzen variabler Länge, die durch „V" gekennzeichnet werden, enthält jeder Block und jeder Satz eine Längenangabe, bestehend aus vier Bytes. VS und VBS spezifizieren blockumspannende Sätze*, wobei VS angibt, daß jeder Block nur einen Satz bzw. einen Teil eines logischen Satzes enthält. Wenn der Programmierer VBS notiert, dann enthält jeder Block so viele Sätze, wie er aufnehmen kann. Die maximale Satzlänge hat keine Auswirkung auf die Blokkung. Sätze Undefinierter Länge werden durch die Formatangabe „U" definiert. Hier erfolgt keinerlei Veränderung eines Blocks, so daß die Verarbeitung der einzelnen Sätze vom Programmierer her gesteuert werden muß. Für den Lese- und Schreibprozeß benötigt natürlich das Betriebssystem eine Angabe, über die maximale Blockgröße. Die Satzformate D und DB vereinbaren Datensätze, die im ASCII-Code gespeichert werden. Der Programmierer kann auch Vereinbarungen von Satzformaten zusammen mit der Block- und Satzlängenangabe in den Steuerkarten des Betriebssystems vornehmen. Das hat den Vorteil, daß Programme änderungsfreundlicher werden. Nächstes Sprachelement der Zusatzliste, notiert nach E N V I R O N M E N T , ist die Angabe der Anzahl der Pufferspeicher, ausgedrückt durch das Schlüsselwort „BUFFERS(n)". Diese Angabe ist nur dann notwendig, wenn mehr als zwei Pufferspeicher, die standardgemäß vorgesehen sind, von einem Programm verwendet werden sollen. Die Anzahl der Pufferspeicher wird durch „n" vereinbart, wobei die maximale Anzahl nicht größer als 255 sein darf. Das Sprachelement CONSECUTIVE, das schon im Abschnitt 3.4.2.3 erwähnt wurde, beschreibt den physischen Aufbau einer Datei, der bei Magnetbändern wie bei Lochkarten rein sequentiell ist. Die Verarbeitung der Datensätze erfolgt ebenfalls sequentiell, wobei allerdings ein Magnetband auch in umgekehrter Richtung abgespielt werden kann. In diesem Fall muß das Dateibeschreibungsattribut „ B A C K W A R D S " in der Dateivereinbarung notiert werden (s. formale Dateivereinbarung). Mit den Zusätzen L E A VE und R E R E A D teilt der Programmierer dem Betriebssystem mit, daß es abweichend vom Normalfall am Ende einer Datei spezielle Maßnahmen einleiten soll. So spezifiziert L E A VE, daß der Daten-
* Sätze, die über Blockgrenzen hinweg geschrieben werden (s. auch Abschn. 4.2.2).
4. Nichtelementare Dateiorganisation und Dateiverarbeitung
198
träger nicht auf den Beginn der Datei zurückgesetzt werden soll. Diese Maßnahme ist vor allem dann erforderlich, wenn auf einer Rolle Magnetband mehrere Dateien untergebracht sind, die nacheinander verarbeitet werden. R E R E A D gibt an, daß das Rückspulen des Bandes durch spezielle Anweisungen im Betriebssystem zu steuern ist. Da es möglich ist, in einem PL/l-Programm auch Teile aufzunehmen, die in C O B O L programmiert wurden, muß dieser Tatbestand ebenfalls über die Dateivereinbarung dem Übersetzer mitgeteilt werden. Das letzte Sprachelement „NCP (ganzzahlige dezimalkonstante)" ist eine Ergänzung zum EVENT-Zusatz. Die wichtigsten Sprachelemente, um Magnetbanddateien zu vereinbaren, haben wir in der Tabelle 4—1 noch einmal zusammengestellt und dabei auch die für Magnetbanddateien zugelassenen Teile der Eingabe- und Ausgabeanweisungen mit aufgenommen. Das Attribut B A C K W A R D S , das angibt, daß auf eine Datei in umgekehrter Reihenfolge zugegriffen werden soll, d.h. vom letzten Satz beginnend bis zum ersten Satz der Sortierfolge, kann nur für Eingabedateien vergeben werden, da es nicht sinnvoll ist, Ausgabedateien rückwärts zu beschriften. Das Pendant zur READ-Anweisung mit dem Zusatz SET, die einen Datensatz nur in den Pufferspeicher einliest, die Übertragung in den Eingabebereich des Hauptspeichers aber unterbindet, ist für den Ausgabeverkehr die L O C A TE-Anweisung. Sie deklariert zunächst den Ausgabepuffer zu einer Basisvariablen, der durch SET(zeigervariable) eine basisbezogene Variable zugeordnet wird. Anschließend erfolgt, ausgelöst durch nachfolgend notierte Anweisungen, eine Übertragung von Daten in den Ausgabepuffer, wobei die Zeigervariable die Strukturierung im Ausgabepuffer steuert. Die LOCATE-Anweisung stellt also nur einen Ausgabesatz im Ausgabepuffer bereit und erst die nächste WRITE-, L O C A T E - oder CLOSE-Anweisung leitet den physischen Schreibprozeß ein. Die Magnetbandverarbeitung soll noch an einem Programmierbeispiel weiter verfolgt werden. Die Bewegungsdaten stehen dabei auf Lochkarten, die Stammdaten auf Magnetbändern. Die Lochkartensätze sind wie folgt aufgebaut: Lochkartenspalte
Inhalt
1- 6 7-10 11-16 17-23 24-79 80
Kontonummer Belegnummer Datum (in der Form: 730530) Betrag (zwei Dezimalstellen) leer Kartenart (hier 1)
Die Stammdaten, die auf Magnetband stehen, werden in folgender Struktur angeliefert:
199
4.1 Magnetbanddateien
M. o
u 3 u •O t/5 3 CO
c
"
u E S ü « u
r—,
5
u
ao c
'S -s .>05 S
0) n :CS
fe O£ Z
3 CA 35 3 'S N ? —
W
w
3 •ö — 3 .2 .2 c es > U
x> es 'C CS >
crt 'S
CA
I T E 'S S iä SP CS u '5 S W i)
60
'5
oo5 f- ? Z O
H Z Pd >
£ >
W
c
u_ C £> w £ CS —1 u E w H s s
U
c
JS
W •C cj J E Q
u 'S N
U JO
tu oi
CD
"O o
00 fi
i> u T3 Q£ cu o C c/5 u
>
cs Z . c a-p W o-O
in
pq fc s « Q oo — > — Z tt. ® — n * w n — « TT Sifc > D
O
oo Q 05
< £ U < 03
Q tu H 05 P U pH üUh H D CD O
EL
ö J2 C X) w ¿5 CS -J u rrl
2
ao
5 06
Q W
06
tU PH PL,
D m
z D
200
4. Nichtelementare Dateiorganisation und Dateiverarbeitung
Anzahl der Stellen auf Magnetband
Inhalt
1 6 6
Satzart (hier 1) Kontonummer Datum (wie bei Lochkarteneingabe mit dem Datum der letzten Buchung) Saldo (neun Stellen, davon zwei Dezimalstellen)
9
Auf Magnetband ist der neue Stammsatz auszugeben. Fernerhin soll eine Liste gedruckt werden mit folgendem Aufbau je Gruppe, d.h. je Kontonummer: Kontonummer Belegnummer Datum Soll Haben alter bzw. neuer Saldo Die Anordnung dieser Daten auf dem Formular ist weitgehend frei. Die zu vergebenden Dateinamen sind: Lochkarteneingabe: Magnetbandeingabe: Magnetbandausgabe: Druckerausgabe:
LEINGAB MEINGAB MAUSGAB LISTE
Als Bezeichner für die Datensätze im Hauptspeicher sollen folgende Namen vergeben werden: Lochkarteneingabe: Magnetbandeingabe: Druckzeilen:
BEWEGUNGSSATZ STAMMSATZ ZEILE
Die Informatik lehrt, daß in der Programmierung nicht sofort mit der Umsetzung einer Aufgabenstellung in eine Programmiersprache begonnen werden soll, sondern daß ein Programmierprojekt Phasen durchläuft. Man kann diesen „Software Life Cycle" in fünf Abschnitte unterteilen: — Auftrags- und Definitionsphase — Entwurfsphase — Codierphase — Testphase — Wartungsphase. In der Entwurfsphase löst der „Software-Designer" eine Aufgabenstellung von oben nach unten (top-down) so lange in Teilaufgaben und Unteraufgaben von Teilaufgaben auf, bis Funktionen vorliegen, die leicht in eine Program-
201
4.1 M a g n e t b a n d d a t e i e n
miersprache umzusetzen sind. Dies bedeutet, daß der Programmentwurf unabhängig von einer Programmiersprache erfolgt. Aus diesem Entwurfsstil resultiert eine baumartige Aufgabenstruktur, in der Fachliteratur auch „schrittweise Verfeinerung" genannt [15]. Wenn wir diese Systematik auf unser Programmierbeispiel anwenden, dann ergibt sich das in Abbildung 4—4 dargestellte Baumdiagramm.
B =S
B>S s -•EOF Stamm.
5'S s ^OF Bew,
Abb. 4—4. Magnetbanddateiverarbeitung als Jackson-Baumdiagramm.
Die Magnetbanddateiverarbeitung läßt sich auf drei Teilaufgaben abbilden, nämlich: 1. die Arbeiten, die am Beginn des Programmlaufs durchzuführen sind, wie das Eröffnen der Dateien, das Drucken der Überschrift in der Ausgabeliste, sowie das Lesen des ersten Bewegungs- und Stammsatzes 2. die eigentliche Dateiverarbeitung, die sich aus den drei Teilaufgaben „bewegte Stammsätze", „nichtbewegte Stammsätze" und „Bewegungen ohne Stammsätze" zusammensetzt 3. die Endarbeiten, nachdem in der Bewegungsdatei oder der Stammdatei das Dateiende erreicht wurde. Hierbei sind zwei Fälle zu unterscheiden. Tritt die Dateiendemeldung zuerst in der Bewegungsdatei auf, dann ist der Rest der Stammdatei als „nichtbewegte Stammsätze" zu verarbeiten. Kommt allerdings die Dateiendemeldung aus der Stammdatei, dann ist der Rest der Bewegungsdatei als „Bewegungen ohne Stammsätze" zu bearbeiten. In dieser Weise wurde das zu lösende Gesamtproblem in überschaubare Teilprobleme aufgelöst, die leicht zu programmieren sind (BEISP20).
4. Nichtelementare Dateiorganisation und Dateiverarbeitung
202 BEISP20
:
PROC OPTIONS
(MAIN);
/******************
VEREINBARUNGSSYSTEM
***************/
/*
DATEIVEREINBARUNGEN
*/
DCL LEINGAB F I L E /*
RECORD
INPUT,
LOCHKARTENEINGABE
MEINGAB F I L E
RECORD INPUT ENV
(FB RECSIZE MAUSGAB F I L E
(23)
/*********** /*
(230)),
(23)
BLKSIZE
(230)),
F I L E OUTPUT ENV
/*
BLKSIZE
RECORD OUTPUT ENV
(FB RECSIZE LISTE
*/
(F(88)
DRUCKLISTE
CTLASA)
*/;
SATZVEREINBARUNGEN
***********/
VEREINBARUNG BEWEGUNGSSATZ
*/
DCL 1 BEWEGUNGSSATZ, 2 KONTONUMMER_BEWEGUNG
CHAR(6),
2 BELEGNUMMER_BEWEGUNG
CHAR(4),
2 DATUM_BEWEGUNG
CHAR(6),
2 BETRAG_BEWEGUNG
PIC
2 TEXT
CHAR(56),
2 KARTENART
CHAR( 1 ) ;
/*
VEREINBARUNG STAMMSATZ
1
S9999V99',
*/
DCL 1 STAMMSATZ, 2 SATZART
CHAR(1),
2 KONTONUMMER
CHAR(6),
2 DATUM
CHAR(6),
2 SALDO
PIC'S9999999V99' ;
/*
VEREINBARUNG
PUFFERSPEICHER
2.
*/
STAMMSATZ
DCL 1 PUFFER_STAMMSATZ L I K E /* DCL 1
STAMMSATZ;
VEREINBARUNG U E B E R S C H R I F T Z E I L E
*/
UEBERSCHRIFT, 2 VORSCHUBSTEUERUNG
CHAR(1) I N I T ( ' 1 ') ,
2 KONTONUMMER
CHAR(15) INIT
2 ALTER_SALDO
('KONTO-NR.'), CHAR(15)
INIT
('ALTER
SALDO'),
203
4.1 Magnetbanddateien 2 BELEG_NUMMER
CHAR(15) INIT
2 DATUM
('BELEG-NR.'), CHAR(10)
INIT 2 SOLL
('DATUM'), CHAR(10)
INIT 2 HABEN
('SOLL'), CHAR(10)
INIT 2 NEUER_SALDO
('HABEN'), CHAR(12)
INIT / * VEREINBARUNG DRUCKLISTE
('NEUER
SALDO');
*/
DCL 1 Z E I L E , 2 VORSCHUBSTEUERUNG
CHAR(1),
2 LEERZEICHEN^
CHAR(3),
2 KONTONUMMER
CHAR(6),
2 LEERZEICHEN_2
CHAR(5),
2 ANZEIGE_SOLL_HABEN
CHAR(1),
2 ALTER_SALDO
PIC'(6)Z9V.99'
2 LEERZEICHEN_3
CHAR(9),
2 BELEG_NUMMER
CHAR(4),
2 LEERZEICHEN_4
CHAR(6),
2 DATUM
CHAR(6),
2 LEERZEICHEN_5
CHAR(3),
2 SOLL
PIC'ZZZ9V.99',
2 LEERZEICHEN_6
CHAR(3),
2 HABEN
PIC
1
ZZZ9.V99',
2 LEERZEICHEN_7
CHAR(2),
2 ANZEIGE_SOLL_HABEN_NEU
CHAR(1),
2 NEUER_SALDO
PIC'(6)Z9V.99'
2 REST
CHAR(4);
/ * * * * * VEREINBARUNGEN ZUR PROGRAMMSTEUERUNG / * BLANKS NACH ZEILE DCL Z E I L E _ 1 CHAR ( 8 8 ) DCL
*****/
*/
DEFINED
ZEILE;
(ENDFILE_BEDINGUNG_STAMMDATEN_EINGABE, ENDFILE_BEDINGUNG_BEWEGUNGSDATEN_EINGABE) B I T (1 ) I N I T
/*****************
CO'B);
ENDE VEREINBARUNGSSYSTEM
ON ENDFILE
(LEINGAB)
***********/
204
4. Nichtelementare Dateiorganisation und Dateiverarbeitung ENDFILE_BEDINGUNG_BEWEGUNGSDATEN_EINGABE = ON ENDFILE
1
1'B;
(MEINGAB)
ENDFILE_BEDINGUNG_STAMMDATEN_EINGABE = /********************** OPEN
ANFANGSTEIL
FILE
(LEINGAB),
FILE
(MEINGAB),
FILE
(MAUSGAB),
FILE
(LISTE) ;
/ * DRUCKEN
' 1'B;
*******************/
UEBERSCHRIFTZEILE, 1 LEERZEILE
WRITE F I L E
(LISTE)
ZEILE_1
=
*/ FROM
(UEBERSCHRIFT);
'0';
WRITE F I L E
(LISTE)
READ
FILE
(LEINGAB)
INTO
(BEWEGUNGSSATZ);
READ
FILE
(MEINGAB)
INTO
(STAMMSATZ);
/*****************
FROM
ENDE ANFANGSTEIL
/********************** DO WHILE
HÄUPTTEIL
(ZEILE);
*******************/
*********************/
(ENDFILE_BEDINGUNG_BEWEGUNGSDATEN_ EINGABE = '0 'B & ENDFILE_BEDIN GUNG_S TAMMDATEN_ EINGABE =
1
0 ' B) ;
I F KONTONUMMER_BEWEGUNG = STAMMSATZ. KONTONUMMER THEN CALL BEWEGTE_STAMMSAETZE; I F KONTONUMMER_BEWEGUNG > STAMMSATZ. KONTONUMMER & ENDFILE_BEDINGUNG_STAMMDATEN_ EINGABE =
'01B THEN
CALL NICHTBEWEGTE_STAMMSAETZE; I F KONTONUMMER_BEWEGUNG < STAMMSATZ. KONTONUMMER &
4.1 M a g n e t b a n d d a t e i e n
205
ENDFILE_BEDINGUNG_BEWEGUNGSDATEN_ EINGABE =
'O'B THEN
CALL
BEWEGUNGEN_OHNE_STAMMSAETZE;
END; /*********************
ENDETEIL
***********************/
I F E N D F I L E _ B E DINGUNG_BEWEGUNGS DATEN_ EINGABE = DO WHILE
_EINGABE CALL
'1'B
THEN
(ENDFILE_BEDINGUNG_STAMMDATEN =
'O'B);
NICHTBEWEGTE_STAMMSAETZE;
END; IF
ENDFILE_BEDINGUNG_STAMMDATEN_ EINGABE = DO WHILE
'1'B
THEN
(ENDFILE_BEDINGUNG_ BEWEGUNGSDATEN_ EINGABE
CALL
='0'B);
BEWEGUNGEN_OHNE_STAMMSAETZE;
END; /A*****************************************************/ BEWEGTE_STAMMSAETZE /****************
:
PROC;
DRUCKAUFBEREITUNG_STAMMDATEN ZEILE.KONTONUMMER =
********/
STAMMSATZ. KONTONUMMER;
ZEILE.ALTER_SALDO
=
STAMMSATZ.SALDO;
SELECT; WHEN
(SIGN
(STAMMSATZ.SALDO)
ZEILE.ANZEIGE_SOLL_HABEN WHEN
(SIGN
=
=
(STAMMSATZ.SALDO)
ZEILE.ANZEIGE_SOLL_HABEN
1)
'H'; =
=
-1)
'S';
OTHERWISE ZEILE.ANZEIGE_SOLL_HABEN
=
'
';
END; /**************
ENDE DRUCKAUFBEREITUNG_STAMMDATEN CALL
*****/
VERARBEITEN_BEWEGUNGSDATEN (STAMMSATZ); READ F I L E INTO
(MEINGAB) (STAMMSATZ);
206
4. Nichtelementare Dateiorganisation und Dateiverarbeitung
END BEWEGTE_STAMMSAETZE; /******************************************************/ NICHTBEWEGTE_STAMMSAETZE : PROC; /**************** DRUCKAUFBEREITUNG STAMMDATEN ********/ ZEILE.KONTONUMMER = STAMMSATZ. KONTONUMMER; ZEILE.ALTER_SALDO = STAMMSATZ.SALDO; SELECT; WHEN (SIGN (STAMMSATZ.SALDO) = 1) ZEILE.ANZEIGE_SOLL_HABEN = 'H'; WHEN (SIGN (STAMMSATZ.SALDO) = -1) ZEILE.ANZEIGE_SOLL_HABEN = 'S'; OTHERWISE ZEILE.ANZEIGE_SOLL_HABEN = ' '; END; ZEILE.DATUM = STAMMSATZ.DATUM; WRITE FILE (LISTE) FROM (ZEILE); ZEILE_1 = 'O'; WRITE FILE (MAUSGAB) READ
FROM (STAMMSATZ); FILE (MEINGAB)
INTO (STAMMSATZ); END_NICHTBEWEGTE STAMMSAETZE; /******************************************************/ BEWEGUNGEN_OHNE_STAMMSAETZE : PROC; ZEILE.KONTONUMMER, PUFFER_STAMMSATZ.KONTONUMMER = KONTONUMMER_BEWEGUNG; ZEILE.ALTER_SALDO, PUFFER_STAMMSATZ.SALDO = 0; CALL VE RARBEITEN_BEWEGUNGS DATEN (PUFFER_STAMMSATZ); END BEWEGUNGEN_OHNE_ STAMMSAETZE;
207
4.1 Magnetbanddateien VERARBEITEN BEWEGUNGSDATEN
:
PROC
(STAMMSATZ);
DCL 1 STAMMSATZ, 2 SATZART
CHAR
(1),
2 KONTONUMMER CHAR
(6),
2 DATUM
(6),
CHAR
2 SALDO DO WHILE
PIC'S9999999V99';
(KONTONUMMER_BEWEGUNG = STAMMSATZ. KONTONUMMER
& ENDFILE_BEDINGUNG_BEWEGUNGSDATEN_ EINGABE = ' 0 'B) ; /*
UPDATEN STAMMSATZ
*/
STAMMSATZ.SATZART
= KARTENART;
STAMMSATZ.DATUM
= DATUM_BEWEGUNG;
STAMMSATZ.SALDO
= STAMMSATZ.SALDO + BETRAG_BEWEGUNG;
/*
DRUCKEN BEWEGUNGSSATZ
*/
ZEILE.BELEG_NUMMER
= BELEGNUMMER_BEWEGUNG;
ZEILE.DATUM
= DATUM_BEWEGUNG;
I F BETRAG_BEWEGUNG > 0 THEN ZEILE.HABEN = BET RAG_BEWEGUNG; ELSE Z E I L E . S O L L
=
BETRAG_BEWEGUNG; WRITE F I L E
(LISTE)
FROM
ZEILE_1
= '
/ * LESEN BEWEGUNGSSATZ READ
(ZEILE);
FILE
(LEINGAB)
'; */
INTO
(BEWEGUNGSSATZ);
END; /********************
GRUPPENWECHSEL
******************/
SELECT; WHEN (SIGN
(STAMMSATZ.SALDO)
=
1)
Z E I L E . A N Z E I G E _ S OLL_HABEN_NE U = WHEN (SIGN
(STAMMSATZ.SALDO)
'H';
= -1)
ZEILE.ANZEIGE_SOLL_HABEN_NEU =
'S';
OTHERWISE ZEILE.ANZEIGE_SOLL_HABEN_NEU
=
'
';
END; ZEILE.NEUER SALDO = STAMMSATZ.SALDO;
208
4. Nichtelementare Dateiorganisation und Dateiverarbeitung
WRITE F I L E
(LISTE)
FROM
(ZEILE); = >o1;
ZEILE_1 WRITE F I L E
(MAUSGAB)FROM
(STAMMSATZ);
END V E R A R B E I T E N _ BEWEGUNGSDATEN; /******************************************************^ END
BEISP20;
Das Programm zur Lösung dieser Aufgabe beginnt damit, daß zunächst die Dateien vereinbart werden, wobei wir aus Übersichtlichkeitsgründen keine Standardannahmen benutzen. Die ENVIRONMENT-Angabe für die Druckdatei LISTE definiert, daß die Druckzeile 88 Stellen lang sein soll (,,F(88)") und daß ASA-Steuerzeichen den Zeilenvorschub des Druckers steuern (CTLASA). Wenn man dieses Programm mit dem Programmierbeispiel „BEI SP15" des Abschnitts 3.4.2.5, das auch diese Steuerzeichen benutzte, vergleicht, fällt auf, daß dort in der ENVIRONMENT-Definition die Angabe „CTLASA" fehlt. Dafür wurde dort in der Job-Control-Sprache, mit der Informationen an das Betriebssystem gegeben werden, ein analoger Hinweis aufgenommen. Der Vollständigkeit halber müssen wir jetzt noch sowohl im Sprachelement „zusatzlistem" (Abschnitt 4.1) als auch in „zusatzlistep" dieses Attribut aufnehmen. Wir definieren: vorschubsteuerung:: = CTLASA I CTL360 Das Attribut CTLASA gibt an, daß das erste Zeichen eines Datensatzes als ASA-Vorschubsteuerzeichen interpretiert werden soll (s. Tabelle 3—10) und CTL360, daß für diese Funktion eine 8-Bit-Kombination herangezogen werden soll. Wie im Programm „BEISP15" werden wieder Strukturen, in diesem Fall die Druckzeile („ZEILE"), nach jedem Druckprozeß durch überlagerndes Definieren gelöscht. In gleicher Weise fügt das Programm nach dem Drucken der Überschriftszeile einen fünfzeiligen Zwischenraum ein, der sich zusammensetzt aus einem zweizeiligen Zwischenraum vor dem Drucken der nächsten Zeile, dem Drucken einer Zeile, bestehend ausschließlich aus Zwischenraumzeichen, und einem zweizeiligen Vorschub vor dem Drucken der ersten Kontozeile. Dieses Programm verwendet zur Strukturierung und zur Gliederung in leicht überschaubare Programmabschnitte ausgiebig interne Prozeduren (BEWEG TE_ST AMMS AETZE, NICHTBEWEGTE_STAMMSAETZE, BEWE GUNGEN_OHNE_STAMMSAETZE, VERARBEITEN_BEWEGUNGS DATEN). Dies ist eine typische Eigenschaft wohlstrukturierter PL/1-Programme, die Elshoff beim Vergleich mit konventionellen PL/1-Programmen gefunden hat [6a]. Er beobachtete, daß in der strukturierten Programmierung das Verhältnis von internen Prozeduren zu Prozeduren gesamt im Mittel
4.2 Magnetplattendateien
209
1:1,12 beträgt, in der herkömmlichen Programmierung aber nur 1:2,45. Weiterhin fällt am Programm BEISP20 auf, daß die internen Prozeduren relativ klein sind (5—24 Anweisungen). Auch diese Beobachtung deckt sich mit den Untersuchungsergebnissen von Elshoff, der eine mittlere Anzahl von Anweisungen je Prozedur (interne und externe) von 57 gefunden hat. Man sollte sich also nicht scheuen, ausgiebig interne und externe Prozeduren einzusetzen, um klare und leicht änderbare Programmstrukturen zu erhalten. Gut dokumentierte Programme zeichnen sich auch dadurch aus, daß der Programmierer nicht die Mühe gescheut hat, Kommentare einzubauen und Bezeichner zu wählen, die selbsterklärend sind. Auch diese Eigenschaft kann man am Programm BEISP20 ablesen. Leider findet man in der Praxis häufig Programme, die für den Nichteinge weihten so schlecht lesbar und damit schwer verständlich sind, daß es häufig leichter ist, ein Programm neu zu schreiben als ein von einem anderen Programmierer geschriebenes Programm zu ändern. Sowohl eine klare Programmstrukturierung als auch eine leicht lesbare Programmdokumentation sind Voraussetzungen, um den Wartungsaufwand von Programmen in erträglichen Grenzen zu halten. Zum Abschluß dieses Beispiels bringen wir noch einen Ausschnitt aus der Ausgabeliste (Spaltenabstände mußten aus satztechnischen Gründen verkleinert werden): KONTO-NR. ALTERSALDO
BELEG-NR.
DATUM
000001
000002
H 1919.50 S 50.00
000003
0.00
1005 2002 2003 3002 3001 3003
731020 731021 731021 731021 731021 731019
4711
731014
000004 000009
000011
S 1000.50 S 5000.50 S 25.50
SOLL
HABEN
NEUERSALDO
1005.50
H2921.00
2005.00
H 1905.00
50.00 9542.00 500.00 30.00
S 9072.00 500.00
S 4500.50
4.2 Magnetplattendateien 4.2.1 Sequentielle Verarbeitung Der Magnetplattenspeicher ist der Repräsentant einer Datei, bei der die Datensätze unter direktem Zugriff stehen. Das Programm kann jeden beliebigen Satz über ein Ordnungsmerkmal direkt aufrufen, ohne daß die Datei von ihrem Anfang bis zum gesuchten Satz in streng sequentieller Folge an einem Lesekopf vorbeigeführt werden müßte. Die sequentielle Verarbeitungsform, die im Grunde genommen eine Magnetbandorganisation auf einem Plattenspeicher simuliert und deshalb die charakteristischen Merkmale dieses Speichermittels negiert, ist der Ausnahmefall, nicht die Regel. Nur aus didaktischen
4. Nichtelementare Dateiorganisation und Dateiverarbeitung
210
Gründen soll mit dieser Verarbeitungsform die Darstellung der Magnetplattendateien beginnen. Obwohl mit jedem physischen Satz eines Plattenspeichers im Gegensatz zum Magnetbandspeicher eine Adresse aufgezeichnet ist, besteht in der sequentiellen Verarbeitungsform kein Zusammenhang zwischen diesen Adressen und dem Ordnungsbegriff der logischen Sätze. Eine Blokkung der logischen Sätze (s. Abb. 4—5) bringt auch hier wieder eine bessere Ausnutzung der Speicherkapazität. Der Aufruf des gespeicherten Datenbestandes erfolgt analog zur Magnetbandorganisation, indem die Bewegungsdaten stapelweise sortiert der Datenverarbeitungsanlage übergeben und sequentiell mit den dazugehörigen Stammdaten zusammengeführt werden. Das „Updaten" unterscheidet sich aber von der Magnetbandverarbeitung insofern, als jetzt Veränderungen unmittelbar im physischen Datensatz vorgenommen werden können. Es ist also nicht notwendig, mit jedem Verarbeitungsprozeß auf der Ausgangsseite der Datenverarbeitungsanlage eine neue Datei zu schreiben. Daraus resultiert eine neue Anweisung, nämlich R E W R I T E . Falls allerdings neue Stammsätze in eine sequentiell organisierte Magnetplattendatei eingefügt werden müssen, entsteht dasselbe Problem wie bei der Bandorganisation, nämlich das Erweitern unter Beibehaltung der vorgegebenen Ordnungsrelation. Deshalb wird die sequentielle Verarbeitungsform bei Magnetplattendateien nur dann eingesetzt, wenn relativ wenig Zugänge und Abgänge auftreten und ein hoher Prozentsatz der Bestandsätze bei jeder Verarbeitung bewegt werden. Damit ergeben sich die in Abbildung 4—5 dargestellten Organisationsformen der sequentiellen Speicherung auf Magnetplattendateien. rtin «eou«ntitlL
MÍ 1 Dot*n Kto-Nr 123
Konnzaichn
Kannzotthfl
Datan Kto-Nr 333
V/,
I
Kannzoichn.
1
Datan Kto.-Nr. 4 SC
MQutnticU.geblockt : Kannzoichn.
!
Daten Datan Daten Kto-Nr 123 Kto.-Nr 333 Kta-Nr. (SE
Kannzaictin.
Datan Kto.-Nr 4(0
inòcxstqutntieU: Ordnung Oaton fnirtifnol i
Adraflindax Kta-Nr Satndr. 1 23 151914 333 151915 456 151916
Kannzaichnung Satndraao 1
Datan
?
Abb. 4—5. Sequentielle Datenorganisation in Magnetplattendateien.
Die ersten beiden Speicherungsformen, die rein sequentielle und die sequentiell geblockte, entsprechen der Magnetbandspeicherung. Wie auf dem Mag-
211
4.2 Magnetplattendateien
netband, so trennen auch hier Klüfte die einzelnen Datensätze einer Spur. Allerdings gibt es in der Magnetplattenorganisation verschieden lange Klüfte, um Nutzdaten von Steuerungsdaten zu unterscheiden. So beginnt jeder Block mit einer Kennzeichnung, die vor allem die Satzadresse enthält, aber auch Angaben über die Länge der Nutzdaten. Die Kluft zwischen dieser Kennzeichnung und den darauf folgenden Daten ist enger als die Kluft zwischen den einzelnen Blöcken. Da bei dieser sequentiellen Speicherungsform nicht bekannt ist, unter welcher Adresse ein bestimmter Datensatz zu finden ist, obwohl die Kennzeichnung die Satzadresse enthält, ist bei dieser Form der Dateiorganisation kein unmittelbarer Zugriff zu den gespeicherten Daten möglich. Sie nutzt demzufolge die spezifische Eigenschaft des Magnetplattenspeichers, die im wahlfreien Speicherzugriff liegt, nicht aus. Ein Kompromiß zwischen der sequentiellen Speicherorganisation und der Forderung nach direktem Zugriff ist die Sonderform der indexsequentiellen Speicherung. Aus einem Adreßverzeichnis, das eine Zuordnungsliste zwischen externem Ordnungsmerkmal und Speicheradresse darstellt (Adreßindex), geht hervor, wo ein bestimmter logischer Datensatz zu finden ist. Damit ergeben sich zwei Untergruppen der sequentiellen Verarbeitung von Magnetplattendateien: sequentielle Verarbeitung von Magnetplattendateien
nur sequentieller Zugriff möglich, wie bei Magnetbanddateien, aber zusätzliche Anweisung REWRITE
sequentieller oder direkter Zugriff
In diesem Abschnitt soll zunächst die linke Klasse der obigen Klassifizierung weiter verfolgt werden. Die indexsequentielle Magnetplattenorganisation, die eine Sonderform der direkten Zugriffsmethode ist, wird in einem eigenen Abschnitt dargestellt werden. Tabelle 4—2 zeigt in Analogie zur Tabelle 4—1 wieder die charakteristischen Strukturelemente der Dateivereinbarung und der Dateianweisungen für Magnetplattendateien, die sequentiell verarbeitet werden. Folgende Änderungen fallen auf. Da in Magnetplattenspeichern die Daten auf ständig rotierenden Platten aufgezeichnet sind, wäre es sinnlos, in diesem Fall das Attribut BACKWARDS, das ein Rückwärtslesen von Magnetbanddateien definiert, zuzulassen. Neu ist in Tabelle 4—2 das Attribut U P D A T E und die R E WRITE-Anweisung. Die Dateivereinbarung U P D A T E besagt, daß in ein und demselben Satz dieser Datei sowohl Daten gelesen als auch geschrieben werden sollen. Diese Datei wirkt also sowohl als Eingabe- als auch als Ausgabedatei. Gelesen werden die Daten einer solchen Datei durch die übliche READAnweisung. Das „Updaten" selbst, d.h. das Überschreiben eines veralteten
4. Nichtelementare Dateiorganisation und Dateiverarbeitung
212
M
O 3
—
3
3 .2 re 'C
eu re > U E 'SC5/ jare Mu 00 'S W O § z o
o Co «N u s |N
1)
Ô M S B (I.J2 »
-C u O « H > C o XI O — -V v
Xw »l_ 'C m cd U Q
Ë i-i u T3 vi 3 73 O S
oc s 3 y1 'C S o S PJ S hH SU SÉ « •bUä^
«45 E O CK E mu S o c u g CL f T) J Ë ta «S. CO b vî
00 0 THEN ZEILE.HABEN = BETRAG_BEWEGUNG; ELSE Z E I L E . S O L L
=
BETRAG_BEWEGUNG; WRITE F I L E
(LISTE)
FROM
ZEILE_1
= '
/ * LESEN BEWEGUNGSSATZ READ
FILE
(LEINGAB)
(ZEILE); '; */
INTO
(BEWEGUNGSSATZ);
END; /********************
GRUPPENWECHSEL
*******************/
SELECT; WHEN (SIGN
(STAMMSATZ.SALDO)
=
1)
ZEILE.ANZEIGE_SOLL_HABEN_NEU = WHEN (SIGN
(STAMMSATZ.SALDO)
ZEILE.ANZEIGE_SOLL_HABEN_NEU
'H';
= -1) =
'S';
OTHERWISE ZEILE.ANZEIGE_SOLL_HABEN_NEU
=
'
';
END; ZEILE.NEUER_SALDO = STAMMSATZ.SALDO; WRITE F I L E ZEILE_1
(LISTE)
FROM
(ZEILE); =
'O1;
242
4. Nichtelementare Dateiorganisation und Dateiverarbeitung
REWRITE F I L E
(PLATGAB)
FROM
(STAMM SATZ)
KEY
(ZWISPEI);
END VE RARBEITEN_ BEWEGUNGSDATEN; /*******************************+*******************+*+/ END
BEISP22;
Dieses Beispiel zeigt deutlich die Vorteile eines funktionell orientierten Entwurfs- und Programmierstils; denn die beiden Prozeduren „BEWEGTE _STAMMSAETZE" und „BEWEGUNGEN_OHNE_STAMMSAETZE" können leicht an die spezifischen Belange der Magnetplattenorganisation angepaßt werden. Dasselbe gilt für die Programmsteuerung in der DO WHILESchleife. Die Funktion „NICHTBEWEGTE_STAMMSAETZE" tritt bei einer direkten Verarbeitung von Dateien nicht mehr in Erscheinung. Dieses letzte Beispiel leitet auch schon über zum methodischen Software-Entwurf, der ein funktioneller Entwurf ist [13a]. Dort stehen Fragen der Änderungsfreundlichkeit und der Wartbarkeit im Vordergrund. Übungsaufgabe: Die Datensätze einer REGIONAL (2)-Datei sollen im Update-Verfahren verarbeitet werden. Die Eingabe der Bewegungssätze in die Datenverarbeitungsanlage erfolgt mit Lochkarten. Folgende Kartenarten kommen vor: 1. Kartenart A : Buchung 2. Kartenart B : Anlegen eines neuen Kontos 3. Kartenart C : Löschen eines Kontos. Es sind folgende Fehlermöglichkeiten programmiert abzufragen: 1. Schlüssel wurde in der gespeicherten Datei nicht gefunden. 2. Ein neues Konto kann nicht gespeichert werden, weil kein Speicherplatz frei ist. 3. Das als Neuzugang deklarierte Konto ist bereits vorhanden. 4. Falsche Kartenart. Weitere Fehler sind nur als Hinweis (Bedingungscode) auszudrucken. Als Umrechnungsmethode zur Bestimmung der Speicheradresse soll das Divisionsrestverfahren in der einfachsten Form gewählt werden. Die Datei enthält maximal 5987 Datensätze. Aufbau Stammsatz: 1 STAMMSATZ, 2 NR CHAR (6), 2 NAME CHAR (56), 2 SALDO PICTURE 'S999999V99';
243
4.2 Magnetplattendateien Aufbau Bewegungssatz (Lochkarte): 1 KARTENSATZ, 2 KNR 2 BELEGNUMMER 2 DATUM 2 BEWEGUNG 2 TEXT 2 KA
CHAR (6), CHAR (4), CHAR (6), PICTURE 'S9999V99', CHAR (5), CHAR (1);
Es sind im Stammsatz Haben- und Sollbuchungen vorzunehmen. Gelöschte Kontos sind mit der Anweisung PUT LIST zu protokollieren. Die durch die drei Kartenarten A, B und C ausgedrückten Funktionen sind als interne Prozeduren zu programmieren.
4.2.4 Sequentielle Verarbeitung von regionalen Magnetplattendateien Es soll jetzt noch der Sonderfall diskutiert werden, daß regional strukturierte Magnetplattendateien sequentiell zu verarbeiten sind. Da in der Dateiform REGIONAL (1) die Datensätze in aufsteigender Folge ihres externen Ordnungsmerkmals gespeichert sind, können sie auch ohne weiteres sequentiell verarbeitet werden. Die Auswahl der Verarbeitungsform hängt davon ab, ob es organisatorisch möglich und wirtschaftlich vertretbar ist, Bewegungsdaten so lange zu stapeln, bis eine genügend große Bearbeitungseinheit (Stapel) zusammengekommen ist. Aber auch auf REGIONAL (2) und REGIONAL (3) ist die herkömmliche sequentielle Verarbeitungsform anwendbar. Tabelle 4—9 zeigt für alle drei Dateiformen die Anweisungsstrukturen. Der Unterschied in der sequentiellen Verarbeitung einer sequentiell organisierten Datei und einer regionalen Datei wird besonders deutlich, wenn man diese Tabelle mit der analogen Tabelle 4—2 vergleicht. Beim Lesen eines Datensatzes mit der READ-Anweisung ist es möglich, aber nicht notwendig, den Schlüssel im logischen Satz mit anzusprechen, indem der KEYTO-Zusatz notiert wird. Er gibt an, daß das externe Ordnungsmerkmal des zu lesenden Satzes in die Zeichenkettenvariable entsprechend den Regeln für die Zeichenkettenzuweisung übertragen werden soll. Die WRITE-Anweisung entspricht dem Fall des direkten Zugriffs. Wir haben sie hier nur der Vollständigkeit halber mit aufgeführt; denn infolge des Dateiattributs „OUT PUT" kommt sie nur für die sequentielle Dateierstellung in Frage. Hingegen ist die REWRITE-Anweisung genauso strukturiert wie im Fall der sequentiellen Dateiorganisation. Dies bedeutet, daß kein externes Ordnungsmerkmal mit abgespeichert werden kann, wie es beim Aufnehmen neuer Datensätze in
244
4. Nichtelementare Dateiorganisation und Dateiverarbeitung
JS.s u TT c B u JE Sì O S 00 S £ Ë 2 1) 1) 'S E £ 3 Ë N 2 « o" e 0) u < U E3 .60 S -: 30 M W3 5 c c S •2 3 — a e £t i «a_>00 N
b u B O > S cO
I
u Xi ¡2
fi '—* Jáo S i ë S IÍ - M
2 e "V (p2>q2),-",(pn,q n ) handelt, dann ist die Genauigkeit des Ergebnisses: (MIN(N,MAX(p1-q1,...,pn-qn)+MAX(q1,...,qn)),MAX(q1,...,qn))
Die eingefügte arithmetische Funktion MIN Definition: MIN entnimmt einer vorgegebenen Menge von zwei oder mehr Ausdrücken x1? x 2 ,..., x n , die nicht komplex sein dürfen, den minimalen Wert. Aufruf: MIN(x 1 ,x 2 ,...,x n ) Ergebnis: Der zurückgegebene Wert wird in der Weise umgewandelt, daß er den maximalen Argumenten der Menge von Arbeitsobjekten x, ... x n genügt. Wenn es sich um Festpunktdaten mit den Genauigkeiten (Pl>qi)>(P2,q2),---,(Pn,qn) handelt, dann ist die Genauigkeit des Ergebnisses folgende: (MIN(N,MAX(p1-q1,...,p„-qn)+MAX(q1,...,qn)),MAX(q1,...,qn))
Anhang
264 Die eingefügte arithmetische Funktion M O D
Definition: M O D hält den Rest, der bei der Division zweier reeller Ausdrücke x, und x 2 entsteht, fest. Aufruf: MOD(x,,x 2 ) Argumente: Vor dem Funktionsaufruf werden Zahlenbasis und Schreibweise jedes Argumentes umgewandelt, entsprechend den Regeln für die Datenkonvertierung in arithmetischen Ausdrücken. Ergebnis: Die Division wird ohne Beachtung der Vorzeichen durchgeführt. Wenn kein Rest bleibt, dann ist das Ergebnis Null. Wenn ein Rest bleibt und die Vorzeichen von Divisor und Dividend gleich sind, dann ist der zurückgegebene Wert der Rest. Wenn ein Rest bleibt und die Vorzeichen des Dividenden und des Divisors verschieden sind, dann ist der zurückgegebene Wert die Differenz zwischen dem Rest und dem Divisor ohne Beachtung der Vorzeichen. Beispiel: MOD(29,6) gibt den Wert 5 zurück, während MOD(—29,6) den Wert 1 zurückgibt. Wenn das Ergebnis als Gleitpunktzahl ausgewiesen wird, dann ist seine Genauigkeit größer als die Genauigkeit der einzelnen Argumente; wenn das Ergebnis eine Festpunktzahl ist, dann wird seine Genauigkeit folgendermaßen definiert: (MIN(N,p2-q2+MAX(q1,q2)),MAX(q1,q2)) wobei (pi,qi) und (p 2 ,q 2 ) die Genauigkeit von „x," bzw. „x 2 " ist. Wenn der Wert des zweiten Argumentes Null ist, dann wird die Bedingung Z E R O D I V I D E gesetzt. Beachte: Wenn die Funktion M O D zusammen mit der Funktion F I X E D auf Argumente verschiedener Schreibweise angewandt wird, dann könnten im Ergebnis signifikante Stellen verloren gehen. Wenn das Bedingungspräfix SIZE wirksam ist, dann wird eine Fehlermeldung gedruckt. Wenn das Bedingungspräfix S I Z E unwirksam ist, dann wird keine Meldung gedruckt und das Ergebnis ist Undefiniert.
Die eingefügte arithmetische Funktion MULTIPLY Definition: M U L T I P L Y berechnet das Produkt der beiden Variablen Xj und x 2 mit der Genauigkeit p[,q]. Aufruf: MULTIPLY(Xi,x 2 ,p[,q]) Argumente: Die Argumente „p" und „q" („q" ist wahlweise zu notieren und
A 2 Mathematische Funktionen
265
kann ein Vorzeichen haben) sind ganzzahlige Dezimalkonstante. Wenn das Ergebnis ein Festpunktwert sein soll, dann müssen „p" und „q" angegeben werden; soll das Ergebnis ein Gleitpunktwert sein, dann muß nur „p" notiert werden. In beiden Fällen darf „p" nicht größer sein als N. Die Genauigkeit des Ergebnisses wird über die Zeit der Funktionsausführung beibehalten.
Die eingefügte arithmetische Funktion PRECISION Definition: PRECISION wandelt den Wert einer Variablen x in die Genauigkeit p[,q] um. Aufruf: PRECISION(x,p[,q]) Argumente: Die Argumente „p" und „q" („q" muß nicht notiert werden und kann ein Vorzeichen haben) sind ganzzahlige Dezimalkonstante. Wenn „x" eine Festpunktzahl ist, dann müssen „p" und „q" angegeben werden; wenn „x" eine Gleitpunktzahl ist, dann muß nur „p" programmiert werden. Ergebnis: Zahlenbasis, Schreibweise und Modus des zurückgegebenen Wertes sind die gleichen wie die von „x".
Die eingefügte arithmetische Funktion REAL Definition: R E A L gibt den Realteil einer komplexen Variablen x zum Aufrufpunkt zurück. Diese Funktion darf auch als Pseudovariable verwendet werden. Aufruf: REAL(x) Ergebnis: Zahlenbasis, Schreibweise und Genauigkeit des Realteils bleiben unverändert.
Die eingefügte arithmetische Funktion R O U N D Definition: R O U N D rundet einen Ausdruck an der Stelle n rechts vom Radixpunkt. Aufruf: ROUND(ausdruck,n) Argument: Das Argument „ausdruck" ist eine Element- oder Bereichsvariable, die den Wert darstellt (oder Werte, im Falle eines Bereichsausdrucks), der gerundet werden soll; das zweite Argument „n" ist eine ganzzahlige dezimale Konstante (mit oder ohne Vorzeichen), die jene Stelle definiert, an der im „ausdruck" gerundet werden soll. Wenn „n" positiv ist, dann wird rechts vom
266
Anhang
Radixpunkt gerundet. Zu beachten ist, daß der Radixpunkt für Gleitpunktvariable links von der höchsten signifikanten Ziffer angenommen wird. Ergebnis: Bei Festpunktwerten gibt R O U N D den Wert zurück, der an der n. Stelle rechts vom Radixpunkt gerundet wurde. Wenn „n" negativ ist, dann ist der zurückgegebene Wert eine ganze Zahl. Wenn „ausdruck" eine Gleitpunktzahl ist, dann wird das zweite Argument ignoriert und das am weitesten rechts stehende Bit der internen Gleitpunktdarstellung, wenn es zuvor den Wert Null hatte, auf Eins gesetzt. Falls dieses Bit das Binärzeichen Eins war, dann bleibt es unverändert. Wenn „ausdruck" eine Kette ist, dann ist der zurückgegebene Wert die gleiche, unveränderte Kette. Zahlenbasis, Schreibweise, Modus und Genauigkeit des zurückgegebenen Wertes sind die gleichen wie die des Wertes von „ausdruck" mit einer Ausnahme: Wenn der Wert von „ausdruck" eine Festpunktzahl mit der Genauigkeit (p,q) ist, dann ist das Ergebnis eine Festpunktzahl mit der Genauigkeit: (MIN(p+l,N),q) Beachte: Das Runden eines negativen Betrages bewirkt, daß der absolute Betrag gerundet wird.
Die eingefügte arithmetische Funktion SIGN Definition: SIGN gibt an, ob der Wert einer Variablen x positiv, negativ oder Null ist. Aufruf: SIGN(x) Argument: Das Argument „x" darf nicht komplex sein. Ergebnis: Diese Funktion gibt einen reellen, dualen Festpunktwert mit der Standardgenauigkeit, entsprechend den folgenden Regeln, zum Aufrufpunkt zurück: 1. Wenn x positiv ist, dann ist der zurückgegebene Wert 1. 2. Wenn x Null ist, dann ist der zurückgegebene Wert 0. 3. Wenn x kleiner als Null ist, dann ist der zurückgegebene Wert - 1 .
Die eingefügte arithmetische Funktion T R U N C Definition: T R U N C schneidet eine Variable x folgendermaßen ab: Zuerst berechnet sie, ob die Variable positiv, negativ oder gleich Null ist. Wenn sie negativ ist, dann gibt T R U N C die kleinste ganze Zahl zurück, die nicht kleiner als x ist; wenn x positiv oder gleich Null ist, dann gibt T R U N C die größte ganze Zahl zurück, die x nicht übersteigt.
A2 Mathematische Funktionen
267
Aufruf: TRUNC(x) Argument: Das Argument „x" darf nicht komplex sein. Ergebnis: Wenn „x" kleiner ist als Null, dann ist der von TRUNC zurückgegebene Wert CEIL(x). Wenn „x" größer oder gleich Null ist, dann ist der zurückgegebene Wert FLOOR(x). In jedem Fall sind Zahlenbasis, Schreibweise und Modus die gleichen wie die der Variablen x. Wenn sie ein Gleitpunktwert ist, dann bleibt die Genauigkeit die gleiche. Für einen Festpunktwert mit der Genauigkeit (p,q) ist die Genauigkeit des Ergebnisses: (MIN(N,MAX(p—q+l,l)),0)
Eingefügte mathematische Funktionen Hierbei handelt es sich um Näherungsverfahren für herkömmliche mathematische Funktionen wie die Winkelfunktionen oder Logarithmen zu verschiedenen Basen. Alle Argumente für diese Funktionen sollen in der internen arithmetischen Darstellungsform und als Gleitpunktzahlen übergeben werden. Jedes Argument, das dieser Regel nicht entspricht, wird wieder vor dem Funktionsaufruf in diese Form konvertiert. In den folgenden Funktionsbeschreibungen wird immer auf das konvertierte Argument Bezug genommen, falls eine Konvertierung notwendig ist. Im allgemeinen kann ein Argument einer eingefügten mathematischen Funktion ein Element- oder Bereichsausdruck sein. In diesem Fall ist der von der Funktion zurückgegebene Wert ein Bereich mit gleichen Dimensionen und gleichen Grenzen wie das Argument (die Funktion wird für jedes Element des Bereiches einmal ausgeführt). Daher liefert die Cosinusfunktion COS mit einem Bereich als Argument auch als Ergebnis einen Bereich, wobei jedes Element der Cosinus des entsprechenden Elementes des Argumentbereiches ist. Falls nicht anders angegeben, kann ein Argument reell oder komplex sein.
Die eingefügte mathematische Funktion ACOS Definition: ACOS berechnet den Arcuscosinus einer Größe x und gibt das Ergebnis im Bogenmaß als Gleitpunktgröße zum Aufrufpunkt zurück. Aufruf: ACOS(x) Argument: Die Größe „x" muß reell sein und ihr absoluter Wert muß kleiner, gleich Eins sein.
Anhang
268
Die eingefügte mathematische Funktion ASIN Definition: ASIN berechnet den Arcussinus einer Größe x und gibt das Ergebnis im Bogenmaß als Gleitpunktgröße zum Aufrufpunkt zurück. Aufruf: ASIN(x) Argument: Die Größe „x" muß reell sein und ihr absoluter Wert muß kleiner, gleich Eins sein. Die eingefügte mathematische Funktion ATAN Definition: A T A N berechnet den Arcustangens einer Größe x und gibt das Ergebnis im Bogenmaß zum Aufrufpunkt zurück. Aufruf: ATAN(x[,y]) Argumente: Das Argument „x" muß immer angegeben werden; das Argument „y" kann der Programmierer wahlweise notieren. Wenn „y" fehlt, stellt ,x" den Wert dar, dessen Arcustangens gefunden werden soll; in diesem Fall kann „x" reell oder komplex sein; aber wenn es komplex ist, darf es nicht gleich ± 1 i sein. Wenn „y" notiert wurde, dann wird die Größe, dessen Arcustangens gefunden werden soll, als der Ausdruck x/y angenommen. In diesem Fall müssen „x" und „y" beide reell sein, und beide dürfen nicht gleichzeitig Null sein. Ergebnis: Wenn „x" allein als Argument angegeben wurde, dann hängt der von A T A N zurückgegebene Wert vom Modus von „x" ab. Wenn „x" reell ist, dann ist der zurückgegebene Wert der Arcustangens von „x", ausgedrückt im Bogenmaß, wobei gilt: —jr/2 0 oder u = 0 und v ^ 0
reell
tg(x)
-
komplex
tg(x)
-
TAND(x) x im Gradmaß
reell
tg(x)
-
TANH(x)
reell
tgh(x)
-
komplex
tgh(x)
-
LOG(x)
SQRT(x)
TAN(x) x im Bogenmaß
-
-
x< 0 —
276
Anhang
A 3 Eingefügte Funktionen für die Bereichsverarbeitung [7]
Alle diese Funktionen benötigen als Argument Bereiche (die aus Ausdrücken bestehen können) und geben einzelne Elementwerte zurück. Ein Aufruf jeder dieser Funktionen wird, da sie einzelne Werte zurückgibt, als Elementausdruck betrachtet.
Die Bereichsverarbeitungsfunktion A L L Definition: ALL prüft alle Bits eines gegebenen Bitkettenbereichs und gibt das Ergebnis, in Form einer Elementbitkette, zum Aufrufpunkt zurück. Diese Kette gibt an, ob alle Bits des Bereichs das Binärzeichen Eins sind oder nicht. Aufruf: ALL(x) Argument: Das Argument „x" ist ein Bereich von Bitketten. Wenn die Elemente des Bereichs keine Bitketten sind, dann werden sie in Bitketten konvertiert. Ergebnis: Der von dieser Funktion zurückgegebene Wert ist eine Bitkette, deren Länge gleich der Länge des längsten Elementes von „x" ist und deren Werte durch folgende Regel bestimmt werden: Wenn die i-ten Bits aller Elemente von „x" existieren und „1" sind, dann ist das i-te Bit des Ergebnisses gleich „1"; andernfalls ist das i-te Bit des Ergebnisses gleich „0".
Die Bereichsverarbeitungsfunktion A N Y Definition: ANY prüft die Bits eines gegebenen Bitkettenbereiches und gibt das Ergebnis, in Form einer Elementbitkette, zum Aufrufpunkt zurück. Sie gibt an, ob mindestens eines der entsprechenden Bits der gegebenen Bereichselemente „1" ist. Aufruf: ANY(x) Argument: Das Argument „x" ist ein Bereich von Bitketten. Wenn die Elemente dieses Bereichs keine Bitketten sind, werden sie in Bitketten konvertiert. Ergebnis: Der von dieser Funktion zurückgegebene Wert ist eine Bitkette, deren Länge gleich der Länge des längsten Elementes in „x" ist und deren Werte durch folgende Regel bestimmt werden:
A 3 Eingefügte Funktionen für die Bereichsverarbeitung
277
Wenn das i.te Bit irgendeines Elementes in „x" existiert und „1" ist, dann ist das i.te Bit des Ergebnisses gleich „1"; andernfalls ist es gleich „0".
Die Bereichsverarbeitungsfunktion DIM Definition: DIM findet die gegenwärtige Ausdehnung eines Bereiches. Aufruf: DIM(x,n) Argumente: Das Argument „x" ist der zu prüfende Bereich; „n" ist die Dimension von „x", deren Ausdehnung gefunden werden soll. Wenn „n" keine duale ganze Zahl ist, dann wird sie in eine solche Zahl mit Standardgenauigkeit umgewandelt. Es ist ein Fehler, wenn „x" weniger als „n" Dimensionen hat, wenn „n" kleiner oder gleich Null ist oder wenn „x" kein Speicherplatz zugewiesen wurde. Ergebnis: Der von dieser Funktion zurückgegebene Wert ist eine duale ganze Zahl mit Standardgenauigkeit, die die Ausdehnung der n-ten Dimension von „x" angibt.
Die Bereichsverarbeitungsfunktion HBOUND Definition: H B O U N D findet die obere Grenze eines Bereiches. Aufruf: HBOUND(x,n) Argumente: Das Argument „x" ist der zu prüfende Bereich; „n" ist die Dimension von „x", von der die obere Grenze gefunden werden soll. Wenn „n" keine duale ganze Zahl ist, wird sie in eine solche Zahl mit Standardgenauigkeit umgewandelt. Es ist ein Fehler, wenn „x" weniger Dimensionen als „n" hat, wenn „n" kleiner oder gleich „0" ist oder wenn „x" kein Speicherplatz zugewiesen wurde. Ergebnis: Der von dieser Funktion zurückgegebene Wert ist eine duale ganze Zahl mit Standardgenauigkeit, die die obere Grenze für die n-te Dimension von „x" afigibt.
Die Bereichsverarbeitungsfunktion LBOUND Definition: LBOUND findet die untere Grenze eines Bereiches. Aufruf: LBOUND(x,n) Argumente: Das Argument „x" ist der zu prüfende Bereich; „n" ist die Dimension von „x", für die die untere Grenze gefunden werden soll. Wenn „n"
278
Anhang
keine duale ganze Zahl ist, wird sie in eine solche Zahl mit Standardgenauigkeit umgewandelt. Es ist ein Fehler, wenn „x" weniger Dimensionen als „n" hat, wenn „n" kleiner oder gleich „0" ist oder wenn „x" kein Speicherplatz zugewiesen wurde. Ergebnis: Der von dieser Funktion zurückgegebene Wert ist eine duale ganze Zahl mit Standardgenauigkeit, die die untere Grenze der n-ten Dimension von „x" angibt.
Die Bereichsverarbeitungsfunktion POLY Definition: POLY formt ein Polynom aus zwei gegebenen Argumenten und gibt das Ergebnis der Berechnung dieses Polynoms zum Aufrufpunkt zurück. Aufruf: POLY(a,x) Argumente: Die Argumente „a" und „x" müssen eindimensionale Bereiche (Vektoren) sein. Sie sind folgendermaßen definiert: a(m : n) x(p : q) wobei (m : n) und (p : q) die Grenzen von „a" und „x" angeben. Ergebnis: Der von dieser Funktion zurückgegebene Wert ist definiert als: n—m j-1 a(m) + X ( a ( m + j ) * [ ] ,=i i=0
x
(P+0)
Wenn (q — p) < (n — m — 1), dann ist x(p + i) = x(q) für (p + i) > q. Wenn m = n, dann ist das Ergebnis a(m). Wenn „x" eine Elementvariable ist, dann wird sie als Bereich mit einem Element interpretiert, d.h. x(l), und das Ergebnis ist dann: n-m a(m+j)*x**j 2 i=o
Die Bereichsverarbeitungsfunktion PROD Definition: P R O D berechnet das Produkt aller Elemente eines Bereiches. Aufruf: PROD(x) Argument: Das Argument „x" sollte ein Bereich von Gleitpunktzahlen in der internen arithmetischen Form sein. Wenn dies nicht der Fall ist, dann wird jedes Element in die interne arithmetische Form und die Gleitpunktdarstellung umgewandelt, bevor es mit dem vorhergehenden Produkt multipliziert wird.
A 4 Eingefügte Funktionen für die Kettenverarbeitung
279
Ergebnis: Der von dieser Funktion zurückgegebene Wert ist das Produkt aller Elemente von „x". Die Zahlendarstellung des Ergebnisses ist Gleitpunkt, während Zahlenbasis, Modus und Genauigkeit die des umgewandelten Elementes von „x" sind.
Die Bereichsverarbeitungsfunktion S U M Definition: SUM berechnet die Summe aller Elemente eines gegebenen Bereiches. Aufruf: SUM(x) Argument: Das Argument „x" sollte ein Bereich von Gleitpunktzahlen in der internen arithmetischen Form sein. Wenn dies nicht der Fall ist, dann wird jedes Element in die interne arithmetische Form und die Gleitpunktdarstellung umgewandelt, bevor es zur vorhergehenden Summe addiert wird. Ergebnis: Der von dieser Funktion zurückgegebene Wert ist die Summe aller Elemente von „x". Die Zahlendarstellung des Ergebnisses ist Gleitpunkt, während Zahlenbasis, Modus und Genauigkeit die der umgewandelten Elemente des Argumentes sind.
A 4 Eingefügte Funktionen für die Kettenverarbeitung [7] Wenn nicht ausdrücklich anders angegeben, kann wieder jedes Argument dieser Funktionen ein Element- oder Bereichsausdruck sein. Im Fall des Bereichsausdrucks gelten wieder die schon im Anhang 2 angegebenen Regeln für die Bereichsgrenzen. Es sind auch als Argumente, wenn nicht anders angegeben, alle Datenklassen zugelassen. Ein arithmetischer Ausdruck wird vor dem Funktionsaufruf in eine Bitkette konvertiert, wenn es sich dabei um eine Dualzahl handelt, und in eine Zeichenkette bei dezimaler Zahlenbasis.
Die eingefügte Kettenfunktion BIT Definition: BIT konvertiert eine Variable x in eine Bitkette mit der Länge 1. Aufruf: BIT(x[,l]) Argumente: Das Argument „1" muß, wenn es angegeben wird, eine ganzzahlige dezimale Konstante sein. Wurde sie nicht notiert, dann gelten die Regeln für die Datenkonvertierung (s. [13]).
Anhang
280
Die eingefügte Kettenfunktion BOOL Definition: BOOL erzeugt eine Bitkette, deren Bitfolge das Ergebnis einer gegebenen booleschen Operation für zwei gegebene Bitketten ist. Aufruf: BOOL(x,y,w) Argumente: Die Argumente „x" und „y" sind die zwei Bitketten, mit denen die durch „w" spezifizierte boolesche Operation ausgeführt werden soll. Wenn „x" und „y" keine Bitketten sind, dann werden sie in diese Form konvertiert. Wenn die Argumente „x" und „y" eine unterschiedliche Länge haben, dann wird die kürzere Kette rechts mit Nullen bis zur Länge der längeren Kette aufgefüllt. Das Argument „w" repräsentiert die boolesche Operation. Es ist eine Bitkette der Länge Vier und durch n, n2 n 3 n 4 definiert. Da es 16 mögliche Bitkombinationen für „w" gibt, sind auch 16 boolesche Operationen in dieser Form zu spezifizieren. Falls notwendig, wird „w" in eine Bitkette der Länge Vier konvertiert. Wenn mehr als ein Argument ein Bereich ist, dann müssen die Bereiche gleiche Grenzen haben und „w" muß ebenfalls als Bereich definiert sein. Ergebnis: Der von dieser Funktion zurückgegebene Wert ist eine Bitkette „z" in der Ausdehnung von „x" bzw. „y". Jedes Bit von „z" ergibt sich aus den entsprechenden Bits von „x" und „y" entsprechend der nachfolgenden Tabelle: Xi
y¡
z¡
0
0
ni
0
i
n2
1
0
n
1
i
n4
3
Diese Tabelle ist folgendermaßen zu interpretieren: Haben die beiden durch eine boolesche Operation verbundenen Operanden den Wert Null, so ist an der entsprechenden Stelle in der Variablen „z" der Wert „n," einzusetzen. In gleicher Weise ergeben sich die Ergebnisse der anderen drei möglichen Bitkombinationen von X| und yj. Beispiel:
U = BOOL(X,Y,'OnO');
In dieser Ergibtanweisung soll die Variable X den Wert '011'B und Y '110'B besitzen. Es würden sich die Bits von U nach folgender Tabelle ergeben:
A 4 Eingefügte Funktionen für die Kettenverarbeitung
Xi
Yj
U¡
0 0 1 1
0 1 0 1
0 1 1 0
281
Diese Tabelle ist folgendermaßen zu interpretieren: Wenn das i.Bit von X und Y das Binärzeichen Null ist, dann nimmt auch das i.Bit von U den Wert Null an. Ist hingegen das i.Bit von X Null und das i.Bit von Y Eins, dann erhält U den Wert Eins. Sind beide Bits, die durch eine boolesche Operation zu verknüpfen sind, das Binärzeichen Eins, dann erhält U den Wert Null. Für unser Beispiel wäre die zum Aufrufpunkt zurückgegebene Bitfolge gegeben durch '101'B.
Die eingefügte Kettenfunktion CHAR Definition: C H A R konvertiert eine Variable x in eine Zeichenkette der Länge 1. Aufruf: CHAR(x[,l]) Argumente: Das zweite Argument „1" muß, wenn es angegeben wird, eine ganzzahlige dezimale Konstante sein. Wenn sie nicht notiert ist, dann wird die Länge von „x" entsprechend den Regeln der Datenkonvertierung berechnet.
Die eingefügte Kettenfunktion HIGH Definition: H I G H bildet eine Zeichenkette der Länge „i" aus dem höchsten Zeichen in der Sortierfolge des Maschinencode. Aufruf: HIGH(i) Argument: Das Argument muß eine ganzzahlige dezimale Konstante sein.
Die eingefügte Kettenfunktion INDEX Definition: INDEX durchsucht eine Kette „x" nach der Bit- oder Zeichenkettenkonfiguration „k". Ist sie gefunden, dann wird die Stelle innerhalb der Kette, an der diese Konfiguration beginnt, zum Aufrufpunkt zurückgegeben.
282
Anhang
Aufruf: INDEX(x,k) Argumente: Es müssen zwei Argumente angegeben werden. Wenn beide Argumente Bitketten sind, findet keine Datenkonvertierung statt. Wenn beide Argumente binär sind, oder wenn ein Argument BIT und ein Argument binär ist, dann werden beide Argumente in Bitketten konvertiert, andernfalls in Zeichenketten. Wenn beide Argumente Bereiche sind, dann müssen die Bereiche gleiche Argumente aufweisen. Ergebnis: Der zurückgegebene Wert ist eine Dualzahl mit Standardgenauigkeit. Sie gibt an: 1. Die Stelle in der Kette, in der die gesuchte Konfiguration beginnt. Wenn in „x" mehr als eine Konfiguration „k" gefunden wird, dann wird die Stellung der zuerst gefundenen Konfiguration, wobei die Suche von links nach rechts vor sich geht, zurückgegeben. 2. Der zurückgegebene Wert ist die Dualzahl Null, wenn die gesuchte Konfiguration in der Kette „x" nicht auftritt oder wenn eines der beiden Argumente die Länge Null hat.
Die eingefügte Kettenfunktion LENGTH Definition: L E N G T H findet die Länge einer Kette „x". Aufruf: LENGTH(x) Argument: Das Argument „x" stellt eine Zeichen- oder Bitkette dar. Ist dieses Argument keine Kette, dann wird es vor dem Aufruf der Funktion in eine Zeichenkette konvertiert, wenn es das Attribut D E C I M A L trägt, oder in eine Bitkette, wenn es BINARY ist. Ergebnis: Der von der Funktion zurückgegebene Wert ist eine ganzzahlige duale Festpunktzahl mit Standardgenauigkeit, welche die gegenwärtige Länge von „x" angibt. Ist das Argument ein Bereichsausdruck, dann wird ein Bereich mit gleichen Grenzen zurückgegeben.
Die eingefügte Kettenfunktion LOW Definition: LOW arbeitet invers zur Funktion H I G H , wobei die Elemente der Kette in der Sortierfolge an letzter Stelle stehen. Aufruf: LOW(i) Argument: Das Argument „i" muß eine vorzeichenlose, ganzzahlige Dezimalkonstante sein.
A 4 Eingefügte Funktionen für die Kettenverarbeitung
283
Die eingefügte Kettenfunktion REPEAT Definition: R E P E A T verkettet eine Kette „x" so oft mit sich selbst, wie das Argument „i" angibt. Aufruf: REPEAT(x,i) Argumente: Das Argument „x" stellt eine Zeichen- oder Bitkette dar, aus der eine neue Kette geformt werden soll. Ist dieses Argument keine Kette, dann wird es vor dem Aufruf der Funktion in eine Bit- oder Zeichenkette konvertiert. Das Argument „i" muß eine ganzzahlige, dezimale Konstante sein und darf wahlweise ein Vorzeichen aufweisen. Wenn „x" ein Bereichsausdruck ist, dann wird „i" auf jedes Element angewendet. Ergebnis: Wenn „i" kleiner oder gleich Null ist, dann wird als Wert das Argument „x" zurückgegeben.
Die eingefügte Kettenfunktion STRING Definition: STRING verkettet alle Elemente einer Variablen in ein einziges Kettenelement. Aufruf: STRING(x) Argument: Das Argument „x" ist eine Element-, Struktur- oder Bereichsvariable, die entweder ganz aus Zeichenketten und/oder numerischen Daten oder ganz aus Bitketten besteht. Wenn „x" eine Elementvariable ist, dann ist der zurückgegebene Wert der gleiche wie der Wert der Variablen. Das Argument „x" darf kein Ausdruck sein, der Operationen enthält, „x" kann das Attribut A L I G N E D oder U N A L I G N E D haben; falls das Attribut ALIGNED gültig ist, sind Zwischenräume nicht im Ergebnis enthalten. Ergebnis: Als Wert wird die Verkettung aller Elemente von „x" zurückgegeben. Wenn in „x" eine oder mehrere Ketten variabler Länge vorkommen, dann ist das Ergebnis ebenfalls eine Kette variabler Länge. Das Ergebnis hat eine maximale Länge von 32767 Bytes.
Die eingefügte Kettenfunktion SUBSTR Definition: SUBSTR entnimmt eine Teilkette der Länge „j" aus einer Kette „x". Diese Funktion kann auch als Pseudovariable verwendet werden. Aufruf: SUBSTR(x,i[,j]) Argument: Wenn „x" keine Kette ist, dann wird dieses Argument in eine Kette konvertiert. Das Argument „i" stellt den Anfangspunkt der gesuchten Teil-
284
Anhang
kette dar. Die Argumente „i" und „j" müssen ganze Zahlen sein oder Ausdrücke, die in eine ganze Zahl konvertiert werden können. Wenn mehr als ein Argument ein Bereich ist, dann müssen die Bereiche gleiche Grenzen aufweisen. Angenommen, die Länge von „x" sei „k", dann müssen „i" und „j" folgenden Bedingungen genügen: 1. j muß kleiner oder gleich k, und größer oder gleich Null sein. 2. i muß kleiner oder gleich k, und größer oder gleich Eins sein. 3. Der Wert von i + j — 1 muß kleiner oder gleich k sein. Das bedeutet, daß die Teilkette, die durch i und j definiert ist, völlig innerhalb von „x" liegen muß. Wenn „j" nicht notiert wurde, dann unterstellt die Sprachsyntax j = k — i + 1. Wenn diese Bedingungen nicht erfüllt sind, dann bewirkt der Aufruf von SUBSTR das Setzen der Bedingung STRINGRAN G E , falls diese wirksam ist. Andernfalls ist das Ergebnis des fehlerhaften Aufrufs Undefiniert. Ergebnis: Der von dieser Funktion zurückgegebene Wert ist eine Kette variabler Länge, deren Ausdehnung sich folgendermaßen darstellt: 1. Wenn j = 0, dann ist der zurückgegebene Wert eine Nullkette. 2. Wenn j > 0, dann ist der zurückgegebene Wert die Teilkette, die beim i. Zeichen oder Bit des ersten Arguments beginnt und j Zeichen oder Bits lang ist. 3. Wenn j nicht notiert wurde, dann ist der zurückgegebene Wert die Teilkette, die beim i. Zeichen oder Bit beginnt und sich bis zum Ende von „x" erstreckt.
Die eingefügte Kettenfunktion TRANSLATE Definition: T R A N S L A T E gibt den übersetzten Wert einer Kette „s" zum Aufrufpunkt zurück. Der Übersetzungsprozeß wird entsprechend einer Übersetzungstabelle ausgeführt, die dieser Funktion in Form der beiden Argumente „r" und „p" mitgeteilt wird. Aufruf: TRANSLATE(s,r[,p]) Argumente: Die Argumente „r" und „p" stellen implizit die Übersetzungstabelle dar. Falls „p" nicht angegeben wurde, wird eine von der Implementierung gelieferte Zeichenkette eingesetzt; beim F-Kompilierer besteht diese Kette aus den 256 EBCDIC-Zeichen, die in aufsteigender Sortierfolge geordnet sind. Falls eine Datenkonvertierung bei den Argumenten notwendig ist, werden folgende Regeln beachtet: Sind alle Argumente Bitketten oder Zeichenketten, dann ist keine Konvertierung notwendig. Sind alle Argumente Dualziffern oder
A 4 E i n g e f ü g t e F u n k t i o n e n für die Kettenverarbeitung
285
bestehen nur aus einer Mischung von Bitketten und Dualziffern, dann werden nur die Dualziffern in Bitketten konvertiert. Andernfalls werden alle Argumente, die noch nicht Zeichenketten sind, in Zeichenketten konvertiert. Falls „r" kürzer als „p" ist, dann wird es rechts mit Zwischenraumzeichen oder Nullen entsprechend dem Kettentyp aufgefüllt, und zwar bis zur Länge von „p". Ergebnis: Der von dieser Funktion zurückgegebene Wert ist eine Kette, deren Länge dem Argument „s" entspricht. Ein Zeichen der Kette „s", das auch in „p" vorkommt, wird durch das entsprechende Zeichen der Kette „r" ersetzt. Beispiel: D C L (S,T) CHAR(10),(P,R) CHAR(3); P = \.K'; R = '-,D'; G E T DATA(S); T = TRANSLATE(S,R,P); PUT DATA(T); In der durch die GET-Anweisung eingegebenen Zeichenfolge werden entsprechend den beiden Zeichenketten „P" und „R" Kommata in Punkte, Punkte in Kommata und der Buchstabe K in D übersetzt.
Die eingefügte Kettenfunktion UNSPEC Definition: UNSPEC gibt in Form einer Bitkette die maschineninterne Form einer Variablen „x" an. Diese Funktion darf auch als Pseudovariable verwendet werden. Aufruf: UNSPEC(x) Argument: Es sind folgende Datenklassen zugelassen: arithmetische Konstante oder Kettenkonstante, Variable, Ausdrücke, Bereiche, Strukturen, Zeiger oder relative Zeiger. Ergebnis: Die Länge der Ergebniskette hängt von den Attributen von „x" ab und wird wie folgt definiert: 1.
2.
Wenn „x" BINARY FIXED mit der Genauigkeit (p,q) ist, dann wird Länge folgendermaßen bestimmt: a) Ist p < 16 und das Argument ist eine skalare Variable, dann ist Länge 16. b) Ist p < 16 und das Argument ist keine skalare Variable, dann ist Länge 32. c) Ist p > 15, dann ist die Länge 32. Wenn „x" D E C I M A L FIXED mit der Genauigkeit (p,q) ist, dann ist Länge als 8*FLOOR ((p+2)/2) definiert.
die die die
die
286
Anhang
3.
Wenn „x" FLOAT BINARY mit der Genauigkeit p ist, dann ist die Länge: a) 32, wenn p kleiner oder gleich 21 ist b) 64, wenn p größer ist als 21. Wenn „x" FLOAT DECIMAL mit der Genauigkeit p ist, dann ist die Länge: a) 32, wenn p kleiner oder gleich 6 ist b) 64, wenn p größer ist als 6. Wenn „x" eine Zeichenkette der Länge n ist oder ein numerischer Zeichenwert, deren Zeichenkettenwert die Länge n hat, dann beträgt die Länge 8*n. Wenn „x" eine Bitkette der Länge n ist, dann ist die Länge n. Wenn „x" komplex ist, dann ist die Länge zweimal so lang wie die Länge des entsprechenden Realteils. Wenn „x" ein Zeiger ist, dann ist die Länge 32. Wenn „x" ein relativer Zeiger ist, dann ist die Länge 32. Wenn „x" ein Gebiet der Größe n ist, dann ist die Länge 8*(n+16).
4.
5.
6. 7. 8. 9. 10.
Die eingefügte Kettenfunktion VERIFY Definition: VERIFY prüft zwei Ketten „x," und „x 2 ", ob jedes Zeichen oder Bit von „X]" auch in „x2" enthalten ist. Ist dies der Fall, dann wird der duale Festpunktwert Null zurückgegeben; andernfalls ist der zurückgegebene Wert die Stelle des ersten Zeichens der Kette „x,", das nicht in der zweiten Kette enthalten ist. Aufruf: VERIFY(x,,x 2 ) Argumente: Wenn beide Argumente Bitketten oder Zeichenketten sind, dann ist keine Datenkonvertierung notwendig. Wenn beide Argumente Dualzahlen sind, oder ein Argument eine Bitkette und das andere eine Dualzahl, dann werden nur die Dualziffern in Bitketten konvertiert. Andernfalls werden beide Argumente, falls sie nicht schon Zeichenketten sind, in Zeichenketten konvertiert. Ergebnis: Der von dieser Funktion zurückgegebene Wert ist eine ganze Dualzahl der Standardgenauigkeit (BIN FIXED(15)). Er wird wie folgt berechnet: Jedes Zeichen oder Bit „c" der Kette „Xj" wird daraufhin überprüft, ob es an irgendeiner Stelle der Kette „x2" erscheint, d.h. ob gilt: INDEX(x 2 ,c) - i = 0 Die Zeichen oder Bits der Kette „x 2 " werden von links nach rechts in dieser Weise überprüft. Wenn ein Zeichen oder Bit in der Verifikationskette „x 2 " nicht enthalten ist, dann wird die Position dieses Zeichens oder Bits zurückge-
A5 Eingefügte Bedingungsfunktionen
287
geben. Ist jedes Zeichen oder Bit der Kette „x^' in der Kette „x 2 " enthalten, dann ist der zurückgegebene Wert Null. Wenn Kette ,,X)" Null ist, dann wird auch der Wert Null zurückgegeben. Wenn Kette „x 2 " Null ist und Kette „Xj" nicht Null, dann bekommt diese Funktion den Wert Eins. Abschließend soll noch die Verwendung der wichtigsten Kettenfunktionen an einigen Beispielen demonstriert werden. Beispiel für Kettenfunktionsaufruf
Ergebnis
Bedeutung
BIT(123) CHAR(9876.5) INDEXCABRAHAM i I ALABAMA','AMA') LENGTH(123) R E P E AT(' A B C ' , + 3 ) S U B S T R C A B R A H A M ' 11 ' A L A B A M A ' ,3,6) TRANSLATE('ABACAD\ 'Z','A') UNSPEC('ZYX')
'000111101 l ' B 9876.5
Dualzahl
14 6 ABCABCABCABC
s. Tab. 3—3b
RAHAMA ZBZCZD '1110100111101000111 0011 l ' B
8 Bits = 1 EBCDIC Zeichen
A 5 Eingefügte Bedingungsfunktionen Diese Funktionen kann der Programmierer verwenden, um Programmunterbrechungen zu untersuchen. Keine dieser Funktionen benötigt Argumente. Jede eingefügte Bedingungsfunktion gibt ihren Wert nur dann zurück, wenn sie in einer „oneinheit" (s. Abschnitt 3.4.2.3) als Ergebnis einer Programmunterbrechung aufgerufen wurde. Damit das Programm zwischen Funktionsnamen und Variablennamen unterscheiden kann, muß der Programmierer entweder die Funktionsnamen als „BUILTIN" explizit vereinbaren oder den Funktionsnamen zusammen mit einer Nullargumentliste verwenden, z.B. IF O N C O D E () = ... (s. Programm „BEISP21").
288
Anhang
Die eingefügte Bedingungsfunktion O N C H A R Definition: Wenn die Bedingung CONVERSION gesetzt wurde (s. Anhang 1), kann O N C H A R verwendet werden, um das Zeichen zu entnehmen, das zum Setzen der CONVERSION-Bedingung geführt hat. Diese Funktion kann nur in einer ON-Einheit für die Bedingung CONVERSION verwendet werden oder in einer ON-Einheit für eine ERROR- oder FINISH-Bedingung, die als Standard-System-Maßnahme eine CONVERSION-Bedingung gesetzt hat. Diese Funktion darf der Programmierer auch als Pseudovariable verwenden. Aufruf: ONCHAR Ergebnis: Der von dieser Funktion zurückgegebene Wert ist eine Zeichenkette der Länge Eins, die das Zeichen enthält, das die CONVERSION-Bedingung gesetzt hat. Dieses Zeichen kann in einer ON-Einheit mit Hilfe der Pseudovariablen ONCHAR oder ONSOURCE verändert werden. Wenn ON CHAR außerhalb dieses Zusammenhangs verwendet wird, dann gibt diese Funktion ein Zwischenraumzeichen zurück. Die eingefügte Bedingungsfunktion O N C O D E Definition: ONCODE kann in jeder ON-Einheit verwendet werden, um den Unterbrechungstyp zu bestimmen, der die Aktivierung der ON-Einheit bewirkt. Aufruf: ONCODE Ergebnis: ONCODE gibt eine ganze Dualzahl mit Standardgenauigkeit zurück. Dieser „CODE" definiert den Unterbrechungstyp, der zum Eingang in die gerade aktive ON-Einheit führte. Wenn ONCODE außerhalb dieses Zusammenhangs verwendet wird, dann wird der Wert Null zurückgegeben. Die eingefügte Bedingungsfunktion O N C O U N T Definition: ONCOUNT kann in jeder ON-Einheit verwendet werden, die wegen abnormaler Beendigung eines E/A-Ereignisses ausgeführt wurde. Sie dient dazu, die Anzahl der Unterbrechungen (einschließlich der gerade laufenden) zu berechnen, die unbehandelt blieben, wenn eine Mehrfachunterbrechung das Ergebnis dieser abnormalen Beendigung war. Aufruf: ONCOUNT Ergebnis: ONCOUNT gibt eine Dualzahl mit Standardgenauigkeit zurück, mit der die Anzahl der Mehrfachunterbrechungen spezifiziert wird. Wenn ONCOUNT in irgendeinem anderen Fall verwendet wird, dann ist der zurückgegebene Wert Null.
A5 Eingefügte Bedingungsfunktionen
289
Die eingefügte Bedingungsfunktion ONFILE Definition: ONFILE ermittelt den Namen der Datei, für die eine E/A- oder CONVERSION-Bedingung gesetzt wurde. Diese Funktion kann in der ONEinheit für jede E/A- oder CONVERSION-Bedingung verwendet werden. Der Programmierer darf sie auch für eine E R R O R - oder FINISH-Bedingung benutzen, die als Standard-Systemmaßnahme als Folge einer E/A- oder CON VERSION-Bedingung gesetzt wurde. Aufruf: ONFILE Ergebnis: Der von dieser Funktion zurückgegebene Wert ist eine Zeichenkette variabler Länge (maximale Länge 31 Zeichen), die aus dem Namen der Datei besteht, für die eine E/A- oder CONVERSION-Bedingung auftrat. Im Fall einer CONVERSION-Bedingung ist der zurückgegebene Wert eine Nullkette, wenn dieser Umwandlungsfehler nicht im Zusammenhang mit einer Datei auftrat.
Die eingefügte Bedingungsfunktion ONKEY Definition: ONKEY liefert den Wert des Schlüssels des Satzes, der bewirkte, daß eine E/A-Bedingung auftrat. Diese Funktion kann in einer ON-Einheit für eine E/A- oder eine CONVERSION-Bedingung verwendet werden. Der Programmierer darf sie auch in einer ON-Einheit für eine E R R O R - oder FI NISH-Bedingung benutzen, die als Standard-Systemmaßnahme zu einer E/Aoder CONVERSION-Bedingung geführt hat. Aufruf: ONKEY Ergebnis: Der von dieser Funktion zurückgegebene Wert ist eine Zeichenkette variabler Länge, die den Schlüssel des Satzes enthält, der die E/A-Bedingung ausgelöst hat. Falls diese Unterbrechung nicht auf einen Schlüssel zurückzuführen ist, wird als Wert eine Nullkette zurückgegeben. Die eingefügte Bedingungsfunktion ONLOC Definition: Wenn eine ON-Bedingung auftrat, dann kann ONLOC in der betreffenden ON-Einheit verwendet werden, um den Eingangspunkt zu der Prozedur, die diese Bedingung auslöste, zu bestimmen. ONLOC darf in jeder ON-Einheit auftreten. Aufruf: ONLOC Ergebnis: Der von dieser Funktion zurückgegebene Wert ist eine Zeichenkette variabler Länge, die den Namen des Eingangspunktes der Prozedur enthält,
290
Anhang
in der die ON-Bedingung gesetzt wurde. Falls ONLOC außerhalb dieses Zusammenhangs auftritt, dann wird eine Nullkette zurückgegeben.
Die eingefügte Bedingungsfunktion ONSOURCE Definition: Wenn eine CONVERSION-Bedingung auftrat, dann kann die Funktion ONSOURCE verwendet werden, um den Inhalt des Feldes zu erhalten, das gerade bearbeitet wurde, als die Unterbrechung auftrat. Diese Funktion darf nur in einer ON-Einheit für die CONVERSION-Bedingung benutzt werden oder in einer ON-Einheit für eine ERROR- oder FINISH-Bedingung, die als Standard-Systemmaßnahme eine CONVERSION-Bedingung auslöste. Diese Funktion kann der Programmierer auch als Pseudovariable verwenden. Aufruf: ONSOURCE Ergebnis: Der von dieser Funktion zurückgegebene Wert ist eine Zeichenkette variabler Länge (maximale Länge 255 Zeichen), der den Inhalt des Feldes angibt, das beim Auftreten der CONVERSION-Bedingung gerade bearbeitet wurde. Diese Kette kann durch das Programm in der ON-Einheit mit Hilfe der Pseudovariablen ONCHAR und ONSOURCE verändert werden. Wenn diese Funktion außerhalb dieses Zusammenhangs auftritt, dann wird eine Nullkette zurückgegeben.
A 6 Pseudovariable [7] Folgende, in den Abschnitten 2 bis 5 des Anhangs beschriebene Funktionen können als Pseudovariable auftreten: 1. als Wertzuweisung arithmetischer Ausdrücke: COMPLEX, IM AG und RE AL; 2. als Kettenverarbeitungsfunktionen-. STRING, SUBSTR und UNSPEC; 3. als Bedingungsfunktionen: ONCHAR und ONSOURCE. Zu beachten ist bei der Verwendung von Pseudovariablen, daß sie nicht geschachtelt werden dürfen. Beispielsweise wäre folgende Anweisung ungültig: UNSPEC(SUBSTR(A,1,2)) = '00'B;
Lösungen der Übungsaufgaben Abschnitt 2.3 Keine gültigen Bezeichner sind:
291
Lösungen der Übungsaufgaben l.ZAEHLER RECHNUNG-1 PL/1_VARIABLE A,B,C
LINZER T O R T E
1. Z A E H L E R beginnt mit einem alphanumerischen Zeichen, das als erstes Zeichen eines Bezeichners nicht zugelassen ist. Der Bindestrich in R E C H NUNG—1 gehört nicht zur Klasse der alphanumerischen Zeichen und darf deshalb bei der Bildung eines Bezeichners nicht verwendet werden. Dasselbe gilt für das Zwischenraumzeichen in LINZER T O R T E . Auch der Schrägstrich von PL/1 und die Kommata des Beispiels 8 gehören nicht zur Klasse der alphanumerischen Zeichen. Das Prozentzeichen im Beispiel 9 ist nur dann zugelassen, wenn damit ein Arbeitsobjekt in einer Übersetzungszeitanweisung vereinbart werden soll (s. Abschnitt 1.3). Als interne Marken sind die beiden Zeichenketten: ANFANGS AN WEIS, und H A U P T P R O G R A M M nicht zugelassen. In beiden Fällen werden wieder Zeichen verwendet, die nicht der Klasse der alphanumerischen Zeichen angehören. Bei den externen Marken sind fehlerhafte Zeichenketten: l.PROC
HAUPTPR.
l . P R O C beginnt mit einem alphanumerischen Zeichen und widerspricht damit der Regel, daß jede Marke mit einem Buchstabenzeichen beginnen muß. Im letzten Beispiel wird auch wieder ein nicht gültiges Zeichen für eine Marke (der Punkt) verwendet. Abschnitt 2.4 1. Die durch das PICTURE-Attribut aufbereiteten Zeichenketten lauten: lfd. Nr. Ergebnis 1 2 3 4 5 6 7 8
01234 01234 123400 1234/00 0012.34 12.34 ****01 1
lfd. Nr. Ergebnis 9 10 11 12 13 14 15
01234 +bbb01234 $1.23 ,12345E10 ,12345b+10 + 123.00Eb03* 123.00E+02
* Der Exponent wird in der Weise durch das PICTURE-Attribut verändert, daß die erste signifikante Ziffer der Mantisse unter Berücksichtigung des Vorzeichens in der Stelle erscheint, in der das erste Ziffernabbildungszeichen in der Abbildungsspezifikation notiert wurde, auch wenn dieses Zeichen eine Nullenunterdrückung markiert.
292
Lösungen der Übungsaufgaben
2. DCL SPALTE(5) DEC FIXED(2,1); 3. DCL TABELLE(4,3) DEC FLOAT(4); DCL TAFEL(—2:2,0:3) CHAR(2); 4. DCL 1 Q l , 2 A CHAR(IO), 2 Bl, 3 C CHAR(20), 3 D CHAR(30), 2 B2, 3 C CHAR(20), 3 D CHAR(30), 1 Q2, 2 A CHAR(IO), 2 Bl, 3 C CHAR(20), 3 D CHAR(30), 2 B2, 3 C CHAR(20), 3 D CHAR(30); Eleganter ist folgende Lösung: DCL 1 Q l , 2 A CHAR(IO), 2 Bl, 3 C CHAR(20), 3 D CHAR(30), 2 B2, DCL 1 Q2 LIKE Q l ; 5. Diese Vereinbarung definiert einen fünfdimensionalen Bereich mit den oberen Grenzen: 1, 2, 3, 4, 5. Das Attribut der Datenelemente ist DEC FI XED(5,0). Abschnitt 3.1 1. 2. 3. 4. 5. 6. 7.
A + B ** 2 (A + B) ** 2 A + B/C (A + B) / C A + B / (C - D) (A + B) / (C - D) Y = A - B / (X ** 2 - C ** 2);
293
Lösungen der Übungsaufgaben
12 * (1 + X / 3 ) ) ;
8.
Y = 1 + X * (1 + X
9.
Y = (A / B -
1) / ( G * ( C / D - 1 ) * * 2 ) ;
10.
Y = A - 1
C**N;
11.
Y = A + (1 -
12.
Y = A * SIN(X) + COS(—B * X);
13.
Y = S Q R T ((1 + A * X * (1 + X * * 3 ) + B * * 4 ) / (1 + A * X ) ) ;
+
C * * N) * * M;
14.
Y = LOG (X + SQRT (X * * 2 -
15.
Y = A * X;
Y = ( Y * (16 * D -
Y * ( 1 2 * B + 10 * Y ) ) -
B ) * C O S ( X ) / (35 * A * * 4 16.
Y = A B S (1 -
17.
a) Y = A & - i B | - i A & B ;
18.
Y = (A > =
19.
LOES1: P R O C E D U R E
b) Y =
1)) + A * X * * 2 ;
D = B * * 2;
X * * 2 * S Q R T (1 + E X P ( X -
BOOL(A,B,'OHO'B); B) & (B > C) & (C >
0);
OPTIONS(MAIN);
D E C L A R E A F I X E D INITIAL(l), B F I X E D INITIAL(2), C FIXED
INITIAL(3),
D F I X E D INITIAL(4), X BIT(l); X = - A
+ B > =
PUT DATA (X); END LOES1; 20.
X =
'O'B
Y =
'O'B
Z =
'IB
a)
b)
c)
d)
X =
" 2 -2 -3 1 0 3 4 2 5
Y
=
15 18 _0
3 6 0
12 3 3
Z =
" 9 9 6
1 4 4
3 6 8
14" u = 11 21
32 * D ) * S Q R T ( Y
16 * D ) ;
(C
999.99
THEN DO; RABAT = BRUTTO *
RFAK;
NETTO = BRUTTO -
RABAT;
END; ELSE NETTO = BRUTTO; ABRUTTO
= ABRUTTO + BRUTTO;
ARABAT
= ARABAT
+ RABAT;
ANETTO
= ANETTO
+ NETTO;
RABAT
=
GET E D I T
0;
(KA,EKNR,EARTNR,EBEZ,EMEN, EPREI)
IF
EOF =
(R
(FOR));
' 1 1 B THEN LEAVE ;
DO WHILE
(KA-!=
GET E D I T
(KA,EKNR,EARTNR,EBEZ,EMEN, EPREI)
' 1'
& EOF =
(R
"O'B);
(FOR));
END; END; PUT E D I T
(AARTNR,ABEZ,AMEN,APREI, ABRUTTO,ARABAT,ANETTO) (COL
(13) ,A,X
(3) ,A, X (3) ,
P'Z.ZZZ.ZZ9 ,X
(3) ,
P1ZZ9V,99',COL
(68) ,
1
P ' ZZ . Z Z Z . Z Z 9 V , 9 9 ' , X P'ZZ.ZZ9V,99 ,COL I
P'ZZ.ZZZ.ZZ9V,99'); END; END; END L O E S 9 ;
(7) , (103),
Lösungen der Übungsaufgaben
305
LOES9 als Baumdiagramm dargestellt: Umsatzstatistik
Gruppen
Anfang
verarb. I ( T EOF)
Drucken
Lesen
Ueberschr.
l.LK
HAUPT SCHLEIFE
Untergruppenverarbeitunq
Drucken Kundennr.
KEKNR = AKNR) Untergruppe
Satzverarbeitung
Druckaufb. Artikelz.
Drucken Artikelz. I(EARTNR = AARTNR)
Satz
Anmerkung: gestellt.
2.
L 0 E S 1 0
Brutto.
Akku
N e t t o . Rab.
rauller.
Lesen n.LK
Die Fehlerroutine beim Lesen der Lochkarten wurde nicht dar-
P R O C E D U R E D C L
O P T I O N S
( M A I N ) ;
F I X E D
( 4 ) ,
J A H R ( 9 )
F I X E D
( 1 ) , ( 1 ) ,
K N R
Q U A R T A L ( 9 )
F I X E D
W E R T ( 9 )
F I X E D
( 6 , 2 ) , ( 1 ) ,
K A
C H A R
A C C U ( 4 , 3 , 6 )
F I X E D
K L T A B ( 6 )
F I X E D
I N I T
( 6 , 2 )
I N I T
( ( 7 2 ) 0 ) ,
( 7 , 2 )
( 1 0 , 1 0 0 , 5 0 0 , 1 0 0 0 , 5 0 0 0 , 1 0 0 0 0 ) ,
Q
F I X E D
B I N ,
S U M M E
F I X E D
(6)
I N I T
( 0 ) ,
B I T
(1)
I N I T
C O ' B ) ;
E O F O N
E N D F I L E
DO
W H I L E G E T
( S Y S I N ) ( E O F
E D I T
=
E O F
=
' 1 ' B ;
' O ' B ) ;
( K N R , ( J A H R
( K ) , Q U A R T A L
( K ) ,
Lösungen der Übungsaufgaben WERT (K) (F
DO K = 1 TO 9 ) , K A )
( 4 ) ,9
(2 F
X ( 3 ) ,A
( 1 ) ,F
(6,2)) ,
(1)) ;
I F EOF = ' 1 ' B THEN LEAVE; DO
WHILE
(KA
'5'
GET EDIT
(KNR,
& EOF =
(JAHR
WERT (K) (F
'O'B);
(K),QUARTAL
DO K = 1 TO
( 4 ) ,9
(2 F
X ( 3 ) ,A
(1),F
(K),
9),KA)
(6,2)) ,
(1) ) ;
END; I F EOF = ' 1 ' B THEN LEAVE; K = 1 ; DO
UNTIL
(K = 9
I F JAHR (K)
| QUARTAL
(K)
= 0);
= 0 THEN IND = 3; ELSE IND = JAHR "
(K)
7;
DO KL = 1 TO 6; I F WERT (K) ACCU
< KLTAB
(KL)
THEN
(QUARTAL
(K),IND,KL)
=
ACCU (QUARTAL
(K),IND,KL)
+ 1;
END; K
= K + 1
END; END; / * AUSDRUCKEN DER ERGEBNISSE
*/
DO Q = 1 TO 4,DO J = 1 TO 3; SUMME = O; DO K = 1 TO 6; SUMME = SUMME + ACCU
(Q,J,K);
END; DO K = 1 TO 6; I F SUMME*|=
0 THEN ACCU ( Q , J , K ) (ACCU
END; END; END;
(Q,J,K)
= * 100)
/ SUMME
Lösungen der Übungsaufgaben
DO J
307
= 1 TO
3;
PUT S K I P
(3)
PUT S K I P
LIST
LIST
(J
+
1967);
('KLEINER(DM)','QUARTAL
•QUARTAL 2 ' ,
'QUARTAL
1',
3',
'QUARTAL 4 ' ) ; DO K = 1 TO
6;
PUT S K I P L I S T
(KLTAB(K),(ACCU(Q,J,K)
DO Q = 1
TO 4 ) ) ; END; END; END 3.
LOES11
:
L0ES10;
PROCEDURE OPTIONS DCL L I S T E
(0
INIT
:
(MAIN);
15)
CHAR
( 0 , 1 , ,
,
,
'8','9
,
1
I
2
I
(1)
, ' 3 , • 4 , , , 5 , , , 6 ,
(2,5)
FIXED
(2),
ERGEB_2
(2,5)
CHAR
(1),
FIXED
(2),
A B
FIXED
(7,5),
G
FIXED
(4),
(K,K1)
FIXED
(5,1);
= 1 TO 1 0 0 0 BY
149.1;
DO K1 = K TO K + 2 BY G
= FLOOR
B
= K1 -
,
0.4;
(K1); G;
DO L = 5 TO 1 BY ERGEB_1
(1,L)
G
-1; = MOD
(G,16);
= G/16;
END; DO M = 1 TO
5;
B
= B *
ERGEB_1 IF
(2,M)
ERGEB_1
16;
= FLOOR
(2,M)
= 0
(B); THEN; ELSE B = (B -
ERGEB_1
(2,M)); END;
I
,'A','B','C','D','E*,'F
ERGEB_1
DO K
I
7 , , 1
),
Lösungen der Übungsaufgaben DO I = 1 TO 2 ; DO Y = 1 TO 5; ERGEB_2 (I,Y) = LISTE (ERGEB_1 (I,Y)); END; END; PUT SKIP EDIT (K1,'=',(ERGEB_2 (1,L) DO L = 1 TO 5),'.1,(ERGEB_2 (2,M) DO M = 1 TO 5)) (X (20),F (6,1),A,5 A,A,5 A) END; END; END L0ES11 ;
Abschnitt 3.4.2.5 L0ES12
:
PROCEDURE OPTIONS(MAIN); DCL KARTE FILE RECORD INPUT, LISTE FILE RECORD OUTPUT ENV (F (115) CTLASA); 2 EKA CHAR (1) , DCL 1 ESATZ, 2 EKNR CHAR (5) , 2 EARTNR CHAR (6) , 2 EBEZ CHAR (20) , 2 EBLNK1 CHAR (10) , 2 EMEN PIC •99999' 2 EPREI PIC '999V99 2 EBLNK2 CHAR (28) ; ASATZ, 2 AASA CHAR (1) , 2 ABLNK1 CHAR (2) , 2 AKNR CHAR (5) , 2 ABLNK2 CHAR (3) , 2 AARTNR CHAR (6) , 2 ABLNK3 CHAR (3) , CHAR (20) , 2 ABEZ 2 ABLNK 4 CHAR (3) , 2 AMEN PIC • z , z z z .
Lösungen der Übungsaufgaben
309
2 ABLNK5
CHAR (3) ,
2 APREI
PIC
2 ABLNK6
CHAR (6) ,
2 ABRUTTO
PIC
2 ABLNK7
CHAR (7) ,
2 ARABAT
PIC
2 ABLNK8
CHAR (6) ,
2 ANETTO
PIC
'ZZ9V,99 1t 'ZZ.ZZZ. ZZ9V, 99 ' , 'ZZ.ZZ9V ,99' , •ZZ.ZZZ .ZZ9V, 99 ' ;
DCL EOF BIT (1)
INIT ('O'B); DCL LEERSATZ CHAR (115) DEFINED ASATZ 1 . LEERSATZ = ' DCL ZWI__KNR
ON
CHAR (5) ,
BRUTTO
FIXED (10,2) INIT (0) ,
NETTO
FIXED (10,2) INIT (0) ,
RABAT
FIXED (9,2)
INIT (0) ,
RFAK
FIXED (3,2)
INIT (0.03)
ENDFILE (KARTE) EOF = ' 1'B; LEERSATZ = '1K U N D E N-S WRITE FILE (LISTE) FROM LEERSATZ = '
T A T I S T I K ' ;
(ASATZ);
' ;
OPEN FILE (KARTE); RE^D FILE (KARTE) INTO (ESATZ); DO WHILE
(EKAT|= '1' & EOF = 'O'B);
READ FILE (KARTE) INTO (ESATZ); END; DO WHILE
(EOF = 'O'B);
ZWI_KNR,AKNR = EKNR; AASA = DO WHILE (EKNR = ZWI_KNR & EOF = 'O'B); AMEN,ABRUTTO,ARABAT,ANETTO = O; AARTNR = EARTNR; ABEZ
= EBEZ;
APREI
= EPREI;
DO WHILE (EARTNR = AARTNR & EKNR = ZWI_KNR & EOF = 'O'B); AMEN
= AMEN + EMEN;
BRUTTO = EMEN * EPREI; IF BRUTTO > 999.99 THEN DO;
Lösungen der Übungsaufgaben
310
RABAT
= BRUTTO
*
RFAK;
NETTO
= BRUTTO
-
RABAT;
END; ELSE NETTO
= BRUTTO;
ABRUTTO = ABRUTTO + BRUTTO; ARABAT
= ARABAT
+ RABAT;
ANETTO
= ANETTO
+ NETTO;
RABAT
= 0;
READ F I L E DO WHILE
(KARTE) (EKA
INTO
=
'1'
(ESATZ); & EOF =
' 0 'B) ; READ F I L E
(KARTE)
INTO
(ESATZ); END; END; WRITE F I L E
(LISTE)
AASA,AKNR =
FROM
(ASATZ);
';
1
END; END; END LOES12; Abschnitt 1.
3.5.2 WI
(S1,S2,W);
: PROCEDURE RETURN
ECOS : ENTRY RETURN
(ASIN
(SIN
(ACOS
: PROCEDURE RETURN
*
S1/S2));
(S1,S2,S3); ((S2
**
2 + S3 * *
S1
**
2)
(2 ASIN
(W)
2-
/
* S2 * S 3 ) ) ) ;
(X);
(ATAN
(X/SQRT
(1 -
X **
2)));
END; ACOS
: PROCEDURE RETURN
(X);
(ATAN
(SQRT
(1 -
X **
END; END W I ; Beispiel
fur Funktionsaufruf : A_WI
:
PROCEDURE
OPTIONS(MAIN);
2)
/
X));
Lösungen der Ü b u n g s a u f g a b e n
S1,S2,W PUT L I S T
PUT S K I P 2.
HALB
:
(WI
51
=
2;
52
=
4;
53
=
(S1,S2,S3));
(ZZ,A); BIT
(ZZ,J,I) (Y,X) =
3;
(ECOS
DCL A ( 4 )
1
1;
(S1,S2,W));
LIST
PROCEDURE
=
(1),
DEC F I X E D
(1),
DEC F I X E D
(2,1 ) ;
4;
Z =
ZZ;
DO U N T I L X = J
(J
=
0);
Z/2.0;
= X;
Y = X IF
J;
Y = 0 THEN A
(I)
=
'O'B
ELSE A
(I)
=
'1'B
1 = 1 - 1 ; Z =
J;
END; IF IF
Z = O THEN A
(I)
=
'O'B;
ELSE A
(I)
=
'1'B;
I
DO J
= 1 THEN = I A
-
RETURN;
1 TO 1 BY -
(J)
=
1;
'O'B;
END; END HALB; L0ES13
:
PROCEDURE DCL
(A
OPTIONS(MAIN);
(4),B
(K,M,I) K =
(4),S
(4),C,D,E,F)
DEC F I X E D
(1);
1;
DO M = 8 TO O BY
-2;
CALL HALB
(K,A);
CALL HALB
(M,B);
E =
'O'B;
DO I
= 4 TO 1 BY
-1;
BIT
(1),
312
Lösungen der Übungsaufgaben D = A (I)
SB
C = (A ( I )
(I) ;
| B (I))
& "ID;
F = C & E; S (I)
= (C | E) & - I F ;
E = F
| D;
END; PUT EDIT ( K , * + ' , M , ' = ' , S )
(SKIP
(2),
F (1) ,X (3) ,A,X
(3) , F
X (3) , A, X (3) , 4
(X (2) ,
B
(1) ,
(1)));
K = K + 1; END; END L 0 E S 1 3 ; D i e B e d e u t u n g d e r V a r i a b l e n A , B , C , D , E u n d F g e h t a u s dem Blockschaltbild
des e i n s t e l l i g e n
dualen
Addierwerks
hervor:
3.MAMU
:
PROCEDURE
(A,B,C);
DCL (A ( * , * ) ,B FIXED
(*,*),C
(*,*))
(10);
DO I = 1 TO HBOUND
(A,1);
DO J = 1 TO HBOUND
(B,2);
C (I,J)
= O;
DO K = 1 TO HBOUND C (I,J)
(A,2);
= A (I,K) C
(I,J);
* B (K,J)
+
Lösungen der Übungsaufgaben
313 END;
END; END; END M A M U ; Dieses U n t e r p r o g r a m m w i r d in der Prozedur "BEISP11" rufen, so daß d o r t an die Stelle der tion der U n t e r p r o g r a m m a u f r u f BEISP11
:
aufge-
Matrizenmultiplika-
tritt:
PROCEDURE
OPTIONS(MAIN);
DCL MATRA
(2,3) FIXED CALL INIT
MATRB
(10)
(3,2) F I X E D ((2)8,
MATRC
INITIAL
(MATRA),
(2)
(10)
INITIAL
112233,1,2),
(2,2) F I X E D
(10)
INITIAL
((4)0) ; PUT DATA
(MATRA,MATRB,MATRC);
PUT PAGE; CALL M A M U PUT DATA
(MATRA,MATRB,MATRC); (MATRC);
END BEISP11 ; Abschnitt
3.5.3
1. B E I S P 1 _ S T R U K T U R I E R T _ A U F R U F DECLARE
: PROCEDURE OPTIONS
(Z1,Z2,Z3) DECIMAL F I X E D EOF
BIT
ON ENDFILE(SYSIN) GET D A T A DO W H I L E
CO'B);
E O F = ' 1'B;
(Z1,Z2);
(EOF =
Z3 = K1
(1) INIT
(MAIN);
(10),
'O'B);
(Z1 ,Z2);
PUT D A T A
(Z3);
GET D A T A
( Z1 , Z 2 ) ;
END; K1
:
PROCEDURE DCL
(Z1,Z2) R E T U R N S
(DEC F I X E D
(Z1,Z2,A,B,C) DO W H I L E
DEC F I X E D
(Z1 " 1 = Z2) ;
DO W H I L E
(Z1 < Z2);
B = Z1 ; A = Z2;
(10)); (10);
Lösungen der Übungsaufgaben
314 C =
A-B;
Z1 =
C;
Z2 =
B;
END; DO WHILE
(Z1
> Z2) ;
A = Z1; B =
Z2;
C =
A-B;
Z1 =
C;
Z2 =
B;
END; END; RETURN
(Z1);
END K1 ; K2
:
PROCEDURE
(Z1,Z2)
RETURNS
(DEC F I X E D
(10))
RECURSIVE; DCL
(Z1,Z2,C)
DEC F I X E D
IF
Z1 > Z2 THEN RETURN
(K2
IF
Z1 =
(Z1);
C =
Z2 THEN RETURN Z2 -
RETURN
(10);
(Z2,Z1));
Z1 ;
(K2
(C , Z 1 ) ) ;
END K 2 ; END
BEISP1_STRUKTURIERT_AUFRUF;
2.L0ES14
:
PROCEDURE OPTIONS /*
(MAIN);
B E I S P 1 5 ALS RECURSIVES
DCL KARTE F I L E
PROGRAMM
RECORD INPUT
*/
ENV
(CONSECUTIVE), LISTE FILE
RECORD OUTPUT ENV
(CONSECUTIVE F /*
(117)
ON ENDFILE
(KARTE)
EOF =
OPEN F I L E
(KARTE),
FILE
(LISTE);
READ F I L E
(KARTE)
CALL HAUPTSL; HAUPTSL
:
CTLASA);
VEREINBARUNGSTEIL WIE IN B E I S P 1 5
PROC
RECURSIVE; LNAM = ENAM;
INTO
*/
'1'B;
(EGB_KARTE);
Lösungen der Übungsaufgaben
315
LORT = EORT; LSTR = ESTR; LKTN = EKTN; LSLD = LSLD + EBTR; NACC = ' - ' ; LKON = 'KONTO-NR.1; LSAL = '
SALDO = DM" ;
DO WHILE ('1'B); READ FILE (KARTE) INTO (EGB_KARTE); IF EOF = '1'B THEN RETURN; IF EKTNT = LKTN THEN LEAVE; LSLD = LSLD + EBTR; END; RNAM RORT RSTR RKTN
= = = =
ENAM; EORT; ESTR; EKTN;
RSLD = RSLD + EBTR; RKON = 'KONTO-NR.'; RSAL = ' SALDO = DM' ; DO WHILE ('1*B); READ FILE (KARTE) INTO (EGB_KARTE); IF EOF = '1'B THEN RETURN; IF EKTN"I= RKTN THEN LEAVE; RSLD = RSLD + EBTR; END; WRITE FIIE (LISTE) FROM (NAM_ZEILE); WRITE FILE (LISTE) FROM (ORT_ZEILE); WRITE FILE (LISTE) FROM (STR_ZEILE); WRITE FILE (LISTE) FROM (KTN_ZEILE); NAM_LEER,ORT_LEER,STR_LEER,KTN_LEER _ i i . CALL HAUPTSL; END; WRITE FILE (LISTE) FROM (NAM_ZEILE); WRITE FILE (LISTE) FROM (ORT_ZEILE); WRITE FILE (LISTE) FROM (STR_ZEILE); WRITE FILE (LISTE) FROM (KTN ZEILE);
316
Lösungen der Übungsaufgaben CLOSE FILE (KARTE), FILE (LISTE) ; END LOES14;
3. LOES15
:
FORM
:
PROCEDURE OPTIONS(MAIN); DCL (M,N) DEC FIXED ( 3 ) ; GET LIST (M,N); BEGIN; DCL (MAT1 (M,N),MAT2 (N,M)) DEC FIXED ( 5 ) ; GET LIST (MAT1); DO I = 1 TO M; PUT EDIT ( (MAT1 ( I , J ) DO J = 1 TO N) ) (R (FORM)); END; FORMAT (SKIP ( 2 ) , ( 9 ) (F (5),X ( 3 ) ) ) ; DO I = 1 TO M; DO J = 1 TO N; MAT2 ( J , I ) = MAT1 ( I , J ) ; END; END; DO I = 1 TO N; PUT EDIT ((MAT2 ( I , J ) DO J = 1 TO M)) (R (FORM)); END; END; END LOES15;
4. 1. Die Variable „TEXT" wurde nicht initialisiert, ein Fehler der häufig gemacht wird. Er kann beseitigt werden, indem bei der Vereinbarung dieser Variablen das Attribut INIT zusammen mit dem Ausgangswert vergeben wird oder eine Wertzuweisung zu dieser Variablen vor dem Aufruf der Prozedur „DRUCKROUTINE" erfolgt. 2. In der Prozedur DRUCKROUTINE muß die Variable UEBER SCHRIFT das Attribut STATIC bekommen; denn nach dem Verlassen dieser Prozedur werden im allgemeinen sämtliche Speicherkapazitäten freigegeben und damit auch die Werte von „UEBERSCHRIFT". Über den sekundären Eingangspunkt „EINGANG" werden sie aber von der Prozedur „VERARBEITUNG" noch zehn mal aufgerufen.
Lösungen der Übungsaufgaben
317
Abschnitt 4.2.3 L0ES16
:
PROCEDURE OPTIONS(MAIN); DCL 1 STAMMSATZ, 2 NR 2 NAME 2 SALDO KARTENSATZ, 2 KNR 2 BELEGNUMMER 2 DATUM 2 BEWEGUNG 2 TEXT 2 KA
CHAR (6) , CHAR (56) , PIC 'S999999V99 CHAR (6) , CHAR (4) , CHAR (6) , PIC 'S9999V99', CHAR (56) , CHAR (1) ; ENV (REGIONAL(2)),
DCL STAMMDA FILE KEYED
KARTE FILE RECORD INPUT; DCL ENDFILE_BEDINGUNG_KARTE BIT(1) INIT ( 1 0'B); DCL REGION CHAR (8), SCHLUESSEL * CHAR (14), /* FUER NR || REGION */ ONBED BIN FIXED (15); ON ENDFILE (KARTE) ENDFILE_BEDINGUNG_KARTE = ' 1 ' B; ON KEY (STAMMDA) BEGIN; ONBED = ONCODE (); IF ONBED = 51 THEN DO; IF KA =' B' THEN CALL SCHREIBEN; ELSE PUT SKIP LIST (KNR,'IN DATEI NICHT GEFUNDEN'); END; ELSE PUT SKIP LIST (KNR,'LOESTE ONBEDINGUNG1,ONBED,'AUS'); END; OPEN FILE (KARTE), FILE (STAMMDA) DIRECT UPDATE; READ FILE (KARTE) INTO (KARTENSATZ);
318
Lösungen der Übungsaufgaben DO WHILE (ENDFILE_BEDINGUNG_KARTE = 'O'B); REGION
= MOD
(KNR,5987);
SCHLUESSEL = KNR || REGION; ONBED
= O; SELECT (KA);
WHEN C A ' ) CALL BUCHUNG ; WHEN ('B1)CALL NEU; WHEN C C ) CALL LOESCH ; OTHERWISE PUT SKIP LIST (KNR,'FALSCHE KARTENART'); END; READ FILE (KARTE) INTO
(KARTENSATZ);
END; BUCHUNG
:
PROCEDURE; READ FILE (STAMMDA) INTO (STAMMSATZ) KEY
(SCHLUESSEL);
IF ONBED = 0 THEN DO; SALDO = SALDO + BEWEGUNG; REWRITE FILE (STAMMDA) FROM (STAMMSATZ) KEY PUT SKIP LIST
(SCHLUESSEL); ('BUCHUNG=',NR, 'NEUER SALDO=',SALDO, 'BEWEGUNG=',BEWEGUNG); END;
END BUCHUNG; NEU
:
PROCEDURE; READ FILE (STAMMDA) INTO (STAMMSATZ) KEY
(SCHLUESSEL);
IF ONBED = O THEN PUT SKIP LIST
(KNR,'NEUZUGEGANGENER
SATZ IN DATEI SCHON VORHANDEN'); /* ONCODE 51 MUSS BEI NEUZUGANG ANSPRECHEN */ END NEU; SCHREIBEN
:
PROCEDURE; NR
= KNR;
NAME
= TEXT;
SALDO
= BEWEGUNG;
WRITE FILE (STAMMDA) FROM (STAMMSATZ)
Lösungen der Übungsaufgaben
319 KEYFROM
PUT S K I P
LIST
(SCHLUESSEL); ('NEUZUGANG =
1
,KNR);
END SCHREIBEN; LOESCH
:
PROCEDURE; DELETE F I L E PUT S K I P
(STAMMDA)
LIST
END LOESCH; CLOSE F I L E FILE END L O E S 1 6 ;
KEY
(KNR,'WURDE
(KARTE), (STAMMDA);
(SCHLUESSEL); GELOESCHT');
Literaturverzeichnis
la] American National Standards Institute, New York: ANSI X3.53-1976 1] Backus, J.W.: The syntax and semantics of the proposed international algebraic language of the Zurich A C M - G A M M Conference. In: Proceedings of the International Conference on Information Processing. Paris 1 5 - 2 0 June 1959, München 1960 2] Bates, F., M.L. Douglas, u. R. Gritsch: PL/1, Einführung in die Programmiersprache für den Selbstunterricht. 2. Aufl., von Rüdiger Gritsch überarb. u. erw., München 1970 3] Berndt, H. u. H. Spreen: Ein PL/l-Dialekt zur Beschreibung funktioneller Eigenschaften von Datenverarbeitungssystemen. In: elektronische datenverarbeitung 12 (1970) 3a] Dijkstra, E.W.: G o To Statement Considered Harmful. In: Communications of the A C M (Letters to the Editor) 11 (1968) 4] D N A , Deutscher Normenausschuß, Fachnormenausschuß Informationsverarbeitung (FNI): DIN 44300, Informationsverarbeitung, Begriffe. Berlin 1972 5] — : D I N 66001, Informationsverarbeitung, Sinnbilder für Datenfluß- und Programmabläufe. Berlin 1977 5a] - : DIN 66255, Informationsverarbeitung, Programmiersprache PL/1. Berlin 1980. 6] E C M A , European Computer Manufacturers Association, ANSI, American National Standards Institute: PL/1, E C M A T C 10/ANSI.X3J1 PL/1 Basis/1, June 1973 6a] Elshoff, J.L. : The Influence of Structured Programming on PL/1 Program Profiles. In: I E E E Transactions on Software Engineering Vol. S E - 3 , NO. 5 (1977), S. 364 ff. 6b] Hantier, S.L., J.C. King: An Introduction to Proving the Correctness of Programs. In: Computing Surveys, Vol. 8, No. 3 (1976), S. 339 7] IBM System-Literatur: PL/l-Handbuch (Teil I), IBM Betriebs-System /360, Sachcode 29, Vorabdruck, Übersetzung der Broschüre „IBM System /360 Operating System PL/ 1(F) Language Reference Manual", IBM Form C 2 8 - 8 2 0 1 - 2 , hrsg. von der International Business Machines Corporation. U S A 1970. 8] ISO, International Organization for Standardization: Programming Languages, ISO/ TC 97/SC5 (ECMA—21) 258, PL/1, February 1972 8a] Jackson, M . A . : Principles of Program-Design. London, New York, San Francisco 1975, S. 18 ff. 9] Lee, R.M.: Basic Fortran IV. Eine Einführung in die Programmierung, Stuttgart o.J. Originalausgabe: A Short Course in Fortran IV Programming. New York 1967 9a] Maurer, H . : Datenstrukturen und Programmierverfahren. Stuttgart 1974, S. 106 10] Noltemeier, H.: Datenstrukturen und höhere Programmiertechniken. Berlin, New York 1972 [10a] Rechenberg, P.: Programmieren für Informatiker mit PL/1, Band 2. München, Wien 1974, S. 68 11] Sammet, J . E . : Programming Languages. History and Fundamentals. Englewood Cliffs. N.J. 1969
322
Literaturverzeichnis
[ 12] Schulz, A . : Informatik für Anwender. Berlin, New York 1973 [ 13] Schulz, A.: Höhere PL/l-Programmierung. Berlin, New York 1976. [13a] Schulz, A.: Der Einfluß von Strukturierungsmethoden der Anwendungsprogrammierung auf die Durchlaufzeit von Programmen. In: Informatik-Fachberichte Nr. 50, Berlin, Heidelberg, New York 1981, S. 160 ff. [13b] Shneiderman, B.: Software Psychology, Human Factors in Computer and Information Systems. Cambridge Massachusetts, 1980, S. 78 [13c] Schulz, A . : Methoden des Softwareentwurfs und Strukturierte Programmierung. Berlin, New York 1982, 2. Auflage [ 14] Wedekind, H . : Datenorganisation. Berlin 1970 [ 15] Wirth, N.: Systematisches Programmieren. Stuttgart 1972 [ 16] Zemanek, H.: Philosophie und Programmierung. In: E und M, Elektrotechnik und Maschinenbau 84 (1967), S. 420
Sach- und Personenregister
Abbildungsketten variable 42, 126 Abbildungskettenvereinbarung 43 Abbildungsspezifikation 43 - , numerische 43, 44, 45, 124, 159 Abbildungszeichen 42, 43, 44, 45, 126, 159 Ablaufstruktur 99, 161, 171, 237 Addition 13,35,61,77 Adresse 210 - , absolute 223 Adressierung - , direkte 26, 216, 217, 222, 223, 225, 226 - , indirekte 26, 217, 218, 219, 222, 224, 225, 227, 245 Adreßindex 211, 245, 246, 249, 250, 251 Adreßkette 218 Änderungsfreundlichkeit 242 Äquivalenz 71 Aktualparameter 166, 167 ALGOL 15, 16, 23, 28, 62, 113, 161, 177 Algorithmus rekursiver 178 ALLOCATE 182 Alphabet 27 Anfangswert 38, 42, 51, 52, 53, 65, 68, 103 ANSI 24,25,30 Antivalenz 70 Anweisung 11,12,13,16,17,20,22,25,29, 31, 33, 34, 35, 36, 38, 41, 55, 56, 60, 70, 77, 86, 89, 113, 161, 162, 174, 184 - , arithmetische 16,17,61,65,68,77 - , ausführbare 34,36,93,98 - , boolesche 32 - , vollständige 13 Anweisungsklasse 33 Anwender 23, 24, 52, 63, 82, 118, 255 - , betriebswirtschaftlich orientierter 114 Arbeitsobjekt 12, 13, 15, 16, 17, 20, 25, 29, 33, 35, 36, 37, 39, 40, 41, 49, 50, 51, 72, 98, 114, 180, 181 -.arithmetisches 32,48,72 boolesches 13,69 - , externes 114 - , internes 114 mehrdimensionales 17, 25, 107 - , nichtskalares 51 - , skalares 17,41, 51,60, 61, 73,75,77,84, 107,119 Arbeitsprozeß 12, 145
- , informationeller 11, 12, 59, 88, 106 Arbeitsvorschrift 11, 12, 13, 29, 86 Argument 65, 69, 166, 168, 170 ASA-Steuerzeichen 159, 208 ASCII-Code 197 Assemblierer 12 Attribut 13, 32, 36, 38, 39, 40, 41, 47, 55, 56, 63, 74, 167, 173, 176, 181, 187, 188, 195 - , alternatives 138, 139 - , arithmetisches 46,50 - , ergänzendes 138, 139, 154 Aufruf 165, 166, 173, 174 Auftrags- und Definitionsphase 200 Ausdruck 59, 60, 166 - , arithmetischer 17, 42, 53, 60, 63, 64, 65, 68, 119 —, boolescher 60,68,69 Ausgabe 68, 113, 118, 121, 123, 125, 126, 127, 128, 130, 131, 132 Ausgabeanweisung 17, 113, 114, 118, 119 Ausgabedatei 195, 198, 211 Ausgabeeinheit 11 Ausgabewerk 11 AUTOMATIC 181 Backus 27 Backus Normalform 28 Backus Notation 30 BACKWARDS 197, 198 BASED 182 Basis der Zahlendarstellung 47 Basisvariable 198 Baum 40, 51, 148 Baumdiagramm 201 Bedingungscode 232, 233, 235, 253 Bedingungspräfix 34, 35, 59, 131, 162 Befehl 11, 12, 88 Befehlswort 12 BEGIN-Block 15, 143, 163, 164, 165, 182, 183, 184, 235 Beginnanweisung 163 Begrenzungszeichen 38, 46, 47 Benutzer 11 Benutzerfreundlichkeit 36 Bereich 51, 52,53,54, 55,57,75,77,78, 84, 103, 107, 137, 147, 164, 187 - , mehrdimensionaler 55
324
Sach- u n d Personenregister
Bereichsanweisung 76 - , ausführbare 75 Bereichsausdruck 75, 77, 120, 183 - , arithmetischer 6 0 , 7 5 , 7 6 — .boolescher 6 8 , 7 5 , 7 7 Bereichsfunktion 78 Bereichsgrenze 52, 53 Bereichsoperand 78 Bereichsvariable 59, 107, 120, 136, 137 Bereichsverarbeitung 68, 77, 85 Bereichsvereinbarung 5 1 , 5 2 Bereichswiederholungsfaktor 53 Betriebssystem 15, 26, 141, 155, 163, 196,
COBOL 23,24,25,30 Code 30,84 Codierphase 200 C O L U M N 119, 126, 127 C O M P L E X 48 Computerentwurfssprache 85 C O N S E C U T I V E 154, 197, 212, 222 C O N T R O L L E D 181 C O N V E R S I O N 125 CONVERSION-Bedingung 110, 125 C O P Y 67, 68, 132 CTLASA 208
197, 198, 208, 222, 224 Bewegungsdatei 192, 194, 201 Bewegungsdaten 191,198,210 Bewegungssatz 192, 193, 194 Bezeichner 16, 2 9 , 3 2 , 3 6 , 3 9 , 4 0 , 4 1 , 4 7 , 4 8 , 51, 53, 54, 55, 56, 59, 137, 138, 158, 166, 185, 187, 209 — .indizierter 75,137 Bezeichnerteil 42 Binärzeichen 28, 29, 41, 53, 72, 108 B I N A R Y 47 Bit 30,41, 108 Bitkette 41, 47, 68, 69, 71, 72, 73, 81, 83, 84, 85, 88, 100, 108, 109, 110, 112, 124, 125 Bitkettenausdruck 68 Bitkettenbereich 78, 85 Bitkettenoperation 68 Blank 43,45 BLKSIZE 197 Block 15, 25, 136, 163, 164, 174, 180, 182, 183, 184, 185, 187 —, externer 182 —, interner 182 Blocken 196 Blockgröße 222 Blocklänge 196, 197 Blockstruktur 15, 25, 166, 180, 182 Blockung 197,210 B O O L 69
Datei 16, 17, 23, 26, 36, 51, 53, 114, 115, 137, 138, 139, 141, 142, 191, 193, 194, 197, 198, 208, 209, 210, 214, 218, 219, 223, 224, 226, 228, 249 - , indexsequentielle 222, 245, 246, 249, 250, 251, 253 -.regionale 227,244,245,253 Dateianweisung 211 Dateiattribut 138, 139, 140, 141, 142, 154, 222,231,244 Dateibeschreibung 191 Dateibeschreibungsattribut 114 Dateibezeichner 141,181,186,188, 232,237 Dateiende 147,201 Dateieröffnung 140, 141 - , explizite 140 - , implizite 139 Dateierstellung 230, 232 - , sequentielle 243 Dateiname 119, 137, 138, 166 Dateiorganisation 139, 154, 191, 211, 212 - , indexsequentielle 245,246,247,248,249 - , regionale 250 - , sequentielle 243 Dateisatz 235
Buchstabenzeichen 28, 29, 36, 42, 43 B U F F E R E D 155,221,249 BUFFERS(n) 197 BY N A M E 78, 107 C A L L by reference 167 CALL-Anweisung 163, 165, 166, 167, 171, 173, 181, 186 CASE-Anweisung 88 C H A R A C T E R 41, 108 C H A R A C T E R - A t t r i b u t 42 CLOSE-Anweisung 141
Dateiverarbeitung 82, 139, 141, 143, 148, 191, 194,201,232,233 —, indexsequentielle 249 - , regionale 236 - , sequentielle 249, 250 Dateivereinbarung 139, 140, 141, 154, 194, 197, 199, 211, 212, 229, 232, 247, 248 Dateizugriff - . d i r e k t e r 154,230 - , sequentieller 154, 155 Daten - , arithmetische 41, 47, 54, 72, 110, 112 — .numerische 4 3 , 5 3 Datenattribut 4 8 , 5 1 , 5 4 Datenausgabe 43, 44, 76, 98, 119, 120, 121, 122, 126, 151 - . s a t z w e i s e 159
Sach- und Personenregister Dateneingabe 47, 120, 125, 151, 230 Datenformat 131 Datenformatelement 121,122,123,125 Datengruppierung 51, 53, 54, 57,176 Datenklasse 176 Datenkonversion 25, 73, 109 Datenkonvertierung 63, 72, 74, 82, 83, 100, 107, 108, 113, 117, 118, 122, 167, 175 Datenliste 115,116,117,119,120,121,125, 126, 130, 132, 136, 137 Datenorganisation 137, 191, 195, 196, 210, 220 Datensatz 16, 25, 26,115, 119,136,137, 192, 198, 216, 224, 227, 236 — .logischer 211 -.physischer 210,216 Datenspeicherung —, gestreute 217 Datenstrom - , satzweiser 115 -.zeichenweiser 115 Datenträger 16,114,118,119,121,151,191 Datenverarbeitung 24, 27 - , betriebliche 53, 56, 76, 95, 126, 179, 187 - , betriebswirtschaftlich orientierte 23, 42 - , kommerzielle 23 - , technisch-wissenschaftliche 23, 136 Datenverarbeitungsanlage 11, 12, 13, 14, 23, 27, 34, 39, 41, 47, 55, 60, 63, 86, 87, 113, 119, 151, 191, 193,210 Datenverarbeitungssystem 11 Datenvereinbarung 24 Datenverkehr - , DATA-gesteuerter 136 - , EDIT-gesteuerter 115, 118, 119, 125 — .formatierter 115 - , LIST-gesteuerter 136 - , satzweiser 140, 151, 152, 153, 154, 158, 159, 160, 191, 195, 228 -.unformatierter 115 - , zeichenweiser 115, 117, 119,140, 143, 147, 151 Datenwort 44, 48, 49, 55, 118, 119, 121, 126, 136 DECIMAL 47 DEFINED-Attribut 57, 160 Definieren - , korrespondierendes 57 -.überlagerndes 57, 160,208 Definition - , implizite 32 DELETE 249 DELETE-Anweisung 115, 228, 245 Dezimalzahl 32, 33, 44, 46, 110 Dezimalziffer 28, 29, 36, 42, 43, 44, 48, 122
325 Dijkstra 19, 20 Dimensionsattribut 51, 52, 56, 176 DIRECT 221 Disjunktion 69, 70 DISPLAY-Anweisung 114, 115 Division 61 Divisionsmethode 217, 224 DO-Anweisung 70, 76, 90, 94, 95, 96, 97, 98, 99, 100, 101, 102, 105, 107, 120, 183 DO-Gruppe 90, 94, 99, 163, 183 DO-REPEAT-Anweisung 96 DO-Schleife 98, 99, 100, 103, 104, 120, 130, 177 DO-UNTIL-Anweisung 96, 100 DO-UNTIL-Schleife 99, 100 DO-WHILE-Anweisung 20, 96, 99, 100 DO-WHILE-Schleife 20, 99, 100, 178, 242 Dokumentation 38, 148, 152 Dokumentationsregeln 51 Dollarzeichen 32, 44, 48 Druckdatei 126 Dualzahl 29, 32, 48, 65, 110, 135 - , ganzzahlige 110 ECMA 30 Eingabe 113, 121, 122, 123, 125, 126, 127, 130, 131, 132, 159 Eingabeanweisung 16, 17, 113, 114 Eingabedatei 20, 116, 153, 195, 198, 211 Eingabeeinheit 11 Eingabewerk 11 Eingangsname 166, 188 Eingangspunkt - . p r i m ä r e r 177 sekundärer 171,177 Eingangsstelle - . p r i m ä r e 161,162,170 - , sekundäre 170,173 Einheit -.syntaktische 31 Einsfunktion 71 Elementanweisung 75 Elementausdruck 20, 76, 77, 88, 91, 120 - , arithmetischer 60, 61, 63, 68, 73, 82, 83 -.boolescher 68, 73, 83, 88, 92 Elementvariable 41, 54, 55, 59, 73, 107, 119, 120, 137 ELSE-Klausel 89,94 Elshoff 208 END-Anweisung 20, 70, 96, 99, 120, 143, 162, 171, 180, 183, 186 Endbedingung 141, 142 Endlosschleife 160 ENTRY-Anweisung 184, 185 ENTRY-Attribut 167, 168, 171, 175
326 ENTRY-Vereinbarung 170, 171, 172, 173 Entblocken 196 Entscheidungsbaum 50 Entwurfsphase 200 ENVIRONMENT 140, 154, 195, 208 ENVIRONMENT-Attribut 155, 197, 226, 249 Ereignisvariable 154 Ergibtanweisung 17, 59, 65, 83 Ersatzspur 216 EVENT 250 EVENT-Zusatz 154, 198 EXCLUSIVE 230 Exklusives Oder 70 Exponent 47, 122, 135 Exponentenfeld 45 Exponentenlänge 48 EXTERNAL 140, 181, 186, 187, 188 Falten 217,218 Fehlerbedingung 142 Fehlerdichte 19 Fehlerschleife 147, 149, 168 Festpunkt 47 Festpunktdarstellung 45, 47, 48, 49, 123, 125 Festpunktkonstante - , dezimale 48 Festpunktvariable 49 Festpunktwert 45 -.dezimaler 43,72 Festpunktzahl 16, 38, 48, 49, 63 - , dezimale 55, 71, 123 - . d u a l e 32,38,49,52,72 FILE 137, 138, 155, 186 FIXED 47 FLOAT 47 Formalparameter 166, 167, 174 FORMAT 131 Format-Vereinbarung 131 Formatelement 117, 118, 119, 122, 125, 126, 130, 131, 132, 135 Formatelement PAGE 128 Formatliste 115, 116, 117, 118, 119, 121, 131, 132, 136, 151, 159 Formatsteuerzeichen 158 Formatvereinbarung 131, 132 FORTRAN 1 6 , 2 3 , 2 4 , 2 5 , 2 6 , 2 9 , 4 0 , 4 2 , 43,47,48,51,52, 60,62, 63,96,107,113, 131, 159, 166, 173, 188 FREE 182 Funktion 60,63,81,84,200 - , arithmetische 64 —, boolesche 70 - , mathematische 64, 65
Sach- und Personenregister Funktionsaufruf 77, 84,163, 186 —, skalarer 61, 63 Funktionsunterprogramm 171, 173, 174, 175, 176 Genauigkeit 33, 47, 49, 51, 64, 185 GENKEY 250 GET-Anweisung 67, 115, 116, 117, 119, 120, 121, 130, 132, 136, 137, 138, 140 Gleitpunkt 47 Gleitpunktaddition 64 Gleitpunktdarstellung 44, 45, 47, 48, 49, 123 Gleitpunktvariable - , dezimale 47 Gleitpunktwert - , dezimaler 43 Gleitpunktzahl 40, 48, 49, 63, 121, 122 - , dezimale 32,40,123 GOTO-Anweisung 17, 18, 19, 20, 22, 35, 87, 88, 89, 143, 147, 163 Graph 54,87 —, gerichteter 86 Graphentheorie 51, 86 Grenze - , obere 52 - , untere 52 Grundoperator 28 Gültigkeitsbereich 180, 181, 182, 184, 185, 186, 187,188 Hash-Code 217 Haussatz 218 Hauptprozedur 15 Hauptspeicher 16 Hauptstruktur 54, 55, 56, 78, 135, 136, 160, 181, 187 IF-Anweisung 17, 22, 36, 71, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 99, 178, 183, 232, 235 IF-Bedingung 88 IGNORE 153 Imaginärteil 48, 49, 65, 124 Implikation 71 Index 51,53,77 INDEXAREA 249,250 INDEXED 222 Infixoperator 61 - , arithmetischer 62 INITIAL 33, 53, 54, 160 INITIAL-Attribut 103 Inklusives Oder 70 INPUT 140, 155, 253
Sach- u n d Personenregister INPUT-Datei 235 INPUT-Modus 235,253 I N T E R N A L 140, 188 Interpunktion 28 Interpunktionszeichen 29, 38, 41 ISO 24 Iteration 22, 87, 148, 178, 179 Jackson 148 Jackson-Baum 148 Jackson-Baumdiagramm 201 Job-Control-Sprache 208 Kette 4 2 , 4 3 , 4 7 , 8 4 Kettenadresse 219 Kettenattribut 53 Kettendaten 4 1 , 8 1 , 1 1 0 , 1 1 2 Kettenfunktion 85, 226 Kettenfunktionsaufruf - , skalarer 85 Kettenkonstante 46, 47 Kettenkonversion 108, 109 Kettenlänge 4 1 , 4 2 , 6 9 Kettenoperator 6 1 , 6 2 , 8 3 Kettung 218 Kettenvariable 42, 82, 108, 160 Kettenverarbeitung 69, 84, 85 Kettenvereinbarung 4 1 , 4 3 Kettenwiederholungsfaktor 53 Kettenzuweisung 100, 110 KEY 228,250 KEY-Bedingung 2 3 0 , 2 3 1 , 2 3 2 , 2 5 2 K E Y E D 221,249,251 K E Y F R O M 228 KEYFROM-Zusatz 232, 249, 251 KEYTO-Zusatz 243,249 KEY-Zusatz 249,253 Klasse 1 3 , 3 1 , 3 9 , 7 2 Kommentar 46, 47, 209 Kompilierer 12, 24, 25, 32, 36, 43, 46, 47, 182 Konjunktion 69, 70 Konstante 40, 41, 46, 60, 61,176 arithmetische 4 6 , 4 8 , 8 3 - . d e z i m a l e 42,110 —, ganzzahlige 49 - , komplexe 48 - , metalinguistische 3 1 , 3 2 Konversion - , arithmetische 108 - . g e m i s c h t e 108,109 Konvertierung 110, 112 L A B E L 35 Längenattribut 4 1 , 4 2 , 4 3
327 Laufvariable 70, 96, 98, 100, 101, 104, 130 L E A V E 197 LEAVE-Anweisung 105 Leerzeichen 29, 35, 46 Leitwerk 11, 17 Lesen 1 9 3 , 2 1 9 , 2 2 7 , 2 3 6 LIKE 56 LIKE-Vereinbarung 56 LINE 126, 127 LINESIZE 140, 141 Liste 25, 26 Listenverarbeitung 25, 26, 153, 182, 255 LOCATE-Anweisung 115,198,245 Magnetband 197, 198, 200 Magnetbanddatei 191, 192, 195, 198, 211 Magnetbanddateiverarbeitung 201 Magnetbandgerät 193 Magnetbandorganisation 209, 210 Magnetbandspeicher 191, 196, 210, 221 Magnetbandverarbeitung 191, 192, 193, 196, 198, 210, 228 Magnetplattendatei 160, 209, 210, 211, 212, 214, 220, 221, 222, 228, 231, 233, 237 Magnetplattendateierstellung - , direkte 232 - , sequentielle 232 Magnetplattenorganisation 211, 242 - , indexsequentielle 211 - , sequentielle 249 Magnetplattenspeicher 154, 191,209,211, 214, 220, 221, 226, 245 Magnetplattenverarbeitung 228, 237 Mantisse 47 Mantissenlänge 48, 122, 123 Marke 35, 36, 88, 183 - , externe 36 - , interne 36 Markenkonstante 35, 88, 131 Markenpräfix 29, 34, 35, 59, 162, 166, 170, 173, 183, 184, 185, 186 Markenvariable 35, 88, 131 Maschinenprogramm 12, 16 Maschinensprache 1 1 , 1 2 , 8 8 Matrizenmultiplikation 102, 104 Matrizenrechnung 76, 77, 102 Mehrfachbelegung 217 Mehrfachzuweisung 217, 219 Mengenlehre 27, 28 Metaklammern 28 Metasprache 2 7 , 2 8 , 3 0 , 3 1 , 3 2 Modularität 25 Modus 48, 50, 51 Multitasking-Funktion 255
328 Name 15, 20, 28, 29, 34, 36, 39, 51, 138, 162, 187 - , gekennzeichneter 55 NAND-Verknüpfung 69,71 NCP 198 Negation 61,69 Neumann, John von 11 NI (Normenausschuß für Informationsverarbeitung) 24 NOR-Verknüpfung 71 Normalform 27 NOSIZE 35 NOSIZE-Bedingung 162 NOWRITE 250 NPL (New Programming Language) 24 Nullanweisung 34, 162 Nullfunktion 70 Nullprozedur 162 Nummernzeichen 29, 32, 48 Oder-Symbol 28,31,32 ODER-Verknüpfung 69,70 ON-Anweisung 117, 142, 143, 230 ON-Bedingung 142, 143 ONCODE 232 ON-Einheit 142, 143 ON ENDFILE 16 ON-ENDFILE-Anweisung 20, 96, 117 ON KEY-Anweisung 230 OPEN-Anweisung 140, 141, 142, 154, 195, 199, 212, 247, 248 Operand 17, 32, 60, 62, 75, 77 —, skalarer 61 Operandenklasse 74 Operation 13, 17 —, boolesche 83 -,dyadische 61 — , monadische 61 Operator 17, 38, 60, 62, 74 -.arithmetischer 29,61,73 - , boolescher 28,61,62,74 OPTIONS (MAIN) 15, 33, 163 ORDER 177 Ordnung 27,28 Ordnungsmerkmal 192, 193, 194, 209, 217, 219, 224, 230, 245 - , externes 211,216,217,219,222, 223, 224, 226, 227, 230, 243, 245, 251 OTHERWISE-Zweig 93 OUTPUT 230, 243, 249, 250, 253 OUTPUT-Datei 249 PAGE 127 PAGESIZE 140, 141
Sach- und Personenregister Parameter 161,162,166,167,173,174,176, 184, 185, 224 Parameterklasse 176 Parameterkonvertierung 174 Parameterliste 184,188 Parameterübergabe 166, 174, 175 Peircefunktion 71 Permutationssymbol 42, 152 Picture-Attribut 42, 44, 45 PL/l-Zeichen 2 8 , 2 9 , 3 1 , 3 5 , 4 1 , 4 2 PL/l-Zeichenvorrat 41,42 Pointer 25 Potenzierung 61 Präfixoperator -.arithmetischer 61 Preprozessor 26 PRINT-Datei 126, 127, 128, 137, 141 PROCEDURE 15,33 PROCEDURE-Block 15, 163 Programm 11, 12, 13, 14, 15, 16, 19, 23, 33, 34, 47, 86 -.gespeichertes 11 -.problemorientiertes 12,27 Programmablauf 14, 16, 41, 87, 88,144 Programmablaufplan 13, 14, 15, 20, 21, 86, 87, 147 Programmausführung 11,18, 20, 100, 104, 149, 161, 163, 164, 180 Programmbegriff 13 Programmblock 15, 25, 132, 161 Programmdokumentation 46, 99, 209 -.änderungsfreundliche 51 Programmentwurf 201,255 Programmentwurfsmethode 255 Programmierfehler 142 Programmiersprache 11,24,201 - . h ö h e r e 39,40 - , maschinenorientierte 12, 113 —, Normung 24 — , problemorientierte 12, 15, 16, 17, 23, 24, 30, 31,33, 38,39,43,61,63,106,113, 161, 175 —, universelle 23 Programmierung - , höhere 11,12,13 - , strukturierte 18, 22, 23, 25, 86, 87, 88, 147, 208 Programmschalter 88 Programmschleife 15,16, 20, 22, 94, 147, 177 Programmsteuerung 86, 87, 194 ProgrammsteuerungsanWeisung 17, 59 Programmstruktur 86, 97,147, 209 Programmstrukturierung 209 Programmtest 11
Sach- und Personenregister Programmverarbeitung —, simultane 154 Programmverzweigung 16, 19, 22, 88 Programmzusammenführung 19, 20 Programmzweig 17, 22 Prozedur 15, 16, 22, 25, 33, 36, 143, 161, 162, 163, 165, 166, 167, 168, 170, 171, 173, 174, 175, 176, 177, 180, 181, 182, 183, 185, 186, 187, 188, 208, 209, 242 - , externe 164, 182, 183, 184, 185, 188, 189, 209 - , interne 165,182,183,186,188,189,208, 209 - , rekursive 177, 179 Prozeduranweisung 161, 162, 166, 167, 170, 173, 174, 175, 176, 177, 183, 184, 185 Prozeduraufruf 166, 167, 188 - , rekursiver 178 Prozedurkörper 162 Prozedurmarkenpräfix - , externer 184 Prozedurparameter 166, 167 Prozentzeichen 26, 29 Prozeß —, informationsverarbeitender 11, 13 Prozeßrechnersprache 24 Pseudovariable 59, 65, 68, 81, 84, 107, 120, 136 Pufferspeicher 197, 249, 250 PUT-Anweisung 35, 67, 68, 104, 115, 116, 118, 119, 122, 125, 126, 130, 132, 137 PUT LIST-Anweisung 135 PUT STRING-Anweisung 147 R-Formatelement 121, 131 READ-Anweisung 115, 152, 153, 154, 198, 211, 214, 227, 228, 235, 236, 243, 245, 249, 250, 253 READ-SET-Anweisung 214 Realteil 48, 49, 65, 124 Rechenanlage -.digitale 12 Rechenberg 178 Rechenwerk 11 RECORD 139, 140, 155 RECSIZE 197 RECURSIVE 177 REENTRANT 177 Referenzliste 167 Region 223, 224, 226 REGIONAL (1) 222, 223, 224, 225, 226, 228, 229, 233, 237, 243, 245 REGIONAL (2) 222,224,225,226,228, 229, 243, 245
329 REGIONAL (3) 222, 224, 225, 226, 228, 229, 230, 232, 233, 237, 243 REGIONAL-Datei 223,232 REGIONAL (l)-Datei 235, 236, 245 REGIONAL (3)-Datei 233, 235 REGIONAL-Modell 26 Regionnummer 222, 223, 224, 225, 226, 227,230, 231,233 Rekursion 177, 179 REORDER 177 REPEAT 105 REREAD 197, 198 RETURN-Anweisung 171, 173 RETURNS 173 RETURNS-Attribut 175 REVERT-Anweisung 143 REWRITE 210 REWRITE-Anweisung 115, 211, 214, 228, 232, 236, 243, 253 Rutishauser 12 Satz 132,224 - , blockumspannender 196, 197, 221 - , logischer 196, 210, 222, 223, 224, 243 — , metalinguistischer 31,32 -.physischer 195 Satzadresse 211,218,219,226 - , relative 223 —, physische 223 Satzgrenze 115, 151 Satzlänge 196, 197 - . f e s t e geblockt 195,196 - , feste ungeblockt 195, 196 - , variable geblockt 195, 196 —, variable ungeblockt 195, 196 Satzformat 212, 221, 222 Schalter 168, 171 Schleife 20, 87, 95, 97, 98, 99, 100,101,102, 104, 147, 160, 178 — .abweisende 20,99 -.geschachtelte 147 - , globale 147 -.iterative 95,96 —, nichtabweisende 99 -.sukzessive 95,96 Schleifensteuerung 95, 96, 99, 104, 130 Schleifenzähler 94, 95, 100, 104 Schlüssel 224, 228, 230, 232, 243, 249 Schlüsselwort 32 Scheinsatz 223,225,226,228,229, 232,235, 236, 245, 249 Schreiben 192 Schreibweise 47, 48, 50, 51 SELECT-Anweisung 87, 88, 92, 93 Selektion 22, 87, 148, 149
330 S E Q U E N T I A L 154,221 Sequenz 22, 86, 148 SET-Zusatz 153 Shefferfunktion 71 Simulation 85 Simulationssprache 24 Simultanverarbeitung 26 S I Z E 35 SIZE-Bedingung 163 Skalenfaktor 45, 49, 110, 123 S K I P 68, 116, 118, 119, 126, 127 Software-Entwurf 242, 255 Software-Entwurfstechnik 25 Software Life Cycle 200 Softwaretechnologie 26 Sonderzeichen 28, 29 Sortierfehler 144, 147, 149, 168, 230, 232, 253 Sortierfolge 84, 192, 194, 198, 230, 251 Speicher 11 Speicheradresse 192, 211, 217, 235, 245 Speicherklassenattribut 181 Speicherorganisation ^ s e q u e n t i e l l e 211 Speicherplatzzuordnung 180, 182 - . d y n a m i s c h e 181 — .statische 180 Speicherprogrammierung 88 Speicherung — .indexsequentielle 211 Speicherzugriff —, direkt 26 Spezifikation 98, 100, 101, 102, 104 Sprache - , natürliche 24, 27, 29, 38, 39, 41 Sprachstruktur —, natürliche 24 Sprunganweisung 88 Spur 215, 218, 223, 224, 225, 226, 228, 230, 251 - , relative 226 Spuradresse 215, 216, 217, 219, 233 Spurbeschreibungssatz 216 Stammdatei 1 9 1 , 1 9 4 , 2 0 1 Stammdaten 141, 191, 192, 198, 210, 233 Stammsatz 194, 196, 200, 230, 235, 236, 237 - , bewegter 194, 201 -.nichtbewegter 194,201 - , ohne Bewegung 1 9 4 , 2 0 1 Standard-Attribut 139 Standard-Ausgabedatei 138 Standard-Datei 137 Standard-Eingabedatei 138 Standardannahme 32, 50, 208 Standardattribut 118, 175
Sach- und Personenregister Standarddatei S Y S I N 117 Standarddatei S Y S P R I N T 117 Standardinterpretation 25, 50, 51, 113 Standardvereinbarung 25, 136 S T A T I C 180, 181 Steuerfluß 148 Steuerungsformatelement 121, 126, 127, 159 S T R E A M 140 Strecke 86, 87, 99 S T R I N G 132 STRING-Funktion 84 STRING-Zusatz 132, 136 Struktur 51, 53, 54, 55, 56, 75, 78, 84, 164, 181, 208 Strukturanweisung 79 Strukturausdruck 78, 120, 183 - , arithmetischer 60, 78 - , boolescher 68 Strukturbezeichner 54 Strukturvariable 59, 107, 120, 137, 153 Strukturverarbeitung 68 Strukturvereinbarung 54, 55 Stufe 54 Stufennummer 54, 55 Subtraktion 13, 14, 61 Suchbegriff 192 Syntax 13, 28, 30, 32, 35, 39, 40, 41, 175, 176, 177, 255 Syntax-Notation 30 S Y S I N 119, 137 SYSPRINT 119,137 Task 26 Teilkette 84 Terminal 30 Testaufwand 20 Testphase 200 Text 2 5 , 2 9 , 3 4 , 4 1 , 4 6 Textverarbeitung 25, 82 T I T L E 140 TITLE-Zusatz 141 Transportanweisung 16, 17, 34, 35, 59, 106, 113, 136, 137 Typ 3 3 , 3 9 Übergabeargument 166, 167, 175, 176, 186 Überlauf 246 Überlaufbereich 219 Überlaufgebiet 246 Überlaufsatz 218, 219, 224, 226 Übersetzer 12, 15, 25, 32, 47, 49, 52, 72 Übersetzeranweisung 59 Übersetzungsprozeß 12, 120 ÜbersetzungszeitanWeisung 26, 29
331
Sach- und Personenregister Umrechnungsverfahren 217, 224, 225, 228 U N B U F F E R E D 221,249 UND-Verknüpfung 69, 70, 84 Universalrechenautomat 11 Unterprogramm 26,103,161,166,170,173, 174, 176, 186, 188 - , rekursives 177 Unterstreichung 36, 126 Unterstreichungszeichen 46 Unterstruktur 54, 55, 56, 78, 153, 158, 181, 187 UPDATE 139,211,232,250,253 U P D A T E - M o d u s 233, 235, 236, 253 Updaten 191, 192, 194, 210, 211, 219, 228, 229, 245 - , sequentielles 245 V A R 83 Variable 33, 38, 40, 41, 44, 47, 48, 60, 61, 65, 106, 180 -.arithmetische 49,50 - , basisbezogene 198 - , binäre 20 - , einfache 47 - , metalinguistische 2 8 , 3 1 , 3 2 , 3 4 V A R Y I N G 42, 43, 108 Verarbeitung 228 - , direkte 245,251,253 - . s e q u e n t i e l l e 17, 209, 211, 219, 243, 244, 245, 251 Verarbeitungsanweisung 17, 59, 106, 107 - , ausführbare 5 9 , 6 0 , 7 2 Vereinbarung 13, 15, 16, 17, 20, 29, 31, 32, 33, 34, 35, 36, 37, 38, 39, 42, 43, 46, 47, 48, 49, 50, 51, 52, 55, 56, 57, 83, 86, 89, 103, 113, 131, 132, 138, 143, 154, 158, 161, 162, 167, 184, 185, 187, 194, 195, 220 - , explizite 41, 47, 161, 182, 185, 188 —, externe 181 - . i m p l i z i t e 50, 54, 182, 185, 186 — .textabhängige 186 Vereinbarungsklasse 33 Verfeinerung - . s c h r i t t w e i s e 201 Vergleich 14 - , arithmetischer 7 1 , 7 2 , 7 3 , 7 4 Vergleichsausdruck 60, 72, 73, 74, 77, 88, 92 Vergleichsbereichsausdruck 73, 75 Vergleichselementausdruck 71, 72, 73, 83 Vergleichsoperation 7 1 , 7 2 , 7 4 Vergleichsoperator 61, 62, 71, 73, 74 Vergleichsstrukturausdruck 73 Verkettung 81, 82
Verkettungsausdruck 60, 82 Verkettungsbereichsausdruck 75, 82 Verkettungselementausdruck 82, 83 Verkettungsstrukturausdruck 82 Verzweigung 86, 87, 88, 149 - , bedingte 88 Vorrangregel 17, 62 Vorschub 68, 118, 126, 127 VSAM 222 Wartbarkeit 242 Wartungsphase 200 Währungssymbol 44 Weg 11, 18, 86, 87 Wert 4 0 , 4 1 , 4 2 , 166, 180 Wertzuordnung - , ausführbare 107 Wertzuweisung 31, 41, 49, 51, 106, 107 - , mehrfache 60 - , metalinguistische 28, 31 WHEN-Bedingung 93 WHEN-Zweig 93 Wiederholungsfaktor 46,53, 118, 130 Wiederholungsspezifikation 43, 120, 130, 136, 137 Wiederholungssymbol 31 Wort 29,31 Wortlänge 121, 122, 123, 125 WRITE-Anweisung 115, 152, 153, 214, 228, 232, 235, 236, 243, 249, 251 Zähler 147 Zählschleife 95 Zahl —, komplexe 48 -.natürliche 13,39,40,54 -.rationale 13,14,20 Zahlenbasis 47, 48, 50, 51 Zahlendarstellung 47, 122 Zahlensystem 97, 110 Zeichen 27, 29, 30, 41, 42, 84, 115 — .alphanumerisches 2 8 , 2 9 , 3 6 Zeichen-Abbildungsspezifikation 42, 43, 124 Zeichenfolge 30 Zeichenkette 41, 43, 46, 47, 54, 55, 72, 81, 82, 83, 84, 108, 109, 110, 112, 118, 121, 123, 130, 153 Zeichenketten-Konstante 46, 47 Zeichenkettenvariable 83 Zeichensatz 27 Zeichenvorrat 27, 28, 29, 30, 31, 41 Zeiger 255 Zeigervariable 26, 153, 198 Zeilenvorschub 159, 208
332 Ziffer 49 Zugriff 191 - , direkter 209, 211, 221, 228, 232, 235, 237, 243, 245, 248, 250 - , indirekter 228,235 - , sequentieller 211, 221, 230, 232, 247, 249, 250 Zuordnung — .dynamische 180 - , statische 180
Sach- u n d Personenregister Zuordnungsanweisung 106, 107, 108, 113, 135 Zusammenführung 87, 88 Zuse 12 Zweig 87 - , abgeschlossener 87 Zwischenraum 28, 29, 42, 43, 44, 45, 46 Zwischenraumzeichen 36, 38, 44, 47, 62, 84, 108, 122, 125, 126, 136 Zylinder 215
w DE
G A. Schulz
Walter de Gruyter Berlin • New York Methoden des Software-Entwurfs und Strukturierte Programmierung 2., bearbeitete und erweiterte Auflage 15,5 x 23 cm. 181 Seiten. 1982. Kartoniert DM 49,50 ISBN 3 1 1 0 0 8 8 9 5 9 (de Gruyter Lehrbuch)
A. Schulz
Höhere PL/1-Programmierung 15,5x23 cm. 214 Seiten. 1976. Kartoniert DM 36,ISBN 311004862 0 (de Gruyter Lehrbuch)
G. Niemeyer
Einführung in das Programmieren in PASCAL Mit Sonderteil UCSD-PASCAL-System
2. verbesserte Auflage. 15,5 x 23 cm. 167 Seiten. 1983. Kartoniert DM 24,ISBN 311009532 7 (de Gruyter Lehrbuch)
E. W. Mägerle
Einführung in das Programmieren in BASIC 2., durchgesehene Auflage. 15,5 x 23 cm. 112 Seiten. 1980. Kartoniert DM 19,80 ISBN 311008227 6 (de Gruyter Lehrbuch)
K. Hambeck
Einführung in das Programmieren in COBOL 3., verbesserte Auflage. 15,5x 23cm. X, 163Seiten. 1981. Kartoniert DM 2 6 ISBN 311008693 X (de Gruyter Lehrbuch)
W. E. Spieß F. G. Rheingans
Einführung in das Programmieren in FORTRAN 6. Auflage. 15,5 x 23 cm. 217 Seiten. Mit 19 Abbildungen und 13 Tabellen. 1980. Kartoniert DM 22,ISBN 3110081350 (de Gruyter Lehrbuch)
St. Hesse W. Kirsten
Einführung in die Programmiersprache MUMPS 15,5 x 23 cm. XIV, 259 Seiten. 1983. Kartoniert DM 39,50 ISBN 311009746 X (de Gruyter Lehrbuch)
Preisänderungen vorbehalten
w DE
G
Walter de Gruyter Berlin • New York
Kimm/Koch/ Simonsmeier/ Tontsch
Einführung in Software Engineering
P. Schnupp Ch. Floyd
Software
P. Schnupp
15,5 x 23 cm. 306 Seiten. 1979. Kartoniert DM 38,- ISBN 3110078368 (de Gruyter Lehrbuch)
Programmentwicklung und Projektorganisation 2., durchgesehene Auflage. 15,5 x 23 cm. 260 Seiten. Mit 74 Abbildungen und 6 Tabellen. 1979. Gebunden DM 64,- ISBN 311 0078651 (de Gruyter Lehrbuch)
Rechnernetze
Entwurf und Realisierung 2., gründlich überarbeitete Auflage. 15,5 x 23 cm. 266 Seiten mit 107 Abbildungen und 9 Tabellen. 1982. Gebunden DM 76,ISBN 3110089513 (de Gruyter Lehrbuch)
G. Niemeyer
Einführung in das Programmieren in ASSEMBLER Systeme IBM, Siemens, Univac, Interdata 4. Auflage. 15,5 x 23 cm. 303 Seiten. 1982. Kartoniert DM 39,50 ISBN 3110087588 (de Gruyter Lehrbuch)
G. Hommel St. Jähnichen C. H. A. Koster Ehinger/Fussy/ Herrmann/ Hoffmann Ch.-M. Hamann
Methodisches Programmieren Entwicklung von Algorithmen durch schrittweise Verfeinerung 15,5x23 cm. 223 Seiten. 1983. Kartoniert DM 32,ISBN 311009636 6
FORTRAN-Lexikon Anweisungen und Begriffe 15,5 x 23 cm. XX, 492 Seiten. 360 Stichworte. 1982. Kartoniert DM 48,- ISBN 311 008359 0
Einführung in das Programmieren in LISP
15,5x23 cm. XIV, 287 Seiten. Mit 54 Abbildungen. 1982. Kartoniert DM 38,- ISBN 311008909 2 (de Gruyter Lehrbuch)
Preisänderungen vorbehalten