02.04.2015 Aufrufe

Allgemeines

Allgemeines

Allgemeines

MEHR ANZEIGEN
WENIGER ANZEIGEN

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

Hurra! Ihre Datei wurde hochgeladen und ist bereit für die Veröffentlichung.

Erfolgreich gespeichert!

Leider ist etwas schief gelaufen!