• Keine Ergebnisse gefunden

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

N/A
N/A
Protected

Academic year: 2022

Aktie "Wintersemester 2005/2006 Hinweise zur Bearbeitung der Klausur zum Kurs 1612 “Konzepte imperativer Programmierung”"

Copied!
34
0
0

Wird geladen.... (Jetzt Volltext ansehen)

Volltext

(1)

Wintersemester 2005/2006 Hinweise zur Bearbeitung der Klausur

zum Kurs 1612 “Konzepte imperativer Programmierung”

Wir begrüßen Sie zur Klausur "Konzepte imperativer Programmierung". Lesen Sie sich die- se Hinweise vollständig und aufmerksam durch, bevor Sie mit der Bearbeitung der Aufgaben beginnen:

1. Prüfen Sie die Vollständigkeit Ihrer Unterlagen. Die Klausur umfasst:

- 2 Deckblätter,

- 1 Formblatt für eine Bescheinigung für das Finanzamt, - diese Hinweise zur Bearbeitung,

- 8 Aufgaben (Seite 2 - Seite 28),

- die Muss-Regeln des Programmierstils, - die Hoare-Regeln

- die Definition der Terminierungsfunktion.

2. Füllen Sie, bevor Sie mit der Bearbeitung der Aufgaben beginnen, folgende Seiten des Klausurexemplares aus:

a) BEIDE Deckblätter mit Namen, Anschrift sowie Matrikelnummer. Markieren Sie vor der Abgabe auf beiden Deckblättern die von Ihnen bearbeiteten Aufgaben.

b) Falls Sie eine Teilnahmebescheinigung für das Finanzamt wünschen, füllen Sie bitte das entsprechende Formblatt aus.

Nur wenn Sie beide Deckblätter vollständig ausgefüllt haben, können wir Ihre Klausur korrigieren!

3. Schreiben Sie Ihre Lösungen auf den freien Teil der Seite unterhalb der Aufgabe bzw.

auf die leeren Folgeseiten. Sollte dies nicht möglich sein, so vermerken Sie, auf welcher Seite die Lösung zu finden ist. Streichen Sie ungültige Lösungen deutlich durch.

4. Schreiben Sie auf jedem von Ihnen beschriebenen Blatt oben links Ihren Namen und oben rechts Ihre Matrikelnummer. Wenn Sie weitere eigene Blätter benutzt haben, hef- ten Sie auch diese, mit Namen und Matrikelnummer versehen, an Ihr Klausurexemplar.

Nur dann werden auch Lösungen außerhalb Ihres Klausurexemplares gewertet!

5. Neben unbeschriebenem Konzeptpapier und Schreibzeug (Füller oder Kugelschreiber) sind keine weiteren Hilfsmittel zugelassen. Die Muss-Regeln des Programmierstils, die Tabelle mit den im Kurs verwendeten Hoare-Regeln und die Definition der Terminie- rungsfunktion finden Sie im Anschluss an die Aufgabenstellung.

6. Es sind maximal 52 Punkte erreichbar. Sie haben die Klausur sicher dann bestanden, wenn Sie mindestens 26 Punkte erreicht haben.

Wir wünschen Ihnen bei der Bearbeitung der Klausur viel Erfolg!

(2)

Aufgabe 1 (2+2+1+2 Punkte)

In der Mathematik gibt es die so genanten Armstrong-Zahlen, die wie folgt definiert werden:

Eine Armstrong-Zahl ist eine Zahl, bei der die Summe der einzelnen Ziffern, die jeweils mit der Anzahl der Ziffern der Zahl potenziert sind, gleich der Zahl ist.

z.B.: 153 = 13 + 53 + 33 (3 Ziffern je hoch 3)

a) Schreiben Sie eine Funktion countZiff, welche die Anzahl der Ziffern einer positiven Zahl zu- rückliefert (in unserem Beispiel die Zahl 3). Benutzen Sie den im Programmrahmen Arm- strongZahlen (siehe unten) vorgegebenen Funktionskopf.

b) Schreiben Sie eine Funktion potenziere, welche die n-te Potenz einer Zahl berechnet. Der Sonderfall des undefinierten Wertes 00 muss nicht berücksichtigt werden. Benutzen und ergänzen Sie den vorgegebenen Funktionskopf (siehe unten).

c) Die Funktion isArmstrong (siehe rechte Seite) gibt true zurück wenn der übergebene Parame- ter eine Armstrong-Zahl ist, sonst false. In dieser Funktion werden die Funktionen countZiff und potenziere benutzt.

Bestimmen Sie, an welcher der Stellen (1) - (4) in der Funktion isArmstrong die Funktion po- tenziere einzusetzen ist und geben Sie die komplette Programmzeile an.

d) Schreiben Sie ein Programm, das zwei positive ganze Zahlen x und y (x > 0, y < MAXINT, x < y, diese Bedingungen müssen Sie nicht überprüfen) einliest und dann alle Armstrong-Zahlen mit x ≤ a ≤ y ausgibt. Auch wenn Sie die Teilaufgaben a) - c) nicht gelöst haben, können Sie die Funktio- nen voraussetzen. Nutzen Sie dazu den vorgegebenen Programmrahmen.

program ArmstrongZahlen (input, output);

type

tNatZahl = 0..maxint;

...

function countZiff (inZahl : tNatZahl): tNatZahl;

{gibt die Stellenanzahl der inZahl zurück}

...

function potenziere ( ??? ): tNatZahl;

{berechnet die n-te Potenz einer Zahl}

...

function isArmstrong (inZahl : tNatZahl): boolean; {prüft ob inZahl eine Armstrong-Zahl ist}

...

(3)

function isArmstrong (inZahl : tNatZahl): boolean; {prüft ob inZahl eine Armstrong-Zahl ist}

var i, j,

ggfArmstrong, AnzDerStellen ZwischErg, EndErg,

LetzteZiffer : tNatZahl;

begin

ggfArmstrong := inZahl;

AnzDerStellen := countZiff(inZahl);

EndErg := 0;

for i := 1 to AnzDerStellen do begin

(1)

LetzteZiffer := ggfArmstrong mod 10;

(2)

ggfArmstrong := ggfArmstrong div 10;

(3)

EndErg := EndErg + ZwischErg (4)

end;

if EndErg = inZahl then isArmstrong := true else

isArmstrong := false; end;

(4)
(5)
(6)

Aufgabe 2 (3+5 Punkte)

Gegeben ist folgende Definition einer linearen Liste:

type

tRefListe = ^tListe;

tListe = record

info: integer;

next: tRefListe end;

a) Implementieren Sie eine Funktion kommtVor, die prüft, ob in einer übergebenen linearen Liste ein Element mit einem ebenfalls zu übergebenden info-Wert vorkommt.

Verwenden Sie folgenden Funktionskopf:

function kommtVor(inRefListe:tRefListe; inWert:integer):boolean;

{Rückgabe true, falls die übergebene Liste ein Element mit info-Komponente inWert enthält, sonst false}

b) Implementieren Sie eine Prozedur Tausche, die in einer übergebenen Liste das Element mit der info-Komponente 0 sucht und die mit diesem Element beginnende Restliste nur durch Ändern der Verkettung aushängt und an den Beginn der Liste einfügt. Sie können davon ausgehen, dass die 0 in der Liste genau einmal vorkommt. Ist das Element mit info-Komponente 0 das erste, so ist nichts zu tun.

Verwenden Sie folgenden Prozedurkopf:

procedure Tausche(var ioRefAnfang: tRefListe);

Ein Beispiel:

Vor dem Aufruf:

Danach:

-9 -7 0 -13 -1 30

ioRefAnfang

-9 -7 0 -13 -1 30

ioRefAnfang

(7)
(8)
(9)
(10)

Aufgabe 3 (5+2 Punkte)

Gegeben sei folgende Typdeklaration:

type

tRefDVListe = ^tDVListe;

tDVListe = record

info: integer;

prev,

next:tRefDVListe end;

Mit Hilfe dieses Typs wird eine so genannte doppelt verkettete Liste gebildet. Im Gegensatz zu den im Kurs betrachteten einfach verketteten linearen Listen besitzt hier ein Listenelement neben einem Zeiger next auf seinen Nachfolger auch einen Zeiger prev auf seinen Vorgänger. So wie der next-Zeiger des letzten Elementes zeigt der prev-Zeiger des ersten Elementes auf nil.

Eine solche Liste werde unverändert über einen Anfangszeiger angesprochen, der das erste Element referenziert.

Die folgende Skizze zeigt ein Beispiel einer solchen doppelt verketteten Liste aus vier Elementen.

a) Implementieren Sie eine Prozedur loeschen, die das erste Element mit einem zu übergebenden info-Wert in der Liste sucht und es aus der Liste löscht. Sie dürfen dabei davon ausgehen, dass das zu löschende Element in der Liste vorkommt.

Die folgende Skizze zeigt z.B. das Ergebnis, wenn aus oben abgebildeter Liste das Element mit Info „2“ gelöscht wurde.

10 -5

ioRefAnfang

2 1

next next next next

prev prev prev

prev

10 -5

ioRefAnfang

1

next next next

prev prev prev

(11)

Benutzen Sie folgenden Prozedurkopf:

procedure loeschen(var ioRefAnfang: tRefDVListe; inSuch:integer);

{Loescht das erste Listenelement mit Info inSuch. Es muss ein solches Element existieren!}

b) Vergleicht man obige Typdeklaration zur Bildung doppelt verketteter Listen mit der z.B. in Auf- gabe 4 gegebenen Typdeklaration zur Bildung binärer Bäume, so stellt man fest, dass beide struk- turell identisch sind und sich nur in Bezeichnern unterscheiden.

Erklären Sie, warum derselbe Typ sowohl zur Bildung von Bäumen als auch zur Bildung von dop- pelt verketteten Listen verwendet werden kann, obwohl doch beides unterschiedliche Datenstruk- turen sind!

Tipp: Überlegen Sie sich, was genau die Typen tDVListe bzw. tBinBaum sowie tRefDVLi- ste bzw. tRefBinBaum beschreiben.

(12)
(13)
(14)

Aufgabe 4 (3+1 Punkte)

Gegeben sei folgende Typdeklaration zur Bildung eines binären Baumes:

type

tRefBinBaum = ^tBinBaum;

tBinBaum = record

info: integer;

links,

rechts:tRefBinBaum end;

a) Implementieren Sie rekursiv eine Prozedur spiegeln, die einen beliebigen übergebenen Baum aus Knoten des Typs tRefBinBaum spiegelt, indem für jeden Knoten des Baumes die beiden Nachfolger vertauscht werden.

Sollte der eingegebene Baum sortiert sein, so wird durch diese Spiegelung übrigens die Sortierung umgekehrt, d.h. aus einem aufsteigend sortierten Baum würde ein absteigend sortierter und umge- kehrt.

Verwenden Sie den folgenden Prozedurkopf, wobei an der mit ?? gekennzeichneten Stelle die Übergabeart geeignet zu ergänzen ist:

procedure spiegeln(??RefWurzel: tRefBinBaum);

b) Handelt es sich hier um eine sinnvolle Anwendung der Rekursion? Begründen Sie Ihre Antwort.

(Eine unbegründete Antwort wie „Ja“ oder „Nein“ wird nicht bewertet!)

(15)
(16)
(17)
(18)

Aufgabe 5 (3 Punkte)

Die Funktion quersumme soll die Quersumme einer eingegebenen natürlichen Zahl berechnen, also die Summe all ihrer Ziffern.

Typdefinition und Funktion seien wie folgt gegeben.

type

tNatZahl = 0..maxint;

function quersumme (inZahl : tNatZahl): tNatZahl;

{berechnet die Quersumme von inZahl}

var qs,

rest : tNatZahl;

begin qs:=0;

rest:=inZahl div 10;

while rest > 0 do begin

qs := qs + rest mod 10;

rest := rest div 10 end; {while}

quersumme:=qs;

end; {quersumme}

Ermitteln Sie die Testfälle für den boundary-interior Pfadtest (interior-Test für genau zwei Schleifen- durchläufe) der Funktion quersumme. Sie brauchen nicht die zu den Testfällen gehörenden Pfade im Kontrollflussgraphen anzugeben.

(19)
(20)

Aufgabe 6 (4+3+3)

Das folgende Programm Aufgabe6 bestimmt die Summe aller geraden Zahlen von 2 bis X.

Formal lässt sich das gewünschte Ergebnis durch folgende Nachbedingung spezifizieren:

Sie sollen zeigen, dass das Programm Aufgabe6 bezüglich der Spezifikation

{ P } S { Q ≡ sum = (X2 + 2X)/4} für ein von Ihnen geeignet zu wählendes Prädikat P partiell korrekt ist.

program Aufgabe6;

const X = ?;

var sum,

z : integer;

begin

sum := 0;

z := 2;

while z < (X+2) do begin

sum := sum + z;

z := z + 2 end

end.

a) Zeigen Sie zunächst, dass

eine Invariante der while-Schleife des Programms Aufgabe6 ist, wobei Xg (bzw. zg) kurz für das Prädikat „X ist gerade“ (bzw. „z ist gerade“) stehe.

Q≡sum X2+2X ---4

=

INV sum z2–2z ---4

⎝ = ⎠

⎛ ⎞ ∧(z≤X+2)∧Xg∧zg

(21)

b) Bestimmen Sie ein geeignetes Prädikat P, so dass die folgende Programmformel PFb gültig wird:

{P}

sum := 0;

z:=2{INV}

Beweisen Sie die Gültigkeit von PFb.

c) Beweisen Sie nun die partielle Korrektheit von Aufgabe6 bezüglich der Spezifikation {P}S{Q}, wobei Sie die Gültigkeit von PFb und die Invarianteneigenschaft von INV vorausset- zen dürfen.

Wichtig: Geben Sie in allen Teilaufgaben die von Ihnen verwendeten Hoare-Regeln explizit an!

(22)
(23)
(24)
(25)
(26)

Aufgabe 7 (4 Punkte)

Zeigen Sie, dass das Programm Aufgabe6 terminiert, indem Sie eine Funktion τ angeben und bewei- sen, dass τ eine Terminierungsfunktion der while-Schleife ist.

(27)
(28)

Aufgabe 8 (3+2+2+2 Punkte)

Beantworten Sie die folgenden Fragen und begründen Sie jeweils Ihre Antworten!

a) Erläutern Sie kurz die wesentliche Gemeinsamkeit von Verifikation und Test eines Programms so- wie die beiden wesentlichen Unterschiede zwischen ihnen.

b) Nehmen Sie Stellung zu folgender Behauptung:

Das Verfahren zur Prüfung, ob ein Element mit einem vorgegebenen info-Wert in einem binären Suchbaum existiert, ist sinnvollerweise rekursiv zu implementieren.

(Anmerkung: Wenn wir vom „info-Wert“ eines Elementes sprechen, beziehen wir uns auf eine Typdeklaration für Binärbäume, wie sie z.B. in Aufgabe 4 gegeben ist. )

c) Terminiert ein total korrektes Programm für jede mögliche Eingabe (also auch für Eingaben, die nicht der Programmspezifikation entsprechen)?

(Eine nicht begründete Antwort wie nur „Ja“ oder „Nein“ wird nicht bewertet.) d) Gegeben sei folgende Repeat-Schleife:

repeat Srepeat until B

Mit Hilfe einer aussagekräftigen Invariante INV konnte die Gültigkeit folgender Programmformel bewiesen werden:

{INV ∧ ¬B} Srepeat {INV ∧ B}

Was können Sie über die Anzahl der Schleifendurchläufe aussagen?

(29)
(30)
(31)
(32)

1. Selbstdefinierte Konstantenbezeichner bestehen nur aus Großbuchstaben. Bezeichner von Standard- konstanten wie z.B. maxint sind also ausgenommen

2. Typbezeichnern wird ein t vorangestellt. Bezeichner von Zeigertypen beginnen mit tRef. Bezeichner formaler Parameter beginnen mit in, io oder out.

3. Jede Anweisung beginnt in einer neuen Zeile; begin und end stehen jeweils in einer eigenen Zeile

4. Anweisungsfolgen werden zwischen begin und end um eine konstante Anzahl von 2 - 4 Stellen eingerückt. begin und end stehen linksbündig unter der zugehörigen Kontrollanweisung, sie wer- den nicht weiter eingerückt.

5. Anweisungsteile von Kontrollanweisungen werden genauso eingerückt.

6. Im Programmkopf wird die Aufgabe beschrieben, die das Programm löst.

7. Jeder Funktions- und Prozedurkopf enthält eine knappe Aufgabenbeschreibung als Kommentar.

Ggf. werden zusätzlich die Parameter kommentiert.

8. Die Parameter werden sortiert nach der Übergabeart: Eingangs-, Änderungs- und Ausgangsparame- ter.

9. Die Übergabeart jedes Parameters wird durch Voranstellen von in, io oder out vor den Parame- ternamen gekennzeichnet.

10. Das Layout von Funktionen und Prozeduren entspricht dem von Programmen.

11. 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.

12. 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.

13. 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.

14. Wertparameter werden nicht als lokale Variable mißbraucht.

15. Die Schlüsselworte unit, interface und implementation werden ebenso wie begin und end des Initialisierungsteils linksbündig positioniert. Nach dem Schlüsselwort unit folgt ein Kommentar, der die Aufgabe beschreibt, welche die Unit löst.

16. Für die Schnittstelle gelten dieselben Programmierstilregeln wie für ein Programm. Dies betrifft Layout und Kommentare. Nach dem Schlüsselwort interface folgt im Normalfall kein Kom- mentar.

17. 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).

18. 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.

19. Die Laufvariable wird innerhalb einer for-Anweisung nicht manipuliert.

20. Die Grundsätze der strukturierten Programmierung sind strikt zu befolgen.

(33)

1. Konsequenzregel 1

2. Nullaxiom

4. Sequenzregel

6. Bedingungsregel 1 3. Zuweisungaxiom

7. while-Regel

{P} S {R}, R ⇒ Q {P} S {Q}

P ⇒ R, {R} S {Q}

{P} S {Q}

{P} {P}

{P<x←expr>} x:=expr {P}

{P} S1 {R}, {R} S2 {Q}

{P} S1; S2 {Q}

{P ∧ B} S1 {Q}, {P ∧ ¬B} S2 {Q}

{P} if B then S1

{P ∧ B} S {Q}, (P ∧ ¬B ) ⇒ Q {P} if B then S {Q}

{P ∧ B} S {P}

{P} while B do S {P ∧ ¬B}

{P} S {Q}, (Q ∧ ¬B) ⇒ P {P} repeat S until B {Q ∧ B}

else S2 {Q}

5. Zusammensetzungsregel {P} S {Q}

{P} begin S end {Q}

8. repeat-Regel Konsequenzregel 2

Bedingungsregel 2

(34)

Definition

Eine Abbildung τ heißt Terminierungsfunktion der while-Schleife while B do S, wenn sie die Bedingungen w1) bis w3) erfüllt:

w1) Seien v1, ..., vr die in B und S vorkommenden Variablen und Kon- stanten. Dann ist τ: ZZ r → ZZ mit τ(v1, ..., vr) ∈ZZ.

w2) Ist vor einem Schleifendurchlauf τ(v1, ..., vr) = t erfüllt, dann ist nach dem Schleifendurchlauf τ(v1, ..., vr) < t erfüllt.

w3) Es existiert ein Wert t*∈ZZ, so dass vor jedem Schleifendurchlauf τ(v1, ...,vr)≥t* gilt.

Bemerkung

i) Beachten Sie, dass S nur dann ausgeführt wird, wenn INV ∧ B erfüllt ist.

Diese Voraussetzung muss man gewöhnlich ausnutzen, um die Eigen- schaften w2) und w3) einer Terminierungsfunktion beweisen zu können.

ii) Eine Invariante INV, mit der sich die Terminierung einer Schleife be- weisen lässt, ist (leider) oft nicht identisch mit einer pk-geeigneten Inva- rianten, mit der sich die partielle Korrektheit zeigen lässt.

Haben wir eine solche t-geeignete Invariante INV gefunden und bewie- sen, dass die Schleife unter dieser Invarianten terminiert, müssen wir au- ßerdem noch zeigen, dass INV auch tatsächlich erfüllt ist, wenn die Programmabarbeitung die Schleife erreicht.

Referenzen

ÄHNLICHE DOKUMENTE

 boolean istVor(Arbeitstag tag) : Liefert true , wenn der durch das Empfängerobjekt be- zeichnete Arbeitstag nach dem Arbeitstag liegt, der durch das Objekt

c) Mit Hilfe des Zeilensummenmaximums kann eine Ordnung auf Matrizen definiert werden. Eine Matrix A ist genau dann „größer“ als eine Matrix B, wenn das Zeilensummenmaximum von A

 boolean istVor(Arbeitstag tag) : Liefert true , wenn der durch das Empfängerobjekt be- zeichnete Arbeitstag nach dem Arbeitstag liegt, der durch das Objekt bezeichnet

b) Schreiben Sie mit Hilfe der Prozedur suchen , die Sie als bekannt voraussetzen können, auch wenn Sie den Teil a) nicht bearbeitet haben, eine Prozedur loeschen, die das

b) Schreiben Sie eine Prozedur, die das größte Element einer solchen Liste löscht, indem sie dessen Vorgänger mit Hilfe der Funktion vorMaximum bestimmt und dessen Nachfolger aus

b) Schreiben Sie mit Hilfe der Prozedur suchen , die Sie als bekannt voraussetzen können, auch wenn Sie den Teil a) nicht bearbeitet haben, eine Prozedur loeschen, die das

Das Programm erzeugt daraufhin für jedes Jahr der Laufzeit eine Zeile, die das angesparte Geld beschreibt, wenn der Geldbetrag Betrag mit einer jährlichen Verzinsung in

Schreiben Sie eine iterative Prozedur DVListenElementEntfernen, die einen Zeiger auf das erste Element einer doppelt verketteten Liste und einen Integer-Wert übergeben bekommt..