Einführung in die Programmiersprache PASCAL Teil 1

Pascal ist neben Fortran und Basic eine der meistverbreitetsten höheren Programmiersprachen. Sie findet ihe Anwendung vor allem im mathematischnaturwissenschaftlichen Bereich, ist aber beispielsweise ebenso für die Datenverwaltung geeignet. Das Hauptmerkmal dieser Sprache liegt in ihrem übersichtlichen Aufbau, der durch spezielle Befehle ermöglicht wird. Dazu gehören verschiedene Anweisungen zur Schleifensteuerung:

	WHILE DO,
	REPEAT UNTIL,
	FOR NEXT

sowie komfortable Verzweigungsmöglichkeiten:

	IF THEN ELSE,
	CASE OF

Dies bildet die Grundlage für eine strukturierte Programmierweise, der Pascal seine hohe Popularität verdankt. Ein Pascalprogramm besteht aus sogenannten Blöcken bzw. Modulen. Diese besitzen nur einen Eingang und auch nur einen Ausgang, wodurch unkontrollierte und schwer überschaubare Sprünge innerhalb eines Programmes vermieden werden. Desweiteren resultiert aus diesem modularen Aufbau eine gute Lesbarkeit der Programme für den Programmierer selbst und auch für den Anwender. Bei vielen anderen Programmiersprachen wurden strukturierte Befehle nachträglich übernommen. So zum Beispiel bei FORTRAN 77 und bei verschiedenen BASIC-Versionen. Auch das Basic des ATARI ST verfügt über solche Befehlserweiterungen gegenüber dem 'Standard Basic’ (WHILE ... WEND, IF ... THEN ... ELSE).

Bleibt die Frage, für welchen Pascal Compiler man sich entscheiden sollte. Wer bisher nur mit Interpretersprachen (BASIC, LOGO) gearbeitet hat, wird bei einem Compiler mit einigen Nachteilen konfrontiert werden.

Nach dem Editieren eines Programmes benötigt jeder Compiler eine gewisse Zeit um ein ablauffähiges Programm zu erzeugen. Man muß hierbei unbedingt unterscheiden zwischen den Diskettencompilern und Compilern, die komplett innerhalb des Rechenspeichers arbeiten. Erstgenannte benötigen meist hohe Compi-lierzeiten und sind in ihrer Handhabung recht umständlich. Dies ist allerdings eine' Eigenschaft mit der alle Compilersprachen zu kämpfen haben, sei es nun FORTRAN, C oder andere.

Eine sehr erfreuliche Ausnahme stellt TURBO-PASCAL dar. Es handelt sich hierbei um einen Compiler, der samt Editor ständig im Rechnerspeicher vorhanden ist. Ein Pascalprogramm kann innerhalb des Rechners übersetzt werden und erreicht somit eine hohe Compiliergeschwindigkeit, die zumindest bei kürzeren Programmen stark an einen Interpreter erinnert. Turbo-Pascal ist das ideale Werkzeug für Einsteiger und Fortgeschrittene. Über den CP/M-Emulator ist Turbo-Pascal bereits für den ATARI ST verfügbar.

(siehe Bericht in dieser Ausgabe).

Doch nun zu der Serie 'Einführung in PASCAL’, die in diesem Heft beginnt. Sie soll einen Einblick in die strukturierte Programmierung und die damit gegebenen Vorteile dieser und darauf aufbauender Programmiersprachen (C, MODULA-2) geben. Pascal bietet dafür gute Voraussetzungen, weil man nach einer kurzen Eingewöhnungszeit gut mit den Besonderheiten und Möglichkeiten zurechtkommt. In diesem Kurs wird deshalb zuerst ein Überblick über diese Möglichkeiten gegeben. Dabei wird nicht alphabetisch jeder Befehl abgehandelt, denn dies kann man im Handbuch nachlesen. Es soll vielmehr anhand von Programmbeispielen gezeigt werden, wie man übersichtliche Programme erstellt und wie man Problemstellungen in eleganter Weise löst.

Die Programme werden mit Turbo-Pascal Version 3.0 erstellt, sie sind jedoch auf allen gängigen Pascal-Compilern lauffähig solange keine Einschränkungen angegeben werden.

Der Kurs beginnt mit einem einfachen Beispiel, an dem man jedoch schon wichtige Merkmale von Pascal aufzeigen kann. Geben Sie nun das Programm (Listing 1) ein und compilieren Sie es. Sollten dabei Fehler auftreten, so müssen Sie das Quellprogramm mit dem Editor verbessern. Wenn das Programm fehlerfrei übersetzt wurde, können Sie es starten. Geben Sie nun eine beliebige Zahl ein und drücken Sie RETURN. Als Ergebnis erscheint das zehnfache Ihrer Zahl auf dem Bildschirm.

	program multiplikation;
	
	const faktor = 10;
	var zahl,ergebnis : real;
	
	begin
		write (' Eingabe : '); 
		read (zahl);
		ergebnis:=zahl*faktor;
		write (ergebnis)
	
	end.

Listing 1

Jedes Pascal-Programm besteht, grob unterteilt, aus drei Teilen. Dies sind der Programmkopf, der Vereinbarungsteil und der Anweisungsteil. Der Programmkopf ist in vielen Pascalversionen zwingend notwendig. Bei Turbo-Pascal kann er jedoch weggelassen werden. Es empfiehlt sich aber trotzdem einen Programmnamen anzugeben, weil man damit den Inhalt des Listings beschreiben kann. Als Programmkopf wurde bei diesem Beispiel ’program multiplikation’ gewählt.

Achtung, bei manchen Pascal-Versionen darf der Programmname nur acht Zeichen lang sein!

In nun folgenden Vereinbarungsteil werden alle Labels (Sprungzeichen), Konstanten, Typen, Variablen, Funktionen und Prozeduren vereinbart. Der Programmierer muß also vor Beginn des Programms festlegen, welche Konstanten, Variablen usw. er im Programm verwendet und von welchem Datentyp sie sind. Bei diesem Programm wird eine Konstante (CONST) mit dem Namen ’faktor’ definiert, und ihr wird der Wert 10 zugewiesen. Hiernach folgt die Vereinbarung der Variablen (VAR). Die Reihenfolge der Vereinbarungen ist bei Pascal nicht beliebig. Die Konstantenvereinbarung muß vor der Vereinbarung der Variablen stehen. Eine komplette Übersicht der Prioritäten im Vereinbarungsteil erfolgt später. Als Variablen werden 'zahl’ und 'ergebnis’ festgelegt, ihr Datentyp steht hinter einem Doppelpunkt und ist der Real-Typ. Dies bedeutet, daß die Variablen Gleichtkommwerte annehmen können.


Bild 1 Programmaufbau

Bei der Benennung der Variablen hat man viele Möglichkeiten. Am Anfang darf nur keine Zahl stehen und Leerzeichen können nicht verwendet werden. Es empfiehlt sich aussagekräftige Namen zu verwenden und nicht nur einzelne Buchstaben. Allerdings ist nur eine bestimmte Anzahl von Zeichen relevant. Bei Turbo-Pascal sind es acht. Dies bedeutet, daß das Programm zwischen 'ergebnis' und ’ergebniswert’ nicht unterscheiden kann. Dies kann zu schwer auffindbaren Fehlern im Programm führen. Mit dieser Anweisung ist der Vereinbarungsteil abgeschlossen. Es dürfen in dem nun folgenden Programm also nur die definierten Variablen und die Konstante 'faktor' Vorkommen, alle anderen würden zu einer Fehlermeldung bei der Compilierung führen.

Der Anweisungsteil wird durch die Befehle:

begin und end.

begrenzt, wobei der Punkt das Ende des gesamten Programms anzeigt. Diese Befehle umschließen immer eine Anweisung oder einen Anweisungsblock und finden somit in Pascal-Programmen öfter ihre Anwendung. Der Anweisungsblock beginnt hier mit einer ’write’-Anweisung, die den in Hochkommas stehenden Text auf dem Bildschirm ausgibt. Die darauffolgende ’read’-Anweisung wartet auf eine Eingabe des Benutzers, die mit < RETURN > abgeschlossen werden muß. Die eingegebene Zahl, alphanumerische Zeichen sind nicht erlaubt, wird der Variablen 'zahl' übergeben. In der nächsten Zeile wird der Variablen 'ergebnis' das Produkt aus 'zahl' und 'faktor' zugewiesen. Die Zuweisung hat in Pascal die Form:

	Variable : = numerischer Ausdruck

Dabei muß aber auf den Datentyp geachtet werden. Man kann zwar eine Integerzahl einer Realvariablen zuweisen, aber nicht umgekehrt. Wenn man also einer Integervariablen eine Realzahl zuweisen will, bricht das Programm schon beim Compilieren mit einer Fehlermeldung ab. Mit dem ’write’-Befehl wird nun die Variable 'ergebnis' auf dem Bildschirm ausgegeben. Das Programm ist damit beendet, für einen erneuten Durchlauf muß man es wieder starten. Nach diesem Durchlauf werden Sie feststellen, daß die Ausgabe auf dem Bildschirm unübersichtlich ist, weil alle Ausgaben Zusammenhängen. Sie können deshalb die Befehle 'write' und 'read' durch ’writeln’ und ’readln’ ersetzen. Dadurch steht jede Ausgabe in einer neuen Zeile. Auffällig bei einem Pascal-Programm ist, daß alle Anweisungen durch ein Semikolon getrennt werden müssen. Von dieser Regel gibt es nur wenige Ausnahmen. So muß zum Beispiel hinter ’begin’ kein Semikolon stehen, und auch hinter der letzten Anweisung vor einem ’end’ ist ein Trennzeichen nicht notwendig. Man kann sie aber trotzdem setzen, sogar mehrere hintereinander haben keine negativen Auswirkungen. Dagegen darf vor einem ’else’ kein Semikolon stehen und auch hinter die letzte ’end’-Anweisung darf keines.

Das Beispielprogramm enthält auch einige Leerzeilen und Leerzeichen. Diese sind nicht notwendig. Man kann sogar mehrere Anweisungen in eine Zeile schreiben (siehe Listing 2), doch würde das der Übersichtlichkeit des Programms sehr schaden:

	program multiplikation;const faktor=10;var zahl,ergebnis:real;begin 
	write(' Eingabe : ');read (zahl);ergebnis:=zahl*faktor;write (ergebnis);end.

Listing 2

In Pascal ist es also möglich, beliebige Abstände zwischen Befehlen zu setzen und somit ein Listing optisch zu strukturieren. Auch die Großschrift kann dazu verwendet werden. Sie kann equivalent zu Kleinbuchstaben verwendet werden und kann mit diesen, sogar innerhalb eines Wortes, gemischt werden.

	Konstante	: faktor = 70
	Variablen	: zahl, ergebnis
	Eingabe 	: zahl
	ergebnis 	:=zahl * faktor
	Ausgabe 	: ergebnis

Bild 2 Folgestruktur

Dieses Programm wird Zeile für Zeile ausgeführt, es läuft also von oben nach unten durch. Diese Programmart nennt man Folgestruktur. Diese Struktur läßt sich einfach als Struktogramm (auch Strukturdiagramm oder Nassi-Shneiderman-Diagramm) darstellen (siehe Bild 2). Mit diesen Diagrammen werden alle grundlegenden Programmstrukturen erklärt. Sie eigenen sich sehr gut für die strukturierte Programmierung und haben die früher verwendeten Programmablaufpläne (PAP) ersetzt.

program potenzen;
label 10;
var zahl,quadrat : integer;
	wurzel : real;

begin
	writeln ('	sqrt(x)	sqr(x)');
10: read (zahl);
	wurzel :=sqrt(zahl); 
	quadrat:=sqr (zahl);
	writeln (wurzel:20,quadrat:10);
	goto 10;
end.

Listing 3

Das zweite Programm (Listing 3) verwendet wieder einige Elemente, die auch im ersten Programm vorkamen. Zusätzlich wird hier mit einem Label gearbeitet. Ein Label ist eine Sprungmarke, die das Ziel eines ’GOTO’-Sprunges markiert. Diese Möglichkeit des Sprunges entspricht dem ’GOTO’-Befebl in Basic und sollte in Programmen möglichst vermieden werden, weil er das Listing unübersichtlich macht. Labels müssen vor der Verwendung definiert werden. In einer Zeile können mehrere Labels vereinbart werden (z. B. label 10,20,1). In Turbo-Pascal dürfen, im Gegensatz zu Standard-Pascal, auch Namen als Labels definiert werden.

Ein Sprung darf jedoch nicht in eine strukturierte Anweisung (Schleife, Auswahlblock) erfolgen! Außerdem sind berechnete Sprünge nicht möglich!

Bei der Variablen Vereinbarung tritt der Datentyp Integer auf. Er legt die Variablenzahl und -quadrat als Ganzzahlen fest. Dies beschränkt ihren Wertebereich auf —32 768 bis 32 767.

Die Funktionen ’sqrt(x)’ und ’sqr(x)’ müssen genau von der Basic-Funktion ’sqr’ unterschieden werden. ’sqr(x)’ bedeutet in Pascal das Quadrat (square) von x. Das Gegenteil ist dann ’sqrt(x)’, die Quadratwurzel (squareroot). Das Argument der beiden Funktionen ist in diesem Fall vom Datentyp 'integer’, es kann jedoch auch als 'real' definiert werden. Wenn das Argument der Funktion ’sqr’ als Integer festgelegt wird, ist auch das Ergebnis im Integerbereich. Das bedeutet, daß es nicht größer als 32 767 werden kann. Bei höherem Argument ist dann das Ergebnis falsch, es wird negativ! Ist das Argument als Real-Zahl festgelegt, so treten diese Probleme nicht auf. Bei der Funktion ’sqrt’ darf das Ergebnis nicht vom Typ Integer sein (siehe auch Bild 3)!

		Argument		Ergebnis
sqr(x)	real, integer	real, integer
sqrt(x)	real, integer	real
* nur bis 32767 (!)	

Bild 3 Funktion sqr(x) und sqrt(x)

Der Befehl ’writeln’ wurde schon zuvor angesprochen, er wird hier jedoch noch für die formatierte Ausgabe erweitert. Da eine Ausgabe der Form ’write (x,y)’ die Werte von x und y ohne Zwischenraum hintereinander schreibt, wird eine andere Form des ’write’-Befehls benutzt. Er hat die Form:

	write (wurzel:20,quadrat: 10)

Hinter jeder Variablen wird nach einem Doppelpunkt die Länge des reservierten Zeilenplatzes angegeben. Die Variable ’wurzel’ hat also einen Platz, der von der letzten Cursorposition zwanzig Stellen nach rechts reicht. In diese Spalten wird nun ihr Wert rechtsbündig hineingeschrieben. Der Platz für die nächste Variable beginnt

dann an der nächsten Stelle und reicht zehn Plätze nach rechts. Wenn der reservierte Platz zu klein ist, wird er bei der Ausgabe überschrieben. Es entsteht dann ein unübersichtliches Zahlengewirr. Deshalb sollte man das Format der Ausgabe gut durchdenken und eventuell mehr Platz als benötigt reservieren. Bei Dezimalzahlen kann man die Anzahl der ’Nachkommastellen’ festlegen. Der Befehl hat dann die Form:

	write (x:10:6)

Dabei gibt die erste Zahl wieder die Gesamtlänge des reservierten Platzes an. Die zweite Zahl die darin enthaltenen Nachkommastellen. Ansonsten gilt dasselbe wie für die Integer Zahlen. Anstelle der Zahlen können auch Variablen oder Konstanten stehen:

	write (x:10:i)

Nachdem nun bei diesem Beispiel auch mit einem Label gearbeitet wurde, ist es an der Zeit die Reihenfolge im Vereinbarungsteil darzustellen. Als erstes kommt die Labelvereinbarung, dann die der Konstanten, Typen, Variablen, Funktionen und zuletzt die der Prozeduren (siehe auch Bild 4). Funktionen, Prozeduren und Typen werden später im Text erklärt. Beim Vereinbaren muß man darauf achten, daß Namen bzw. Bezeichnungen nicht mehrmals verwendet werden. Die Compilierung wird dann mit ’Duplicate identifier or lable’ abgebrochen.


Bild 4: Reihenfolge beim Vereinbarungsteil

Das dritte Programm (Listing 4) enthält als Kern eine einfache Auswahlanweisung. Sie wird in Bild 5 als Struktogramm dargestellt. Mit der ’if-Anweisung wird kontrolliert, ob die eingegebene Zahl Eins ist. Dann wird der Text ’hallo’ ausgegeben. Das Programm geht dann in der nächsten Zeile weiter und gibt den Text 'wie geht es?’ aus. Falls die eingegebene Zahl Zwei ist, überspringt das Programm die Zeile, die hinter der ’then’-Anweisung steht und gibt nur den Text 'wie geht es ?’ aus. Da es hierbei nur eine Möglichkeit gibt, nennt man diese Art der Auswahl auch einseitige Auswahl.

Bild 5 einfache Auswahlstruktur

	program auswahl;
	
	var eingabe : real;
	
	begin
		writeln (' 1 oder 2' ); 
		readln (eingabe); 
		if eingabe = 1
			then write ('hallo ');
		writeln ('wie geht es ?') 
	end.

Listing 4

Eine größere Bedeutung hat jedoch die mehrseitige Auswahl, die in Bild 6 dargestellt wird. Mit diesem Programm (Listing 5) wird eine quadratische Gleichung mit der p-q-Formel gelöst. Die Variable ’wurzel’ bekommt den Inhalt des Wurzelausdrucks zugewiesen. Nun wird mit ’iP abgefragt, ob der Wurzelausdruck kleiner als Null ist. Das Ergebnis wäre dann negativ und die Wurzel läßt sich nicht berechnen. Deshalb wird der Text 'keine reelle Lösung’ ausgedruckt. Danach wird mit der Anweisung fortgefahren, die hinter dem Auswahlblock steht. Wenn nun aber die Bedingung (wurz<0) nicht erfüllt ist, so wird bei ’else’ nachgesehen, ob diese Bedingung (wurz=0) zutrifft. Gegebenenfalls wird dann 'nur eine Lösung’ ausgegeben. Treffen beide Bedingungen nicht zu, so ist die zweite ’else’-Abfrage an der Reihe. Hier muß keine Bedingung gestellt werden, weil alle anderen Fälle bereits herausgesiebt wurden. Bei der ’if-then-else’-Anweisung wird also nur eine der Bedingungen ausgeführt und dann mit der Anweisung, die hinter dem Abfrageblock steht, fortgefahren (siehe Struktogramm). Dabei können vor dem letzten ’else’ noch beliebig viele Abfragen der Form ’else if...’ eingefügt werden.

Wie man aus dem Struktogramm (Bild 6) erkennen kann handelt es sich bei diesem Programm um einen Sonderfall der zweiseitigen Auswahl, weil mehrere bzw. zwei Auswahlmöglichkeiten ineinander verschachtelt sind. Wenn man jedoch die Zeile mit der ’else if’-Anweisung streicht erhält lman eine reine zweiseitige Auswahl.

Zu Beachten ist hierbei, daß vor einem ’else’ kein Semikolon stehen darf! Soll hinter einer Abfrage mehr als eine Anweisung stehen, so muß diese mit ’begin ... end’ umschlossen werden!

(Fortsetzung folgt)

(MN)

Bild 6: mehrseitige Auswahlstruktur
program QuadratischeGleichung;
var x 1, x2,p,q,wurz : real;

begin
	writeln ('Quadratische Gleichung');
	writeln ('gib p und q ein !');
	readln (p,q); 
	wurz:=(p*p/4-q);
	if wurz<0
		then writeln ('keine relle loesung !')
	else if wurz=0
		then writeln ('nur ein loesung :',-p/2)
	else
		begin
			wurz;=sqrt(wurz);
			x1:=-p/2+wurz;
			x2:=-p/2-wurz;
			writeln ('x1 =', x1);
			writeln ('x2 =',x2);
		end;
	writeln ('-------------------------')

end.

Listing 5



Aus: ST-Computer 02 / 1986, Seite 53

Links

Copyright-Bestimmungen: siehe Über diese Seite