Allgemeines
Allgemeines
Allgemeines
Sie wollen auch ein ePaper? Erhöhen Sie die Reichweite Ihrer Titel.
YUMPU macht aus Druck-PDFs automatisch weboptimierte ePaper, die Google liebt.
Übung zur Vorlesung ”<br />
Programmieren“, Wintersemester 12/13<br />
Übungsleiter: Sebastian Ebers, <br />
<strong>Allgemeines</strong><br />
Aufgabenblatt 4<br />
Abgabe: 08.01.2013, vor der Vorlesung (14:15 Uhr, AM 1)<br />
Max. Punktzahl: 49<br />
• Geben Sie als 3er oder 4er-Gruppe Ihre Lösung termingerecht unter Nennung von<br />
Vor- und Nachnamen sowie Matrikelnummern und Übungsgruppennummer auf jeder<br />
abgegebenen Seite ab. Bei Übungspartnern aus mehreren Gruppen kennzeichnen Sie<br />
bitte die Gruppe, in der die korrigierten Abgaben zurückgegeben werden sollen.<br />
• Unvollständige sowie unleserliche Angaben und Lösungen führen zu Punktabzügen.<br />
• Zur Bearbeitung der Aufgaben ist es erforderlich, sich selbständig über die Inhalte<br />
der Vorlesung und der Übung hinaus zu informieren. Die angegebenen Quellen und<br />
Hinweise sind als Anregung und nicht als erschöpfende Auflistung zu verstehen.<br />
• Senden Sie die compilierbaren (übersetzbaren) Java-Quellcode-Dateien an<br />
proguebungabgabe@itm.uni-luebeck.de mit dem Betreff<br />
“Uebung Nr 4 , , , ”<br />
Java-Quellcode-Dateien, die sich nicht übersetzen lassen, führen zu erheblichem Punktabzug.<br />
Gleiches gilt für nicht (rechtzeitig) abgegebenen Quellcode.<br />
Geben Sie den erstellten Quellcode sowie die Antworten auf die Fragen zusätzlich<br />
textuell auf Papier ab!<br />
• Sie können sämtliche Java-Aufgaben an Ihrem privaten Computer bearbeiten und<br />
lösen. Die Java-Dateien müssen sich jedoch auf einem der Pool-Rechner übersetzen<br />
und ausführen lassen. Zur Sicherheit sollten Sie Programme, die nicht im Pool erstellt<br />
wurden, vor der Abgabe auf einen Pool-Rechner kopieren und dort testen.<br />
• Die Betreuer der Übungsgruppen helfen gerne, wenn es bei der Lösung der Übungsaufgaben<br />
zu Problemen kommt. Sie können jedoch bei Problemen mit der Installation<br />
und Einrichtung von Java auf Ihren Computern keine Hilfestellung leisten.<br />
1
Aufgabe 4.1: Iteration und Rekursion (11 Punkte)<br />
Die folgenden Teilaufgaben sollen in die rekursive Programmierung einführen und den<br />
Unterschied zwischen iterativer und rekursiver Programmierung verdeutlichen. Als<br />
Lösung ist der gesamte kommentierte Code abzugeben. Es ist nicht nötig, einzelne<br />
Abgaben zu den jeweiligen Aufgabenteilen anzufertigen.<br />
a) Fakultät<br />
Auf Übungsblatt 3 haben Sie in Aufgabe 2 eine iterative Berechnung der Fakultät<br />
implementiert:<br />
n∏<br />
n! = 1 · 2 · 3 · ... · n = k<br />
Diese Art der Programmierung durch Wiederholung der gleichen Anweisung<br />
(beispielsweise in einer FOR-Schleife) wird als iterativ (lat. iterare, wiederholen)<br />
bezeichnet. Eine andere Möglichkeit ist die rekursive (lat. recurrere, zurücklaufen)<br />
Lösung. Dabei wird innerhalb der Methode die Methode selbst aufgerufen.<br />
(i) Implementieren Sie die Methode public static long fakultaet(int n)<br />
rekursiv. Verwenden Sie dazu die rekursive Definition der Fakultät:<br />
{<br />
1 falls n = 0<br />
n! =<br />
n · (n − 1)! falls n > 0<br />
Hinweis: Fakultäten für negative Zahlen sind nicht definiert.<br />
k=1<br />
(2 P.)<br />
(ii) Schreiben Sie ein Hauptprogramm (es genügt auch eine Main-Methode<br />
innerhalb der im vorherigen Teil erstellten Klasse), das die Ergebnisse der<br />
Rekursion von n = 1 bis n = 12 ausgibt.<br />
(1 P.)<br />
b) Kaninchen<br />
Auf einer Insel setzt ein geschäftstüchtiger Kaninchenzüchter ein junges Kaninchenpaar<br />
aus. Die Tiere sind nach 2 Monaten geschlechtsreif und bekommen<br />
dann jeden Monat ein Paar als Nachwuchs. Im dritten Monat gibt es also ein<br />
neues Paar, welches im 5. Monat selbst wieder Nachwuchs bekommt usw..<br />
Dabei sei vorausgesetzt, dass immer genug Futter vorhanden ist, der Nachwuchs<br />
immer ein Männchen-Weibchen-Paar ist, keine Fressfeinde auf der Insel leben<br />
und die Kaninchen unsterblich sind.<br />
(i) Schreiben Sie ein rekursives Programm, welches die Anzahl der Kaninchenpaare<br />
im Monat n ausgibt. Die Populationsstärke wird durch die<br />
Fibonacci-Folge f 1 , f 2 , ... mit der rekursiven Bildungsvorschrift<br />
⎧<br />
⎨ 0 falls n = 0<br />
f n =<br />
1 falls n = 1<br />
⎩<br />
f n−1 + f n−2 falls n ≥ 2<br />
definiert.<br />
Erstellen Sie dazu die Methode public static long fibonacci(int n),<br />
welche die Anzahl der Paare im n-ten Monat ausgibt.<br />
2
Erweitern Sie Ihr Hauptprogramm so, dass die Anzahl der Paare der Monate<br />
1 bis 12 und außerdem die Anzahl der Paare nach 2, 3, 4 und 5 Jahren<br />
am Bildschirm angezeigt werden.<br />
(3 P.)<br />
(ii) Was fällt Ihnen bei der (Dauer der) Berechnung der letzten beiden Werte<br />
auf?<br />
(1 P.)<br />
(iii) Warum tritt dieser Effekt auf?<br />
(2 P.)<br />
(iv) Implementieren Sie die Rekursion in einer neuen Methode so, dass dieser<br />
Effekt nicht auftritt!<br />
(2 P.)<br />
Hinweis: Die Lösung der Teilaufgabe 4.1b)(iv) ist deutlich schwerer, als die Anzahl<br />
der Punkte vermuten lässt.<br />
3
Aufgabe 4.2: Gültigkeitsbereiche (10 Punkte)<br />
Analysieren Sie das folgende Programm und achten Sie dabei insbesondere auf die verschiedenen<br />
Gültigkeitsbereiche der Klasse, der Methoden und der lokalen Variablen.<br />
Was wird auf der Konsole ausgegeben, wenn das Programm mit dem Übergabeparameter<br />
21 aufgerufen wird? Begründen Sie Ihre jeweilige Antwort kurz.<br />
(6 P.)<br />
1 public class Gueltigkeitsbereiche {<br />
2<br />
3 static int i = 10;<br />
4<br />
5 public static void main(String[] args) {<br />
6<br />
7 System.out.println("a) i = "+i);<br />
8<br />
9 i = Integer.valueOf(args[0]);<br />
10<br />
11 System.out.println("b) i = "+i);<br />
12<br />
13 int i = 5;<br />
14<br />
15 System.out.println("c) i = "+i);<br />
16<br />
17 classMethod();<br />
18<br />
19 System.out.println("f) i = "+i);<br />
20<br />
21 Gueltigkeitsbereiche bereiche = new Gueltigkeitsbereiche();<br />
22 System.out.println("j) j = " + bereiche.memberMethod());<br />
23 }<br />
24<br />
25 public static void classMethod(){<br />
26<br />
27 System.out.println("d) i = "+i);<br />
28<br />
29 int i = 42;<br />
30<br />
31 System.out.println("e) i = "+i);<br />
32 }<br />
33<br />
34 public int memberMethod(){<br />
35<br />
36 int j = 88;<br />
37 {<br />
38 j = 5;<br />
39 System.out.println("g) i = "+(++i));<br />
40 System.out.println("h) j = "+j);<br />
41 }<br />
42<br />
43 System.out.println("i) i = " + i);<br />
44 return j;<br />
45 }<br />
46 }<br />
4
Aufgabe 4.3: Finden von Programmierfehlern (12 Punkte)<br />
In dieser Aufgabe geht es darum, logische bzw. semantische Fehler in der Programmierung<br />
zu finden.<br />
Gegeben sei folgendes Programm:<br />
1 public class SwitchCase {<br />
2<br />
3 public static void main(String[] args) {<br />
4 System.out.println("1. Tag: ");<br />
5 System.out.println(gibWochentagName(1));<br />
6 System.out.println(istArbeitstag(1));<br />
7<br />
8 System.out.println("6. Tag: ");<br />
9 System.out.println(gibWochentagName(6));<br />
10 System.out.println(istArbeitstag(6));<br />
11<br />
12 System.out.println("7. Tag: ");<br />
13 System.out.println(gibWochentagName(7));<br />
14 System.out.println(istArbeitstag(7));<br />
15 }<br />
16<br />
17 public static String gibWochentagName(int ganzZahl) {<br />
18 switch (ganzZahl) {<br />
19 case 1:<br />
20 return "Montag";<br />
21 case 2:<br />
22 return "Dienstag";<br />
23 case 3:<br />
24 return "Mittwoch";<br />
25 case 4:<br />
26 return "Donnerstag";<br />
27 case 5:<br />
28 return "Freitag";<br />
29 case 6:<br />
30 return "Samstag";<br />
31 default:<br />
32 return "Sonntag";<br />
33 }<br />
34 }<br />
35<br />
36 public static String istArbeitstag(int wochentag) {<br />
37 String rueckgabe = gibWochentagName(wochentag);<br />
38 switch (wochentag) {<br />
39 case 1:<br />
40 rueckgabe += " ist der " + wochentag + ". Arbeitstag";<br />
41 case 2:<br />
42 rueckgabe += " ist der " + wochentag + ". Arbeitstag";<br />
43 case 3:<br />
44 rueckgabe += " ist der " + wochentag + ". Arbeitstag";<br />
45 case 4:<br />
46 rueckgabe += " ist der " + wochentag + ". Arbeitstag";<br />
47 case 5:<br />
48 rueckgabe += " ist der " + wochentag + ". Arbeitstag";<br />
49 case 6:<br />
50 rueckgabe += " ist ein Wochenendtag";<br />
51 default:<br />
52 rueckgabe += " ist ein Wochenendtag";<br />
53 }<br />
54 return rueckgabe+"!";<br />
55 }<br />
56 }<br />
5
Anforderungen / Beabsichtigte Funktionalität:<br />
• Die Methode public static String gibWochentagName(int ganzZahl) soll<br />
für eine übergebene Zahl den Namen des entsprechenden Wochentags (Montag<br />
bei 1, Dienstag bei 2, usw.) zurückgeben.<br />
• Die Methode public static String istArbeitstag(int wochentag) soll zusätzlich<br />
zum Namen des Wochentags zurückgeben, ob es sich um einen Arbeitstag<br />
oder einen Wochenendtag handelt.<br />
a) Geben Sie an, was auf der Konsole ausgegeben wird.<br />
(4,5 P.)<br />
b) Nennen und erläutern Sie, was die Methode<br />
public static String istArbeitstag(int wochentag) zurückgibt, falls<br />
wochentag kleiner als 1 oder größer als 7 ist.<br />
(1,5 P.)<br />
c) In welchen Fällen funktioniert das Programm wie beabsichtigt? Machen Sie<br />
Korrekturvorschläge, damit das Programm die Anforderungen erfüllt.<br />
(3 P.)<br />
d) Für den sechsten Fall (case 6) gibt es zwei mögliche Lösungen. Nennen und<br />
erläutern Sie hier beide Lösungen.<br />
(3 P.)<br />
6
Aufgabe 4.4: Der Weihnachtswald (16 Punkte)<br />
In dieser Aufgabe geht es darum, Weihnachtsbäume verschiedener Größen zu zeichnen:<br />
1 *<br />
2 ***<br />
3 *****<br />
4 *******<br />
5 *********<br />
6 ***********<br />
7 * *************<br />
8 *** ***************<br />
9 * ***** *****************<br />
10 *** ******* *******************<br />
11 ***** ********* *****<br />
12 * ******* *********** *****<br />
13 *** *** *** *****<br />
14 ***** *** *** *****<br />
15 * *** *** *****<br />
a) Erzeugen Sie zwei Klassen mit den Namen Weihnachstwald und<br />
Weihnachtsbaum. Weihnachtswald enthält die main-Methode. Der Konstruktor<br />
von Weihnachtsbaum ist<br />
public Weihnachtsbaum(int hoehe)<br />
Die Klasse Weihnachtsbaum enthält zudem eine private Objekt-Variable hoehe<br />
vom Typ int und eine öffentliche Methode zeichne() ohne Übergabe- und<br />
Rückgabewert.<br />
b) Implementieren Sie den Konstruktor so, dass er der Objekt-Variablen hoehe<br />
den Übergabewert zuweist.<br />
c) In der Methode zeichne() ist nun folgende Funktionalität umzusetzen: Sie<br />
zeichnet den Weihnachtsbaum in zwei Teilen. Zuerst wird die Krone, dann der<br />
Baumstumpf gezeichnet.<br />
Die Baumkrone soll jeweils so hoch sein, wie die Objekt-Variable hoehe vorgibt.<br />
Die Größe des Stumpfes wird davon abhängig folgendermaßen berechnet:<br />
Der Stumpf entspricht ⌋ einem Quadrat. Die Größe des Quadrates berechnet sich<br />
mittels 2·⌊ hoehe +1. Der Stumpf befindet sich zentriert unterhalb der Krone.<br />
4<br />
Implementieren Sie mit dieser Formel die Methode zeichne() so, dass mit<br />
Hilfe der Methoden System.out.print() bzw. System.out.println()<br />
der Weihnachtsbaum auf der Konsole ausgegeben wird.<br />
d) Erzeugen Sie in der main-Methode der Klasse Weihnachtswald ein Objekt der<br />
Klasse Weihnachtsbaum, übergeben Sie eine Höhe über die Kommandozeile<br />
und lassen Sie den Baum ausgeben.<br />
Für den Fall, dass die eine Höhe kleiner 3 oder größer 30 übergeben wird, soll<br />
Ihr Programm eine Fehlermeldung ausgeben, dass der Baum zu klein bzw. zu<br />
groß ist.<br />
7
Hinweise<br />
• Als Lösung ist der gesamte kommentierte Code abzugeben, es ist nicht nötig,<br />
einzelne Abgaben zu den jeweiligen Aufgabenteilen anzufertigen.<br />
• Es muss pro Start des Programms nur ein Weihnachtsbaum ausgegeben werden<br />
- insbesondere müssen nicht zwei oder drei Weihnachtsbäume nebeneinander<br />
ausgegeben werden. Wer dies jedoch implementieren möchte, bekommt einen<br />
extra Goldstern für dieses Übungsblatt.<br />
• Zum Zeichnen der Krone benötigen Sie mehrere ineinander verschachtelte for-<br />
Schleifen. Es kann hilfreich sein, wenn Sie das Zeichnen der Krone zunächst auf<br />
dem Papier ausprobieren, um die benötigte Anzahl an Leerzeichen und Sternen<br />
pro Zeile und somit den passenden Algorithmus zu bestimmen.<br />
• Da Zeilen- und Zeichenabstand in der Konsole evtl. unterschiedlich sind, wird<br />
der quadratische Stumpf meist eher als Rechteck denn als Quadrat dargestellt.<br />
Wichtig ist die gleiche Anzahl an Sternchen in den Zeilen und Spalten des<br />
Stumpfes.<br />
• Experimentieren Sie mit verschiedenen Höhenangaben, um sich zu vergewissern,<br />
dass Ihr Programm funktioniert.<br />
• Testen Sie Ihr Programm unbedingt auch in der Konsole. Editoren wie Sci-<br />
TE verwenden evtl. eine nichtproportionale Schiftart 1 bei der Darstellung Ihrer<br />
Konsolenausgaben. Das führt dazu, dass Ihre Bäume schief aussehen, obwohl<br />
Ihr Programm korrekt funktioniert.<br />
1 http://de.wikipedia.org/wiki/Nichtproportionale_Schriftart<br />
8