Kurs 1612 Konzepte imperativer Programmierung Musterlösung zur Klausur am

Ähnliche Dokumente
Kurs 1612 Konzepte imperativer Programmierung Musterlösung zur Nachklausur am

Kurs 1613 Einführung in die imperative Programmierung Musterlösung zur Nachklausur am

( = 18 Punkte)

Kurs 1612 Konzepte imperativer Programmierung Musterlösung zur Nachklausur am

Bitte hier unbedingt Matrikelnummer und Adresse eintragen, sonst keine Bearbeitung möglich "Konzepte imperativer Programmierung"

Kurs 1613 Einführung in die imperative Programmierung Musterlösung zur Klausur am

Kurs 1613 Einführung in die imperative Programmierung Musterlösung zur Nachklausur am

Kurs 1613 Einführung in die imperative Programmierung Musterlösung zur Klausur am

Kurs 1613 Einführung in die imperative Programmierung Musterlösung zur Klausur am

Kurs 1613 Einführung in die imperative Programmierung

Kurs 1613 Einführung in die imperative Programmierung Musterlösung zur Klausur am

Kurs 1613 Einführung in die imperative Programmierung Lösungen der Aufgaben zum Studientag

Kurs 1613 Einführung in die imperative Programmierung

Wintersemester 2005/2006 Hinweise zur Bearbeitung der Klausur zum Kurs 1612 Konzepte imperativer Programmierung

Wie schreibe ich ein Programmierstils in Deutschland

Kurs 1613 Einführung in die imperative Programmierung

Kurs 1613 Einführung in die imperative Programmierung

Kurs 1613 Einführung in die imperative Programmierung

Wintersemester 2007/2008 Hinweise zur Bearbeitung der Klausur zum Kurs 1613 Einführung in die imperative Programmierung

Fernuniversität in Hagen r- I Name. Vorname ~- Fachbereich Informatik. ( ) Vollzeitstudent ( ) Teilzeitstudent ( ) Zweithörer ( ) Gasthörer

Wintersemester 98/99 Hinweise zur Bearbeitung der Klausur zum Kurs 1612 Konzepte imperativer Programmierung

Wintersemester 2010/2011 Hinweise zur Bearbeitung der Klausur zum Kurs 1613 Einführung in die imperative Programmierung

Partielle Korrektheit von Programmen. Beispiele an der Tafel

{P} S {Q} {P} S {Q} {P} S {Q} Inhalt. Hoare-Kalkül. Hoare-Kalkül. Hoare-Tripel. Hoare-Tripel. Hoare-Tripel

Problem: Gegeben Spezifikation (P,Q) und Implementierung S Gesucht formaler (automatisierbarer?) Beweis, dass S (P,Q) erfüllt.

3. Übungsblatt zu Algorithmen I im SoSe 2017

Informatik II, SS 2014

Kurs 1612 Konzepte imperativer Programmierung Kurs 1613 Einführung in die imperative Programmierung

Humboldt-Universität zu Berlin Berlin, den Institut für Informatik

9. Rekursion. 1 falls n 1 n (n 1)!, andernfalls. Experiment: Die Türme von Hanoi. Links Mitte Rechts. Mathematische Rekursion

Das Suchproblem. Gegeben Menge von Datensätzen. Beispiele Telefonverzeichnis, Wörterbuch, Symboltabelle

Das Suchproblem 4. Suchen Das Auswahlproblem Suche in Array

Beispiel 1 zur Verifikation eines bedingten Anweisung. Hoare-Regel für die bedingte Anweisung. else

Hinweise zur Bearbeitung der Klausur zum Kurs Einführung in die imperative Programmierung

Algorithmen und Programmieren II Programmverifikation {V} P {N}

Beispiel 1 zur Verifikation eines bedingten Anweisung. Hoare-Regel für die bedingte Anweisung. Beispiel 2 zur Verifikation eines bedingten Anweisung

Copyright, Page 1 of 7 Heapsort

Das Suchproblem 4. Suchen Das Auswahlproblem Suche in Array

Grundlagen der Informatik

1. Erste Schritte 2. Einfache Datentypen 3. Anweisungen und Kontrollstrukturen 4. Verifikation 5. Reihungen (Arrays) II.1.4. Verifikation - 1 -

Algorithmen und Datenstrukturen

Das Suchproblem. Gegeben Menge von Datensätzen. Beispiele Telefonverzeichnis, Wörterbuch, Symboltabelle

1. Erste Schritte 2. Einfache Datentypen 3. Anweisungen und Kontrollstrukturen 4. Verifikation 5. Reihungen (Arrays) II.1.4. Verifikation - 1 -

n 1. Erste Schritte n 2. Einfache Datentypen n 3. Anweisungen und Kontrollstrukturen n 4. Verifikation n 5. Reihungen (Arrays)

Studientag zum Kurs 01613

Kapitel 4: Dynamische Datenstrukturen. Algorithmen und Datenstrukturen WS 2017/18. Pro f. Dr. Sán do r Fe k e te

Bitte hier unbedingt Matrikelnummer und Adresse eintragen, sonst keine Bearbeitung möglich "Konzepte imperativer Programmierung"

Vorlesung Datenstrukturen

Lösungsvorschläge zur Hauptklausur 1661 Datenstrukturen I

! 1. Erste Schritte! 2. Einfache Datentypen! 3. Anweisungen und Kontrollstrukturen! 4. Verifikation! 5. Reihungen (Arrays) II.1.4. Verifikation - 1 -

Lösungsvorschläge zur Hauptklausur Datenstrukturen

Aufgaben, Hilfestellungen und Musterlösungen zum Modul 5 Druckversion

3. Suchen. Das Suchproblem. Suche in Array. Lineare Suche. 1 n. i = n Gegeben Menge von Datensätzen.

Algorithmen und Datenstrukturen Tutorium Übungsaufgaben

5 Bäume. 5.1 Suchbäume. ein geordneter binärer Wurzelbaum. geordnete Schlüsselwertmenge. heißt (schwach) sortiert, g.d.w. gilt:

Beispiellösungen zu den Übungen Datenstrukturen und Algorithmen SS 2008 Blatt 6

Kurs 1663 Datenstrukturen" Musterlösungen zur Klausur vom Seite 1. Musterlösungen zur Hauptklausur Kurs 1663 Datenstrukturen 15.

Korrektheit und Hoare-Kalkül für Imperative Programme

Semantik von Programmiersprachen SS 2017

Vordiplom für Wirtschaftswissenschaften Allgemeine Informatik II SS Juli 2002 Bearbeitungszeit: 120 Minuten BEISPIELLÖSUNG

Informatik II, SS 2018

Counting - Sort [ [ ] [ [ ] 1. SS 2008 Datenstrukturen und Algorithmen Sortieren in linearer Zeit

Übung Algorithmen und Datenstrukturen

Programm heute. Algorithmen und Datenstrukturen (für ET/IT) Suchen. Lineare Suche. Such-Algorithmen. Sommersemester Dr.

Algorithmen und Datenstrukturen

Vorlesung Datenstrukturen

4 Spezifikation und Verifikation

Kapitel 4: Dynamische Datenstrukturen. Algorithmen und Datenstrukturen WS 2012/13. Prof. Dr. Sándor Fekete

Teil 1: Suchen. Ausgeglichene Bäume B-Bäume Digitale Suchbäume. M.O.Franz, Oktober 2007 Algorithmen und Datenstrukturen - Binärbäume 1-1

Informatik Abitur Bayern 2017 / II - Lösung

Übung Algorithmen und Datenstrukturen

Kurs 1575, Klausur vom , Musterlösung

Informatik II Übung 3

Kurs 1575, Musterlösung der Klausur vom

Vorlesung Informatik 2 Algorithmen und Datenstrukturen

Grundlagen der Informatik

Übung zur Vorlesung Programmierung

1. Teilklausur. Name:... Vorname:... Matrikel-Nummer:...

Kurs 1613 Einführung in die imperative Programmierung

13. Binäre Suchbäume

m n 1 Kurs Fach KursNr Art Abb. 1.1: Das ER-Diagramm

Spezielle Datenstrukturen

C. A. R. Hoare. An Axiomatic Basis for Computer Programming. Nicolas Schelp. Proseminar Assertions SS 2007

Technische Universität München SoSe 2015 Institut für Informatik I Mai 2015 Dr. Tobias Lasser. Aufgabe 1 Rechnen mit Landau-Symbolen

Einführung in die Programmierung II. 9. Dynamische Datenstrukturen: Binärbäume

Algorithmen und Datenstrukturen 1

10. Übungsblatt zu Algorithmen I im SS 2010

Übung zu Algorithmen und Datenstrukturen (für ET/IT)

Binärbäume: Beispiel

5.3 Korrektheit und Verifikation

Vorlesung Datenstrukturen

Heapsort, Quicksort, Mergesort. 8. Sortieren II

Beispiellösung zu den Übungen Datenstrukturen und Algorithmen SS 2008 Blatt 5

Algorithmen und Datenstrukturen 12

Datenstrukturen und Algorithmen (SS 2013)

Tiefensuche (Depth-First Search) Robert Hilbrich

14. Sortieren II Heapsort. Heapsort. [Max-]Heap 7. Heapsort, Quicksort, Mergesort. Binärer Baum mit folgenden Eigenschaften

Transkript:

Kurs 1612 Konzepte imperativer Programmierung 1 Aufgabe 1 a) Wir müssen zunächst die Abbruchbedingung des Verfahrens festlegen: Wir beenden die Rekursion, wenn das zu untersuchende Feldstück nur noch aus einem Element besteht. In diesem Fall ist der dort eingetragene Wert das Maximum des Feldstücks. Im anderen Fall erfolgen zwei rekursive Aufrufe der Prozedur für die beiden "Hälften" des Feldes. Von den zwei ermittelten Teilmaxima wird dann das Maximum bestimmt. Wir geben zusätzlich ein umgebendes Programm an, welches den Test der Prozedur ermöglicht: program Maximum (input, output); { dient dem Test der Prozedur rekmax } const UNTEN = 0; OBEN = 10; type tindex = UNTEN..OBEN; tfeld = array[tindex] of integer; var Feld : tfeld; k : tindex; maxi : integer; procedure rekmax ( invon, inbis : tindex; var infeld : tfeld; var outmax : integer); { bestimmt rekursiv den maximalen Feldeintrag von infeld ueber ein divide and conquer-verfahren } var schnitt : tindex; max1, max2 : integer; if inbis = invon then outmax := infeld[invon] else

2 Kurs 1612 Konzepte imperativer Programmierung schnitt := (inbis + invon) div 2; rekmax (invon, schnitt, infeld, max1); rekmax (schnitt + 1, inbis, infeld, max2); if max1 > max2 then outmax := max1 else outmax := max2 end { if } end; { rekmax } writeln ('Bitte 11 integer-zahlen eingeben!'); for k := UNTEN to OBEN do read (Feld[k]); readln; rekmax (UNTEN, OBEN, Feld, maxi); writeln ('Das Maximum lautet ', maxi) end. { Maximum } Anmerkung: In Übereinstimmung mit Muss-Regel 12 übergeben wir das Feld als Referenzparameter, um so Speicherplatz und (Kopier-)Zeit einzusparen. Wir bezeichnen den Parameter aber trotz Referenzübergabe als infeld, da es sich um einen reinen Eingabeparameter handelt. b) Dieses Beispiel ist keine sinnvolle Anwendung der Rekursion. Es handelt sich nämlich um ein einfaches lineares Problem (in Abhängigkeit von der Anzahl der Feldelemente), welches durch einen einzigen Felddurchlauf zu lösen wäre, ohne Verwendung eines Stapels oder einer anderen Hilfsdatenstruktur. Dabei müssten wir jedes Feldelement genau einmal betrachten. Beim rekursiven Verfahren müssen nach wie vor alle Feldelemente betrachtet werden. Allerdings ergeben sich zusätzlich rekursive Aufrufe, und zwar mehr als Feldelemente vorhanden sind (fast doppelt so viele wie Feldelemente), und jeder Aufruf verursacht Parameterübergaben, Aufteilung in zwei Hälften usw... Aufgabe 2 a) Zum Einfügen am Listenende wird ein neues Element erzeugt und zwischen Ende und Anfang der Liste eingefügt. Außerdem muss der Listenende-Zeiger natürlich auf das neu eingefügte Element gesetzt werden, da es das neue Listenende bildet. Da dieser Zeiger sich ändert, ist er als io-parameter zu übergeben, während der einzufügende Wert ein reiner in-parameter ist. procedure appendnotempty(inzahl:integer; var iorefende:trefelement); {fügt inzahl am Ende der nicht-leeren Liste ein.}

Kurs 1612 Konzepte imperativer Programmierung 3 var neu:trefelement; new(neu); neu^.info := inzahl; { Element einfügen: } neu^.next := iorefende^.next; iorefende^.next := neu; { Neues Listenende markieren } iorefende := neu; end; b) In dieser Teilaufgabe sind sämtliche Sonderfälle zu beachten, nämlich die leere Liste und der Fall, dass das gesuchte Element nicht vorkommt, also nicht gefunden wird. In letzterem Fall wird die Liste bis zum Ende durchlaufen. Die Besonderheit liegt hier nun darin, dass das Listenende nicht an einem NIL-Zeiger erkannt werden kann, sondern dass vielmehr zu überprüfen ist, ob der Laufzeiger auf dem von inrefende referenzierten letzten Element angekommen ist. function find(insuchwert:integer; inrefende:trefelement):trefelement; {Sucht ein Element mit Info insuchwert in der in inrefende übergebenen Liste. Rückgabe von nil, falls nicht gefunden, sonst Rückgabe einer Referenz auf das gefundene Element.} var lauf:trefelement; {Sonderfall 1: Leere Liste => Ergebnis: NIL} if inrefende = nil then find:=nil else {Suchen, Abbruch bei Fundstelle oder am Listenende} lauf:=inrefende^.next; {erstes Element} while (lauf<>inrefende) and (lauf^.info<>insuchwert) do lauf:=lauf^.next; if lauf^.info<>insuchwert then {Sonderfall 2: Nicht gefunden => Ergebnis: NIL} find:=nil else {Normalfall: Gefunden => Ergebnis: Fundstelle} find:=lauf;

4 Kurs 1612 Konzepte imperativer Programmierung end; { if } end; { find } Aufgabe 3 Eine einfache Lösung, welche die vereinfachenden Annahmen (Liste enthält mindestens ein nicht negatives Element) ausnutzt, sieht wie folgt aus: In einer ersten Schleife wird so lange das erste Element gelöscht, bis die Liste nicht mehr mit einem negativen Element nt. Anschließend wird in einer zweiten Schleife die Liste mit einem Zeiger namens lauf durchlaufen. Immer wenn lauf auf den Vorgänger eines negativen Elementes zeigt, wird sein Nachfolger aus der Liste gelöscht. In beiden Fällen wird ein Zeiger namens loesch benutzt, um das zu löschende Element nach seinem Entfernen aus der Liste nach wie vor ansprechen zu können, so dass es dann mittels dispose(loesch)auch aus dem Speicher gelöscht werden kann. Die folgenden Grafiken veranschaulichen das Löschen eines Listenelements innerhalb einer Liste. Entfernen eines Elementes aus der Liste: loesch := lauf^.next; lauf^.next := loesch^.next; 4-3 1 0 lauf loesch Nun kann das Element gelöscht werden. dispose(loesch): 4-3 1 0 lauf loesch procedure LoescheNegative(var iorefanfang: trefelement); { loescht alle negativen Zahlen aus iorefanfang, Liste darf nicht leer sein und muss mindestens eine

Kurs 1612 Konzepte imperativer Programmierung 5 nicht-negative Zahl enthalten! } var loesch, lauf: trefelement; { Loeschen am Anfang } while iorefanfang^.info < 0 do loesch := iorefanfang; iorefanfang := iorefanfang^.next; dispose(loesch); end; { while } { Loeschen aller restlichen negativen Zahlen, dazu die Liste bis zum letzten Element durchlaufen} lauf := iorefanfang; while lauf^.next <> nil do if lauf^.next^.info < 0 then loesch := lauf^.next; lauf^.next := loesch^.next; dispose(loesch); end else lauf := lauf^.next; { Wichtig: lauf nur im else-fall weitersetzen, im then-fall wurde bereits der Nachfolger von lauf entfernt und als nächstes ist der neue Nachfolger von lauf zu untersuchen. } end { while } end; { LoescheNegative }

6 Kurs 1612 Konzepte imperativer Programmierung Aufgabe 4 a) Die Implementierung des Suchalgorithmus für binäre Suchbäume aus dem Kurstext kann fast identisch übernommen werden: Es entfällt der Rückgabezeiger, statt dessen wird am Ende eine die Ausgabeanweisung eingefügt: procedure Baumpfad ( inwurzel : trefbinbaum; insuch : integer); { sucht rekursiv im Suchbaum, auf dessen Wurzel inwurzel zeigt, den Wert insuch und gibt die Werte der besuchten Knoten in umgekehrter Reihenfolge auf dem Bildschirm aus } if inwurzel <> nil then if insuch < inwurzel^.info then Baumpfad (inwurzel^.links, insuch) else if insuch > inwurzel^.info then Baumpfad (inwurzel^.rechts, insuch); { else gefunden, Ausgabe erfolgt unten } writeln (inwurzel^.info) end { if } end; {Baumpfad} b) Für eine einfache Suche in einem solchen Baum wäre die Rekursion nicht sinnvoll, da wie beim Durchlaufen einer Liste nur ein einziger Pfad beschritten wird, was sich iterativ in einer einfachen Schleife realisieren lässt, und zwar ohne einen Stapel oder ähnliche Hilfsmittel. In diesem Fall liegt das Problem jedoch darin, dass die Werte auf diesem Pfad rückwärts ausgegeben werden sollen. Eine iterative Lösung müsste dazu in einem Vorwärts-Pfaddurchlauf die Werte auf dem Suchpfad explizit auf einem Stapel speichern, um sie anschließend in umgekehrter Reihenfolge ausgeben zu können. Die rekursive Lösung nimmt uns diese Arbeit mit Hilfe des implizt verwalteten Stapels ab. Deshalb ist die rekursive Lösung hier sinnvoll.

Kurs 1612 Konzepte imperativer Programmierung 7 Aufgabe 5 Wir werten zunächst das Prädikat A) zu true aus, indem wir ein Testdatum wählen, dessen erstes Element 0 ist (die weiteren Werte im Array sind beliebig). Mit dem zweiten Testdatum werten wir A) gezielt zu false aus. Die Prädikate A), B) und F) sind damit schon vollständig überdeckt, als nächstes überdecken wir C), indem wir in einer anderen als der ersten Array-Komponente eine Null eintragen. Danach sind nur noch E) und I) unüberdeckt. Um I) gezielt zu false auszuwerten, wählen wir nun als Testdatum ein unsortiertes Feld, das keine Null enthält. Mit den vier angegebenen Testdaten erreichen wir die minimale Mehrfach-Bedingungsüberdeckung. Zwei dieser Testdaten decken bereits die Existenz von Fehlern auf (die Funktion enthält übrigens mehr als einen Fehler). Prädikate infeld 0 1 2 3 1 2 3 4 1 0 2 3 2 1 3 4 A) infeld[1]=0 T F F F B) i<feldmax T,F T,F T C) infeld[i]=0 F T,F F D) infeld[i-1] T F,T F <= infeld[i] E) C) or D) T T F F) B) and E) (while-bedingung) T,F T,F F G) infeld[i]=0 F T,F H) isnull F T F I) infeld[i] T F > infeld[i-1] erwartete Ausgabe null sortiert null unsort. tatsächliche Ausgabe null unsort. null sortiert Hinweise zur ausgefüllten Tabelle: Die doppelten Linien kennzeichnen, dass ein Prädikat mit den links davon stehenden Testdaten bereits vollständig überdeckt wurde. Rechts davon haben wir der Vollständigkeit halber die Auswertung der bereits überdeckten Prädikate unter den noch folgenden Testdaten zusätzlich (grau) mit aufgeführt, diese Angaben sind aber nicht notwendig.

8 Kurs 1612 Konzepte imperativer Programmierung Aufgabe 6 a) Um zu zeigen, dass { R y 0 } (0) S 14,23 { R x + u = 2 H-y+1 (y 0 x = u) } eine gültige Programmformel ist, wenden wir als erstes die erste Bedingungsregel an. Demnach müssen wir nur die Gültigkeit der Programmformeln und { R y 0 u = 0 } (1) S 15, 18 { R } { R y 0 u 0 } (2) S 20, 23 { R } zeigen, wobei (2) in der Aufgabenstellung als gültig vorausgesetzt wird. Nach Anwendung der Zusammensetzungsregel auf (1) genügt es, die Gültigkeit der Programmmformel (3) zu zeigen: { R y 0 u = 0 } (3) S 16, 17 { R } Dazu müssen wir die Sequenzregel anwenden. Wir benötigen also ein Prädikat T, so dass die Programmformeln und { R y 0 u = 0 } S 16 { T } (4) { T } S 17 { R } (5) gültig sind. Dazu wenden wir das Zuweisungsaxiom auf (5) an und erhalten T x + u = 2 H-(y-1)+1 (y-1 0 x = u), d.h. mit diesem T ist (5) laut Zuweisungsaxiom gültig. Nun wenden wir das Zuweisungsaxiom auf (4) an und erhalten eine Vorbedingung T, so dass { T } S 16 { T } gültig ist: T x + x = 2 H-(y-1)+1 (y-1 0 x = x) Es gilt:

Kurs 1612 Konzepte imperativer Programmierung 9 R y 0 u = 0 x + u = 2 H-y+1 (y 0 x = u) y 0 u = 0 x = 2 H-y+1 (y 0 x = u) y 0 u = 0 (wegen u = 0) T 2x = 2 H-y+2 T ist äquivalent zu T : T x + x = 2 H-(y-1)+1 (y-1 0 x = x) x + x = 2 H-(y-1)+1 (y-1 0 true) x + x = 2 H-(y-1)+1 true x + x = 2 H-(y-1)+1 T Wir können nun die zweite Konsequenzregel zum Nachweis der Gültigkeit von (4) anwenden. Damit ist nun auch die Gültigkeit der Programmformel (0) gezeigt. b) Aus Teilaufgabe a) folgt, dass R vor und nach jedem Schleifendurchlauf erfüllt ist. Also ist R eine Invariante der while-schleife. Da außerdem y 0 die Schleifenabbruchbedingung ist, können wir die while-regel anwenden und erhalten die Gültigkeit der Programmformel { R } S 13, 23 { R y = 0 } c) Wir zeigen als nächstes, dass { P H 0 } (1) S 10, 12 { R x + u = 2 H-y+1 (y 0 x = u) } eine gültige Programmformel ist und anschließend, dass die Implikation R y = 0 Q gültig ist. Wir wenden die Sequenzregel zweimal auf (1) an und müssen nun zeigen, dass es Prädikate S und S gibt, so dass die Programmformeln und { P } (2) y := H; { S } { S } (3) x := 1; { S }

10 Kurs 1612 Konzepte imperativer Programmierung { S } (4) u := 1; { R } gültig sind. Wir wenden das Zuweisungsaxiom auf (4) an und erhalten S x + 1 = 2 H-y+1 (y 0 x = 1) Als nächstes wenden wir das Zuweisungsaxiom auf (3) an und erhalten S 1 + 1 = 2 H-y+1 (y 0 1 = 1) Nun wenden wir das Zuweisungsaxiom auf (2) an und erhalten S 1 + 1 = 2 H-H+1 (H 0 1 = 1) 1 + 1 = 2 H-H+1 1 + 1 = 2 true Da offensichtlich P S gilt, können wir die zweite Konsequenzregel anwenden und erhalten somit die Gültigkeit von (2) und damit ingesamt auch von (1). Mit der Sequenzregel können wir so auch die Gültigkeit von { P }S 10, 23 { Q R y = 0 } und mit der Zusammensetzungsrefel die Gültigkeit von { P }S 9, 24 { Q } zeigen. Es bleibt nun nur noch zu zeigen, dass Q Q gilt: Q x + u = 2 H-y+1 (y 0 x = u) y = 0 x + u = 2 H+1 x = u y = 0 wegen y = 0 x + x = 2 H+1 x = u wegen x = u x = 2 H Somit ist die partielle Korrektheit des Programms Potenzieren bezüglich der Spezifikation {P H 0} S {Q x = 2 H } bewiesen.

Kurs 1612 Konzepte imperativer Programmierung 11 Aufgabe 7 a) Gegeben sei eine konkrete terminierende While-Schleife S mit zugehöriger Terminierungsfunktion τ. Laut Bedingung w3 aus der Definition einer Terminierungsfunktion gibt es demnach zu τ eine untere Schranke t* Z. Ist dann auch t*-1 eine solche untere Schranke, d.h. ist t* nicht eindeutig bestimmt? Ja, das gilt tatsächlich. Die Definition einer Terminierungsfunktion verlangt lediglich die Existenz einer unteren Schranke t*, so dass vor jedem Schleifendurchlauf der Funktionswert von τ (im Folgenden kurz τ genannt) größer oder gleich t* ist. Offensichtlich gilt: t*-1 < t* τ, also ist auch t*-1 eine untere Schranke, wie übrigens jede ganze Zahl, die kleiner als t* ist. Beim Terminierungsnachweis gilt es lediglich zu zeigen, dass die Schleife terminiert, nicht wann sie terminiert. Dazu wird gezeigt, dass eine streng monoton fallende Folge ganzer Zahlen nach unten beschränkt, also endlich ist. Dazu genügt der Nachweis der Existenz einer unteren Schranke, die größte untere Schranke muss nicht ermittelt werden. b) Nehmen Sie Stellung zu folgender Behauptung: Um die partielle Korrektheit eines Programms S bezüglich der Spezifikation {P} S {Q} nachzuweisen, muss die Gültigkeit der Programmformel {P} S {Q} gezeigt werden. Die partielle Korrektheit wurde wie folgt definiert: Das Programm S ist partiell korrekt bezüglich der Spezifikation {P} S {Q}, wenn - eine gültige Programmformel {P } S {Q } existiert und dabei - P P sowie - Q Q gilt. Der Nachweis der Gültigkeit der Programmformel {P} S {Q} ist demnach hinreichend, aber nicht notwendig. Es genügt der Nachweis der Gültigkeit einer Programmformel {P } S {Q } mit zwei von P und Q verschiedenen Prädikaten (einer schwächeren Vorbedingung und stärkeren Nachbedingung). Allerdings kann man anmerken, dass die Gültigkeit der Programmformel {P } S {Q } und der beiden Implikationen auch die Gültigkeit von {P} S {Q} impliziert, wie sich durch Anwendung der beiden Konsequenzregeln des Hoare-Kalküls nachweisen lässt. c) Sei die Programmformel {P} S {Q} gültig. Ist so sichergestellt, dass das Programm S für jede P-konforme Eingabe eine Q-konforme Ausgabe produzieren wird? Die Gültigkeit der Programmformel stellt lediglich die partielle Korrektheit bezüglich der Spezifikation {P} S {Q} sicher. Jedoch könnte das Programm S dennoch für P-konforme Eingaben gar keine Ausgabe (und somit auch keine Q-konforme Ausgabe) produzieren, nämlich falls es nicht terminiert. d) Ist für die Ermittlung von Testfällen zu strukturorientierten Tests außer einer vorliegenden Implementierung des Prüflings auch seine Spezifikation erforderlich? Ja. Ein Testfall ist eine Menge von Testdaten, und jedes Testdatum enthält neben Eingabedaten auch eine Angabe der erwarteteten Ausgabe. Letztere lässt sich nur aus der Spe-

12 Kurs 1612 Konzepte imperativer Programmierung zifikation ableiten. Die Implementierung wird lediglich dazu herangezogen, gezielt Testfälle zu bilden, deren Eingabedaten zu bestimmten Pfaddurchläufen führen oder gewisse Bedingungen gezielt zu true oder false auswerten, um so eine bestimmte Abdeckung zu erreichen, also die Wahrscheinlichkeit zu verringern, dass man wichtige Konstellationen von Eingabedaten beim Test vergisst. Es ist aber unabhängig von der Strategie bei der Testdaten-Auswahl immer wichtig, bei der Durchführung eines Tests anschließend zu überprüfen, ob das tatsächliche Verhalten des Prüflings mit dem laut Spezifikation erwarteten übereinstimmt, die Spezifikation ist also unverzichtbar (vgl. z.b. Aufgabe 5).