Grundlagen der Programmierung (Vorlesung 14) Ralf Möller, FH-Wedel ❚ Vorige Vorlesung ❙ Verifikation von Anweisungen und Anweisungsfolgen ❙ Schleifen ❚ Inhalt dieser Vorlesung ❙ Funktionen und Prozeduren ❚ Lernziele ❙ Grundlagen der systematischen Programmentwicklung Schleifen Schleifen (2) Ganzzahlige Division mit Rest mittels While z Spezifikation y var x, y, q, r : N0 y { y > 0 } S { q * y + r = x fi r < y} y V P y P: q * y + r = x y I fi r<y fi –B y Gut: Spezifikation schon in der richtigen Form z { V } S0 { I }; z { I } while B do { I fi B } S1 { I } end while { P } Ganzzahlige Division mit Rest mittels While z var x, y, q, r : N0 z { y > 0 } q, r := 0, x { q * y + r = x } V So I B z while r ≥ y do z {q * y + r = x fi r >= y} q, r := q+1, r-y {q * y + r = x} z end while S1 z {q * y + r = x fi r < y} fi –B P I Terminierungsbeweis z Für die Variante t wähle: r z Zeige Fortschritt: y {I fi B fi t > T} S1 {t = T} muß korrekt sein, d.h. {I fi B fi r > T} q, r := q+1, r-y {r = T} muß korrekt sein x Also r¨ r-y in Nachbedingung einsetzen x Damit ergibt sich r-y = T x Es ergibt sich: r > T, wenn y > 0 y (I fi t £ 0) ¡ –B muß gültig sein, d.h. (I fi r £ 0) ¡ r < y muß gültig sein x Unter der Voraussetzung, daß r £ 0 und y > 0 ist r < y immer erfüllt ° Y ¾ÀîQÀ Á ½ ¹ r³ÛQÚo HH rstu é ï[ðRñò'óõôðöw÷wò'ö/Z\[zò^],_lñò'ó÷ ðöw÷wò'ö|ðö/`ba4ced4fò'óhgmò'ö E0 !/5+º»:!/:Å!T"bß75!/:XQ0E ¾íÀÉîEÀ Á ½ aЩAFDSR0E!DS:0E!ß 8 ¾íÀÉîEÀ Á ½ Øç æOâeÚOÙUç4¡ ¿4Ƚ ¶ìÂÆ æ`ÛWâe@ç ¡kÙ04ç ¡ rH < p3F$OFDSW ê Ç ¶ì À a ЩAFDS Øç/ æOâeÚÙUç@¡ % ê Ç ¶ì À ×2Æ æ`ÛWâeç@¡kÙ0ç4¡ Ê ß Øç æOâeÚOÙUç4¡ ÀÈ<Ê ê Ç ¶ë À rH < DS1$p3 ª#«¬ Ë"bß75!/: qþ *Щ/FD/,!p3DOÿZßO8 0E!/5:D !Î /P ª,9¬ ðº»l/:!:~ß+0E!5:Eß P6 ª´ ¬ 5,+/0E5*û-58!/F#0< ½6¾e¿À .51ßO8W"!/5AD!Î /,!/: 5 ȼ$1:80Ep3p35/@*ЩFDËDS1PA:56 ª ´/µ ¬ 5,+/0E5*û-58!/F#0< ·UÁ4ÂÄà À .51ýßO8Ë"!5,D!Î /,!/: ЩAFDS ßOl,1F ЩAFDS,!/p3DußO8 Ò w Ø wxlxlxp)0E90E!5:6D !/Î PlG />©@-D!ΠЩ/FD !:80E!9©/.è, û !/p3D p 1Î :>©A' ß 5">©4+0E!5:D!Î /PßO8èG ê Ç ¶ì À aЩ/FD 0E:p3 ¾íÀÉîEÀ Á ½ a Щ/FDRoUÛQÚB'& @+0E5 ê Ç ¶ì À aЩ/FD ° Y ¾ÀîQÀ Á ½ ¹ r³ÛQÚo HH rstu é ï[ðRñò'óõôðöw÷wò'ö/Z\[zò^],_lñò'ó÷ ðöw÷wò'ö|ðö/`ba4ced4fò'óhgmò'ö E0 !/5+º»:!/:Å!T"bß75!/:XQ0E ¾íÀÉîEÀ Á ½ aЩAFDSR0E!DS:0E!ß 8 ¾íÀÉîEÀ Á ½ Øç æOâeÚOÙUç4¡ ¿4Ƚ ¶ìÂÆ æ`ÛWâe@ç ¡kÙ04ç ¡ rH < p3F$OFDSW ê Ç ¶ì À a ЩAFDS Øç/ æOâeÚÙUç@¡ % ê Ç ¶ì À ×2Æ æ`ÛWâeç@¡kÙ0ç4¡ Ê ß Øç æOâeÚOÙUç4¡ ÀÈ<Ê ê Ç ¶ë À rH < DS1$p3 ª#«¬ Ë"bß75!/: qþ *Щ/FD/,!p3DOÿZßO8 0E!/5:D !Î /P ª,9¬ ðº»l/:!:~ß+0E!5:Eß P6 ª´ ¬ 5,+/0E5*û-58!/F#0< ½6¾e¿À .51ßO8W"!/5AD!Î /,!/: 5 ȼ$1:80Ep3p35/@*ЩFDËDS1PA:56 ª ´/µ ¬ 5,+/0E5*û-58!/F#0< ·UÁ4ÂÄà À .51ýßO8Ë"!5,D!Î /,!/: ЩAFDS ßOl,1F ЩAFDS,!/p3DußO8 Ò w Ø wxlxlxp)0E90E!5:6D !/Î PlG />©@-D!ΠЩ/FD !:80E!9©/.è, û !/p3D p 1Î :>©A' ß 5">©4+0E!5:D!Î /PßO8èG ê Ç ¶ì À aЩ/FD 0E:p3 ¾íÀÉîEÀ Á ½ a Щ/FDRoUÛQÚB'& @+0E5 ê Ç ¶ì À aЩ/FD éëêíìwê é a@ced4fò'óhgmò'ö/çEö%ñò>ó_ôðAöb÷wò'ö · ß ¾ ¹ r³ÛQÚo HH rstu Í#0EÎ /5{©AFDS · ß ¾ àFáWÜEâãábäå æ âUå ØÙ0ÚVÛYÜEÙzÝÞv ½ ßPØÙUÚVÛYÜEÙzÝÞ ¤ Øç æOâeÚOÙUç4¡ ° Ê ß ÀÈ<Ê · ß ¾ Fà áYÜEâ ábäVåTæ ØÙ0ÚVÛYÜEÙzÝÞv ØÙ0ÚVÛYÜEÙzÝÞ ¤ Øç æOâ1ÚOÙU@ç ¡ 5,+Ëö÷0E!DXÊ0E,>0E/ rH < º»l!A!:%É$­0EÎ POp3F ê Ç ¶ì À aЩAFDS 5,+Ð@#0E^­ß P 5,+-ú2xß7^ 5,+ЩAFDS,!/p3D zà áYÜEâãáwäVåTæ âUå ØÙUÚÛWÜEÙzÝÞ v % (oç[Ûxæ# æOÜá âUå ØÙUÚÛWÜEÙzÝÞ ¤ % ê Ç ¶ì À àFáWÜEâãábäå æ (ç[Ûxæy æOÜá Ê ß Øç æOâeÚOÙUç4¡% àFáWÜEâãáwäVåTæ âUå àFáWÜEâãáwäVåT æ )+* ÀÈ<Ê ê Ç ¶ë À ê Ç ì¶ Â À aЩ/FD 0E:p3 Urbildbereich (Parameter) und Bildbereich (Ergebnistyp) ❚ Beispiel: ❙ Funktion sin ❙ Urbildbereich: R (-> Parameter) ❙ Bildbereich R, genauer: Intervall [-1, 1] (-> Typ) ❚ Mehr als ein Parameter möglich ❚ Stelligkeit einer Funktion ❙ Anzahl der Parameter Funktionen: Schreibweise ❚ Erklärung anhand von Beispielen ❚ quadrat(x : N0) : N0 Ergebnistyp x*x Parametertyp (formaler) Parameter Parametertrenner Ausdruck ❚ quadratsumme(a : N0 ; b : N0) : N0 quadrat(a) + quadrat(b) Funktionsaufruf mit Aktualparameter Vereinbarung: abkürzende Schreibweise ❚ quadratsumme(a, b : N0) : N0 quadrat(a) + quadrat(b) ❚ steht für ❚ quadratsumme(a : N0 ; b : N0) : N0 quadrat(a) + quadrat(b) Vorbedingungen und Nachbedingungen ❚ Zum Teil Vorbedingungen als Typen der Parameter formulierbar ❚ Parametertypen legen die Vorbedingungen meist nur partiell fest ❚ Problembeispiel: Division durch 0 ❚ div(x : N0 ; y : N0): N0 ❚ Gleiches gilt für die Ergebnistypen Funktionsrumpf ❚ Folge von Anweisungen ❚ mit "abschließendem" Ausdruck ❚ min(x : N0 ; y : N0) : N0 if x > y then y else x end if Funktionen: Motivation Information Hiding (Kapselung) (1) Information Hiding (Kapselung) (2) ❚ Noch zu klären: Semantik des Funktionsaufrufs Zuweisung und Arrays: Ergänzung ❚ Arraydenotation über Tupel ❙ var f : array [0..2] of N0; f := (42, 17, 9) ❚ Zuweisung von Arrays: Kopiersemantik ❙ var f, g : array [0..2] of N0; ❙ f := (42, 17, 9); ❙ g := f; ... ❚ Arrays als Werte von Funktionen (am Beispiel) ❙ f(i : N0) : array [0..1] of N0 (i+1, i-1) ❚ Erweiterung der Zuweisung für Arrays ❙ var a : array [0..1] of N0; ❙ var x, y : N0; (x, y) := f(3) a := f(3) Auswertestrategien Lokale Variablen, Blöcke ❚ Bisher: Variablen "global" am Anfang eines Algorithmus vereinbart ❚ Nun: Variablen "lokal" nur für den Teilalgorithmus einer deklarierten Prozedur ❚ Notation: ❙ begin var .... ; .... end Kopf des Blockes mit lokalen Variablen Rumpf des Blockes (Sequenz von Anweisungen) ❚ Blöcke können Anweisung oder Ausdruck sein Blöcke: Freie und gebundene Variablen ❚ Variablen, die im Kopf eines Blockes aufgeführt sind, heißen gebunden (bzgl. eines Blockes) ❚ Variablen, die im Rumpf vorkommen, aber nicht gebunden sind, heißen frei (bzgl. eines Blockes) Auswertestrategie für Blöcke ❚ Vor der Auswertung wird ein Block transformiert ❚ Für die lokalen Variablen werden neue, in der Auswertereihenfolge bisher nicht benutzte Namen vergeben ❚ Anschließend werden die in den Anweisungen im Rumpf des Blockes verwendeten lokalen Variablen durch die entsprechenden neuen Variablen ersetzt ❚ Ist die bei dieser Ersetzung betrachtete Anweisung wieder ein Block, so werden nur die freien Variablen dieses Blockes ersetzt Funktionen: Auswertestrategie (1) ❚ Sei f definiert als f(x1: T1, ..., xn: Tn) : Tresult ❚ <Rumpf von f> ❚ Ein Funktionsaufruf f(a1, ..., an) einer n-stelligen Funktion f mit Aktualparametern a1, ..., an wird ausgewertet, indem aus den (formalen) Parametern und dem Rumpf der Funktion f folgender Block gebildet wird ❙ begin var x1: T1; x2: T2; ...; xn : Tn; <Rumpf von f> end ❚ Anschließend wird der Block wie oben beschrieben zur Auswertung transformiert Funktionen: Auswertestrategie (2) ❚ Es entsteht ein Block ❙ begin var x1': T1; x2': T2; ...; xn' : Tn; <Rumpf von f mit Ersetzungen> end ❚ Der Block wird wie folgt umgeformt und ausgewertet ❙ begin var x1': T1; x2': T2; ...; xn' : Tn; x1', x2', ..., xn' := a1', ..., an' ; <Rumpf von f mit Ersetzungen> end ❚ wobei a1', ..., an' die Ergebnisse der entsprechenden Auswertung von a1, ..., an sind Parameter, Sichtbarkeit, Lebensdauer ❚ Der oben skizzierte Übergabemechanismus heißt Call-by-value ❚ Wertezuweisungen an Parameter sind möglich, da Parameter wie Blockvariablen mit Initialisierung zu behandeln sind ❚ Transformation garantiert Sichtbarkeitsregeln (Variablenskopus) ❚ Was passiert bei "Neueintritt" in den Block? ❙ "Alte" Namen werden nicht neu vergeben ❙ "Alte" Werte gehen also verloren Ausdrücke vs. Anweisungen (Beispiel 2) ❚ amittel(g : array [0..n-1] of N0) : N0 begin var j, am : N0 ; j, am := 0, 0; while j < n do j, am := j + 1, ((j * am) + g[j]) / (j+1) end while; am end Zusammenfassung, Kernpunkte ❚ Blöcke ❙ Auswertungsstrategie, ❙ Sichtbarkeit (Skopus) ❙ Lebensdauer ❚ Funktionen ❙ Aktual- vs. Formalparameter ❙ Auswertungsstrategie Was kommt beim nächsten Mal? ❚ Prozeduren ❚ Rekursion