Seite: 2 Kurs 1612 “Konzepte imperativer Programmierung” Klausur am 07.03.1998 Aufgabe 1 (8 Punkte) Eine natürliche Zahl n heißt peq%kt, wenn n als Summe aller natürlicher Zahlen i (1 I i 5 5 ), durch die n ohne Rest teilbar ist, dargestellt werden kann. Die Zahl 28 ist beispielsweise eine perfekte Zahl. Es ist 28 = 1 + 2 + 4 + 7 + 14 und 1, 2,4, 7 und 14 sind genau alle Zahlen, durch die 28 ohne Rest teilbar ist. Schreiben Sie ein Programm perf ekteZah1, das alle perfekten Zahlen zwischen 1 und 1000 auf dem Bildschirm ausgibt. Seite: 4 Kurs 1612 “Konzepte imperativer Programmierung” Klausur am 07.03.1998 Aufgabe 2 (3+5+5+2=15Punkte) . Gegeben sind eine einfach verkettete lineare Liste mit mindestens zwei Elementen und die üblichen Typdefinitionen: Uwe tRefListe = "tListe; tliste = record info : integer; next : tRefListe end; Eine Beispielliste zeigt folgende Abbildung: RefListe Bearbeiten Sie die folgenden Teilaufgaben a) - d) und benutzen Sie dazu die angegebenen Typdefinitionen. a) Implernentieren Sie eine rekursive Prozedur UmgedrehtAusgeben, mit der die inf o-Komponenten der Listenelemente in umgekehrter Reihenfolge auf dem Bildschirm ausgegeben werden. b) Implernentieren Sie eine rekursive Prozedur drehenRek, mit der die Verzeigerung der Liste umgedreht wird. Nach Beendigung der Prozedur soll die Liste aus dem obigen Beispiel dann also folgendermaßen aussehen: RefListe Gehen Sie davon aus, daß es einen Zeiger auf den neuen Anfang der Liste gibt. Das brauchen Sie also nicht noch extra sicherstellen. c) Implernentieren Sie eine iterative Variante drehen1 t der unter b) beschriebenen Prozedur. d) Handelt es sich in den Teilaufgaben a) und b) um sinnvolle Anwendungen der Rekursion? Begründen Sie Ihre Antwort. Seite: 8 Kurs 1612 “Konzepte imperativer Programmierung” Klausur am 07.03.1998 Aufgabe 3 (3+3+3=9Punkte) Ausgehend von der Typdefinition für einen Binärbaum und eines Teils der Implementation einer Funktion Suchen geben wir drei verschiedene Alternativen für den Rest des Rumpfes dieser Funktion an. Ihre Aufgabe ist es, die verschiedenen Implernentationen zu analysieren, indem Sie die nachfolgenden Teilaufgaben a) bis c) bearbeiten. tme tRefBinBaum = “tBinBaum; tBinBaum = record info : integer; links, r e c h t s : tRefBinBaum end; function Suchen ( inRefWurze1 : tRefBinBaum; insuchwert : ??) : ??; { . . . . 1 var E r g e b n i s : tRefBinBaum; begin if inRefWurze1 = nil E r g e b n i s := nil else then . . . ( Alternativen A bis C } Suchen := Ergebnis end; { Suchen > Seite: 9 Kurs 1612 “Konzepte imperativer Programmierung” K1ausuram07.03.1998 Name: Matrikelnummer: Alternative A: if inRefWurze1 = insuchwert then Ergebnis := inRefWurze1 else begin Ergebnis := Suchen (inRefWurzel^.links, insuchwert); if Ergebnis = nil then Ergebnis := Suchen (inRefWurzel^.rechts, insuchwert) end; Alternative B: if inRefWurze1". info = insuchwert then Ergebnis := inRefWurze1 else begin Ergebnis := Suchen (inRefWurzel".links, insuchwert); if Ergebnis = nil then Ergebnis := Suchen (inRefWurzel".rechts, insuchwert) end; Alternative C: if inRefWurze1". info = inSuchwert".info then Ergebnis := inRefWurze1 else begin Ergebnis := Suchen (inRefWurzel^.links, insuchwert); if Ergebnis = nil then Ergebnis := Suchen (inRefWurzel^.rechts, insuchwert) end; Seite: 10 Kurs 1612 “Konzepte imperativer Programmierung” Klausur am 07.03.1998 Kreuzen Sie für jede der folgenden Aussagen diejenige(n) Alternative(n) an, auf die die jeweilige Aussage zutrifft: a:) Der Funktionskopf A B T- Cl Ll Cl C keine function Suchen ( inRefWurze1 : tRefBinBaum; insuchwert : tRefBinBaum) : tRefBinBaum; ist eine syntaktisch korrekte Deklaration für die Alternative(n) . . . Der Funktionskopf CI function Suchen ( inRefWurze1 : tRefBinBaum; insuchwert : i n t e g e r ) : i n t e g e r ; ist eine syntaktisch korrekte Deklaration für die Alternative(n) . . . . Der Funktionskopf function Suchen ( inRefWurze1 : tRefBinBaum; insuchwert : i n t e g e r ) : tRefBinBaum; ist eine syntaktisch korrekte Deklaration für die Alternative(n) . . . . b) Kreuzen Sie an, zu welcher Alternative der Kommentar jeweils gehört. { liefert den Zeiger auf ein Element des Baumes, dessen Wert der info-Komponenten mit dem Wert von insuchwert uebereinstimmt; gibt es ein solches Element nicht, w i r d n i l zurueckgegeben > Cl { liefert den Zeiger auf ein Element des Baumes, dessen Wert der info-Komponenten mit dem Wert der info-Komponenten von insuchwert uebereinstimmt; gibt es ein solches Element nicht, wird nil zurueckgegeben } Ll Seite: Kurs 1612 “Konzepte imperativer Programmierung” Klausur am 07.03.1998 Name: Matrikelnummer: A B Cl Cl Von Suchen wird der Wert nil zurückgegeben. CI Cl Die Funktion wird auf jeden Fall mit einem Laufzeitfehler abbrechen. ci Ll ( liefert den Wert von insuchwert, falls insuchwert auf ein Element des Baumes zeigt, sonst nil } c) Bei einem Aufruf der Funktion innerhalb eines Programms sei der aktuelle Parameter für insuchwert gleich nil. Auf welche Alternative(n) treffen die folgenden Aussagen dann zu? Ein solcher Aufruf ist nicht möglich, da das Programm vom a Compiler gar nicht erst übersetzt wird. C keine 11 Seite: 12 Kurs 1612 “Konzepte imperativer Programmierung” Klausur am 07.03.1998 Aufgabe 4 (8 Punkte) Bei dem folgenden binären Baum haben alle inneren Knoten zwei Söhne: Implementieren Sie eine rekursive Funktion zweisoehne, die ermittelt, ob alle inneren Knoten eines binären Baumes genau zwei Söhne haben oder nicht. Gehen Sie von den folgenden Typdefinitionen und der Deklaration des Funktionskopfes von zweisoehne aus: tme tRefBiqBaum = "tBinBaum; tBinBaum = record info : integer; links, rechts : tRefBinBaum end; function zweisoehne (inRefWurze1 : tRefBinBaum) : boolean; { gibt genau dann den Wert true zurueck, wenn alle inneren Knoten des Baumes, auf dessen Wurzel inRefWurze1 zeigt, zwei Soehne haben, sonst den Wert false > Beachten Sie, daß die Funktion für einen leeren Baum true zurück gibt, denn alle inneren Knoten des leeren Baumes haben zwei Söhne. Seite: 14 Kurs 1612 “Konzepte imperativer Programmierung” Klausur am 07.03.1998 Aufgabe 5 (8 Punkte) Personennamen bestehen aus einem Vor- und einem Nachnamen, für die folgende Regeln gelten: - Nachnamen können auch Doppelnamen sein, die durch einen Bindestrich miteinander verbunden sind. - Vornamen können Einzel- oder Mehrfachnamen sein, wobei jeder einzelne wieder ein mit Bindestrich verknüpfter Doppelname sein kann. - Jeder Teil eines Namens besteht aus mindestens zwei Zeichen, von denen das erste ein Großbuchstabe ist und alle weiteren Kleinbuchstaben sind. Alle Ausnahmen von diesen genannten Regeln (z.B. Vorsilben, Titel, Abkürzungen oder Großbuchstaben im Namen, die nicht am Namensanfang stehen) bleiben unberücksichtigt. Beispiele: - Helmut Friedhelm Sommer-Maalzahn - Claudia Maalzahn - Karl-Heinz Werner Fürth Ergänzen Sie die folgende Grammatik G, so daß damit solche Personennamen erzeugt werden können (@ bezeichnet ein Leerzeichen): G= (N T, P, S> T = t -7 0, A, B, .., Z, Ä, Ö, Ü, a, b, .., z, ä, ö, ü, ß} N = { <Start>, <groß>, <klein>, . . . . . .} s = <start> .. .. .. P = { <groß> ::= AIBI..IZIAIOIU, eklein> ::= albl..lzlälölülß, ...... > Seite: 16 Kurs 1612 “Konzepte imperativer Programmierung” Klausur am 07.03.1998 Aufgabe 6 (6 + 6 = 12 Punkte) Mit dem Programm Flaechenberechnung soll die Fläche eines Rechtecks ermittelt werden. Das Rechteck ist bestimmt durch die x- und y-Koordinaten zweier gegenüberliegender Eckpunkte: prograxn Flaechenberechnung; (* berechnet die Flaeche eines Rechtecks *) const Xl = ?; Y1 = ?; x2 = ?; Y2 = ?; var Hoehe, Breite, Flaeche integer; : { P = XlfX2 A YlfY2 > begin Hoehe := Yl - Y2; B r e i t e := Xl - x2; Flaeche := Hoehe * Breite; if Flaeche -C 0 t h e n Flaeche := - F l a e c h e end. (* Flaechenberechnung *) ( Q = Flaeche=I(Xl-X2) .(Yl-Y2)1 > Dabei ist: 1x1 = x für x 20 -x für xc0. a) Zeigen Sie zunächst mit Hilfe der Hoare-Regeln die Gültigkeit folgender Programmformel: { Pif = Flaeche=Hoehe - Breite A Flaeche f 0 > if Flaeche < 0 t h e n Flaeche := - F l a e c h e { Qif s Flaeche=IHoehe - Breite1 A F l a e c h e > 0 > Geben Sie dazu die jeweils verwendeten Hoare-Regeln an. Hinweis: Gegebenenfalls müssen Sie ausnutzen, daß x = y 3 [XI= lyl gilt. uesamten Programms. Setzen Sie b) Zeigen Sie nun mit Hilfe der Hoare-Regeln die Gültigkeit des b Geben Sie wieder die jeweils verwendedazu die Gültigkeit der Programmforrnel unter a) voraus. Seite: 20 Kurs 1612 “Konzepte imperativer Programmierung” Klausur am 07.03.1998 Aufgabe 7 (4 + 6 = 10 Punkte) Mit dem folgenden Programmausschnitt soll innerhalb eines größeren Programms der größte gemeinsame Teiler zweier integer-Variablen x und y berechnet werden. Der genaue Kontext des Programms ist hier nicht relevant. Die partielle Korrektheit des gesamten Programms sei jedoch bereits gezeigt. ( INV = . . . > while x <> y do if x > y then X : = x - y else Y := y - x; a) Für welche Wertebereiche von x und y terminiert die while-Schleife? Begründen Sie Ihre Aussage. b) Beweisen Sie die Terminierung der while-Schleife, indem Sie eine Terminierungsfunktion Z für die while-Schleife angeben. Verwenden Sie die Einschränkung der Wertebereiche von x und y aus Teil a) als Invariante INV der while-Schleife und zeigen Sie mit deren Hilfe die Eigenschaften w 1) bis w3) einer Terminierungsfunktion. (Den formalen Nachweis, daß INV tatsächlich eine Invariante der while-Schleife ist, brauchen Sie nicht zu führen.) Seite: 22 Kurs 1612 “Konzepte imperativer Programmierung” Klausur am 07.03.1998 Aufgabe 8 (4 + 3 + 4 + 3 = 14 Punkte) Man kann zwei natürliche Zahlen x und y nach folgendem Prinzip miteinander multiplizieren: Man halbiert x, wobei ein eventueller Rest vernachlässigt wird, und verdoppelt parallel dazu y solange, bis x den Wert 0 erreicht hat. Addiert man nun alle Zwischenwerte von y, die zu einem ungeraden Zwischenwert von x gehören, hat man das Produkt der ursprünglichen Zahlen. Als Beispiel soll das Produkt aus 10lund 32 ermittelt werden: x: Y: 101 32 50 64 25 128 12 256 6 512 3 1024 1 @@ 0 4096 Es ist 101 * 32 = 32 + 128 + 1024 + 2048 = 3232. Mit der folgenden Funktion Produkt wird der beschriebene Algorithmus implementiert. tme tNatZah1 = O..maxint; 1 function P r o d u k t ( inZahl1, inZahl : tNatZah1): tNatZah1; { berechnet das Produkt aus inZahl u n d inZahl > var x, YI P : integer; 7 8 9 10 11 12 13 14 15 16 17 18 19 begin X : = inZahl1; Y := inZahl2; P := 0; w h i l e x >= 1 do begin if x mod 2 = 1 then P := p + y; X := x d i v 2 ; Y := y *2 end; Produkt := p end; { Produkt > Ihre Aufgabe ist es, einen datenflußorientierten Test der Funktion Produkt durchzuführen, indem Sie die Teilaufgaben a) bis d) bearbeiten. Seite: 23 Kurs 1612 “Konzepte imperativer Programmierung” Klausur am 07.03.1998 Name: Matrikelnummer: a) Erstellen Sie den Kontrollflußgraphen in Datenflußdarstellung. Geben Sie dazu jeweils an, welche Programmzeilen von einem Knoten repräsentiert werden, welche defund c-uses dem Knoten bzw. p-uses den von dem Knoten ausgehenden Kanten zuzuordnen sind. Das kann in folgender Form geschehen: 1 - 19 b) Ermitteln Sie die du-Mengen für die Variable x. c) Geben Sie für die unter b) ermittelten du-Mengen der Variablen x alle Teilpfade im Kontrollflußgraphen an. d) Geben Sie ausführbare Pfade im Kontrollflußgraphen an, in denen alle unter c) ermittelten Teilpfade enthalten sind, und ermitteln Sie zu jedem dieser Pfade ein Testdatum. (Die assoziierten Testfälle brauchen Sie nicht angeben.) - Seite: 29 Kurs 1612 “Konzepte imperativer Programmierung” Zusammenfassung der Muß-Regeln 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. Selbstdefinierte Konstantenbezeichner bestehen nur aus Großbuchstaben. Bezeichner von Standardkonstanten wie z.B. maxint sind also ausgenommen Typbezeichnern wird ein t vorangestellt. Bezeichner von Zeigertypen beginnen mit tRe f. Bezeichner formaler Parameter beginnen mit in, io oder out. Jede Anweisung beginnt in einer neuen Zeile; begin und end stehen jeweils in einer eigenen Zeile Anweisungsfolgen werden zwischen begin und end um eine konstante Anzahl von 2 - 4 Stellen eingeruckt. begin und end stehen linksbündig unter der zugehörigen Kontrollanweisung, sie werden nicht weiter eingerückt. Anweisungsteile von Kontrollanweisungen werden genauso eingerückt. Im Programmkopf wird die Aufgabe beschrieben, die das Programm löst. Jeder Funktions- und Prozedurkopf enthält eine knappe Aufgabenbeschreibung als Kommentar. Ggf. werden zusätzlich die Parameter kommentiert. Die Parameter werden sortiert nach der Übergabeart: Eingangs-, Änderungs- und Ausgangsparameter. Die Übergabeart jedes Parameters wird durch Voranstellen von in, io oder out vor den Parameternamen gekennzeichnet. Das Layout von Funktionen und Prozeduren entspricht dem von Programmen. Jede von einer Funktion oder Prozedur benutzte bzw. manipulierte Variable wird als Parameter übergeben. Es werden keine globalen Variablen manipuliert. Einzige Ausnahme sind Modul-lokale Variablen, die in den Parameterlisten der exportierten Prozeduren und Funktionen des Moduls nicht auftauchen, selbst wenn sie von diesen geändert werden. Jeder nicht von der Prozedur veränderte Parameter wird als Wertparameter übergeben. Lediglich Felder können auch anstatt als Wertparameter als Referenzparameter übergeben werden, um den Speicherplatz für die Kopie und den Kopiervorgang zu sparen. Der Feldbezeichner beginnt aber stets mit dem Präfix in, wenn das Feld nicht verändert wird. Funktionsprozeduren werden wie Funktionen im mathematischen Sinne benutzt, d.h. sie besitzen nur Wertparameter. Wie bei Prozeduren ist eine Ausnahme nur bei Feldern erlaubt, um zusätzlichen Speicherplatz und Kopieraufwand zu vermeiden. Wertparameter werden nicht als lokale Variable mißbraucht. Die Schlüsselworte unit, interf acc und implementation werden ebenso wie begin und end des Initialisierungsteils linksbündig positioniert. Nach dem Schlüsselwort uni t folgt ein Kommentar, der die Aufgabe beschreibt, welche die Unit löst. Für die Schnittstelle gelten dieselben Programmierstilregeln wie für ein Programm. Dies betrifft Layout und Kommentare. Nach dem Schlüsselwort interf acc folgt im Normalfall kein Kommentar. Für den Implementationsteil gelten dieselben Programmierstilregeln wie für ein Programm. Nach dem Schlüsselwort implementation folgt nur dann ein Kommentar, wenn die Realisierung einer Erläuterung bedarf (z.B. wegen komplizierter Datenstrukturen und/oder Algorithmen). In Programmen oder Moduln, die andere Moduln importieren (,,benutzen“), wird das Schlüsselwort uses auf dieselbe Position eingerückt wie die Schlüsselworte const, type, var usw. Die Laufvariable wird innerhalb einer f or-Anweisung nicht manipuliert. Die Grundsätze der strukturierten Programmierung sind strikt zu befolgen. Seite: 30 Kurs 1612 “Konzepte imperativer Programmierung” Hoare-Regeln 1. KonseauenzreEel 1 Konseauenzregel2 2. Nullaxiom 3. Zuweisung_axiom 4 * Seauenzreeel {PI {PI { P<xtexpr>} x : =expr {P} {PI SI {RL {RI s, IQ) {PI SI; s, IQ1 5.Zusammensetzung.srenel 6. Bedinqmgsreeel 1 {PI s IQ> {P} begin S end {Q} {PABJ S, {QL W-W $7 IQ) {P} if B then SI eise s, {QI Bedinnunesregel2 {P} if B then S 7. while-Regel 8. reneat-Regel {Q} {PABI s {PI {P} while B do S {PATB} {PI S {QL (Q A-I* P {P} repeat S until B {QAB} Kurs 1612 “Konzepte imperativer Programmierung” Terminierungsfunktion Definition Eine Abbildung z heißt Terminierungsfunktion der while-Schleife while B do S, wenn sie die Bedingungen wl) bis w3) erfüllt: wl)’ Seien vl, . . . . v, die in B und S vorkommenden Variablen und Konstanten. Dann ist 7: Z ’+ Z mit r(vl, . . . . vr) f Z. w2) Ist vor einem Schleifendurchlauf z(vt, . . . . vr) = t erfüllt, dann ist nach dem Schleifendurchlauf z(vl, . . . . vr) < t erfüllt. w3) Es existiert ein Wert t*EZ, so daß vor jedem Schleifendurchlauf ‘c(q, ***, vr) 2 t* gilt. i) Beachten Sie, daß S nur dann ausgeführt wird, wenn INV A B erfüllt ist. Diese Voraussetzung muß man gewöhnlich ausnutzen, um die Eigenschaften w2) und w3) einer Terminierungsfunktion beweisen zu können. .- i) Eine Invariante INV, mit der sich die Terminierung einer Schleife beweisen läßt, ist (leider) oft nicht identisch mit einer geeigneten Invarianten, mit der sich die partielle Korrektheit zeigen läßt. Haben wir eine solche Invariante INV gefunden und bewiesen, daß die Schleife unter dieser Invarianten terminiert, müssen wir außerdem noch zeigen, daß INV auch tatsächlich erfüllt ist, wenn die Programmabarbeitung die Schleife erreicht Seite: 31