In den ersten drei Folgen des Kurses wurden die Grundlagen der Programmiersprache Pascal vermittelt. Ab dieser vierten Folge wird immer wieder auf Elemente der Grundlagen zurückgegriffen, weshalb Sie sich in jedem Fall mit dem Inhalt der ersten drei Folgen vertraut machen sollten. Die Teile 4 und 5 behandeln die Unterprogramme (Prozeduren und Funktionen), d.h. deren Verwendung.
Ein Programm soll einfach und übersichtlich sein. Die Wartbarkeit eines Softwareproduktes ist heute ein sehr wichtiges Kriterium. Bei der Entwicklung ist unbedingt darauf zu achten, dass übersichtliche Einheiten in Form von Unterprogrammen entstehen, die zusammen die Funktionalität des Gesamtsystems ergeben. Unterprogramme sind Prozeduren und Funktionen.
Es gibt mehrere Gründe, warum Prozeduren eingesetzt werden sollen und können:
Allgemein kann man sagen, Prozeduren erzeugen aus einer Eingangsdatenmenge eine Ausgangsdatenmenge. Es lassen sich folgende Prozeduren unterscheiden:
Wie die Variablen sind die Prozeduren im Deklarationsteil aufzuführen. Prozeduren enthalten Variablen, Konstanten und Anweisungen - also eine einzeln testbare Einheit. Prozeduren können weitere Funktionen und Prozeduren enthalten. Prozeduren werden im Vereinbarungsteil mit
gekennzeichnet.
Prozeduren werden im Hauptprogramm (oder in einer anderen Prozedur) mit ihrem Namen und der Parameterliste aufgerufen.
Eine Prozedur kann allein mit ihrem Namen aufgerufen werden, wenn keine Daten für den Ablauf benötigt werden. Es können aber zu jeder Zeit globale Daten eingesetzt werden. Da in der objektorientierten Programmierung der Einsatz von globalen Daten nicht mehr vorgesehen ist, sollten ausschließlich lokale Daten eingesetzt werden.
Hier soll der Einsatz der Prozedur an einem einfachen Beispiel erläutert werden. Sind an zwei oder mehr Stellen im Programm gleichlautende Programmzeilen vorhanden, kann man sie als Prozedur auslagern. An den betreffenden Stellen erfolgt dann nur noch der Prozeduraufruf.
In dem vereinfachten Struktogramm (Abbildung 20: es fehlen hier einige Anweisungen, die im Programmcode stehen) wiederholen sich vor und in der Schleife zwei Zeilen (grau hinterlegt). Diese können, speziell, wenn es noch mehr Zeilen sind, ausgelagert werden. Die Auslagerung bedeutet eine wesentliche Vereinfachung. Die Anweisungen sind als Programmteil nur einmal im Speicher. Durch Aufruf des ausgelagerten Bereichs mit dem vereinbarten Namen - dem Prozeduraufruf - verzweigt das Programm zur Prozedur und nach deren Abarbeitung wieder in das Hauptprogramm. In dem obigen Struktogramm müssten dann die 2 jeweils grau hinterlegten Zeilen durch die folgende ersetzt werden.
Für die Prozedur "ZaehlerEingabe" erstellt man dann ein eigenes Struktogramm.
Der Programmcode für das komplette Beispielprogramm aus Abbildung 20 sieht dann wie folgt aus: (Listing 1).
Wie zu sehen ist, steht im Deklarationsteil nach der Vereinbarung der Variablen die Prozedur "ZaehlerEingabe". Sie wird wie ein "normales" Programm mit dem Namen, gefolgt von dem Schlüsselwort be-gin, eingeleitet und mit dem Schlüsselwort end beendet. Wichtig ist hierbei, dass hinter dem end kein Punkt, sondern ein Semikolon folgt! Dieser Prozedur können beliebig viele Prozeduren folgen. Im Programmteil wird die Prozedur dann einfach über deren Namen aufgerufen. Der restliche Teil des Programms, mit Ausnahme der Anweisung ClrEol, die die Zeile, in der der Cursor steht, von der Cursorposition bis zum Zeilenende löscht, sollte nach den ersten 3 Folgen dieses Kurses klar sein und wird deshalb nicht mehr erläutert.
Soll eine Prozedur mit unterschiedlichen Werten aufgerufen werden, kann eine "Prozedur mit Wertübergabe" eingesetzt
program Wasserverbrauch; uses crt; var ZaehlerAlt, ZaehlerNeu, Verbrauch, SummeVerbr: real; procedure ZaehlerEingabe; begin GotoXY(35, 6); ClrEol; readln(ZaehlerAlt) GotoXY(35, 8); ClrEol; readln(ZaehlerNeu) end; begin ClrScr; GotoXY(5, 3); write('Summe des Wasserverbrauchs'); GotoXY(5, 6); write(,Alter Zahlerstand (Ende=0): ,); GotoXY(5, 8); write(,Neuer Zahlerstand (Ende=0): ,); GotoXY(5,12); write(,Verbrauch: ... ,); GotoXY(5,14); write(,Summe Verbrauch: ... ,); SummeVerbr := 0; ZaehlerEingabe; { Prozedur-Aufruf } while (ZaehlerNeu <> 0) and (ZaehlerAlt <> 0) do begin if ZaehlerNeu < ZaehlerAlt then ZaehlerNeu := ZaehlerNeu + 100000; Verbrauch := ZaehlerNeu - ZaehlerAlt; SummeVerbr := SummeVerbr + Verbrauch; GotoXY(17, 12); write(Verbrauch :8 :0); GotoXY(23, 14); write(SummeVerbr :8 :0); ZaehlerEingabe ( Prozedur-Aufruf ) end; GotoXY(60, 22); write(,Ende des Programms'); end.
werden. Der Ablauf, die Tätigkeit der Prozedur, richtet sich nach diesen übergebenen Werten. Unterschiedliche Werte können unterschiedliche Arbeitsweisen ergeben. Mit jedem Aufruf wird der aktuelle Wert an die Prozedur übergeben.
Der Aufruf erfolgt nach folgendem Schema:
Prozedurname (Parameterliste);
In der Parameterliste werden die Variablen mit ihrem Datentypen vereinbart. Bei mehreren Variablen gleichen Datentyps werden diese durch ein Komma getrennt vor dem Doppelpunkt aufgelistet. Variablen verschiedenen Datentyps werden nach der Nennung des Datentyps durch ein Semikolon getrennt. In dem folgenden Beispiel sollen in einem Ausgabeprogramm Leerzeilen eingefügt werden. Je nach Druckposition sind mehr oder weniger Leerzeilen vorzusehen (Listing 2).
Kurze Wiederholung:
Für den Einsatz einer Prozedur sind nötig:
(Liste der formalen Parameter); Vereinbarung von Variablen begin
end;
Prozedurname (Liste der aktuellen Parameter);
Wichtig: Die formalen und aktuellen Parameter müssen hinsichtlich Datentyp und Anzahl der Elemente übereinstimmen Aufbau der Prozedur mit Wertübergabe:
program NAME; uses ... var...
procedure Prozedurname(Variablenname: Datentyp);
var Lokalevariable: Datentyp;
begin
end; begin
Prozedurname(aktuellerParameter);
end.
(Beispiel siehe Listing 3).
Zulässige Datentypen:
Die Datentypen der Prozedurvereinbarung dürfen nur aus einem einfachen Wort bestehen:
integer, char, real (jeweils ein Wort)
string (immer 256 Bytes = 255 Zeichen)
Nicht zulässig ist z.B. string[40]! Als Abhilfe hierzu kann man hinter der Befehls-
program Ausgabe;
uses crt;
procedure LEER(Anzahl: integer); {Die Prozedur übernimmt
var Lauf: integer; {einen Parameter, begin
for Lauf := 1 to Anzahl do {der als Laufgrenze einge-
writeln; {setzt wird. end;
begin
ClrScr;
writeln(,Es folgt 1 Leerzeile'); LEER(1); (Aufruf mit Anzahl = 1 }
writeln(,Es folgen 4 Leerzeilen'); LEER(4); {Aufruf mit Anzahl = 4 }
writeln(,Es folgen 2 Leerzeilen');
LEER(2); (Aufruf mit Anzahl = 2 }
writeln('Das genügt!'); end.
procedure BEISPIELl(H, L, K: integer); begin
end; begin
BEISPIELl(trunc(Netto * MWST), 3, 24); end.
procedure BEISPIEL2(A, B, C: integer; D, E: char; Y, Z: real);
begin
end; begin
BEISPIEL2(2, 6, 4, ,a', ,b', 123.12, 0.14);
end.
Prozedurname(Variable A, Variable B); Prozedurname(Zahl_l, Zahl_2);
Beispiel 1 - Vereinbarungen:
procedure PRODOKT(var A, B, C: integer);
procedure FORMEL(var A, B, C: integer; var X, Y: real);
Beispiel 2 - Programm:
program VERBRAUCH;
uses crt;
type string20=string[20];
var VERBRAUCH, ALTWERT, NEUWERT : longint;
procedure EINGABE(var Wert: longint; HINWEIS: string20);
begin
write(HINWEIS) {der als Laufgrenze einge- }
readln(WERT) {setzt wird. }
end;
begin
ClrScr;
writeln('Bestimmung des Verbrauchs');
writeln('Werte bitte ganzzahlig eingeben!');
EINGABE(NEDWERT, ,abgelesenerWert: ,); {Aufruf }
EINGABE(ALTWERT, ,letzterWert: ,); {Aufruf }
VERBRAUCH := NEUWERT - ALTWERT;
writeln('Der Verbrauch betragt: ', VERBRAUCH); end.
zeile uses ... eine TYPE-Vereinbarung treffen, mit der man einen neuen Datentypen definiert:
uses...
type Text = string[40];
procedure ADRESSE(Name, Vorname: text);
6.1.3 Prozeduren mit Variablenübergabe
Wird das Ergebnis einer Prozedur unterschiedlichen Variablen zugewiesen, kann die "Prozedur mit Variablenübergabe" eingesetzt werden.
Eine vorhandene Prozedur kann nun einfach mit unterschiedlichen Variablennamen aufgerufen werden.
Allgemeine Form:
procedure Prozedurname(var Variable1, Variable2: Datentyp); var... begin
end;
Das Schlüsselwort var in der Parameterliste sorgt dafür, dass nur die Adresse, an der der Inhalt der Variablen abgelegt ist, übergeben wird und nicht der Inhalt der Variablen.
Hieraus folgt, dass wenn der Variablen (z.B. Variablei) während des Prozedurablaufes ein Wert zugewiesen wird, dieser auch nach dem Verlassen der Prozedur in der Variablen steht.
In den Struktogrammen (Abbildungen 23 und 24) zum Programm in Beispiel 2 zeigen sich die Grenzen der Darstellung. Die Übergabe von Werten oder Variablen an eine Prozedur wird separat z.B. im Team vereinbart.
In der nächsten Folge dieser Reihe folgen dann die Funktionen, die im Gegensatz zu den Prozeduren auch direkt einen Wert zurückgeben können.