21
12.12.2006 281 © A. Poetzsch-Heffter, TU Kaiserslautern Ein Algorithmus heißt determiniert, wenn er bei gleichen zulässigen Eingabewerten stets das gleiche Ergebnis liefert. Andernfalls heißt er nicht-determiniert. Begriffsklärung: (determiniert) Beispiele: (Determiniertheit) 1. Jeder Algorithmus, der eine Funktion berechnet, ist determiniert. 2. Der Algorithmus von der letzten Folie ist determiniert. 4.2 Grundkonzepte prozeduraler Programmierung Algorithmen lassen sich mit unterschiedlichen Sprachmitteln beschreiben: - umgangssprachlich - mit graphischen Notationen - mit mathematischer Sprache - mit programmiersprachlichen Mitteln. 12.12.2006 282 © A. Poetzsch-Heffter, TU Kaiserslautern Gemäß des prozeduralen Paradigmas (vgl. F6) wird - der Zustand eines Systems mit Variablen beschrieben - werden die möglichen Systemabläufe algorithmisch formuliert und - bilden Prozeduren das zentrale Strukturierungs- und Abstraktionsmittel. Begriffsklärung: (prozedurales Paradigma) Beispiel: (Prozedurale Systemsicht) Ein Rechensystem (z.B. PC) kann man prozedural wie folgt beschreiben: - Jede Datei ist eine Variable für Listen von Bytes. - Nach dem Starten des Rechners wird ein nicht- terminierender Algorithmus ausgeführt: while( true ) { warte auf Eingabe eines Programmnamens; starte Programm mit eingegebenem Namen als parallelen Algorithmus; } - Jedes Programm entspricht dabei einer Prozedur. 12.12.2006 283 © A. Poetzsch-Heffter, TU Kaiserslautern Der Abschnitt 4.2 stellt diejenigen Grundkonzepte der prozeduralen Programmierung vor, die als Voraussetzung für die objektorientierte Programmierung benötigt werden: Deklaration und Verwendung von Variablen • Anweisungen Deklaration und Verwendung von Prozeduren Zur praktischen Programmierung verwenden wir eine Teilsprache von Java. Vorteile : - Der Übergang zur objektorientierten Programmierung wird einfacher. - Der Zusammenhang zwischen prozeduraler und objektorientierter Programmierung wird klarer. 4.2.1 Sprachliche Basis: Teilsprache von Java Nachteile : - Da klassenlose, rein prozedurale Programmierung von Java nicht unterstützt wird, entsteht ein notationeller Mehraufwand. - Bestimmte Sprachelemente bleiben zunächst unerklärt. 12.12.2006 284 © A. Poetzsch-Heffter, TU Kaiserslautern Basisdatenstrukturen in Java: Java bietet insbesondere Basisdatenstrukturen mit den Typen boolean char int, long, short, float, double sowie entsprechende Funktionen und Konstanten. Die nichtstrikten Operationen sind: _ ? _ : _ statt if _ then _ else _ in ML _ && _ statt _ andalso _ in ML _ || _ statt _ orelse _ in ML Vorgehen : - Basisdatentypen - Ausdrücke - Variablendeklarationen - Programmstruktur und vereinfachte Notation

4.2 Grundkonzepte prozeduraler Programmierung · Zuweisung : (engl. assignment) ... Semantik: Werte den Ausdruck aus und weise das Ergebnis der Variablen zu. (In Java ist eine Zuweisung

  • Upload
    others

  • View
    2

  • Download
    0

Embed Size (px)

Citation preview

Page 1: 4.2 Grundkonzepte prozeduraler Programmierung · Zuweisung : (engl. assignment) ... Semantik: Werte den Ausdruck aus und weise das Ergebnis der Variablen zu. (In Java ist eine Zuweisung

12.12.2006 281© A. Poetzsch-Heffter, TU Kaiserslautern

Ein Algorithmus heißt determiniert , wenn erbei gleichen zulässigen Eingabewerten stets dasgleiche Ergebnis liefert.

Andernfalls heißt er nicht-determiniert .

Begriffsklärung: (determiniert)

Beispiele: (Determiniertheit)

1. Jeder Algorithmus, der eine Funktion berechnet, ist determiniert.

2. Der Algorithmus von der letzten Folie ist determiniert.

4.2 Grundkonzepteprozeduraler Programmierung

Algorithmen lassen sich mit unterschiedlichen Sprachmitteln beschreiben:

- umgangssprachlich

- mit graphischen Notationen

- mit mathematischer Sprache

- mit programmiersprachlichen Mitteln.

12.12.2006 282© A. Poetzsch-Heffter, TU Kaiserslautern

Gemäß des prozeduralen Paradigmas (vgl. F6) wird

- der Zustand eines Systems mit Variablen beschrieben

- werden die möglichen Systemabläufe algorithmischformuliert und

- bilden Prozeduren das zentrale Strukturierungs-und Abstraktionsmittel.

Begriffsklärung: (prozedurales Paradigma)

Beispiel: (Prozedurale Systemsicht)

Ein Rechensystem (z.B. PC) kann man prozeduralwie folgt beschreiben:

- Jede Datei ist eine Variable für Listen von Bytes.

- Nach dem Starten des Rechners wird ein nicht-terminierender Algorithmus ausgeführt:

while( true ) {

warte auf Eingabe eines Programmnamens;

starte Programm mit eingegebenem Namenals parallelen Algorithmus;

}

- Jedes Programm entspricht dabei einer Prozedur.

12.12.2006 283© A. Poetzsch-Heffter, TU Kaiserslautern

Der Abschnitt 4.2 stellt diejenigen Grundkonzepteder prozeduralen Programmierung vor, die als Voraussetzung für die objektorientierte Programmierung benötigt werden:

• Deklaration und Verwendung von Variablen

• Anweisungen

• Deklaration und Verwendung von Prozeduren

Zur praktischen Programmierung verwenden wir eine Teilsprache von Java.

Vorteile:

- Der Übergang zur objektorientierten Programmierungwird einfacher.

- Der Zusammenhang zwischen prozeduraler undobjektorientierter Programmierung wird klarer.

4.2.1 Sprachliche Basis: Teilsprache von Java

Nachteile:

- Da klassenlose, rein prozedurale Programmierungvon Java nicht unterstützt wird, entsteht ein notationeller Mehraufwand.

- Bestimmte Sprachelemente bleiben zunächstunerklärt.

12.12.2006 284© A. Poetzsch-Heffter, TU Kaiserslautern

Basisdatenstrukturen in Java:

Java bietet insbesondere Basisdatenstrukturenmit den Typen

boolean

char

int, long, short,

float, double

sowie entsprechende Funktionen und Konstanten.

Die nichtstrikten Operationen sind:

_ ? _ : _ statt if _ then _ else _ in ML

_ && _ statt _ andalso _ in ML

_ || _ statt _ orelse _ in ML

Vorgehen:

- Basisdatentypen

- Ausdrücke

- Variablendeklarationen

- Programmstruktur und vereinfachte Notation

Page 2: 4.2 Grundkonzepte prozeduraler Programmierung · Zuweisung : (engl. assignment) ... Semantik: Werte den Ausdruck aus und weise das Ergebnis der Variablen zu. (In Java ist eine Zuweisung

12.12.2006 285© A. Poetzsch-Heffter, TU Kaiserslautern

Ausdrücke in Java:

Mittels der Konstanten und Funktionen derelementaren Datenstrukturen lassen sich analog zu ML Ausdrücke bilden.

(Darüber hinaus kann man deklarierte Prozedurenin Ausdrücken aufrufen. Dadurch können bei derAuswertung von Ausdrücken Seiteneffekteentstehen.)

Beispiel: (Ausdrücke in Java)

5 + 89

45 / 6

47474747L * a für geeignetes a

3.6 * (-4 + 23)

d == 78 + e für geeignete d, e

7 >= 45 == true

abs(a) + abs(d) für geeignete a, d, abs

sein | !sein für geeignete Variable sein

true || tuEs() für geeignete Prozedur tuEs

a > b ? a : b // liefert max(a,b)

12.12.2006 286© A. Poetzsch-Heffter, TU Kaiserslautern

Programmstruktur und -syntax:

Variablendeklarationen in Java:

Eine Variablendeklaration hat die Form:

<Typbezeichner> <Variablenbezeichner> ;

und definiert eine neue Variable vom angegebenen Typ mit dem angegebenem Bezeichner. Beispiele:

int a;

boolean b;

float meineGleitkommavariable;

char cvar;

Eine Variablendeklarationsliste entsteht durch Aneinanderreihen von einzelnen Deklarationen.

Ein prozedurales Programm besteht aus:

- einer Liste von Typdeklaration

- einer Liste von globalen Variablendeklarationen

- einer Liste von Prozedurdeklarationen

- einer Hauptprozedur

In Java lassen sich prozedurale Programme mit folgendem Programmrahmen formulieren:

12.12.2006 287© A. Poetzsch-Heffter, TU Kaiserslautern

public class <Programmname>extends InputOutput {

static <Typdeklaration >...static <Typdeklaration >

static <Variablendeklaration >...static <Variablendeklaration >

static <Prozedurdeklaration >...static <Prozedurdeklaration >

public static void main(String[] args)

<Prozedurrumpf>

}

<Programmname>.java

1

1

k

n

wobei k ≥ 0, m ≥ 0, n ≥ 0.

Bemerkung:• Die Reihenfolge der Deklarationen kann vertauscht

werden.

• Die hier nicht erklärten Sprachkonstrukte werdenin Kapitel 5 behandelt.

1

m

12.12.2006 288© A. Poetzsch-Heffter, TU Kaiserslautern

• Wir gehen davon aus, dass die Datei InputOutput.ja vaim aktuellen Dateiverzeichnis liegt. Sie stellt ber eit:

Konventionen:

public class InputOutput {

public static int readInt(){...}

public static String readString(){...}

public static char readChar(){...}

public static void print(int i){...}

public static void println(int i){...}

public static void print(char c){...}

public static void println(char c){...}

public static void print(String s){...}

public static void println(String s){...}}

• Im Folgenden werden wir die ersten beiden und die letzte Zeile des Programmschemas der letztenFolie sowie die Schlüsselwörter static undpublic auf Folien der Übersichtlichkeit halber weglassen.

Page 3: 4.2 Grundkonzepte prozeduraler Programmierung · Zuweisung : (engl. assignment) ... Semantik: Werte den Ausdruck aus und weise das Ergebnis der Variablen zu. (In Java ist eine Zuweisung

12.12.2006 289© A. Poetzsch-Heffter, TU Kaiserslautern

Beispiel: (Notation prozeduraler Programme)

public class Foo extends InputOutput {

static int a;

static boolean bvar;

static int abs( int n ) {if( n>=0 ){

return n;} else {

return -n;}

}

static void setA() {a = abs(a);

}

public static void main( String[] args ){

println("Eingabe von a:");

a = readInt();

setA();

println( a );}

}

Foo.java

12.12.2006 290© A. Poetzsch-Heffter, TU Kaiserslautern

Abkürzend schreiben wir hier:

int a;

boolean bvar;

int abs( int n ) {if( n>=0 ){

return n;} else {

return -n;}

}

void setA() {a = abs(a);

}

void main( String[] args ){

println("Eingabe von a:");

a = readInt();

setA();

println( a );}

12.12.2006 291© A. Poetzsch-Heffter, TU Kaiserslautern

Bemerkung:

• Die Konzepte sind rekursiv von einander abhängig:

- Anweisungen benutzen Variablen und Ausdrücke

- Prozeduren basieren auf Anweisungen

- Verwendung von Variablen kann nur im Kontextvon Anweisungen und Prozeduren erklärt werden.

- Ausdrücke erlauben die Verwendung von Prozeduren.

Überblick übers weitere Vorgehen:

• Anweisungen

• Prozeduren

• Variablen in Programm und Speicher

• Felder

• Benutzerdefinierte Typen

• Sichtbarkeit von Bindungen

• Iteration und Rekursion

• Weitere prozedurale Sprachkonzepte

12.12.2006 292© A. Poetzsch-Heffter, TU Kaiserslautern

Anweisungen sind programmiersprachliche Be-schreibungsmittel:

- Einfache Anweisungen beschreiben Aktionen.

- Zusammengesetzte Anweisungen beschreiben, wie mehrere Aktionen auszuführen sind, alsoTeile von Algorithmen.

Begriffsklärung: (Anweisung)

• In der programmiersprachlichen Realisierung der Konzepte verwischen ihre Grenzen; z.B.:

- Parameter lassen sich wie Variable verwenden.

- Einfache Anweisungen lassen sich in Aus-drücken verwenden.

4.2.2 Anweisungen

while( <Bedingung> ) {

<Anweisungen>}

Beispiel: (Anweisungen)

1. Zuweisung eines Werts an eine Variable:

2. Schleifenanweisung:

<Variable> = <Wert > ;

Page 4: 4.2 Grundkonzepte prozeduraler Programmierung · Zuweisung : (engl. assignment) ... Semantik: Werte den Ausdruck aus und weise das Ergebnis der Variablen zu. (In Java ist eine Zuweisung

12.12.2006 293© A. Poetzsch-Heffter, TU Kaiserslautern

Wir betrachten die folgenden Anweisungen und ihreRealisierung in Java:

• Einfache Anweisungen:- Zuweisung- Prozeduraufruf

• Anweisungsblöcke

• Schleifenanweisungen:- while-, do-, for-Anweisung

• Verzweigungsanweisungen:- bedingte Anweisung- Fallunterscheidung- Auswahlanweisung

• Sprunganweisungen:- Abbruchanweisung- Rückgabeanweisung

Bemerkung:

Unterschied: Anweisung / Ausdruck

- Die Auswertung von Ausdrücken liefert ein Ergebnis.

- Die Ausführung von Anweisungen verändert den Zustand. Im Allg. liefert sie kein Ergebnis.

12.12.2006 294© A. Poetzsch-Heffter, TU Kaiserslautern

Zuweisung: (engl. assignment)

Syntax in Java:

<Variable> = <Ausdruck> ;

Semantik:

Werte den Ausdruck aus und weise das Ergebnisder Variablen zu. (In Java ist eine Zuweisungsyntaktisch ein Ausdruck, liefert also einen Wert u ndzwar das Ergebnis der Auswertung von der rechtenSeite der Zuweisung.)

Beispiele:

a = 27 % 23;

b = true;

meineGleitkommavariable = 3.14;

Sprechweise:

„Variable b ergibt sich zu true “ oder

„Variable b wird true zugewiesen“ .

Einfache Anweisungen

12.12.2006 295© A. Poetzsch-Heffter, TU Kaiserslautern

Bemerkung:

In einer Zuweisung (und anderen Sprachkon-strukten) kann eine Variable v mit zwei Bedeutungen vorkommen:

1. Das Vorkommen links vom Zuweisungszeichenmeint die Variable. Man spricht vom L-Wert(engl. l-value) des Ausdrucks v .

2. Das Vorkommen rechts vom Zuweisungszeichenmeint den in v gespeicherten Wert. Man spricht vom R-Wert (engl. r-value) des Ausdrucks v .

Die Unterscheidung wird wichtiger, wenn auch linksdes Zuweisungszeichens komplexere Ausdrückestehen.

Beispiel: (L-Wert, R-Wert)

a = 7 + a ;

L-Wert R-Wert

12.12.2006 296© A. Poetzsch-Heffter, TU Kaiserslautern

Prozeduraufruf: (engl. procedure call)

Syntax:

<Prozedurbezeichner> ( <AktuelleParameterliste> ) ;

<AktuelleParameterliste> �

ε | <Ausdrucksliste>

<Ausdrucksliste> �

<Ausdruck>

| <Ausdruck> , <Ausdrucksliste>Semantik:

Werte die Ausdrücke der aktuellen Parameter aus.Übergebe die Ergebnisse an die formalen Parameter.Führe die Anweisungen der Prozedur aus.Liefere den Rückgabewert, wenn vorhanden.

Beispiele:

1. Prozeduraufruf mit Ergebnis:

a = ggt(a,abs(45-87)); // Zuweisung

2. Prozeduraufruf mit Seiteneffekt:

print( ggt(24,248)); // Anweisung

Page 5: 4.2 Grundkonzepte prozeduraler Programmierung · Zuweisung : (engl. assignment) ... Semantik: Werte den Ausdruck aus und weise das Ergebnis der Variablen zu. (In Java ist eine Zuweisung

12.12.2006 297© A. Poetzsch-Heffter, TU Kaiserslautern

Ein Anweisungsblock (engl. block statement) ist eine Liste bestehend aus Deklarationen und Anweisungen.

Anweisungsblöcke

Syntax in Java:

{ <DeklAnweisListe> }

<DeklAnweisListe> � ε

| <Deklaration>

| <Anweisung>

| <Deklaration> <DeklAnweisListe>

| <Anweisung> <DeklAnweisListe>

Semantik:

Stelle den Speicherplatz für die Variablen bereit u ndführe die Anweisungen der Reihe nach aus.

12.12.2006 298© A. Poetzsch-Heffter, TU Kaiserslautern

Beispiel:

{ int i; i = 7; int a; a = 27 % i; }

Üblicherweise schreibt man Deklarationen und Anweisungen untereinander, so dass ein Textblock entsteht.

{

int i;int x;i = readInt();x = abs(i);

}

Schleifenanweisungen (engl. loop statements)steuern die iterative, d.h. wiederholte Ausführung von Anweisungen/Anweisungsblöcken.

while-Anweisung:

Syntax in Java:

while( <boolescherAusdruck> ) <Anweisung>

Schleifenanweisungen

12.12.2006 299© A. Poetzsch-Heffter, TU Kaiserslautern

Semantik:

Werte den Ausdruck aus, die sogenannte Schleifen-bedingung . Ist die Bedingung erfüllt, führe die Anweisung aus, den sogenannten Schleifenrumpf , und wiederhole den Vorgang. Andernfalls beende die Ausführung der Schleifenanweisung.

Beispiel:

Aus der Prozedur ggt:

while( m>0 )

{ v = n % m;n = m;m = v;

}

Bemerkung:

Der Schleifenrumpf ist in den meisten Fällen einAnweisungsblock. Syntaktisch korrekt ist aber auch z.B.:

while( true ) print(i);

while( m>0 ) {v = n % m;n = m;m = v;

}

12.12.2006 300© A. Poetzsch-Heffter, TU Kaiserslautern

do-Anweisung:

Syntax in Java:

do <Anweisung> while( <boolescherAusdruck> ) ;

Semantik:

Führe die Anweisung aus. Werte danach den boole-schen Ausdruck aus. Ist die Bedingung erfüllt ist, wiederhole den Vorgang. Andernfalls beende die Ausführung der Schleifenanweisung.

Bemerkung:

Die do-Anweisung ist immer dann sinnvoll, wenn maneinen Vorgang mindestens einmal ausführen muss.

In solchen Situationen spart man sich gegenüber derVerwendung der while-Schleife die anfänglich unnöti ge Auswertung der Bedingung.

Page 6: 4.2 Grundkonzepte prozeduraler Programmierung · Zuweisung : (engl. assignment) ... Semantik: Werte den Ausdruck aus und weise das Ergebnis der Variablen zu. (In Java ist eine Zuweisung

12.12.2006 301© A. Poetzsch-Heffter, TU Kaiserslautern

Beispiel:

Wir betrachten die Ausgabe der Elemente einer nicht -leeren Liste. Wir gehen davon aus, dass es einen Ty pIntList mit Prozeduren head, tail und isempty gibt:

IntList grades;

int g;

... // Zuweisung an die Variable noten

// Ausgabe der nicht-leeren Notenliste

do {

g = head(grades);

println(g);

grades = tail(grades);

} while( !isempty(grades) );

for-Anweisung (Zählanweisung):

Die for-Anweisung dient vorrangig zur Bearbeitungvon Vektoren und Matrizen, deren einzelneKomponenten über Indizes angesprochen werden.

Wir betrachten zunächst ein Beispiel:

12.12.2006 302© A. Poetzsch-Heffter, TU Kaiserslautern

// Skalarprodukt

void main( String[] args ){ int i;

// zwei Vektoren mit jeweils 3 Elementen

int v1[] = new int[3]; int v2[] = new int[3];int skalprod;

v1[0] = 1;v1[1] = 3;v1[2] = 8;

v2[0] = 2;v2[1] = 3;v2[2] = 4;

skalprod = 0;

for( i = 0; i<3; i++ ) { skalprod = skalprod + v1[i]*v2[i] ;

}println( skalprod );

}

Beispiel: (Zählanweisung)

12.12.2006 303© A. Poetzsch-Heffter, TU Kaiserslautern

Syntax in Java:

for( <Ausdrucksanweisung1> ;

<boolescherAusdruck> ;

<Ausdrucksanweisung2> ) <Anweisung>

<Ausdrucksanweisung> � <Variable> = <Ausdruck>

| <Variable> ++

| <Variable> --Semantik:

Ausdrucksanweisung:

1. Produktion: wie bei Zuweisung.

2./3. Produktion: Lese den Wert der Variablen. Erhöhe/erniedrige den Wert der Variablen um 1.Liefere den gelesenen Wert zurück.

for-Schleife:Ausdrucksanweisung1

boolescherAusdruck

Anweisung

Ausdrucksanweisung2

true

false

12.12.2006 304© A. Poetzsch-Heffter, TU Kaiserslautern

Verzweigungsanweisungen

Verzweigungsanweisungen (engl. branch statements)stellen Bedingungen an die Ausführung einerAnweisung oder wählen einen von mehreren Zweigen zur Ausführung aus.

Bedingte Anweisung:

Syntax in Java:

if( <boolescherAusdruck> ) <Anweisung>

Semantik:

Werte den Ausdruck aus. Ist das Ergebnis true,führe die Anweisung aus. Andernfalls ist die Ausführung sofort beendet.

Beispiele:

if( i != 0 ) { n = k/i; }

if( gute_Idee_vorhanden

&& genug_Zeit_zur_Vorbereitung )

{

halte_anregende_Weihnachtsvorlesung();

mache_schneller_damit_frueher_fertig();

}

Page 7: 4.2 Grundkonzepte prozeduraler Programmierung · Zuweisung : (engl. assignment) ... Semantik: Werte den Ausdruck aus und weise das Ergebnis der Variablen zu. (In Java ist eine Zuweisung

12.12.2006 305© A. Poetzsch-Heffter, TU Kaiserslautern

Fallunterscheidung:

Syntax in Java:

if( <boolescherAusdruck> ) <Anweisung1>

else <Anweisung2>Semantik:

Werte den Ausdruck aus. Ist das Ergebnis true,führe Anweisung1, andernfalls Anweisung2 aus.

Beispiel:

if( i!=0 ) {

n = k/i;

n++;

} else {

fehlerbehandlung(“Division durch Null“);

}

Auswahlanweisung:

Auswahlanweisungen erlauben es, in Abhängigkeit von dem Wert eines Ausdrucks direkt in einen vonendlich vielen Fällen zu verzweigen. In Javagibt es dafür die switch-Anweisung. Wir verzichtenhier auf eine genaue Beschreibung von Syntax undSemantik und betrachten ein Beispiel:

12.12.2006 306© A. Poetzsch-Heffter, TU Kaiserslautern

// AuswahlanweisungsTest

void main( String[] args ){

char c;

boolean machWeiter = true;

do {

print("Ein Zeichen aus {a,b,c,e}:");

c = readChar();

switch( c ) {

case 'a': proza(); break;

case 'b': prozb(); break;

case 'c': prozc(); break;

case 'e':

machWeiter = false;

break;

default:

print("Falsches Eingabezeichen");

}

} while( machWeiter );

}

Beispiel: (Auswahlanweisung)

wobei proza, prozb, prozc beliebige Prozeduren sind, zum Beispiel:

12.12.2006 307© A. Poetzsch-Heffter, TU Kaiserslautern

void proza() {

/* hier könnte 'was Interessantes stehen */

println("Ich bin Prozedur A. Alles gut?");

println("Probleme mit dem Weina'stress?\n");

}

void prozb() {

/* hier natürlich auch */

println("Wer A sagt, muss auch B sagen.");

println("Haben Sie schon A gesagt.\n");

}

void prozc() {

println("C wie no comment. Cool,oder?\n");

}

12.12.2006 308© A. Poetzsch-Heffter, TU Kaiserslautern

Sprunganweisungen

Sprunganweisungen (engl. jump statements) legeneine Fortsetzungsstelle der Ausführung fest, die möglicherweise weit von der aktuellen Anweisungentfernt liegt. Wir betrachten hier nur Sprünge, di e der Programmstruktur folgen.

Abbruchanweisung:

Syntax in Java:

break;

Semantik:

Die Ausführung wird am Ende der umfassenden zusammengesetzen Anweisung fortgesetzt.

Beispiele:

1. In Auswahlanweisung: siehe oben.

2. In Schleifenanweisungen:

while( true ) { ... if( <Abbruchbedingung> ) break;...

}

Page 8: 4.2 Grundkonzepte prozeduraler Programmierung · Zuweisung : (engl. assignment) ... Semantik: Werte den Ausdruck aus und weise das Ergebnis der Variablen zu. (In Java ist eine Zuweisung

12.12.2006 309© A. Poetzsch-Heffter, TU Kaiserslautern

Rückgabeanweisung:

Syntax in Java:

return ;

return <Ausdruck> ;

Semantik:

1. Produktion:Nur in Prozeduren ohne Rückgabewert erlaubt.Beende die Ausführung der Prozedur. Setze die Ausführung an der Aufrufstelle fort.

2. Produktion: Nur in Prozeduren mit Rückgabewert erlaubt.Werte den Ausdruck aus. Beende die Ausführung der Prozedur.Liefere den Wert des Ausdrucks als Ergebnis und setze die Ausführung an der Aufrufstelle fort.

Beispiel:

int abs( int n ) { if( n>=0 ) {

return n;

} else {

return -n;}

}

12.12.2006 310© A. Poetzsch-Heffter, TU Kaiserslautern

Eine Prozedur ist eine Abstraktion einer Anweisung.Sie gibt der Anweisung einen Namen und legt fest,was die Parameter der Anweisung sind. Prozedurenkönnen Ergebnisse liefern.

Begriffsklärung: (Prozedur)

Prozeduren erlauben es, von konkreten Anweisungenbzw. Anweisungssequenzen zu abstrahieren.

D.h. Prozeduren legen die Parameter einer zusammen-gesetzten Anweisung fest und geben ihr einen Namen.Dies ermöglicht:

- Wiederverwendung,

- Schnittstellenbildung und Information Hiding.

Darüber hinaus ermöglichen Prozeduren die rekursiveAusführung von Anweisungen.

4.2.3 Prozeduren

12.12.2006 311© A. Poetzsch-Heffter, TU Kaiserslautern

Beispiel: (Prozedur als Abstraktion)

Prozeduren abstrahieren Anweisungen genauso, wie Funktionen Ausdrücke abstrahieren (vgl. Folie 108).

Bemerkung:

Aufgabe: Berechne den Absolutbetrag einer ganzen Zahl gespeichert in Variable i und schreibe ihn in die Variable x.

Algorithmus:Wenn i größer oder gleich 0, liefere i als Ergebnis ;andernfalls –i. Weise das Ergebnis an x zu.

void main(...){int i;int x;i = readInt();

int result;if( i>=0 ) {

result = i;} else {

result = -i;}

x = result;}

Abstraktion bzgl. i ,result wird zum Ergebnis.

12.12.2006 312© A. Poetzsch-Heffter, TU Kaiserslautern

Deklaration von Prozeduren/Methoden:

Syntax in Java:

<Typ> <Prozedurbezeichner> ( <formaleParameter> )

<Anweisungsblock>

Semantik:

Die Semantik ist durch den Aufrufmechanismus und den Anweisungsblock, den sogenannten Prozedurrumpf bestimmt (Genaueres siehe unten).

int abs( int n ) {if( n>=0 ) {

return n;} else {

return -n;}

}

void main(...){int i;int x;i = readInt();

x = abs(i);}

Page 9: 4.2 Grundkonzepte prozeduraler Programmierung · Zuweisung : (engl. assignment) ... Semantik: Werte den Ausdruck aus und weise das Ergebnis der Variablen zu. (In Java ist eine Zuweisung

12.12.2006 313© A. Poetzsch-Heffter, TU Kaiserslautern

Bemerkung:Ein- und Ausgabeoperationen sind typischerweisedurch Prozeduren realisiert.

Beispiele:

1. Iterativer Algorithmus zur Berechnung vom ggT:

2. Rekursiver Algorithmus zur Berechnung vom ggT:

int ggT ( int m, int n ) { int v;

while( m>0 ) { v = n % m;n = m;m = v;

}return n;

}

int ggT ( int m, int n ) {

if( m == 0 ) {

return n;

} else {

return ggT(n%m,m);

}

}

12.12.2006 314© A. Poetzsch-Heffter, TU Kaiserslautern

Prozeduren, die Ergebnisse liefern, heißenFunktionsprozeduren .

Definition: (Funktionsprozedur)

Bemerkung:

Begriffsklärung: (Effekte)

Die Ausführung von Prozeduren verändert denSpeicherzustand und bewirkt Ein- und Ausgaben.Zusammenfassend sprechen wir von den Effektender Ausführung einer Prozedur, aufgeteilt in:

• Haupteffekte : Abliefern von Ergebnissen,Verändern von Variablenparametern;

• Seiteneffekte : Ein- und Ausgabe, Verändern globaler Variablen, Erzeugen und Löschen dynamischer Variablen (z.B. Instanzvariablen).

• Variablenparameter und dynamische Variablenbetrachten wir erst später.

• Eine Funktionsprozedur kann benutzt werden, umeine Funktion zu implementieren (Beispiel ggT).Sie kann aber auch hauptsächlich zur Realisierungvon Seiteneffekten benutzt werden.

12.12.2006 315© A. Poetzsch-Heffter, TU Kaiserslautern

Beispiel: (Prozedur mit Seiteneffekt)

Prozedur, die Zahlen von der Eingabe liest undaddiert, bis eine Null eingegeben wird. Die Summeder eingegebenen Zahlen wird ausgedruckt, dieAnzahl der Eingaben zurückgeliefert:

// Summiere

int summiere() { // Arbeitet nur bei korrekter Eingabe// der Zahlen durch Benutzerint anz = 0;int summe = 0;int eingabe;

do {print("Summand (0 beendet):");eingabe = readInt();summe += eingabe;anz++;

} while( eingabe != 0 );

println( "Summe: " + summe ); return anz-1;

}

12.12.2006 316© A. Poetzsch-Heffter, TU Kaiserslautern

void main( String[] args ) { boolean b = true;

while( b ) { int anzahl;anzahl = summiere();println("Es wurden "+ anzahl

+ " Zahlen summiert");

println("Beenden mit j/n:");char c;c = readChar();if( c == 'j' ) {

b = false;}

}}

Anwendung der Prozedur summiere :

Bemerkung:

• Die Hauptprozedur main wird vom Betriebssystemaufgerufen. Das Starten eines prozeduralen Programms entspricht dem Aufruf der Hauptprozedur.

• Argumente vom Programmaufruf werden main als String-Feld mitgegeben.

Page 10: 4.2 Grundkonzepte prozeduraler Programmierung · Zuweisung : (engl. assignment) ... Semantik: Werte den Ausdruck aus und weise das Ergebnis der Variablen zu. (In Java ist eine Zuweisung

12.12.2006 317© A. Poetzsch-Heffter, TU Kaiserslautern

Definition: (rekursive Prozedurdekl.)

Eine Prozedurdeklaration P heißt direkt rekursiv , wenn der Prozedurrumpf einen Aufruf von P enthält.

Eine Menge von Prozedurdeklarationen heißenverschränkt rekursiv oder indirekt rekursiv(engl. mutually recursive), wenn die Deklarationengegenseitig voneinander abhängen.

Eine Prozedurdeklaration heißt rekursiv , wenn sie direkt rekursiv ist oder Element einer Menge verschränkt rekursiver Prozeduren ist.

Bemerkung:Wir identifizieren Prozeduren mit ihren Prozedur-deklarationen. D.h. zwei Prozedurdeklarationen deklarieren immer zwei unterschiedliche Prozeduren.( Im Unterschied dazu konnten zwei Funktions-

deklarationen die gleiche Funktion deklarieren.)

Beispiel: int p1 ( int n ) { return 1; }

int p2 ( int n ) { return 1; }

sind zwei unterschiedliche Prozeduren.

12.12.2006 318© A. Poetzsch-Heffter, TU Kaiserslautern

Beispiel: (rekursive Prozeduren)

// Aufrufbaum

final int TAB = 4;int indent = 0 ; // Einruecktiefe

void drucke_eingerueckt( String s ) {int i;for( i = 0; i<indent; i++ ) {

print(" "); } println( s );

}

void s() { drucke_eingerueckt("Betrete s");indent += TAB;indent -= TAB; drucke_eingerueckt("Verlasse s");

}

void r( int ir ) { drucke_eingerueckt("Betrete r");indent += TAB;if( ir < 2 ) {

s(); }indent -= TAB;drucke_eingerueckt("Verlasse r");

}

12.12.2006 319© A. Poetzsch-Heffter, TU Kaiserslautern

void p( int i ) { drucke_eingerueckt("Betrete p");indent += TAB;if( i > 2 ) {

p( 2 ); q( 2 );r( 2 );

}indent -= TAB;drucke_eingerueckt("Verlasse p");

}

void q( int iq ) { drucke_eingerueckt("Betrete q");indent += TAB;p(iq);indent -= TAB;drucke_eingerueckt("Verlasse q");

}

- r und s sind nicht rekursiv.

- q ist verschränkt rekursiv.

- p ist direkt und verschränkt rekursiv.

(Beachte: q wurde vor seiner Deklaration angewendet.)

12.12.2006 320© A. Poetzsch-Heffter, TU Kaiserslautern

Mit der Hauptprozedur:

ergibt sich folgende Ausgabe:

public static void main( String[] args ) { drucke_eingerueckt("Betrete main");indent += TAB;p(3); r(1);indent -= TAB; drucke_eingerueckt("Verlasse main");

} }

Betrete mainBetrete p

Betrete pVerlasse pBetrete q

Betrete pVerlasse p

Verlasse qBetrete rVerlasse r

Verlasse pBetrete r

Betrete sVerlasse s

Verlasse rVerlasse main

Jeder Balken entspricht einer Prozedurinkarnation.Es gibt mehrere Inkarnationen der gleichen Prozedur .

Abl

auf

Page 11: 4.2 Grundkonzepte prozeduraler Programmierung · Zuweisung : (engl. assignment) ... Semantik: Werte den Ausdruck aus und weise das Ergebnis der Variablen zu. (In Java ist eine Zuweisung

12.12.2006 321© A. Poetzsch-Heffter, TU Kaiserslautern

Beim Aufruf einer Prozedur p wird eine neue Inkarnation von p erzeugt. Dabei wird:

- Speicherplatz für die lokalen Variablen angelegt;

- die Anweisung gemerkt, an der nach Ausführungder Prozedurinkarnation fortzusetzen ist.

Die Lebensdauer einer Prozedurinkarnation beginnt mit deren Erzeugung und endet mit der Ausführung des Rumpfes zu dieser Inkarnation. Die Lebensdauer erstreckt sich über einen Teil des Programmablaufs.

Bemerkung:Eine wichtige Struktur des Ablaufs prozeduralerProgramme ist der Aufrufbaum. Am Beispiel:

Begriffsklärungen: (zur Prozedurausführung)

main.1

p.1

p.2

p.3

q.1 r.1 s.1

r.2

Die Lebensdauern von Inkarnationen der gleichenProzedur können sich überlappen (z.B.: p.1 und p.3 ).

12.12.2006 322© A. Poetzsch-Heffter, TU Kaiserslautern

Der Prozeduraufrufbaum beschreibt die Prozedur-aufrufstruktur in einem Programm- oder Prozedur-ablauf.

Seine Baumknoten sind mit Prozedurinkarnationen markiert, so dass jede Inkarnation PI genau dieInkarnationen als Kinder hat, die von PI aus erzeug twurden und zwar in der Reihenfolge des Ablaufs.

Bemerkung:Die Lebensdauern von Inkarnationen der gleichenProzedur können sich überlappen. Deshalb musses ggf. mehrere Kopien/Instanzen der gleichen lokalen Variablen geben.

Beispiel:// Lebensdauer

void p( int i ){ //b(p)

int a;a = i; //1(p)if( a == 2 ) { //2(p)

p( a-1 ); //3(p) } println(i); //4(p)

} //e(p)

int c;

void main(...){ //b(m)

p(2); //1(m)

} //e(m)

12.12.2006 323© A. Poetzsch-Heffter, TU Kaiserslautern

4.2.4 Variablen in Programm und Speicher

Jede Variablendeklaration definiert eine Programmvariable. Wir unterscheiden:

- globale Variablen

- (prozedur-)lokale Variablen

- Klassenvariablen, Attribute, usw.

Jeder Programmvariablen entsprechen zurAusführungszeit/Laufzeit des Programms eine odermehrere Speichervariablen:

- Jeder globalen Variablen ist genau eine Speicher-variable zugeordnet.

- Ist v eine lokale Variable zur Prozedur p, dann gi btes zu jeder Inkarnation von p eine Speichervariablefür v.

- (andere Variablentypen behandeln wir später).

Begriffsklärung: (statisch/dynamisch)Statisch bezeichnet man in der Programmiertechnikalle Aspekte, die sich auf das Programm beziehen un ddie man aus ihm ersehen kann, ohne es auszuführen. Statische Aspekte sind unabhängig von Eingaben.

Dynamisch bezeichnet man alle Aspekte, die sich aufdie Ausführungszeit beziehen.

12.12.2006 324© A. Poetzsch-Heffter, TU Kaiserslautern

Definition: (Lebensdauer von Variablen)

Die Lebensdauer einer Speichervariable ist der Teil des Ablaufs, in dem sie für die Ausführungbereit steht.

Die Lebensdauer globaler Variablen erstreckt sich über den gesamten Ablauf des Programms.

Variablen zu lokalen Deklarationen leben solange wie die zugehörige Prozedurinkarnation bzw. überdie Dauer der Ausführung ihres Blocks.

Beispiele: (statisch/dynamisch)

Statisch:

- Programmvariablen

- Prozedurdeklarationen

- Anweisung

- Aspekte der Übersetzung

Dynamisch:

- Speichervariablen

- Prozedurinkarnationen

- Ablauf, Ausführung

- Aufrufbäume

- Lebensdauer (von Prozedurinkarnationen, usw.)

Page 12: 4.2 Grundkonzepte prozeduraler Programmierung · Zuweisung : (engl. assignment) ... Semantik: Werte den Ausdruck aus und weise das Ergebnis der Variablen zu. (In Java ist eine Zuweisung

12.12.2006 325© A. Poetzsch-Heffter, TU Kaiserslautern

Beispiel: (Lebensdauer von Variablen)

Wir betrachten den Ablauf des obigen Programms mit den Markierungen und die Variablenlebensdauer:

c a.1 a.2

b(m.1)

1(m.1)

b(p.1)

1(p.1)

2(p.1)

3(p.1)

b(p.2)

1(p.2)

2(p.2)

4(p.2)

e(p.2)

4(p.1)

e(p.1)

e(m.1)

Bemerkung:

Es gibt auch Variablen, deren Lebensdauer direktüber Anweisungen gesteuert werden kann.

12.12.2006 326© A. Poetzsch-Heffter, TU Kaiserslautern

Beispiel: (Lebensdauer von Variablen, die 2.)

int k = 0;while( k<0 ) {

int i = 0;while( i<3 ){

int j;i++;j += i;printf("%i\n",i);

}k++;

}

Was ist die Lebensdauer von j? (siehe Vorlesung)

Wir betrachten den Ablauf des folgenden C-Programmfragments:

12.12.2006 327© A. Poetzsch-Heffter, TU Kaiserslautern

4.2.5 Felder

Ein Feld (engl. Array) ist ein n-Tupel von Variablen des gleichen Typs T (vgl. Folie 180).

Die genaue Syntax und Semantik von Feldern istvon Sprache zu Sprache verschieden.

In Java sind Felder Objekte. Objekte veranschaulich enwir durch einen rechteckigen Kasten:

- die Titelzeile enthält den Typ;

- der Hauptteil enthält die Variablen/Komponentenmit ihren Namen bzw. Indizes.

Variablen für Felder speichern Referenzen/Zeiger auf das Feldobjekt.

int[] a:

b:

Beispiel: (Veranschaulichung eines Felds)

length: 3

0 : -7

1 : 46

2 : 0

int[] a = new int[3] ;

int[] b = a

12.12.2006 328© A. Poetzsch-Heffter, TU Kaiserslautern

Feldtypen, Operationen auf Feldern:

Mit T[] wird in Java der Typ von Feldern mit Komponenten vom Typ T bezeichnet. Deklaration einer Variablen

T[] a;

stellt nur den Speicherplatz für die Variable berei t;sie erzeugt kein Feld!

Ein neues Feld mit n Komponenten vom Typ T wird von dem Ausdruck new T[n] erzeugt. Der Ausdruck liefert eine Referenz auf des Feldals Ergebnis. Initialisierung:

- Die Variable length ist mit n initialisiert.

- Alle anderen Komponenten sind mit dem Initialwert des Typs T initialisiert. (Für alleZahltypen ist der Initialwert 0, für boolean ister false .)

Die Lebensdauer eines Felds

- beginnt mit der Erzeugung und

- endet mit der Terminierung des Programms.

Page 13: 4.2 Grundkonzepte prozeduraler Programmierung · Zuweisung : (engl. assignment) ... Semantik: Werte den Ausdruck aus und weise das Ergebnis der Variablen zu. (In Java ist eine Zuweisung

12.12.2006 329© A. Poetzsch-Heffter, TU Kaiserslautern

Beispiel: (Lebensdauer von Feldern)

int[] erzeugeFeld( int n ) {int size = n < 0 ? 0 : n;return new int[size];

}

void eineProz() {int[] a = erzeugeFeld(78);...

}

Sei im Folgenden exp ein Ausdruck von einem ganz-zahligen Typ (byte, short, int, long), der sich zu k aus-wertet.

Ausdrücke zum Lesen und Schreiben eines Felds a:

- a.length liefert die Anzahl der Feldkomponenten

- a[exp] erzeugt eine IndexOutOfBounds-Ausnahme

falls k < 0 oder a.length ≤ k; andernfalls:R-Wert: der in der k-ten Feldkomponente

gespeicherte Wert;

L-Wert: die k-te Feldkomponente, d.h. z.B. weist

a[exp] = 7 ;

der k-ten Feldkompente den Wert 7 zu.

12.12.2006 330© A. Poetzsch-Heffter, TU Kaiserslautern

Beispiel: (Programmieren mit Feldern)

Das folgende Programm liest zwei Vektoren ein undgibt die Summe aus:

void main(String[] args) {

int i;

int[] a = new int[3]; // 3-elementiger Vektorint[] b = new int[3];

for( i=0; i<3; i++){

println("Eingabe a["+i+"]:");

a[i] = readInt();

println("Eingabe b["+i+"]:");

b[i] = readInt();

}

int[] c = new int[3];

for( i=0; i<3; i++){

c[i] = a[i] + b[i];

}

for( i=0; i<3; i++ ) {

println("c["+i+"] == "+c[i]);

}

}

12.12.2006 331© A. Poetzsch-Heffter, TU Kaiserslautern

String[] argf;float [] vector_3d = new float[3];int [][] matrix_3x3 = new int[3][3];

Beispiele: (2-dimensionale Felder & Initialisierung von Feldern)

Folgendes Beispiel zeigt weitere Erzeugungs- undInitialisierungsmöglichkeiten bei Feldern:

char[] vor = new char[3];

vor[0] = 'v';

vor[1] = 'o';

vor[2] = 'r';

char[] Fliegen = {'F','l','i','e','g','e','n'};

char[][] satz = { Fliegen,

{'f','l','i','e','g','e','n'},

vor,

Fliegen };int i,j;

String s = "";

for( i = 0; i < satz.length; i++ ) {

for( j = 0; j < satz[i].length; j++ ) {

s = s + satz[i][j];

}

if( i+1 < satz.length ) s = s + " ";

}

println( s + ".");

12.12.2006 332© A. Poetzsch-Heffter, TU Kaiserslautern

Nach der Zuweisung an ���� entsteht folgendesGeflecht:

char ����length: 4

0 :

satz:

Fliegen:

vor:

char ��1 : 2 : 3 :

length: 30 : ‘v‘ 1 : ‘o‘ 2 : ‘r‘

char ��length: 7

0 : ‘F‘ 1 : ‘l‘ 2 : ‘i‘ 3 : ‘e‘

5 : ‘e‘ 6 : ‘n‘

char ��length: 7

0 : ‘f‘ 1 : ‘l‘ 2 : ‘i‘ 3 : ‘e‘

5 : ‘e‘ 6 : ‘n‘

4 : ‘g‘ 4 : ‘g‘

Page 14: 4.2 Grundkonzepte prozeduraler Programmierung · Zuweisung : (engl. assignment) ... Semantik: Werte den Ausdruck aus und weise das Ergebnis der Variablen zu. (In Java ist eine Zuweisung

12.12.2006 333© A. Poetzsch-Heffter, TU Kaiserslautern

4.2.6 Benutzerdefinierte Typen

Die meisten prozeduralen Sprachen unterstützenbenutzerdefinierte Typen, insbesondere Verbundtypen.

Begriffsklärung: (Verbunde)Ein (Variablen-)verbund (engl. Record) ist ein n-Tupel von Variablen nicht notwendig des gleichen Typs. Die einzelnen Variablen nennt man die Komponenten des Verbunds. Die Komponenten werden über deklarierte Namen angesprochen.

Die genaue Syntax und Semantik von Verbunden istvon Sprache zu Sprache verschieden.

In Java lassen sich Verbunde nur als vereinfachteObjekte deklarieren und erzeugen. Als Ergebnis der Erzeugung erhält man dabei eine Referenz aufden Verbund. Die Referenz kann man in Variablenvom Verbundtyp speichern. Verbunde mit Referenzennennen wir referenzierte Verbunde .

Da wir im Folgenden nur referenzierte Verbundebetrachten, sprechen wir einfach von Verbunden.

12.12.2006 334© A. Poetzsch-Heffter, TU Kaiserslautern

Sprachmittel für (referenzierte) Verbunde:

- Deklaration eines Verbundtyps

- Deklaration von Variablen für (Referenzen auf)Verbunde

- Erzeugung von Verbunden

- Lesen der Verbundkomponenten

- Zuweisen an Verbundkomponenten

Paarp:

q: ersteKomp: 3

zweiteKomp : -7

Beispiel: (Veranschaulichung eines referenzierten Verbunds)

12.12.2006 335© A. Poetzsch-Heffter, TU Kaiserslautern

Syntax anhand von Beispielen:

class Paar {int ersteKomp;int zweiteKomp;

}

Deklaration einesVerbundtyps Paar :

Deklaration der Variablen p, q für Referenzen auf Verbunde vom Typ Paar :

Paar p;Paar q;

Erzeugung eines Verbundsvom Typ Paar und Zuweisungder Referenz an p:

p = new Paar();

Weitergabe einer Referenz, hier von p an q:

q = p;

Lesen einer Komponente: int a;a = p.ersteKomp;

Schreiben einer Komponente: int a;p.ersteKomp = a+1;

Der Initialwert für Verbund-typen ist null :

class C {Paar pk;

}

new C().pk == null

12.12.2006 336© A. Poetzsch-Heffter, TU Kaiserslautern

Verbunde zur Realisierung von Tupeln:

Deklaration eines Verbundtyps Student mitName und Matrikelnummer.

class Student {String name;int matNr;

}

studentDrucken( Student s ) {println("Name: " + s.name );println("Matriklenummer: " + s.matNr );

}

Deklaration einer Prozedur zum Drucken der Daten von Studenten:

Erzeugen eines Verbunds vom Typ Student,Zuweisung an eine Variable, Initialisieren derKomponenten und Ausdrucken:

Student sv = new Student();sv.name = "Max Planck";sv.matNr = 12390573;

studentDrucken( sv );

Page 15: 4.2 Grundkonzepte prozeduraler Programmierung · Zuweisung : (engl. assignment) ... Semantik: Werte den Ausdruck aus und weise das Ergebnis der Variablen zu. (In Java ist eine Zuweisung

12.12.2006 337© A. Poetzsch-Heffter, TU Kaiserslautern

Rekursive referenzierte Verbunde:

Beispiel: (Einfachverkettete Listen)

class IntList {int head;IntList tail;

}

Bei einfachverketteten Listen wird für jedes Listenelement ein Verbund mit zwei Komponentenangelegt:

- zum Speichern des Elements

- zum Speichern der Referenz auf den Rest der Liste.

IntList

head: 6 tail:

IntList IntList

head: -3 tail:

head: 84 tail:

Verbunddeklarationen können rekursiv sein, z.B.:

Mit rekursiven Verbunden lassen sich Listen,Bäume und allgemeine Graphen realisieren.

Die Liste [6,-3,84] erhält also folgende Repräsent ation:

12.12.2006 338© A. Poetzsch-Heffter, TU Kaiserslautern

/* Prozedur sortiert prüft, ob dieübergebenen List l sortiert ist.Vorbedingung: l darf keinen Zyklus enthalten

*/boolean sortiert( IntList l ){

if( l == null || l.tail == null ) {return true;

} else if( l.head <= l.tail.head ){return sortiert( l.tail );

} else {return false;

} }

void main( String[] argf ){

IntList l1 = new IntList();

IntList l2 = new IntList();IntList l3 = new IntList();

l1.head = 1;l2.head = 2;l3.head = 3;l1.tail = l2;l2.tail = l3;l3.tail = null;

println("" + sortiert(l1) );l3.head = 0;println("" + sortiert(l1) );

} }

Beispielprogramm:

12.12.2006 339© A. Poetzsch-Heffter, TU Kaiserslautern

Begriffsklärung: (Geflecht)

Eine Menge von Verbunden, die sich gegenseitig referenzieren, nennen wir ein Geflecht . Insbesonderekönnen Geflechte Zyklen enthalten.

Beispiel: (Geflecht)

KA

a1: a2: 8

KA

a1: a2: 97

KB

b:

KA

a1: a2: -6

: KB

b:

: KB

b:

Graphisch stellen wir null durch einen ausgefülltenkleinen Kreis dar.

Notation:

12.12.2006 340© A. Poetzsch-Heffter, TU Kaiserslautern

Verändern von Geflechten:

Anders als die Datentypen in reinen funktionalen Programmierung lassen sich Geflechte lokal modifizieren.

Veränderung an einem Verbund x wirken sich auf alle Verbunde und Variablen aus, die x direkt oderindirekt referenzieren.

Als Beispiel für Veränderungen betrachten wir eine Implementierung binärer Suchbäume:

/* Verbundtyp für Binärbäume mitMarkierung vom Typ int

*/class BinTree {

int elem;BinTree left, right;

}

Den leeren Binärbaum repräsentieren wir durch dieKonstante null . Wir betrachten die folgendenProzeduren:

- Prüfen, ob ein Element in einem Baum enthalten ist .

- Ausdrucken der Markierungen eines Baumes.

- Konstruktorprozedur mit Initialisierung

- Sortiertes Einfügen

Page 16: 4.2 Grundkonzepte prozeduraler Programmierung · Zuweisung : (engl. assignment) ... Semantik: Werte den Ausdruck aus und weise das Ergebnis der Variablen zu. (In Java ist eine Zuweisung

12.12.2006 341© A. Poetzsch-Heffter, TU Kaiserslautern

/* Prozedur contains prüft, ob Markierung ein b enthalten ist.Vorbedingung: b ist binärer Suchbaum

*/boolean contains( BinTree b, int e ) {

if( b == null ) {return false;

} else if( e < b.elem ){return contains(b.left,e);

} else if( b.elem < e ){return contains(b.right,e);

} else {return true;

}}

/* Prozedur printTree durchläuft den Baum inInorder-Reihenfolge und druckt die Markierungenaus, jede in eine Zeile.

*/void printTree( BinTree b ) {

if( b != null ) {if( b.left != null ) printTree(b.left);println(b.elem);if( b.right != null ) printTree(b.right);

}}

12.12.2006 342© A. Poetzsch-Heffter, TU Kaiserslautern

/* Sortiertes Einfügen. Erhält Suchbaumeigenschaft */BinTree sorted_insert( BinTree b, int e ) {

if( b == null ) {return mkBinTree(e);

} else {modifying_sorted_ins(b,e);return b;

} }

void modifying_sorted_ins( BinTree b, int e){if( e < b.elem ) {

if( b.left == null ) {b.left = mkBinTree(e);

} else {modifying_sorted_ins(b.left,e);

}} else if( b.elem < e ) {

if( b.right == null ) {b.right = mkBinTree(e);

} else {modifying_sorted_ins(b.right,e);

}} }

/* Konstruktorprozedur */BinTree mkBinTree( int e ) {

BinTree newbt = new BinTree();newbt.elem = e;return newbt;

}

12.12.2006 343© A. Poetzsch-Heffter, TU Kaiserslautern

void main( String[] argf ){

BinTree bt = mkBinTree(12);

sorted_insert(bt,3);

sorted_insert(bt,12);

sorted_insert(bt,233);

sorted_insert(bt,11);

sorted_insert(bt,12343);

sorted_insert(bt,-2343);

sorted_insert(bt,233);

printTree(bt);

}

Hauptprozedur zum Testen:

Bemerkung:

• Mit referenzierten Verbundstypen lassen sich nicht nur Listen und Bäume in unterschiedlicherForm realisieren, sondern auch allgemeine Graphen.

• Anspruchsvollere Algorithmen werden in Abschnitt 4.3 behandelt.

12.12.2006 344© A. Poetzsch-Heffter, TU Kaiserslautern

4.2.7 Sichtbarkeit von Bindungen

Deklarationen binden Bezeichner an Programm-elemente (z.B. an Variablen oder an Prozeduren). Die Sichtbarkeitsregeln bestimmen, welche Bindungenwo zulässig und benutzbar sind.

Beispiel: (Sichtbarkeit von Bindungen)

public class Sichtbarkeiten {

static int m;

static void p( int p ) { int m;int a = 7;{

int m = 0; // unzulässigif( p > 0 ) {

p(p-1); }

}}

public static void main(String[] a ){

m = 1;p(m);

}}

Folgender Programmtext ist kein Java-Programm,da nur eine Variablenbindung für den Bezeichner m erlaubt ist:

Page 17: 4.2 Grundkonzepte prozeduraler Programmierung · Zuweisung : (engl. assignment) ... Semantik: Werte den Ausdruck aus und weise das Ergebnis der Variablen zu. (In Java ist eine Zuweisung

12.12.2006 345© A. Poetzsch-Heffter, TU Kaiserslautern

Programme sind in Deklarationsbereiche (engl. scopes ) eingeteilt. In der betrachteten Java-Teilsprachegibt es die folgenden Deklarationsbereiche:

- das gesamte Programm

- jede Prozedur/Methode

- jeder Anweisungsblock

Die Deklarationsbereiche sind geschachtelt(engl. nested ). Ein Deklarationsbereich darf auf seiner äußersten Schachtelungsebene für jeden Bezeichner nur eine Deklaration enthalten.

Zu jeder Deklaration gibt es einen Gültigkeitsbereich .In der betrachteten Java-Teilsprache gilt:

Der Gültigkeitsbereich einer Deklaration erstrecktsich bei

- Prozeduren und globalen Variablen über den gesamten direkt umfassenden Deklarationsbereich;

- lokalen Variablen von der Deklarationsstelle bis z umEnde des direkt umfassenden Deklarationsbereichs.

Begriffsklärung: (zur Sichtbarkeit)

12.12.2006 346© A. Poetzsch-Heffter, TU Kaiserslautern

Grundsätzlich gilt:

Eine Bindung B, die in einem Deklarationsbereich Ddeklariert wurde, verschattet (engl. to shadow , to hide ) andere Bindungen mit gleichem Bezeichner, die außerhalb von D vereinbart wurden, in dem Gültigkeitsbereich von B.

Eine Bindung ist an den Stellen ihres Gültigkeits-bereichs sichtbar , an denen sie nicht verschattet ist.Den Bereich, in dem eine Bindung B sichtbar ist,nennt man den Sichtbarkeitsbereich von B.

Bemerkung:

• Statt von Deklarationsbereichen spricht manteilweise von Blöcken und dementsprechend vonder Blockstruktur eines Programms.

• Die Begriffe Sichtbarkeits-, Gültigkeitsbereich undLebensdauer werden leider häufig auch andersverwendet.

• Die erläuterten Bereiche sind Bereiche des Program m-texts. Dementsprechend beschreiben alle oben eingeführten Begriffe statische Aspekte.

• Sichtbarkeitsregeln sind im Allg. sprachspezifisch.

12.12.2006 347© A. Poetzsch-Heffter, TU Kaiserslautern

int m;

void p

( int p )

{

int m;

int a = 7;

{

int m = 0; //unzulässig

if( p > 0 )

{

p(p-1);

}

}

}

void main

( String[] a )

{

m = 1;

p(m);

}

Beispiel: (Deklarationsbereiche)

1

1.1

1.2

1.1.1

1.2.1

12.12.2006 348© A. Poetzsch-Heffter, TU Kaiserslautern

// Sichtbarkeiten2

void p

( int p )

{ int a = 7;

{ int m = 1;

println("m:"+ m);

}

{

println("m:"+ m);

int m = 2;

println("m:"+ m);

}

}

int m = 0;

void main

( String[] p )

{

int m = 3;

p(m);

}

Beispiel: (Sichtbarkeitsanalyse)

1

1.1

1.2

1.2.1

1.1.1

Page 18: 4.2 Grundkonzepte prozeduraler Programmierung · Zuweisung : (engl. assignment) ... Semantik: Werte den Ausdruck aus und weise das Ergebnis der Variablen zu. (In Java ist eine Zuweisung

12.12.2006 349© A. Poetzsch-Heffter, TU Kaiserslautern

Beispiel: (Gültigkeitsbereiche)

Der Gültigkeitsbereich der globalen Variablen merstreckt sich über das ganze Programm.Der Gültigkeitsbereich der lokalen Variablen mjeweils von der Deklarationstelle bis zum Ende desdirekt umfassenden Anweisungsblocks:

// Sichtbarkeiten2

void p

( int p )

{ int a = 7;

{ int m = 1;

println("m:"+ m);

}

{

println("m:"+ m);

int m = 2;

println("m:"+ m);

}

}

int m = 0;

...

12.12.2006 350© A. Poetzsch-Heffter, TU Kaiserslautern

Beispiel: (Sichtbarkeitsbereiche)Eine Bindung B, die in einem Deklarationsbereich Ddeklariert wurde, verschattet andere Bindungen mit gleichem Bezeichner, die außerhalb von D vereinbart wurden, im Gültigkeitsbereich von B.

Also wird das globale m von den lokalen verschattet :

// Sichtbarkeiten2

void p

( int p )

{ int a = 7;

{ int m = 1;

println("m:"+ m);

}

{

println("m:"+ m);

int m = 2;

println("m:"+ m);

}

}

int m = 0;

...

12.12.2006 351© A. Poetzsch-Heffter, TU Kaiserslautern

Bemerkung:

• In realistischen Programmiersprachen können dieSichtbarkeitsregeln insgesamt recht komplex sein.

• Die Kenntnis der Sichtbarkeitsregeln ist wichtig,um Fehlermeldungen vom Übersetzer zu verstehenund um Namensprobleme beim Importierenvon Modulen geeignet behandeln zu können.

• Sichbarkeitsregeln bieten eine erste Einführung indie Behandlung von Namensräumen.

12.12.2006 352© A. Poetzsch-Heffter, TU Kaiserslautern

Beispiel:

Berechne das Maximum einer Liste ganzer Zahlen.Für die leere Liste liefere 0 als Ergebnis.

Wir gehen davon aus, dass es einen Typ IntList mit Funktionsprozeduren head, tail und isempty gibt sowie:

int max( int m, int n ) {

return (m > n) ? m : n;

}

Wir verzichten auf eine allgemeine Behandlungund betrachten nur ein Beispiel (vgl. Goos, Band 3 ,S. 152 ff)

4.2.8 Iteration und Rekursion

Rekursive Prozeduren lassen sich in vielen Fällenin iterative Programme transformieren, d.h. in Programme, die keine Rekursion, sondern nurSchleifen enthalten.

Die Lösung mit rekursiven Prozeduren kann eleganterund einfacher sein. Demgegenüber ist eine iterativeLösung meist effizienter.

Die Transformation rekursiver Prozeduren in iterati veProgramme ist ein klassisches Beispiel für optimierende Programmtransformationen.

Page 19: 4.2 Grundkonzepte prozeduraler Programmierung · Zuweisung : (engl. assignment) ... Semantik: Werte den Ausdruck aus und weise das Ergebnis der Variablen zu. (In Java ist eine Zuweisung

12.12.2006 353© A. Poetzsch-Heffter, TU Kaiserslautern

1. Rekursive Ausgangsfassung:

int maxl( IntList il ) {

if( isempty(il) ) {

return 0;

} else if( isempty(tail(il)) ) {

return head(il);

} else { // (Laenge von il) >= 2

return max(head(il),maxl(tail(il)));

}

}

void main( String[] args ) {

IntList l = ... ;

println("maxl: "+ maxl(l) );

}

Die Funktionsprozedur maxl ist linear rekursiv, abernicht repetitiv. Führe zur Einbettung einen zusätzl ichenParameter ein, der das Maximum des gesehenenPräfixes mitführt (vgl. Folien 125ff).

12.12.2006 354© A. Poetzsch-Heffter, TU Kaiserslautern

2. Repetitive Fassung durch Einbettung:

int maxlrep( int aktmax, IntList il ) {

if( isempty(il) ) {

return aktmax;

} else {

return maxlrep( max(aktmax,head(il)),

tail(il) );

}

}

int maxl( IntList il ) {

if( isempty(il) ) {

return 0;

} else {

return maxlrep( head(il), tail(il) );

}

}

void main( String[] arges ) {

IntList l = ... ;

println("maxl: "+ maxl(l) );

}

Die Funktionsprozedur maxl ist nicht mehr rekursivund kann expandiert werden.

12.12.2006 355© A. Poetzsch-Heffter, TU Kaiserslautern

3. Repetitive Fassung nach Expansion von maxl:

int maxlrep( int aktmax, IntList il ) {

if( isempty(il) ) {

return aktmax;

} else {

return maxlrep( max(aktmax,head(il)),

tail(il) );

}

}

void main( String[] args ) {

IntList l = ... ;

int mx;

if( isempty(l) ) {

mx = 0;

} else {

mx = maxlrep( head(l), tail(l) );

}

println("maxl: " + mx );

}

Transformiere die Funktionsprozedur maxlrep in eineProzedur, die ihr Ergebnis in globaler Variable abl iefert.

12.12.2006 356© A. Poetzsch-Heffter, TU Kaiserslautern

4. Repetitive Fassung nach Einführung einer Ergebnisvariablen:

int res;

void maxlrep( int aktmax, IntList il ) {

if( isempty(il) ) {

res = aktmax;

} else {

maxlrep( max(aktmax,head(il)), tail(il));

}

}

void main( String[] args ) {

IntList l = ... ;

int mx;

if( isempty(l) ) {

mx = 0;

} else {

maxlrep( head(l), tail(l) );

mx = res;

}

println("maxl: " + mx );

}

Nun folgt der zentrale Schritt der Transformation derrepetitiven Fassung in eine iterative Fassung:

Page 20: 4.2 Grundkonzepte prozeduraler Programmierung · Zuweisung : (engl. assignment) ... Semantik: Werte den Ausdruck aus und weise das Ergebnis der Variablen zu. (In Java ist eine Zuweisung

12.12.2006 357© A. Poetzsch-Heffter, TU Kaiserslautern

5. Iterative Fassung mit Prozeduraufruf:

int res;

void maxlrep( int aktmaxpar, IntList ilpar ) {

int aktmax = aktmaxpar;

IntList il = ilpar;

while( !isempty(il) ) {

aktmax = max(aktmax,head(il));

il = tail(il);}

res = aktmax;}

void main( String[] args ) {

IntList l = ... ;

int mx;

if( isempty(l) ) {

mx = 0;

} else {

maxlrep( head(l), tail(l) );

mx = res;

}

println("maxl: " + mx );}

Expansion von der Prozedur maxlrep:12.12.2006 358© A. Poetzsch-Heffter, TU Kaiserslautern

6. Iterative Fassung:

int res;

void main( String[] args ) {

IntList l = ... ;

int mx;

if( isempty(l) ) {

mx = 0;

} else {

int aktmax = head(l);

IntList il = tail(l);

while( !isempty(il) ) {

aktmax = max(aktmax,head(il));

il = tail(il);

}

res = aktmax;

mx = res;

}

println("maxl: " + mx );

}

Vereinfachung durch Elimination unnötiger Variablen.

12.12.2006 359© A. Poetzsch-Heffter, TU Kaiserslautern

7. Vereinfachte iterative Fassung:

void main( String[] args ) {

IntList l = ... ;

int mx;

if( isempty(l) ) {

mx = 0;

} else {

mx = head(l);

IntList il = tail(l);

while( !isempty(il) ) {

mx = max(mx,head(il));

il = tail(il);

}

}

println("maxl: " + mx );

}

Bemerkung:• Formal kann man Programmtransformation mit

Regelsystemen beschreiben.

• Programmtransformationen sind nicht nur wichtig zu rEffizienzsteigerung, sondern auch um Programme

- verständlicher zu machen (Redesign);

- an neue Anforderungen anzupassen.

12.12.2006 360© A. Poetzsch-Heffter, TU Kaiserslautern

Beispiel: (Transformationsregel)

Transformationsregel: repetitiv � iterativ

Seien p ein Prozedurname, T1,...,Tn Typbezeichner, A1,..,An und B seiteneffektfreie-Ausdrücke,C und D Anweisungen, die keinen Aufruf

von p enthalten:

void p( T1 x1, ... , Tn xn) { if( B ) {

C} else {

Dp( A1(x1,...xn),..., An(x1,...,xn) );

}}

void p( T1 y1, ... , Tn yn) { T1 x1 = y1;...Tn xn = yn;while( !B ) {

Dx1 = A1(x1,...,xn);... xn = An(x1,...,xn);

}C

}

Page 21: 4.2 Grundkonzepte prozeduraler Programmierung · Zuweisung : (engl. assignment) ... Semantik: Werte den Ausdruck aus und weise das Ergebnis der Variablen zu. (In Java ist eine Zuweisung

12.12.2006 361© A. Poetzsch-Heffter, TU Kaiserslautern

Für obiges Transformationsbeispiel (Folie 356)ergibt sich mit der Regel:

p ≡ maxlrep ,

T1 ≡ int, x1 ≡ aktmax,

T2 ≡ IntList , x2 ≡ il,

B ≡ isempty(il)

C ≡ res = aktmax;

D ≡ // leere Anweisung

A1 ≡ max(aktmax,head(il))

A2 ≡ tail(il)

A1,A2 und B sind seiteneffektfrei;C und D enthalten keinen Aufruf von � �� ����;die Regel ist also auf � �� ���� anwendbar undliefert:

void maxlrep( int y1, IntList y2) { int aktmax = y1;IntList il = y2;while( !isempty(il) ) {

aktmax = max(aktmax,head(il));il = tail(il);

}res = aktmax;

}

Durch konsistente Parameterumbenennung erhält man die Prozedur von Folie 357.

12.12.2006 362© A. Poetzsch-Heffter, TU Kaiserslautern

Bemerkung:

• Im Prinzip lassen sich Programme mit Transformationsregeln genauso umformen wie mathematische Ausdrücke.

• Die Transformationsregeln für realistische Programmiersprachen sind sehr komplex.Dies beginnt bereits bei einer präzisen Behandlungvon Namen (vgl. Sichtbarkeitsregeln).

Wir haben hier nur den Sprachkern prozeduralerSprachen betrachtet. Weitere Sprachkonzepte:

• Verbünde, variante Verbünde

• Zeiger ggf. mit Zeigerarithmetik

• Prozedurparameter

• Generische/parametrische Typen

• Modul-/Paketkonzepte

• Kapselung/Schnittstellen

4.2.9 Weitere prozedurale Sprachkonzepte