Blatt - AG Softwaretechnik

Werbung
TU Kaiserslautern
Prof. Dr. A. Poetzsch-Heffter
Dipl.-Inf. J.-M. Gaillourdet
Fachbereich Informatik
Dipl.-Inform. M. Reitz
AG Softwaretechnik
Dipl.-Inform. K. Geilmann
Dipl.-Inf. P. Michel
M. Sc. Y. Welsch
Übungsblatt 9: Software-Entwicklung 1 (WS 2008/09)
Ausgabe: in der Woche vom 15.12. bis zum 19.12.
Abgabe: in der Woche vom 05.01. bis zum 09.01.
Abnahme: max 2 Tage nach Abgabe
Aufgabe 1 Imperative Programmierung mit Java (Präsenzaufgabe)
Kreuzen Sie an, ob folgende Aussagen wahr oder falsch sind. Falls eine Aussage nicht eindeutig ist, diskutieren Sie die verschiedenen Interpretationsmöglichkeiten.
wahr
falsch
Ausdrücke in Java erzeugen keine Seiteneffekte.
Auf der rechten Seite einer Zuweisung kann ein Prozeduraufruf stehen.
Der Rumpf einer while-Anweisung wird mindestens einmal ausgeführt.
Geschachtelte Fallunterscheidungen lassen sich durch eine Auswahlanweisung ersetzen.
Auf jede Variable kann während der gesamten Programmausführung zugegriffen
werden.
Eine Variable des Typs bool[] speichert ein Feld.
Jeder Ausdruck ist eine Anweisung.
Es gibt Anweisungen, welche die Reihenfolge, in der Anweisungen abgearbeitet werden,
beeinflussen.
Überall dort wo eine einzelne Anweisung stehen kann, kann auch ein Anweisungsblock
stehen.
Die Schleifenvariable einer for-Schleife kann auch um mehr als 1 pro Schleifendurchlauf
erhöht werden.
Prozeduren enthalten Anweisungen und liefern immer ein Ergebnis.
Eine Prozedur kann sich in ihrem Rumpf nicht selber aufrufen.
Jede Prozedurinkarnation hat ihre eigenen lokalen Variablen.
Wenn v eine lokale Variable einer Prozedur ist, dann wird mit v immer die gleiche Speichervariable angesprochen.
Ein Programm kann Felder erzeugen, auf die es später nicht mehr zugreifen kann.
Es kann mehrere Variablen geben die auf das gleiche Feld zeigen.
Aufgabe 2 Einfache prozedurale Programmierung (Präsenzaufgabe)
Benutzen Sie für folgende Aufgaben wieder die Klasse IO.
a) Schreiben Sie eine Java-Prozedur, die von der Kommandozeile eine Zahl n liest und, wenn n durch 2 oder
3 teilbar ist, diese Zahl wieder ausgibt, ansonsten n mit einer zusätzlich eingelesenen Zahl multipliziert
und ausgibt.
b) Schreiben Sie eine Java-Prozedur, die von der Kommandozeile eine Zahl n und einen String s liest, und
diesen dann n mal ausgibt
c) Sie kennen die Fakultätsfunktion in ihrer funktionalen Formulierung.
fun fac 0 = 1
| fac n = n * fac (n -1);
Programmieren Sie eine äquivalente Prozedur int fac(int n) {...} in Java. Verwenden Sie dabei
eine While-Schleife, um die Rekursion der gegebenen Version zu ersetzen.
Aufgabe 3 Variablen, Zustand und Schleifen (Einreichaufgabe)
Wir betrachten folgendes prozedurale Programm, dass den ggT von zwei Zahlen berechnet:
1
public class GGT {
2
public static void main( String [] args) {
int m;
int n;
3
4
5
6
m = IO. readInt ();
n = IO. readInt ();
7
8
9
while (m > 0) {
int v;
10
11
12
v = n % m;
n = m;
m = v;
13
14
15
}
16
17
IO. println (n);
18
}
19
20
}
a) Geben Sie für die Eingaben 30 und 24 die Sequenz der Ausführungszustände an. Als Speicherzustand
können Sie die Belegung der Variablen – sofern sie lebendig sind – verwenden und für den Steuerungszustand die Zeilennummer der nächsten Aktion. Betrachten Sie Zuweisungen und Deklarationen als
Aktion.
b) Schreiben Sie das Programm um, so dass es bei gleicher Funktionalität eine for Schleife benutzt.
c) Schreiben Sie das Programm um, so dass es bei gleicher Funktionalität eine do-while Schleife benutzt.
d) Geben Sie an, wie man allgemein eine for Schleife der Form
for(I; C; U) { B }
in eine while Schleife überführen kann.
e) Geben Sie eine sinnvolle Abstraktion für den Anweisungsblock von Zeile 10 bis 16 an, indem Sie eine
neue Prozedur einführen. Ersetzen Sie den Block entsprechend durch einen Aufruf dieser Prozedur.
Aufgabe 4 Felder und Matrizenmultiplikation (Präsenzaufgabe)
Eine zwei dimensionale Matrix kann mittels zweidimensionaler Felder leicht dargstellt werden. In dem
Diagramm unten steht eine graue Box, wie z.B.
3
, für die von Java intern verwaltete Länge eines Feldes.
3









0
1
2
3
4
5
6
7
8









3
0.0 1.0 2.0
3
3.0 4.0 5.0
3
6.0 7.0 8.0
Implementieren Sie die unten angegebenen Prozeduren zur Arbeit mit Matrizen. erzeuge erstellt eine neue
Matrix mit den übergebenen Ausmaßen. set setzt einen einzelen Wert in einer Matrix neu. get liefert den
Wert, der an einer angegebenen Stelle der Matrix gespeichert ist. zeilen liefert die Zahl der Zeilen der
Matrix zurück, spalten ist analog definiert. ausgabe soll eine Matrix zwei dimensional als Text ausgeben.
Wenn unsinnige Zeilen- oder Spaltenangaben einer Prozedur übergeben werden, geben Sie eine Fehlermeldung mit IO aus.
double [][] erzeuge (int zeilen , int spalten ) { ... }
void set( double [][] m, int zeile , int spalte , double wert) { ... }
double get( double [][] , int zeile , int spalte ) { ... }
int zeilen ( double [][] m) { ... }
int spalten ( double [][] m) { ... }
void ausgabe ( double [][] m) { ... }
Aufgabe 5 Felder und Matrizenmultiplikation (Einreichaufgabe)
a) Realisieren Sie die Matrizenmultiplikation in der Prozedur mmult. Wenn die übergebenen Matrizen
nicht zum Multiplizieren geeignet sind, geben Sie null zurück. Verwenden Sie die bereits definierten
Hilfsprozeduren aus Aufgabe 5 a).
double [][] mmult ( double [][] a, double [][] b) { ... }
b) Zweidimensionale Matrizen lassen sich auch mit einem eindimensionalen Feld darstellen, siehe Grafik.









0
1
2
3
4
5
6
7
8









9
0.0 1.0 2.0 3.0 4.0 5.0 6.0 7.0 8.0
Wie lautet die Formel um von Zeile und Spalte auf den zugehörigen Feldindex zu kommen?
class Matrix {
int zeilen , spalten ;
double [] feld;
}
Matrizen stellen wir nun mit dem Verbund Matrix dar. Implementieren Sie die folgenden Prozeduren
analog zu den Aufgaben 4 und 5.
void ausgabe ( Matrix m) { ... }
Matrix erzeuge (int zeilen , int spalten ) { .... }
void set( Matrix m, int zeile , int spalte , double wert) { ... }
double get( Matrix m, int zeile , int spalte ) { ... }
int zeilen ( Matrix m) { ... }
int spalten ( Matrix m) { ... }
Matrix mmult ( Matrix a, Matrix b) { ... }
c) In der praktischen Anwendung von Matrizen treten sogenannte Bandmatrizen auf. Diese zeichnen sich
durch zwei Dreiecke mit Nullen, links unten und rechts oben aus. Das Band entlang der Diagonale ist
dann die wesentliche Information, die wir nun speichern und bearbeiten wollen. Die Geometrie einer
solchen Matrix wird also nicht nur durch die Zahl der Zeilen und Spalten, sondern auch durch die Zahl
der Diagonalen, die nicht Null sind, bestimmt. Dabei ist die Bandbreite die Zahl der diagonalen Reihen
auf einer Seite der längsten Diagonalen. Die Grafik zeigt eine Bandmatrix mit der Breite 1.


 1 6 0 0


 10 2 7 0


 0 11 3 8


 0 0 12 4



0 0 0 13
0
0
0
9
5















3
5
6.0
7.0
8.0
9.0
2.0
3.0
4.0
5.0
5
1.0
5
10.0 11.0 12.0 13.0
class BandMatrix {
int zeilen , spalten ;
int bandbreite ;
double [][] feld;
}
Implementieren Sie die folgenden Prozeduren:
void ausgabeB ( BandMatrix m) { ... }
BandMatrix erzeugeB (int zeilen , int spalten , int bandbreite ) { ... }
int convZeileB ( BandMatrix m, int zeile , int spalte ) { ... }
void setB( BandMatrix m, int zeile , int spalte , double wert) { ... }
double getB( BandMatrix m, int zeile , int spalte ) { ... }
int zeilenB ( BandMatrix m) { ... }
int spaltenB ( BandMatrix m) { ... }
Matrix mmultB ( Matrix a, BandMatrix b) { ... }
d) Schreiben Sie ein Programm unter Verwendung der Lösung von Teil a) oder b), das y nach folgender
Gleichung für ein eingegebenes n berechnet.
!n
!
!
1 1
1
x
·
=
1 0
0
y
Was berechnet dieses Programm?
Aufgabe 6 Rekursion und Iteration (Einreichaufgabe)
Schreiben Sie zwei Java-Funktionen, die auf sortierten Feldern von ganzen Zahlen mittels binärer Suche
bestimmen, ob eine Zahl im Feld enthalten ist. Sie können dabei folgende Vorlagen verwenden:
static boolean binarySearch (int [] sorted , int key) {
return bSearchH (sorted , 0, sorted . length - 1, key );
}
static boolean bSearchH (int [] sorted , int first , int last , int key) {
...
}
a) Implementieren Sie die Funktion bSearchH rekursiv.
b) Implementieren Sie die Funktion bSearchH iterativ.
c) Testen Sie ihre Funktionen.
Aufgabe 7 Weihnachtsaufgabe (freiwillige Zusatzaufgabe)
In dieser Aufgabe werden wir mit Hilfe einer Turtle Grafik Implementierung Bilder zeichnen. Bei der Turtle
Grafik haben Sie eine Zeichenfläche auf der sich eine Schildkröte (oder zumindest etwas ähnliches) mit
einem Zeichenstift befindet. Die Schildkröte können Sie mit verschiedenen Befehlen steuern.
• penup() und pendown() heben bzw. senken den Zeichenstift
• forward(x) lässt die Schildkröte x Schritte in Blickrichtung laufen, wobei eine Linie gezeichnet
wird, wenn der Zeichenstift unten ist
• turn(a) dreht die Blickrichtung der Turtle um a Grad
Laden Sie die Datei turtle.zip von der Webseite und entpacken Sie sie. Übersetzen und starten Sie die
Datei TurtleGraphics.java. Sie sehen eine einfache Beispielzeichnung. Der Zeichencode befindet sich
in der Prozedur draw(). Diese Prozedur ist auch der Startpunkt für ihre Zeichnungen. In der Klasse Turtle
finden sie alle Prozeduren mit der Sie die Turtle steuern können.
a) Schreiben Sie eine Prozedur square() die ein Quadrat zeichnet und rufen Sie sie im Rumpf von draw
auf. Natürlich können Sie Prozeduren, Variablen, Schleifen, usw. verwenden.
b) Schreiben Sie Prozeduren für die folgenden Bilder:
c) Das nächste Bild ist die Kochkurve in verschiedenen Tiefen. Finden Sie heraus wie sie vom Bild der Tiefe n zum Bild der Tiefe n+1 kommen und schreiben Sie eine Prozedur koch(int t, int l) die eine
Kochkurve der Tiefe t zeichnet, der Parameter l gibt die Kantenlänge an. Schreiben Sie eine Prozedur
snow() die aus Kochkurven eine Schneeflocke zusammensetzt.
Tiefe 1
Tiefe 2
Schneeflocke
Tiefe 3
Hinweis: Es kann hilfreich sein sich weitere Primitive zur Steuerung der Schildkröte selbst als Prozedur
zu definieren, wie zum Beispiel backward, left, right oder move(x), wobei letzteres zum Beispiel die
Schildkröte ohne zu zeichnen vorwärts bewegen könnte. Damit können Sie dann immer abstrakter und
natürlicher komplexe Bilder beschreiben.
d) Folgende Bilder sind ebenfalls durch rekursives zeichnen von Strukturen mit Selbstähnlichkeit entstanden. Die Vorschrift für den Farn finden Sie als Beispiel in TurtleGraphics. Über eine Möglichkeit
das Sierpinski Dreieck zu malen können Sie sich auf http://en.wikipedia.org/wiki/L-system
informieren. Die Abbildung unten links zeigt die Drachenkurve, die unten rechts kann durch minimales
modifizieren der Sierpinski Funktion berechnet werden.
Zugehörige Unterlagen
Herunterladen