Proinformatik: Objektorientierte Programmierung Freie Universität Berlin Grundlegende Prinzipien der Programmentwicklung Sommersemester 2011 Prof. Dr. Marco Block-Berlitz (Mediadesign Hochschule in Berlin) 52 Proinformatik: Objektorientierte Programmierung Freie Universität Berlin Übersicht zum Vorlesungsinhalt zeitliche Abfolge und Inhalte können variieren Grundlegende Prinzipien der Programmentwicklung • • • • • • • • • • Programm als Kochrezept Methoden der Programmerstellung Pseudocode Erstellen eines Javaprogramms Einfaches Klassenkonzept Sequentielle Anweisungen Verzweigungen Schleifentypen Sprunganweisungen Wiederholende Programmabschnitte Sommersemester 2011 Prof. Dr. Marco Block-Berlitz (Mediadesign Hochschule in Berlin) 53 Proinformatik: Objektorientierte Programmierung Freie Universität Berlin Sommersemester 2011 Prof. Dr. Marco Block-Berlitz (Mediadesign Hochschule in Berlin) 54 Proinformatik: Objektorientierte Programmierung Freie Universität Berlin Sommersemester 2011 Prof. Dr. Marco Block-Berlitz (Mediadesign Hochschule in Berlin) 55 Proinformatik: Objektorientierte Programmierung Freie Universität Berlin Rezept für sechs Portionen von Omas Eierpfannkuchen Die Reihenfolge der Anweisungen ist wichtig! Sommersemester 2011 Prof. Dr. Marco Block-Berlitz (Mediadesign Hochschule in Berlin) 56 Proinformatik: Objektorientierte Programmierung Freie Universität Berlin Pseudocode vom Rezept Mit Pseudocode bezeichnen wir die lesbare Notation eines Programms in keiner spezifischen Programmiersprache, sondern in einer allgemeineren Form: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 vier Eier in eine Schüssel schlagen und verrühren Mehl in die Schüssel hinzugeben -> wenn Teig noch nicht schwer zu rühren ist gehe zu 2 Milch in die Schüssel geben -> wenn Teig nicht leicht zu rühren ist gehe zu 4 etwas Fett in einer Pfanne erhitzen einen Teil in die Pfanne geben, bis Boden gut bedeckt -> wenn süße Variante gewünscht gehe zu 9 ansonsten zu 10 Apfelscheiben hinzugeben, gehe zu 11 Wurst und Käse hinzugeben die Eierpfannkuchen von beiden Seiten gut braun braten -> wenn süße Variante gewünscht gehe zu 13 ansonsten zu 14 mit Marmelade, Apfelmus oder Zucker garnieren FERTIG Alltägliche Prozesse können als Programme verstanden werden. Es gibt immer wiederkehrende Vorgehensweisen. Bei genauerer Betrachtung gibt es sogar nur drei. Alle anderen Methoden sind leicht als Spezialfall dieser drei zu interpretieren. Sommersemester 2011 Prof. Dr. Marco Block-Berlitz (Mediadesign Hochschule in Berlin) 57 Proinformatik: Objektorientierte Programmierung Freie Universität Berlin Aktivitätsdiagramm Ein weißes Kästchen steht für eine Anweisung, die das Programm auszuführen hat: eine Anweisung Start zwei Anweisung verketten A B + A B Ende Eine Anweisung mit der gestartet wird, markieren wir zusätzlich mit einem ausgefüllten Kreis. Eine finale Anweisung wird ebenfalls gesondert markiert. Diese Abbildungsform wird auch als Aktivitätsdiagramm bezeichnet und gehört zum Sprachumfang der grafischen Modellierungssprache UML (Unified Modeling Language) die aktuell in der Softwareentwicklung standardmäßig eingesetzt wird. Sommersemester 2011 Prof. Dr. Marco Block-Berlitz (Mediadesign Hochschule in Berlin) 58 Proinformatik: Objektorientierte Programmierung Freie Universität Berlin Sequentieller Programmablauf Prinzipiell kann ein Programm Anweisung für Anweisung hintereinander weg geschrieben werden. Kein Abschnitt wird dabei wiederholt. Das könnte beispielsweise eine maschinelle Qualitätsprüfung sein (Prüfen: Größe, Form, Farbe, ...) Sommersemester 2011 Prof. Dr. Marco Block-Berlitz (Mediadesign Hochschule in Berlin) 59 Proinformatik: Objektorientierte Programmierung Freie Universität Berlin Verzweigungen Oft kommt es vor, dass eine Entscheidung getroffen werden muss, die die Wahl der nachfolgenden Anweisungen beeinflusst: Verzweigung In unserem Rezeptbeispiel ist es beispielsweise die Wahl der Variante. Es gibt auch die Möglichkeit, eine Verzweigung in beliebig vielen Wegen fortzufahren. Wir sprechen dann von einer Mehrfachverzweigung: Sommersemester 2011 Prof. Dr. Marco Block-Berlitz (Mediadesign Hochschule in Berlin) 60 Proinformatik: Objektorientierte Programmierung Freie Universität Berlin Sprünge Sprünge sind ein Spezialfall einer Verzweigung: Anstatt einen unabhängigen Weg zu beschreiten, springen wir zu einen späteren Programmabschnitt und machen dort weiter. Damit können wir Programmpassagen bei Bedarf überspringen. Sommersemester 2011 Prof. Dr. Marco Block-Berlitz (Mediadesign Hochschule in Berlin) 61 Proinformatik: Objektorientierte Programmierung Freie Universität Berlin Schleifen Schleifen sind ebenfalls ein Spezialfall einer Verzweigung: Wir können einen bestimmten Prozessabschnitt solange wiederholen lassen (z.B. Mehl in eine Schüssel geben) bis ein gewünschtes Ergebnis erreicht ist. Schleifen kommen oft verschachtelt vor (Mehrfachschleifen): Sommersemester 2011 Prof. Dr. Marco Block-Berlitz (Mediadesign Hochschule in Berlin) 62 Proinformatik: Objektorientierte Programmierung Freie Universität Berlin Parallelität Das dritte wichtige Konzept, neben sequentieller Abfolge und dem Sprung ist die Parallelität: beide Pfade werden parallel ausgeführt wenn beide fertig sind, geht es weiter Zwei Striche auf den Verzweigungspfeilen sollen bedeuten, dass die beiden Wege gleichzeitig bearbeitet werden sollen und sich später wieder treffen können. Sommersemester 2011 Prof. Dr. Marco Block-Berlitz (Mediadesign Hochschule in Berlin) 63 Proinformatik: Objektorientierte Programmierung Freie Universität Berlin Kombination zu Programmen In der Kombination ergeben die vorgestellten Methoden: Programme! Schauen wir uns dazu nochmal das Kochrezeptbeispiel an: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 vier Eier in eine Schüssel schlagen und verrühren Mehl in die Schüssel hinzugeben -> wenn Teig noch nicht schwer zu rühren ist gehe zu 2 Milch in die Schüssel geben -> wenn Teig nicht leicht zu rühren ist gehe zu 4 etwas Fett in einer Pfanne erhitzen einen Teil in die Pfanne geben, bis Boden gut bedeckt -> wenn süße Variante gewünscht gehe zu 9 ansonsten zu 10 Apfelscheiben hinzugeben, gehe zu 11 Wurst und Käse hinzugeben die Eierpfannkuchen von beiden Seiten gut braun braten -> wenn süße Variante gewünscht gehe zu 13 ansonsten zu 14 mit Marmelade, Apfelmus oder Zucker garnieren FERTIG Dargestellt als Aktivitätsdiagramm: Wir erlauben mehrere nacheinanderfolgende Anweisungen in einem Kästchen zu notieren, wenn es der kompakten Übersicht dienlich ist. Sommersemester 2011 Prof. Dr. Marco Block-Berlitz (Mediadesign Hochschule in Berlin) 64 Proinformatik: Objektorientierte Programmierung Freie Universität Berlin Erstellen eines Javaprogramms in Pseudocode Wir können mal an dieser Stelle die Erstellung eines Javaprogramms mit Hilfe von Pseudocode ausdrücken: 1 2 3 4 5 6 7 8 9 10 11 12 13 öffne einen Texteditor lege ein Dokument mit gewünschtem Programmnamen an schreibe ein Javaprogramm speichere es mit der Endung ".java" in Ordner <X> gehe außerhalb des Editors in einer Konsole zu Ort <X> schreibe "javac <Programmname>.java" -> wenn der Javacompiler Fehler ausgibt gehe zu 8 sonst 11 gehe zurück zum Editor korrigiere angezeigte Fehler gehe zu 4 schreibe "java <Programmname>" -> wenn das Programm noch nicht das Gewünschte tut gehe zu 8 FERTIG Auch das können wir wieder als Aktivitätsdiagramm darstellen: Sommersemester 2011 Prof. Dr. Marco Block-Berlitz (Mediadesign Hochschule in Berlin) 65 Proinformatik: Objektorientierte Programmierung Freie Universität Berlin Erstellen eines Javaprogramms Wir können Javaprogramme mit folgender Syntax in der Konsole kompilieren: javac <Programmname>.java und anschließend so ausführen: java <Programmname> Versuchen wir an dieser Stelle einmal die folgenden Programmzeilen entsprechend den Anweisungen des Pseudocodes einzugeben und das Programm zu starten. public class TestProgramm { public static void main(String[] args) { System.out.println("Das habe ich ganz allein geschafft!"); } } Wenn wir alles richtig gemacht haben, wird eine Textzeile in der Konsole ausgegeben: C:\Java>javac TestProgramm.java C:\Java>java TestProgramm Das habe ich ganz allein geschafft! Sommersemester 2011 Prof. Dr. Marco Block-Berlitz (Mediadesign Hochschule in Berlin) 66 Proinformatik: Objektorientierte Programmierung Freie Universität Berlin Editor und Konsole Kompilieren und Ausführen von Programmen: Java-Programme in der Konsole ausführen Java-Programme in einem Editor erstellen Sommersemester 2011 Prof. Dr. Marco Block-Berlitz (Mediadesign Hochschule in Berlin) 67 Proinformatik: Objektorientierte Programmierung Freie Universität Berlin Programmieren mit einem einfachen Klassenkonzept Das folgende Programm tut erstmal herzlich wenig, soll aber zeigen, welche Zeilen wir für alle folgenden Beispiele benötigen: public class MeinErstesProgramm { public static void main(String[] args) { // HIER KOMMEN DIE ANWEISUNGEN DES PROGRAMMS HIN } } Das Einrücken der Zeilen innerhalb eines Blocks (so wird der Abschnitt zwischen { und } genannt) dient der Lesbarkeit. Sommersemester 2011 Prof. Dr. Marco Block-Berlitz (Mediadesign Hochschule in Berlin) 68 Proinformatik: Objektorientierte Programmierung Freie Universität Berlin Programme kommentieren Es gibt zwei Möglichkeiten in Java Kommentare zu schreiben: // Ich bin ein hilfreicher Kommentar in einer Zeile /* Falls ich einen Kommentar über mehrere Zeilen hinweg schreiben möchte, so verwende ich ein öffnendes und schließendes Kommentarsymbol */ public class Kommentierung { // ich kann auch hier stehen public static void main(String[] args) { /* An diese Stelle schreiben wir die Programmanweisungen */ } } Wir müssen immer darauf achten, unsere Programme nicht nur ausreichend, sondern verständlich zu kommentieren. Es ist nicht immer einfach, ein langes Programm ohne hilfreiche Kommentare zu verstehen. Dies trifft sogar auf selbst geschriebene Programme zu, erst recht auf die von anderen. Daher sind gerade in Projekten, bei denen mehrere Programmierer zusammenarbeiten, Kommentare unverzichtbar. Sommersemester 2011 Prof. Dr. Marco Block-Berlitz (Mediadesign Hochschule in Berlin) 69 Proinformatik: Objektorientierte Programmierung Freie Universität Berlin Einrücken von Anweisungsblöcken Kommentare und Syntaxhighlighting reichen nicht! public static int zaehleUmgebung(boolean[][] m, int x, int y){ int ret = 0; for (int i=(x-1);i<(x+2);++i){ for (int j=(y-1);j<(y+2);++j){ try {if (m[i][j]) ret += 1;}catch (IndexOutOfBoundsException e){} } }// einen zuviel mitgezaehlt? if (m[x][y])ret -= 1; return ret; } public static int zaehleUmgebung(boolean[][] m, int x, int y) { int ret = 0; for (int i=(x-1); i<(x+2); ++i) { for (int j=(y-1); j<(y+2); ++j) { try { if (m[i][j]) ret += 1; } catch (IndexOutOfBoundsException e) {} } } // einen zuviel mitgezaehlt? if (m[x][y]) ret -= 1; return ret; } Sommersemester 2011 Prof. Dr. Marco Block-Berlitz (Mediadesign Hochschule in Berlin) 70 Proinformatik: Objektorientierte Programmierung Freie Universität Berlin Sequentielle Anweisungen Wir haben bereits gesehen, dass Anweisungen mit ; abgeschlossen werden: public class Sequentiell { public static void main(String[] args) { int a=5; // Anweisung 1 a=a*2; // Anweisung 2 a=a+10; // Anweisung 3 a=a-5; // Anweisung 4 } } Welchen Wert hat a? Wir können das überprüfen: Geben wir dazu am Ende noch folgende Zeile dazu: System.out.println("a hat den Wert: "+a); Sommersemester 2011 Prof. Dr. Marco Block-Berlitz (Mediadesign Hochschule in Berlin) 71 Proinformatik: Objektorientierte Programmierung Freie Universität Berlin Sommersemester 2011 Prof. Dr. Marco Block-Berlitz (Mediadesign Hochschule in Berlin) 72 Proinformatik: Objektorientierte Programmierung Freie Universität Berlin Verzweigungen mit if I Die Syntax für eine Verzweigung kann auf verschiedene Weisen formuliert werden. Wenn eine Bedingung erfüllt ist, führe eine einzelne Anweisung aus. Die Syntax dafür sieht wie folgt aus: if (<Bedingung>) <Anweisung>; Ein Beispiel: if (a<b) a=b; Welchen Wert hat a? Es können auch mehrere Anweisungen (ein Anweisungsblock) ausgeführt werden: if (<Bedingung>) { <Anweisung1>; <Anweisung2>; ... } Sommersemester 2011 Prof. Dr. Marco Block-Berlitz (Mediadesign Hochschule in Berlin) 73 Proinformatik: Objektorientierte Programmierung Freie Universität Berlin Verzweigungen mit if II Eine Erweiterung dazu ist die if-else-Verzweigung: if (<Bedingung>) <Anweisung1>; else <Anweisung2>; Ein Beispiel: if (a<b) c=b; else c=a; Wir können auch Bedingungen verknüpfen: if (<Bedingung1>) <Anweisung1>; else if (<Bedingung2>) <Anweisung2>; Sommersemester 2011 Prof. Dr. Marco Block-Berlitz (Mediadesign Hochschule in Berlin) 74 Proinformatik: Objektorientierte Programmierung Freie Universität Berlin Guter Programmierstil Da bei einer Bedingung immer ein Ausdruck steht, der entweder true oder false ist, können wir den folgenden Abschnitt: if (a == true) // tue etwas ersetzen durch: if (a) // ist a true, tue etwas Der Grund ist einleuchtend, da bei jedem Wert von a die Gleichung a==(a==true) erfüllt ist. Wird a auf false getestet, machen wir das entsprechend so: if (!a) // ist a false, tue etwas Sommersemester 2011 Prof. Dr. Marco Block-Berlitz (Mediadesign Hochschule in Berlin) 75 Proinformatik: Objektorientierte Programmierung Freie Universität Berlin Verzweigung mit switch I Um nun Mehrfachverzweigungen zu realisieren und nicht zu einer unübersichtlichen Flut von if-Verzweigungen greifen zu müssen, steht uns switch zur Verfügung: switch (<Ausdruck>) { case <Konstante1>: <Anweisung1>; [break;] case <Konstante2>: <Anweisung2>; [break;] [default:] <Anweisung3>; } Leider gibt es für die Verwendung ein paar Einschränkungen, so können wir nur Bedingungen überprüfen in der Form: Hat int a den Inhalt 4? Als Ausdruck lassen sich verschiedene primitive Datentypen auf Ihren Inhalt untersuchen. Zu den erlaubten gehören: char, byte, short, int und (seit Java 7 auch) String. Sommersemester 2011 Prof. Dr. Marco Block-Berlitz (Mediadesign Hochschule in Berlin) 76 Proinformatik: Objektorientierte Programmierung Freie Universität Berlin Verzweigung mit switch II Hier ein kleines Beispiel zu switch: int i = 0; // hier mal unterschiedliche i probieren switch(i){ case 0: System.out.println("0"); break; case 1: System.out.println("1"); case 2: System.out.println("1 oder 2"); break; case 3: System.out.println("3"); break; default: System.out.println("hier landen alle anderen..."); } Wenn wir die switch-Verzweigung beispielsweise mit den Zahlen i=0,1,2,3,4 fünf Mal nacheinander durchlaufen würden, erhielten wir die folgende Ausgabe: C:\Java>java Verzweigung 0 1 1 oder 2 1 oder 2 3 hier landen alle anderen... Sommersemester 2011 Prof. Dr. Marco Block-Berlitz (Mediadesign Hochschule in Berlin) 77 Proinformatik: Objektorientierte Programmierung Freie Universität Berlin Motivation zu Schleifen Folgendes Programm ist gegeben, das eine Zahl quadriert und das Ergebnis ausgibt: System.out.println("1 System.out.println("2 System.out.println("3 System.out.println("4 System.out.println("5 System.out.println("6 zum zum zum zum zum zum Quadrat Quadrat Quadrat Quadrat Quadrat Quadrat ist ist ist ist ist ist "+(1*1)); "+(2*2)); "+(3*3)); "+(4*4)); "+(5*5)); "+(6*6)); Es wäre sicherlich auch eine unangenehme Aufgabe, alle ganzen Zahlen zwischen 1 und 1000 auf diese Weise quadrieren und ausgeben zu lassen. Daher ist das Schleifen-Konzept ziemlich nützlich. Angenommen, wir möchten die Aufgabe lösen, alle Quadrate der Zahlen zwischen 1 und 1000 auszugeben. Dann könnten wir das in Pseudocode in etwa so ausdrücken: Beginne mit i=1 Gib den Wert i*i aus Falls i<=1000 -> Erhöhe i um 1 und springe zu Zeile 2 Oder in Worten ausgedrückt: Starte mit i=1 und solange i<=1000 erfüllt ist, mache folgendes: gib das Quadrat von i aus und erhöhe anschließend i um 1. Sommersemester 2011 Prof. Dr. Marco Block-Berlitz (Mediadesign Hochschule in Berlin) 78 Proinformatik: Objektorientierte Programmierung Freie Universität Berlin Schleife mit for Wir benötigen zunächst eine Variable, die zu Beginn mit einem Startwert initialisiert wird. Die Schleife führt den nachfolgenden Anweisungsblock solange aus, erhöht oder verringert dabei die Variable um einen Wert, bis die angegebene Bedingung nicht mehr erfüllt ist: for (<Initialisierung>; <Bedingung>; <Aktualisierung>) { <Anweisung>; } Im Programm könnten wir die zu Beginn geschilderte Aufgabe, alle Quadratzahlen für die Werte 1 bis 1000 auszugeben, mit einer for-Schleife so lösen: for (int i=1; i<=1000; i=i+1) System.out.println(i+" zum Quadrat ist "+(i*i)); Mit int i=1 geben wir einen Startwert vor. Die Schleife führt die Anweisungen innerhalb der geschweiften Klammern solange aus und erhöht jedes Mal i um 1 bis die Bedingung i<=1000 nicht mehr erfüllt ist. Sommersemester 2011 Prof. Dr. Marco Block-Berlitz (Mediadesign Hochschule in Berlin) 79 Proinformatik: Objektorientierte Programmierung Freie Universität Berlin Beispiele zur for-Schleife I Wir können aber auch andere Konstruktionen mit einer for-Schleife realisieren. Beispielsweise könnten wir bei 0 anfangen, in Fünferschritten weiterlaufen und alle Werte bis einschließlich 25 erzeugen: Umsetzung in Java: for (int i=0; i<=25; i=i+5) System.out.println("Aktueller Wert für i ist "+i); Sommersemester 2011 Prof. Dr. Marco Block-Berlitz (Mediadesign Hochschule in Berlin) 80 Proinformatik: Objektorientierte Programmierung Freie Universität Berlin Beispiele zur for-Schleife II Eine Schleife muss Variablen nicht immer vergrößern, wir können auch bei 4 beginnend immer 3 abziehen, bis wir bei -11 angelangt sind: Umsetzung in Java: for (int i=4; i>=-11; i=i-3) System.out.println("Aktueller Wert für i ist "+i); Sommersemester 2011 Prof. Dr. Marco Block-Berlitz (Mediadesign Hochschule in Berlin) 81 Proinformatik: Objektorientierte Programmierung Freie Universität Berlin Beispiele zur for-Schleife III Im folgenden Beispiel wollen wir mit einer Schleife die Summe der Zahlen berechnen: int summe=0; for (int i=1; i<=n; i++) summe += i; Da bei der Definition einer for-Schleife, die drei Teile <Initialisierung>, <Bedingung> und <Aktualisierung> nicht nur optional sind, sondern sogar mehrfach eingesetzt werden dürfen, können wir die Summe sogar ganz ohne Anweisungsteil berechnen: int summe=0; for (int i=1; i<=n; summe+=i, i++); Soviel an dieser Stelle: Neben der for-Schleife gibt es noch mehr Schleifenvarianten. Jede hat auf Grund der Programmästhetik ihre Existenzberechtigung, obwohl leicht zu zeigen ist, dass wir mit einer Variante immer auskommen könnten. Sommersemester 2011 Prof. Dr. Marco Block-Berlitz (Mediadesign Hochschule in Berlin) 82 Proinformatik: Objektorientierte Programmierung Freie Universität Berlin Schleife mit while Manchmal ist es nicht klar, wie viele Schleifendurchläufe benötigt werden, um ein Ergebnis zu erhalten. Da wäre es schön, eine Möglichkeit zu haben, wie diese: Wiederhole die Anweisungen solange, eine Bedingung erfüllt ist. Genau diesen Schleifentyp repräsentiert die while-Schleife. Hier die zugehörige Syntax: while (<Bedingung>) { <Anweisung>; } Wir werden das Beispiel aus der for-Schleife wieder aufnehmen und sehen, wie das mit while gelöst werden kann: int i=1; while (i<=1000){ System.out.println(i+" zum Quadrat ist "+(i*i)); i=i+1; } Sommersemester 2011 Prof. Dr. Marco Block-Berlitz (Mediadesign Hochschule in Berlin) 83 Proinformatik: Objektorientierte Programmierung Freie Universität Berlin Schleife mit while - Gefahr Endlosschleife Die Schleife wird einfach solange ausgeführt, bis die Bedingung hinter while nicht mehr erfüllt ist. Hier ist natürlich auch die Gefahr gegeben, dass die Schleife endlos laufen kann, wie in diesem Beispiel zu sehen ist: int i=1; while (i<=1000){ System.out.println(i+" zum Quadrat ist "+(i*i)); } Warum ergibt das eine Endlosschleife? Sommersemester 2011 Prof. Dr. Marco Block-Berlitz (Mediadesign Hochschule in Berlin) 84 Proinformatik: Objektorientierte Programmierung Freie Universität Berlin Schleife mit do-while I Die do-while-Schleife führt im Gegensatz zur while-Schleife zuerst den Anweisungsblock einmal aus und prüft anschließend die Bedingung: do { <Anweisung>; } while (<Bedingung>); Damit haben wir im Gegensatz zur while-Schleife, die kopfgesteuert ist, eine fußgesteuerte Schleife. Schauen wir uns dazu mal folgendes Beispiel an: int i=0; do { i++; System.out.println("Wert von i: "+i); } while (i<5); Wir erhalten folgende Ausgabe: C:\Java>java Schleifen Wert von i: 1 Wert von i: 2 Wert von i: 3 Wert von i: 4 Wert von i: 5 Sommersemester 2011 Prof. Dr. Marco Block-Berlitz (Mediadesign Hochschule in Berlin) 85 Proinformatik: Objektorientierte Programmierung Freie Universität Berlin Schleife mit do-while II Wenn wir die Bedingung so ändern, dass sie von vornherein nicht erfüllt ist: int i=0; do { i++; System.out.println("Wert von i: "+i); } while (i<0); geschieht trotzdem das Folgende: C:\Java>java Schleifen Wert von i: 1 Das war auch zu erwarten, da die Überprüfung der Bedingung erst nach der ersten Ausführung stattfindet und deshalb der Schleifeninhalt mindestens einmal ausgeführt wird. Sommersemester 2011 Prof. Dr. Marco Block-Berlitz (Mediadesign Hochschule in Berlin) 86 Proinformatik: Objektorientierte Programmierung Freie Universität Berlin Sprunganweisungen Es gibt Situationen in denen es notwendig ist, eine Schleife vorzeitig zu beenden. Dazu werden wir uns den Datentyp char noch einmal etwas genauer anschauen. Java verwendet für den char den sogenannten Unicode-Zeichensatz1) der zwei Bytes benötigt und damit umfangreicher ist, als der bekannte ASCII-Zeichensatz (American Standard Code for Information Interchange). Er soll einen universellen Zeichensatz für die Darstellung unterschiedlicher Sprachen sein. Die ersten 128 Zeichen entsprechen dabei dem ASCII-Zeichsatz. Nehmen wir als Ausgangsbeispiel den folgenden Programmabschnitt: for (int i = 33; i < 127; i++) { char symbol = (char)i; System.out.print(i+": "+symbol+"\t"); if ((i%8) == 0) System.out.println(); } Es werden die ersten sichtbaren Zeichen der ASCII-Tabelle ausgegeben. Mit \t wird ein Tabulatorschritt bei der Ausgabe eingefügt und alle acht Symbole ein Zeilenumbruch vorgenommen, um die Tabelle übersichtlich zu halten. 1) http://www.unicode.org/ Sommersemester 2011 Prof. Dr. Marco Block-Berlitz (Mediadesign Hochschule in Berlin) 87 Proinformatik: Objektorientierte Programmierung Freie Universität Berlin ASCII-Tabelle Wir erhalten folgende Ausgabe: 33: ! 41: ) 49: 1 57: 9 65: A 73: I 81: Q 89: Y 97: a 105: i 113: q 121: y 34: " 42: * 50: 2 58: : 66: B 74: J 82: R 90: Z 98: b 106: j 114: r 122: z Sommersemester 2011 35: # 43: + 51: 3 59: ; 67: C 75: K 83: S 91: [ 99: c 107: k 115: s 123: { 36: $ 44: , 52: 4 60: < 68: D 76: L 84: T 92: \ 100: d 108: l 116: t 124: | 37: % 45: 53: 5 61: = 69: E 77: M 85: U 93: ] 101: e 109: m 117: u 125: } 38: & 46: . 54: 6 62: > 70: F 78: N 86: V 94: ^ 102: f 110: n 118: v 126: ~ 39: ' 47: / 55: 7 63: ? 71: G 79: O 87: W 95: _ 103: g 111: o 119: w 40: ( 48: 0 56: 8 64: @ 72: H 80: P 88: X 96: ` 104: h 112: p 120: x Prof. Dr. Marco Block-Berlitz (Mediadesign Hochschule in Berlin) 88 Proinformatik: Objektorientierte Programmierung Freie Universität Berlin Sprunganweisungen Angenommen, wir suchen ein bestimmtes Symbol in der Tabelle und wollen die Position ausgeben. Anschließend soll die Schleife beendet werden. Das Beenden kann beispielsweise dadurch erzwungen werden, indem die Zählvariable einer for-Schleife innerhalb der Schleife auf einen Wert gesetzt wird, der die Bedingung zum Weiterlaufen nicht mehr erfüllt. Schauen wir uns das Beispiel dazu an: for (int i = 33; i < 127; i++) { char symbol = (char)i; if (symbol == 'A'){ System.out.println("Symbol "+symbol+" an Position "+i+" gefunden."); i=127; // schlechter Programmierstil } else System.out.println("bisher nichts passendes gefunden ..."); } Das ist allerdings sehr unschön und bei komplizierteren Ausdrücken für Leser schlecht nachzuvollziehen, wann die Schleife verlassen wird. Aus diesem Grund gibt es Sprunganweisungen! Sommersemester 2011 Prof. Dr. Marco Block-Berlitz (Mediadesign Hochschule in Berlin) 89 Proinformatik: Objektorientierte Programmierung Freie Universität Berlin Sprung mit break Der Sprungbefehl break schließt nicht nur die case-Fälle bei switch, sondern beendet auch unmittelbar while-, do-while- und for-Schleifen: for (int i = 33; i < 127; i++) { char symbol = (char)i; if (symbol == 'A'){ System.out.println("Symbol "+symbol+" an Position "+i+" gefunden."); break; } System.out.println("bisher nichts passendes gefunden ..."); } Die for-Schleife wird abgebrochen, wenn das Symbol 'A' identifziert worden ist. Anschließend wird mit den Anweisungen, die nach der Schleife kommen fortgefahren. Sommersemester 2011 Prof. Dr. Marco Block-Berlitz (Mediadesign Hochschule in Berlin) 90 Proinformatik: Objektorientierte Programmierung Freie Universität Berlin Ergänzung zur for-Schleife I An dieser Stelle wollen wir nochmal kurz auf die Konstruktion einer for-Schleife eingehe. Wir hatten ja angedeutet, dass es auch möglich ist, eine Schleife mit leerem Definitions- und Manipulationsbereich zu definieren: for (;;) { // Endlosschleife } Es gibt keine Bedingung, die unsere Schleife zum Abbruch führen kann. Diese Schleife könnte beispielsweise in den Stellen Anwendung finden, in denen solange etwas auszuführen ist, bis ein bestimmtes Ereignis auftritt. Dann kann die Schleife mit break beendet werden: for (;;) { // tue etwas bedingung = prüfen(); if (bedingung) break; } Wenn die Funktion prüfen ein true liefert, wird die Schleife durch break beendet. Sommersemester 2011 Prof. Dr. Marco Block-Berlitz (Mediadesign Hochschule in Berlin) 91 Proinformatik: Objektorientierte Programmierung Freie Universität Berlin Ergänzung zur for-Schleife II Besser ist es, in diesem Fall eine while-Schleife zu verwenden und die Schleife abzubrechen, wenn die Bedingung zum Abbrechen erfüllt ist: bedingung = false; while (!bedingung) { // tue etwas bedingung = prüfen(); } Dazu müssen wir die Bedingung zu Beginn auf false setzen und bei while negiert überprüfen. Sommersemester 2011 Prof. Dr. Marco Block-Berlitz (Mediadesign Hochschule in Berlin) 92 Proinformatik: Objektorientierte Programmierung Freie Universität Berlin Sprung mit continue Kommen wir zu unserem Ursprungsbeispiel mit der Suche in der ASCII-Tabelle aus dem vorhergehenden Abschnitt zurück. Jetzt wollen wir alle Großbuchstaben identifizieren und deren Positionen ausgeben: for (int i = 33; i < 127; i++) { char symbol = (char)i; if ((symbol>='A') && (symbol<='Z')) System.out.println("Symbol "+symbol+" an Position "+i+" gefunden."); else System.out.println("nichts passendes gefunden..."); } Für solche Fälle, in denen wir bei erfolgreicher Suche mit der Schleife weitermachen wollen, können wir das Schlüsselwort continue statt dem if-elseKonstrukt verwenden: for (int i = 33; i < 127; i++) { char symbol = (char)i; if ((symbol>='A') && (symbol<='Z')){ System.out.println("Symbol "+symbol+" an Position "+i+" gefunden."); continue; } System.out.println("nichts passendes gefunden..."); } Sommersemester 2011 Prof. Dr. Marco Block-Berlitz (Mediadesign Hochschule in Berlin) 93 Proinformatik: Objektorientierte Programmierung Freie Universität Berlin Sprungmarken I Bei verschachtelten Schleifen wird immer die aktuelle innere Schleife beendet. Um aber explizit anzugeben, zu welcher Schleife gesprungen werden soll, lassen sich Marken unterbringen (markierte Anweisungen). Diese Marken werden mit folgender Syntax angegeben: <Marke>: Wenn hinter break oder continue eine Marke steht, dann springt das Programm zu der Marke und beendet die Schleife: continue <Marke>; Sommersemester 2011 Prof. Dr. Marco Block-Berlitz (Mediadesign Hochschule in Berlin) 94 Proinformatik: Objektorientierte Programmierung Freie Universität Berlin Sprungmarken II Die Idee besteht darin, Schleifen gezielt beenden zu können oder entsprechend weiterlaufen zu lassen. Angenommen, wir haben zwei verschachtelte for-Schleifen, die uns die Paare von Groß- und Kleinbuchstaben finden sollen: Aussen: for (int i = 33; i < 127; i++) { for (int j = 33; j < 127; j++) { char symbol1 = (char)i; char symbol2 = (char)j; if (Character.isUpperCase(symbol1) && (symbol2 == Character.toLowerCase(symbol1))){ System.out.println("Symbol "+symbol1+" ["+ i+"] und Symbol "+symbol2+" ["+ j+"] sind ein Paar."); continue Aussen; } } } Wir erhalten: Symbol A [65] und Symbol a [97] sind ein Paar. Symbol B [66] und Symbol b [98] sind ein Paar. ... Symbol Z [90] und Symbol z [122] sind ein Paar. Sommersemester 2011 Prof. Dr. Marco Block-Berlitz (Mediadesign Hochschule in Berlin) 95 Proinformatik: Objektorientierte Programmierung Freie Universität Berlin Ausgelagerte Programmabschnitte in Java Programme bestehen aus Ketten von Anweisungen, das wissen wir bereits. Oft kommt es dabei vor, dass sich Folgen von Anweisungen wiederholen. Eine Sequenz von Anweisungen, bei der sich B und C wiederholt. Wir erstellen eine neue Anweisung mit dem Namen BC, die B und C nacheinander ausführt. Die neue Anweisung BC wird entsprechend eingesetzt: In diesen Fällen können wir das Programm übersichtlicher gestalten, indem wir diese Anweisungsblöcke zu einer neuen Anweisung, deren Bezeichnung wir fast frei wählen können, zusammenfassen. Der große Vorteil besteht darin, dass wir den Anweisungsblock nur noch einmal schreiben müssen. Das vermindert die Fehleranfälligkeit. Sommersemester 2011 Prof. Dr. Marco Block-Berlitz (Mediadesign Hochschule in Berlin) 96 Proinformatik: Objektorientierte Programmierung Freie Universität Berlin Motivation zu Funktionen public class Ausgabe{ public static void main(String[] args){ int a=4; System.out.println(); System.out.println("*******************************************"); System.out.println("*** Wert der Variable ist "+a); System.out.println("*******************************************"); System.out.println(); a=(a*13)%12; System.out.println(); System.out.println("*******************************************"); System.out.println("*** Wert der Variable ist "+a); System.out.println("*******************************************"); System.out.println(); a+=1000; System.out.println(); System.out.println("*******************************************"); System.out.println("*** Wert der Variable ist "+a); System.out.println("*******************************************"); System.out.println(); } } Sommersemester 2011 Prof. Dr. Marco Block-Berlitz (Mediadesign Hochschule in Berlin) 97 Proinformatik: Objektorientierte Programmierung Freie Universität Berlin Funktionen in Java Funktionen repräsentieren einen Programmabschnitt, der einmal formuliert beliebig oft aufgerufen und verwendet werden kann. Eine Funktion erhält dabei einen eindeutigen Namen (beginnend mit einem Kleinbuchstaben). Diese Variablen gelten zunächst nur innerhalb der Methode (daher werden sie auch lokale Variablen genannt) auch wenn in der main-Methode eine Variable mit dem gleichen Namen existiert, haben diese beiden nichts miteinander zu tun. Die Syntax unserer Funktionen sieht zunächst erstmal so aus: public static <Datentyp> <Funktionsname>( <Datentyp> Parameter1, <Datentyp> Parameter2, ...) { // Funktionskörper } Aus der Mathematik wissen wir, dass Funktionen auch ein Ergebnis liefern - genau ein Ergebnis. Auch für unsere Funktionen gilt das. Falls, wie in unserem Fall, kein Rückgabewert existiert, schreiben wir als Rückgabewert das Schlüsselwort void. Sommersemester 2011 Prof. Dr. Marco Block-Berlitz (Mediadesign Hochschule in Berlin) 98 Proinformatik: Objektorientierte Programmierung Freie Universität Berlin Ausgabe in Funktion auslagern Jetzt wollen wir versuchen, mit Hilfe einer Funktion, die Ausgabe ein wenig zu erleichtern. In unserem Ausgabebeispiel ist a ein Eingabeparameter für die neue Funktion. Die Funktion schreiben wir laut Konvention oberhalb der main-Funktion. Für die Lesbarkeit des Programms sind sprechende Namen, in unserem Beispiel gibAus, unerlässlich: public class AusgabeFunktion{ public static void gibAus(int a){ // neue Funktion System.out.println(); System.out.println("*******************************************"); System.out.println("*** Wert der Variable ist "+a); System.out.println("*******************************************"); System.out.println(); } // main-Funktion public static void main(String[] args){ int a=4; gibAus(a); a=(a*13)%12; gibAus(a); a+=1000; gibAus(a); } } Sommersemester 2011 Prof. Dr. Marco Block-Berlitz (Mediadesign Hochschule in Berlin) 99 Proinformatik: Objektorientierte Programmierung Freie Universität Berlin Funktionen mit Rückgabewert Schauen wir uns noch ein weiteres Beispiel an. Dazu berechnen wir in einer Funktion für die Eingabe x den Wert f(x)=x*13-1024\%(34+12): public class Funktion{ public static int funktion(int x){ int wert=(x*13)-1024%(34+12); return wert; } public static void main(String[] args){ for (int i=0; i<10; i++) System.out.println("x="+i+" und f(x)="+funktion(i)); } } In diesem Beispiel gibt die Funktion einen int-Wert mit der Anweisung return zurück und wird beendet. Sollten noch Zeilen nach einem return stehen, so gibt Java einen Fehler aus, denn diese Zeilen können nie ausgeführt werden. Als Ausgabe erhalten wir: C:\Java>java Funktion x=0 und f(x)=-12 x=1 und f(x)=1 x=2 und f(x)=14 x=3 und f(x)=27 ... x=9 und f(x)=105 Sommersemester 2011 Prof. Dr. Marco Block-Berlitz (Mediadesign Hochschule in Berlin) 100 Proinformatik: Objektorientierte Programmierung Freie Universität Berlin Wichtiges Konzept Die Auslagerung von Programmabschnitten in Funktionen ist eines der wichtigsten Programmierkonzepte. Aus Gründen der Übersichtlichkeit und besseren Fehlersuche werden wir dieses Konzept so oft es geht einsetzen ... Sommersemester 2011 Prof. Dr. Marco Block-Berlitz (Mediadesign Hochschule in Berlin) 101 Proinformatik: Objektorientierte Programmierung Freie Universität Berlin Sommersemester 2011 Prof. Dr. Marco Block-Berlitz (Mediadesign Hochschule in Berlin) 102