F A C H H O C H S C H U L E F Ü R D I E W I R T S C H A F T F H D W , H A N N O V E R S O F T WA R E E N G I N E E R I N G E LEMENTE DER P ROGRAMMIERUNG ERSATZKLAUSUR Studiengang: Wirtschaftsinformatik/Informatik Studienquartal: I. Theoriequartal Prüfungsumfang: Elemente der Programmierung (Stand 25. 3. 03) und Musterlösungen Beispielaufgaben. Dozent: Hellberg/König/Löwe Termin: 22. April 2003 Dauer: 180 Minuten 50 Punkte sind zu erreichen: Wissen 20, Anwendung 20 und Transfer 10 Punkte. Bestanden ab 25 Punkte. TEIL I: WISSEN (40 MINUTEN) Aufgabe 1 (2 Punkte): Welche vier groben Phasen unterscheidet man in der Software-Entwicklung? Aufgabe 2 (1 Punkt): Welche der folgenden Aussagen sind richtig? (a) Mit ausführlichen Tests zeigt man, dass die Software keine Fehler mehr hat! (b) Mit ausführlichen Tests versucht man, Fehler möglichst frühzeitig zu finden! Aufgabe 3 (5 Punkte): Was ist die Semantik für (a) Typnamen, (b) Konstantennamen, (c) Operatorennamen, (d) Ausdrücke ohne Variablen und (e) Ausdrücke mit Variablen? Aufgabe 4 (2 Punkte): Wie ändert sich die Auswertung der Funktion f(x:Card,y:Card):Card, wenn wir einen Parameter lazy machen: f(x:Card,/\y:Card):Card? Was hat Laziness mit Striktheit zu tun? Aufgabe 5 (5 Punkte): Erläutern Sie, wie man die Bedeutung der folgenden rekursiven Gleichung gewinnt: f(x:String):Card::= ?(=(_C(x),“!“),5,-(f(S_(x)),1)).1 Welchen Funktionskommentar „[*…*]“ schreiben sie für f? Aufgabe 6 (2 Punkte): Bei Funktionsdeklarationen unterscheidet man die Schnittstelle und die Implementierung. Welchen Teil bezeichnet man als den abstrakten Teil, welchen als den konkreten? Warum? Aufgabe 7 (1 Punkt): Wie viele Elemente hat die Bedeutung des Typs C in: a():A, b():B, A++B:C ? Aufgabe 8 (2 Punkte): Warum sollten Funktionsimplementierungen kurz sein? Wie erreicht man das? TEIL II: ANWENDUNG ( 95 MINUTEN) 2 Aufgabe 9 (2 Punkte): Schreiben Sie eine Funktion, die prüft, ob eine Zahl (Card) Fibonacci-Zahl3 ist! (a) Geben Sie Testfälle an, die Sie zum Test Ihrer Implementierung benötigen! Begründen Sie die Wahl! (b) Implementieren Sie die Funktion in LOMF! (Setzen Sie dabei die Funktion aus Fußnote 3 voraus!) Aufgabe 10 (2 Punkte): Sie sollen eine Implementierung der Funktion fib3(x:Card):Card angeben! In Abwandlung zur gängigen Fibonacci-Funktion werden hier nicht die letzten zwei sondern die letzten drei fib3-Zahlen zur nächsten fib3-Zahl zusammengezählt. (Achten sie nicht auf Effizienz!) S_(x:String):String liefert x ohne den ersten Buchstaben. _C(x:String):String liefert den ersten Buchstaben von x. Falls x die leere Zeichenkette ist, ist in beiden Fällen das Ergebnis x. 2 Bei allen Entwicklungsaufgaben können sie nur die Basisfunktionen ohne Angabe der Definition benutzen! 3 fibonacci(x:Card):Card ::= ?(x.<(2),1,fibonacci(x.-(1)).+(fibonacci(x.-(2)))). 1 Aufgabe 11 (2 Punkte): Sie sollen eine Funktion fibN(n:Card,x:Card):Card entwickeln! Hier soll für alle n > 0 gelten: (i) fibN(n, x) = 1 falls x < n und (ii) fibN(n, x) = fibN(n, x-1) + ... + fibN(n, x-n) sonst! (a) Geben Sie Testfälle an, die Sie zum Test Ihrer Implementierung vorbereiten? Begründen Sie die Wahl! (b) Implementieren Sie die Funktion in LOMF! (Hinweis: Ihre Implementierung soll immer terminieren!) Aufgabe 12 (5 Punkte): Entwickeln Sie eine fünfwertige Logik in folgendem Umfang: (a) Definieren Sie einen Datentyp L5 mit den Werten Falsch, FastFalsch, Vielleicht, FastWahr und Wahr. (b) In der Reihenfolge, in der die „Wahrheitswerte“ in (a) notiert sind, soll der Grad der „Wahrheit“ steigen! Machen Sie das durch die Implementierung einer totalen Ordnung le(x:L5,y:L5):Bool4 in LOMF explizit! Diese Funktion soll genau dann true liefern, wenn x in der Liste unter (a) nicht hinter y steht. (Achtung: Hier sind geeignete Spezialisierungen von L5 hilfreich!) (c) Definieren Sie den And-Operator and(x:L5,y:L5):L5 so als LOMF-Funktion, dass er das Minimum von x und y bzgl. le als Ergebnis liefert. Wir wollen jetzt den And-Operator, der ja assoziativ ist, gleich auf mehrere Argumente anwenden: (d) Definieren Sie eine einfache Liste ListL5, in der nur „Daten“ aus L5 eingetragen sind! (e) Definieren Sie den Operator and(x:ListL5):L5 so als LOMF-Funktion, dass er alle Einträge in x mit dem And-Operator aus (c) verknüpft! Aufgabe 13 (9 Punkte): Arithmetische Ausdrücke ohne Variablen sind entweder Konstanten oder Funktionsanwendungen. Konstanten sind elementar und bestehen nur aus dem Namen der Konstanten. Funktionsanwendungen sind zusammengesetzt und bestehen auch aus einem Namen, nämlich dem der angewendeten Funktion, und aus einer nicht leeren Liste von Argumenten, die selbst wieder beliebige Ausdrücke sind. (a) (2 Punkte): Definieren Sie LOMF-Datentypen für Konstanten, Funktionsanwendungen und Ausdrücke! (b) (2 Punkte): Zeichnen Sie diese Struktur als UML-Diagramm! (c) (2 Punkte): Schreiben Sie eine Funktion asString(e:Ausdruck):String, die den Parameter e als vollständig geklammerten Ausdruck mit Funktionsnamen vor den öffnenden Klammern und mit Kommata zwischen Argumentausdrücken (wenn es zwei oder mehr sind) ausgibt. Hinweise: Alle Namen sollen als String modelliert werden! Abstrakte Listenschnittstellen sind nicht gefordert! Beachten Sie die Programmierregeln aus der Vorlesung und dem Skript! (d) (3 Punkte): Erweitern Sie (a) bis (c) um Variablen als einer weiteren Variante elementarer Ausdrücke, die auch nur aus einem Namen bestehen. TEIL III: TRANSFER (45 MINUTEN) Aufgabe 14 (4 Punkte): Zum Auswerten von syntaktisch korrekten Ausdrücken in polnischer Notation mit zweistelligen Operatoren konnten wir ein Verfahren benutzen, das einen Stapelspeicher verwendet: Mache den Stapelspeicher leer. Lese den Ausdruck in polnischer Notation einmal von links nach rechts! Verfahre dabei so: (1) Wenn ein Operand gelesen wird, dann lege ihn oben auf dem Stapel ab. (2) Wenn ein Operator gelesen wird, dann (i) verknüpfe die beiden Operanden oben auf dem Stapel mit dem Operator, (ii) nimm die beiden Operanden vom Stapel und (iii) lege das Ergebnis oben auf den Stapel. Das Ergebnis ist am Ende des Verfahrens das einzige Element im Stapelspeicher. Beschreiben Sie auf ähnliche Weise ein Verfahren, das einen vollständig geklammerten normalen arithmetischen Ausdruck mit ausschließlich zweistelligen Operatoren (sagen wir +, , * und /) in die polnische 4 le für englisch „less or equal“! 2 Notation umwandelt, z. B. „((12+31)*(41+55))“ in „12 31 + 41 55 + *“. (Auf Trennzeichen zwischen Zahlen verzichten wir, da wir Zahlen nicht ziffernweise schreiben oder lesen, sondern immer ganz.) Setzen Sie wieder voraus, dass der Ausdruck syntaktisch in Ordnung ist. Das bedeutet unter anderem, dass er für jeden Operator ein passendes Paar aus öffnender und schließender Klammer enthält. Lesen Sie die Eingabe wieder nur einmal von links nach rechts. Gelesen werden kann dabei nur (a) eine öffnende Klammer, (b) eine schließende Klammer, (c) ein (kompletter) Operand oder (d) ein Operator. Hilfreich ist die Benutzung eines Stapelspeichers. Das Ergebnis bauen Sie schrittweise durch „hinten Anfügen“ von kompletten Operanden oder Operatoren auf. Aufgabe 15 (1 Punkt) Ist diese Definition der Typanpassung für beliebige Typen Type immer strikt? Begründen Sie die Antwort! asType(x:Anything):Type::= §() >>> asType(x:Type):Type::= x Aufgabe 16 (3 Punkte) Warum ist folgende Definition der Gleichheit problematisch? equal(x:Anything,y:Anything):Bool::= false >>> equal(x:Card,y:Card):Bool::= x.=(y) >>> equal(x:Nothing,y:Nothing):Bool::= true Aufgabe 17 (2 Punkte) Ein Programm prima?(function:String,input:String):Bool ist zu entwickeln, das als Eingabe eine Funktionsimplementierung function (als Text) mit dem Funktionskopf f(x:card):Card erhält und eine Eingabe input für diese Implementierung (ebenfalls als Text). Das Program prima? soll genau dann true ausgeben, wenn der Eingabetext eine korrekte LOMFImplementierung mit dem vorgegebenen Funktionskopf ist, die für die Eingabe input einen Wert, der von §() verschieden ist, liefert. Sonst soll sie false liefern. Was ist an folgendem Vorschlag faul: (1) Übergebe function dem Lomf-System im Programmeingabefenster und rufe check auf! (2) Bei Syntax-Fehlern gib false aus! (3) Sonst schreibe “f(“ +S+ input +S+ “)“ in das Testeingabefenster von Lomf und löse execute aus! (4) Bei Syntax-Fehlern gib false aus! (5) Sonst warte, bis das Ergebnis ausgegeben wird. Ist es ungleich §() gebe true sonst false aus! (6) Gerät Lomf in eine Endlosschleife, gib false aus! 3