Arrays und Methoden Programmiervorkurs WS 2010 / 11
Einleitung Bisher sind einfach Programme möglich Nun wollen wir Organisation und Stil verbessern Gesamter Code sollte nicht an einer Stelle stehen Nicht jedes Mal Code kopieren für mehrmaliges Ausführen 2
Bisheriger Stil Ausgabe von ans falls es positiv ist Andernfalls um 10 inkrementieren public static void main(string[] args) { int ans = 0; if (ans > 0) System.out.println(ans); else ans = ans + 10; // Mache etwas mit ans if (ans > 0) System.out.println(ans); else ans = ans + 10; // Und wieder eine Änderung if (ans > 0) System.out.println(ans); else ans = ans + 10; 3
Einleitung Bisher sind einfach Programme möglich Nun wollen wir Organisation und Stil verbessern Gesamter Code sollte nicht an einer Stelle stehen Nicht jedes Mal Code kopieren für mehrmaliges Ausführen Lösung ist es Code zu kapseln / auszulagern Verhalten abstrahieren und durch Symbole repräsentieren Dadurch wird Komplexität verdeckt und Kopien entfernt 4
Methoden public static RÜCKGABETYP NAME(PARAMETERLISTE) { BEFEHLE return EXPRESSION; Methoden fassen Programmcode zusammen Sie sollten immer eine spezielle Aufgabe besitzen Letztendlich sind sie wie kleine Programme 5
Methodennamen public static RÜCKGABETYP NAME(PARAMETERLISTE) { BEFEHLE return EXPRESSION; NAME: beliebiger sinnvoller Name für die Methode Name sollte Verhalten / Sinn der Funktion beschreiben CamelCase-Schreibweise (einlangernameeinermethode) Ziffern ausser am Anfang erlaubt 6
Rückgabetypen public static RÜCKGABETYP NAME(PARAMETERLISTE) { BEFEHLE return EXPRESSION; RÜCKGABETYP: beliebiger Datentyp (int, String, ) Spezialfall void bedeutet: Methode gibt nichts zurück Dann benötigt return keine EXPRESSION Später mehr dazu... 7
Parameter public static RÜCKGABETYP NAME(PARAMETERLISTE) { BEFEHLE return EXPRESSION; PARAMETERLISTE: Liste von Variablen, die der Methode übergeben werden (kann auch leer sein!) Beispiele: int x, int y String a, double b, int c 8
Return public static RÜCKGABETYP NAME(PARAMETERLISTE) { BEFEHLE return EXPRESSION; return: spezieller Befehl, der die Methode abbricht und Ergebnis von EXPRESSION zurückgibt Ergebnis von EXPRESSION muss vom Typ RÜCKGABETYP sein! 9
Erstes Beispiel public static void voneinsbisn(int n) { for (int i = 1; i <= n; i++) { System.out.print(i + " "); Wir betrachten zunächst Rückgabetyp void Methode gibt nichts zurück, d.h. berechnet nichts, das den Aufrufenden interessiert Muss sie aber auch nicht, denn sie gibt bloß Zahlen aus 10
Erstes Beispiel public static void voneinsbisn(int n) { for (int i = 1; i <= n; i++) { System.out.print(i + " "); voneinsbisn(3); voneinsbisn(10); Ausgabe: 1 2 3 Ausgabe: 1 2 3 4 5 6 7 8 9 10 Mit voneinsbisn(x) kann nun die neue Methode aufgerufen werden Quasi wie ein neuer Java-Befehl x ist hierbei ein Wert für den Parameter n 11
Anwendung public static void main(string[] args) { int ans = 3; for (int i = 1; i <= ans; i++) { System.out.print(i + " "); // Mache etwas mit ans public static void main(string[] args) { int ans = 3; voneinsbisn(ans); // Mache etwas mit ans voneinsbisn(ans); for (int i = 1; i <= ans; i++) { System.out.print(i + " "); // Und wieder eine Änderung for (int i = 1; i <= ans; i++) { System.out.print(i + " "); // Und wieder eine Änderung voneinsbisn(ans); public static void voneinsbisn(int n) { for (int i = 1; i <= n; i++) { System.out.print(i + " "); 12
Grund für Methoden Wieso sollte man sein Programm zerstückeln? Programme werden häufig sehr komplex Nicht jeder Programmierer versteht das gesamte Projekt! Programm einfacher gestalten: Muss man überhaupt verstehen WIE es gemacht wird, wenn man weiss, DASS es gemacht wird? NEIN! Fehlerresistenz, Kopien verhindern, Parametrisierbar,... 13
Rückgabewerte // Berechnet das Quadrat von x public static int square(int x) { return x * x; int wert = square(3); wert: 9 Die Methode square(x) gibt einen Integer zurück square sollte zum Beispiel nicht f oder sq benannt werden - Verwendet sinnvolle Namen! Weiterhin tut das Kommentar nicht weh... ;) 14
Verschachtelung public static int square(int x) { return x * x; public static void main(string[] args) { int a = square(3); int b = square(square(3)); // log(9 + 2^2^2 * 1.5) double c = Math.log(square(3) + square(square(2)) * 1.5); if(square(c) > b && a < b) { // Mache was Methoden können auch verschachtelt werden Math.log(...) ist auch eine Methode Nur auf passende Rückgabewerte und Parameter der Methoden achten 15
Altes Beispiel public static void main(string[] args) { int ans = 0; if (ans > 0) System.out.println(ans); else ans = ans + 10; // Mache etwas mit ans public static void main(string[] args) { int ans = 0; meinemethode(ans); // Mache etwas mit ans meinemethode(ans); if (ans > 0) System.out.println(ans); else ans = ans + 10; // Und wieder eine Änderung // Und wieder eine Änderung meinemethode(ans); if (ans > 0) System.out.println(ans); else ans = ans + 10; Änderungen an ans bleiben nach dem Aufruf nicht erhalten! 16
Sichtbarkeit (Scoping) Variablen sind nur innerhalb ihrer {...- Blöcke gültig Man kann sogar nur {... setzen ohne Schlüsselwort public static void main(string[] args) { { int scoping; 17 int a; if(true) { int b; a = 1; // Okay b = 2; // Fehler // --------------------------------------- public static void func(int d) { c = 3; // Fehler public static void main(string[] args) { int c; func(3); d = 4; // Fehler // --------------------------------------- public static void func(int e) { e = 6; public static void main(string[] args) { int e = 5; func(e); // e ist immernoch 5!
Aufrufe Methoden können von fast überall aufgerufen werden Innerhalb von {...- Blöcken Innerhalb einer if public static void func(int v) { System.out.print(v + " "); System.out.println(func2(v + 2)); if(func2(10) > 3) System.out.print(func2(10) + " "); func2(v + 1); public static int func2(int v) { System.out.print(v + " "); return v - 5; Innerhalb einer for, while public static void main(string[] args) { int wert = 5; func(wert); Ausgabe: 5 7 2 10 10 5 6 18
7 Minuten Pause 19
Rekursion public static void func(int v) { System.out.print(v + " "); func(v + 1); func(0); Ausgabe: 0 1 2 3 4 5 6 7 8 9 10 <...> Was passiert wenn eine Methode sich selbst aufruft? Die Aufruferliste (Stack) wächst hier ständig an main(...) func(0) func(1) func(2) func(3) func(4) func(5) func(6)... 20
Rekursion Das Problem ist das unsere Funktion nicht terminiert Unser Programm steckt in einer Endlosrekursion fest Wichtig bei Rekursion ist der Rekursionsanker An einer Stelle darf der Aufruf von func(.) nicht stattfinden Also erhält man meistens eine Bedingung die entscheidet ob: Die Funktion sich selbst aufruft oder sie einfach return aufruft 21
Rekursion verbessert public static void func(int v) { System.out.print(v + " "); if(v < 10) func(v + 1); else return; func(0); Ausgabe: 0 1 2 3 4 5 6 7 8 9 10 <ENDE> Nun terminiert unser Programm ordentlich Rekursionsanker sind wichtig, deshalb: Die Bedingungen gut kontrollieren! Die Parameter sollten sich der Bedingung nähern! 22
Rekursionsanker Was genau heißt sollte sich der Bedingung annähern Problem ist einfach -> Lösung direkt ausgeben Beispiel: 0! = 1 Rekursionsanker Problem zu schwierig -> Problem einfacher machen Beispiel: 5! = 5 * 4! Rekursion 23
Beispiel public static int fakultaet(int n) { int ergebnis = 1; for (int i = 2; i <= n; i++) { ergebnis *= i; return ergebnis; Fakultät kann iterativ berechnet werden (n!) 24
Beispiel public static int fakultaet(int n) { if (n == 0) { return 1; return n * fakultaet(n - 1); Fakultät ist auch rekursiv möglich Ähnlicher zur mathematischen Definition 0! = 1 n! = n * (n - 1)! Prinzipiell kann jede iterative Lösung auch rekursiv geschrieben werden und umgekehrt 25
Beispiel 3! fakultaet(4) = 4 * fakultaet(3) = 4 * 3 * fakultaet(2) = 4 * 3 * 2 * fakultaet(1) = 4 * 3 * 2 * 1 * fakultaet(0) = 4 * 3 * 2 * 1 * 1 = 24 Was passiert denn nun genau? 4! = 4 * 3 * 2 * 1 = 24 26
Wechselseitige Rekursion Methoden rufen sich gegenseitig auf Eine Form der Rekursion die Kopfschmerzen verursacht 4 ist gerade wenn 3 ungerade ist 3 ist ungerade, wenn 2 gerade ist 2 ist gerade wenn 1 ungerade ist 1 ist ungerade boolean even(int x) { if (x == 0) return true; if (x == 1) return false; return odd(x - 1); boolean odd(int x) { if (x == 0) return false; if (x == 1) return true; return even(x - 1); Auswertung: even(4) odd(3) even(2) odd(1) true! 27
Nachtrag Wieso haben wir gezeigt was eine Endlosschleife ist? Es ist wichtig das Verhalten zu kennen bei Fehlern Was passiert bei Endlosschleifen? - Terminiert nicht Was passiert bei Endlosrekursion? - StackOverflowError Was passiert bei teilen durch 0? - ArithmeticException Probiert es bewusst aus! Es hilft bei ungewollten Fehlern! 28
Rekursion vs. Iteration Rekursion wird häufig verwendet wenn: Strikt der mathematischen Definition gefolgt wird Grund: Einfachheit Iteration wenn: Jedes Element anschauen (immer wieder das Gleiche) Grund: Ein wenig effizienter als Rekursion Meistens intuitiver / verständlicher als Rekursion (K.I.S.S. - Keep It Simple and Stupid) 29
Signatur public static RÜCKGABETYP NAME(PARAMETERLISTE) { BEFEHLE return EXPRESSION; Methoden besitzen eine Signatur Diese besteht aus (RÜCKGABETYP), NAME, PARAMETERLISTE Welche Methode aufgerufen wird entscheidet die verwendete Signatur 30
Überladung Signaturen ausgenutzt um Methoden zu überladen Ein Name aber verschiedene Implementierungen public static void func(int value) { System.out.println("int"); public static void func(integer value) { System.out.println("Integer"); public static void func(boolean value) { System.out.println("boolean"); public static void main(string[] args) { func(1); func(new Integer(1)); func(true); Output: int Integer boolean 31
Dokumentation und Hilfe Wie hilft man sich selbst weiter bei Problemen? Zwei Anlaufadressen für solche Fälle: Java ist auch eine Insel, Einsteiger-Buch (kostenlos online) Offizielle Dokumentation (nicht unbedingt anfängertauglich) Weiterhin natürlich noch die Web-Suchmaschinen Viel Müll dabei, das Brauchbare zeigt sich erst nach ein paar Versuchen Übt bitte, sinnvoll zu suchen Wichtig für das spätere Studium! 32
7 Minuten Pause 33
Arrays Wir haben sie bereits genutzt public static void main(string[] args) {... args ist ein Array (engl. für Feld oder Datenfeld ) Im Prinzip ein Schubladensystem Jede Schublade hat eine Nummer (Index) Und natürlich deren Inhalt 34
Schubladen zum Beispiel: int[] A = {2, 2, 5, 9, 1092; 35
Schubladen zum Beispiel: int[] A = {2, 2, 5, 9, 1092; Mit A[2] erhält man den Wert an Stelle [2] z.b. int a = 3 + A[2]; // Ergibt 8 36
Syntax Deklaration durch int[] myarray = new int[10]; wird 10 Schubladen haben Direkte Initialisierung int[] A = {1, 2, 3, 3, 5, 7, 5; Arrays anderer Datentypen double[] B = {0.23, 5, 8.009; String[] args; 37
Zugriff auf Elemente Array mittels new int[10] erstellt Die Array-Elemente sind durchnummeriert Das 1. Element hat die Nummer 0 und das letzte die Nummer 9 array[i] gibt also das i+1te Element zurück! Mathematik in der Informatik funktioniert halt ein Bisschen anders. Wir fangen bei 0 zu zählen an und nicht wie der Rest der Welt bei 1 38
Bisher Listen Wir kennen bisher nur Arrays der Art: int[] i = new int[4]; int[] i = {1, 2, 3, 4; Damit können wir eindimensionale Listen darstellen 1 2 3 4 39
Nun Tabellen Wir können aber auch eine Dimension höher gehen int[][] i = new int[4][2]; int[][] i = {{1,2, {3,4, {5,6, {7,8; Damit kann man Tabellen speichern und verarbeiten 1 3 5 7 2 4 6 8 Der Zugriff auf die 6 erfolgt dann über i[2][1] 40
Länge eines Arrays public void int methode(int[] array) { int laenge = array.length; Woher weiß die Funktion wie viele Elemente das Array besitzt? Es existieren auch andere Funktionen, dafür einfach mal in die Dokumentation schauen! 41
Zugriffsfehler public class intarray { public static void main(string[] args) { int[] a = {0, 1, 2, 3, 4; for (int i = 0; i <= 5; i++) { System.out.println(a[i]); 42
Exceptions Exception in thread "main java.lang.arrayindexoutofboundsexception: 5 at intarray.main(intarray.java:5) Exceptions sind Fehler, die zur Laufzeit des Programms auftreten, d.h. nicht vom Compiler entdeckt werden Dies geschieht durch einen Zugriff auf ein nicht vorhandenes Element im Array (out of bounds - außerhalb der Grenzen) Einer der Fehler die am meisten vertreten sind 43
Sortieren public static String tostring(int[] array) { String s = ""; // Leeren String vorbereiten for (int i = 0; i < array.length; i++) s += array[i] + " "; // Der Reihe nach anhaengen return s; Wir wollen die Zahlen 5,3,2,8,1 aufsteigend sortieren Zuerst brauchen wir eine Möglichkeit den Inhalt eines int[]-arrays auf der Kommandozeile anzuzeigen 44
main public static void main(string[] args) { int[] array = { 5, 2, 3, 1, 8 ; System.out.println(toString(array)); array = sort(array); System.out.println(toString(array)); 45
sort - Idee Nun fehlt noch die Methode sort(int[] array) Diese Methode soll das Array sortieren Als erstes brauchen wir eine Anleitung zum Sortieren einer linearen Liste von Zahlen (eigentlich Stoff aus GdI II) Eine Anleitung um ein bestimmtes Problem zu lösen heißt in der Informatik Algorithmus Es gibt verschiedene Algorithmen zum Lösen des Sortierproblems Wir nehmen an dieser Stelle selection sort 46
sort - Algorithmus Durchgang 5 3 2 8 1 1 1 3 2 8 5 2 1 2 3 8 5 3 1 2 3 8 5 4 1 2 3 5 8 5 1 2 3 5 8 Fast wie bei Rekursion - Schrittweise vereinfachen Man sucht bei jedem Durchgang die kleinste Zahl der Restliste Die kleinste Zahl wird dann mit der ersten Zahl der Restliste ausgetauscht Danach wird mit der Restliste weitergemacht 47
sort - Implementierung public static int[] sort(int[] array) { for (int i = 0; i < array.length; i++) { // Gehe ueber alle Elem. int minelt = Integer.MAX_VALUE; // Kleinstes Elem. int minpos = -1; // Position davon for (int j = i; j < array.length; j++) { // Ab dem Rest der Liste if (minelt >= array[j]) { // Falls neues Elem. minelt = array[j]; //-kleiner als kleinstes minpos = j; //-Elem. ist, neu merken int temp = array[i]; // Kleinstes mit Elem. array[i] = minelt; //-mit dem Anfang tauschen array[minpos] = temp; return array; 48
Vorgehen Das Vorgehen, wie eben sollte man immer verwenden Zuerst steht die Idee WAS man tun möchte Darauf aufbauend der Algorithmus WIE man es umsetzt Erst dann die Implementierung WIE man es Java beibringt Andere Reihenfolgen enden meistens im Chaos... 49
Mensa! 50