University of Paderborn Software Engineering Group E. Kindler University of Paderborn Software Engineering Group E. Kindler Technische Informatik für Ingenieure (TIfI) WS 2006/2007, Vorlesung 10 II. Grundlagen der Programmierung Ekkart Kindler 9.2. Objektvariablen als Verweise … Datenstrukturen Rekursive Datenstrukturen Zusammenfassung Beispiel University of Paderborn Software Engineering Group E. Kindler University of Paderborn Software Engineering Group E. Kindler Beispiel: Adresse adr; adr = new Adresse(); adr.name = “Egon“; Für einen selbstdefinierten Datentyp kann man Variablen dieses Typs deklarieren! Eine solche Variable ist ein Verweis (Pointer) auf ein Objekt dieses Typs! adr Adresse name String “Egon“ vorname ort E. Kindler: Technische Informatik für Ingenieure, WS 2006/07, Universität Paderborn Objektvariable als Verweise VL 10 3 E. Kindler: Technische Informatik für Ingenieure, WS 2006/07, Universität Paderborn null: Der undefinierte Verweis University of Paderborn Software Engineering Group E. Kindler Objektvariable verhalten sich analog zu Array-Variablen: Ein Parameter mit selbstdefiniertem Datentyp ist ein Referenzparameter! Alle Attribute eines mit new neu angelegten Objekts erhalten zunächst den vordefinierten Wert des entsprechenden Datentyps (Zur Erinnerung: Zahlen: 0 bzw. 0.0, Zeichen: \u0000, Wahrheitswerte: false, sonst null) VL 10 4 University of Paderborn Software Engineering Group E. Kindler Der vordefinierte Wert für alle nicht-primitiven Datentypen ist null null kann jeder Variablen mit nicht-primitivem Datentyp zugewiesen werden („null hat jeden Typ“; Genaueres später) Wenn adr == null gilt; führt der Zugriff adr.name zu einem Laufzeitfehler!! Achtung: Beim Programmieren aufpassen! Exception in thread "main" java.lang.NullPointerException at Test.main(Compiled Code) E. Kindler: Technische Informatik für Ingenieure, WS 2006/07, Universität Paderborn VL 10 5 E. Kindler: Technische Informatik für Ingenieure, WS 2006/07, Universität Paderborn VL 10 6 1 9.3. Rekursive Datentypen class Liste { Adresse adr; Liste next; } Adresse Adresse name name name vorname vorname vorname ort ort ort Liste Liste Liste next next next adr Prinzip: University of Paderborn Software Engineering Group E. Kindler adr Adresse University of Paderborn Software Engineering Group E. Kindler Ein Attribut eines Objekts kann denselben Datentyp haben wie das Objekt selbst! (Im Datentyp Liste ist das Attribut next wieder vom Typ Liste) Dies ist möglich, da ein Wert des Attributs ein Verweis auf ein Objekt ist (und nicht das Objekt selbst) Der Wert null entspricht dem „Terminierungs-fall“ adr null E. Kindler: Technische Informatik für Ingenieure, WS 2006/07, Universität Paderborn Beispiel: Adressverwaltung 2 (AV2) VL 10 7 AV2: Datentypen University of Paderborn Software Engineering Group E. Kindler Bisher haben wir in der Adressverwaltung am Anfang ein Feld der Länge 100 angelegt; die Anzahl der gespeicherten Adressen war dadurch beschränkt. Nun verwalten wir die Adressen in einer Liste; dadurch können wir beliebige viele Adressen einfügen; außerdem können wir Adressen an der alphabetisch richtigen Stelle einfügen (sortierte Liste). E. Kindler: Technische Informatik für Ingenieure, WS 2006/07, Universität Paderborn AV2: Adressein- und -ausgabe VL 10 E. Kindler: Technische Informatik für Ingenieure, WS 2006/07, Universität Paderborn 9 8 University of Paderborn Software Engineering Group E. Kindler class Adresse { String name; String vorname; String ort; } class Liste { Adresse adr; Liste next; } E. Kindler: Technische Informatik für Ingenieure, WS 2006/07, Universität Paderborn AV2: rekursive Ausgabe der Liste University of Paderborn Software Engineering Group E. Kindler VL 10 VL 10 10 University of Paderborn Software Engineering Group E. Kindler public class Adressverwaltung { public static Adresse readAdr() { /* Druckt alle Adressen der Liste der Reihe nach * (also alphabetisch sortiert) aus. */ public static void printListe(Liste liste) { if (liste != null) { printAdr(liste.adr); printListe(liste.next); } } // wie gehabt } public static void printAdr(Adresse adr) { // wie gehabt } E. Kindler: Technische Informatik für Ingenieure, WS 2006/07, Universität Paderborn VL 10 11 E. Kindler: Technische Informatik für Ingenieure, WS 2006/07, Universität Paderborn VL 10 12 2 AV2: rekursive Suche und Ausgabe AV2: rekursives Einfügen University of Paderborn Software Engineering Group E. Kindler public static Liste insertAdr(Liste liste, Adresse adr) { /* Druckt alle Adressen der Liste mit dem Namen * name aus. */ public static void printNameAdr(Liste liste, String name) { if (liste != null) { if (name.equals(liste.adr.name)) { printAdr(liste.adr); } if (liste == null) { Liste ergebnis = new Liste(); Nach new gilt: ergebnis.next == ergebnis.adr = adr; null return ergebnis; } else if (liste.adr.name.compareTo(adr.name)<= 0) { // name der einzufuegenden Adresse ist groesser // als der erste Name in dieser Liste liste.next = insertAdr(liste.next,adr); return liste; } else if (name.compareTo(liste.adr.name) >= 0) { // name ist groesser als der name der erste // Name in der liste printNameAdr(liste.next, name); } } } E. Kindler: Technische Informatik für Ingenieure, WS 2006/07, Universität Paderborn AV2: rekursives Einfügen VL 10 13 E. Kindler: Technische Informatik für Ingenieure, WS 2006/07, Universität Paderborn AV 2: Hauptprogramm University of Paderborn Software Engineering Group E. Kindler { VL 10 14 University of Paderborn Software Engineering Group E. Kindler public static void main(String[] args) { Liste liste = null; Liste ergebnis = new Liste(); ergebnis.adr = adr; ergebnis.next = liste; int option; do { return ergebnis; Out.println("Waehlen Sie '1', '2' oder '3' "); option = In.readInt(); In.readLine(); } } E. Kindler: Technische Informatik für Ingenieure, WS 2006/07, Universität Paderborn AV 2: Hauptprogramm (Forts.) University of Paderborn Software Engineering Group E. Kindler VL 10 15 E. Kindler: Technische Informatik für Ingenieure, WS 2006/07, Universität Paderborn Datenstrukturen University of Paderborn Software Engineering Group E. Kindler VL 10 16 University of Paderborn Software Engineering Group E. Kindler Rekursive (direkt oder indirekt) Datentypen sind die Grundlage der meisten Datenstrukturen der Informatik if (option == 1) { liste = insertAdr(liste, readAdr()); } else if (option == 2) { Out.println("Bitte einen Namen eingeben: "); String name = In.readLine(); printNameAdr(liste, name); Listen Bäume } else if (option == 3) { printListe(liste); } Graphen ... } while (option >= 1 && option <= 3); } } E. Kindler: Technische Informatik für Ingenieure, WS 2006/07, Universität Paderborn VL 10 17 E. Kindler: Technische Informatik für Ingenieure, WS 2006/07, Universität Paderborn VL 10 18 3 Datenstrukturen Probleme University of Paderborn Software Engineering Group E. Kindler University of Paderborn Software Engineering Group E. Kindler 1.Der Anfang der Liste „wandert“ (beim Einfügen oder Löschen an der ersten Position der Liste). Dies ist ein Problem, wenn mehrere Variablen immer auf dieselbe Liste verweisen sollen: z.B. Es sind auch zyklische Strukturen möglich! (beliebige Graphen) Beispiel: zyklische Liste l1 l2 nach Löschoperation auf l1: ! # l1 " $ l2 E. Kindler: Technische Informatik für Ingenieure, WS 2006/07, Universität Paderborn Lösung: Verankerte Liste class Liste { Adresse adr; Liste next; } class Anker { Liste liste; } VL 10 19 Verankerte Liste University of Paderborn Software Engineering Group E. Kindler a2 a1 a2 public static void deleteAdr(Anker a, String name) { a.liste = deleteAdr(a.liste, adr); // deleteAdr wie gehabt } ... deleteAdr(a1, name); Zugriffsoperationen VL 10 21 public static void insertAdr(Anker a, Adresse adr) { a.liste = insertAdr(a.liste, adr); // insertAdr wie gehabt} VL 10 22 University of Paderborn Software Engineering Group E. Kindler 2. In einem großen Programm gibt es viele Funktionen und Datentypen. Teilweise sind es Funktionen, die von anderen nicht benutzt werden sollen (z.B. Liste, insertAdr). Woher weiß man, welche Funktionen und Prozeduren benutzt werden sollen und welche nicht? public static void printListe(Anker a, Adresse adr) { a.liste = printListe(a.liste, adr); // printListe wie gehabt } public static void printNameAdr(Anker a,String name) { a.liste = printNameAdr(a.liste, name); // printNameAdr wie gehabt } VL 10 20 University of Paderborn Software Engineering Group E. Kindler E. Kindler: Technische Informatik für Ingenieure, WS 2006/07, Universität Paderborn Weitere Probleme: University of Paderborn Software Engineering Group E. Kindler E. Kindler: Technische Informatik für Ingenieure, WS 2006/07, Universität Paderborn VL 10 Der Anker ist nur ein Verweis auf ein Listenelement. Im Programm, das die Liste benutzt, werden nur Verweise auf den Anker gespeichert. Verweise auf Listenelemente selbst werden nur zur Verwaltung der Liste selbst benutzt. Alle Zugriffsoperationen auf die Liste werden indirekt über Zugriffsoperationen auf den Anker aufgerufen. Der Anker verweist immer auf den aktuellen Anfang der Liste. a1 E. Kindler: Technische Informatik für Ingenieure, WS 2006/07, Universität Paderborn E. Kindler: Technische Informatik für Ingenieure, WS 2006/07, Universität Paderborn 23 E. Kindler: Technische Informatik für Ingenieure, WS 2006/07, Universität Paderborn VL 10 24 4 Weitere Probleme: Lösungsansatz University of Paderborn Software Engineering Group E. Kindler University of Paderborn Software Engineering Group E. Kindler 1. Wir definieren die Funktionen dort, wo sie hingehören: Zusammen mit dem entsprechenden Datentyp. Dann nennen wir den Datentyp Klasse und die Funktionen Methode der Klasse 3. Wie verhindert man, daß Datenstrukturen unabsichtlich oder böswillig zerstört werden? a1 2. Wir definieren Zugriffsrechte auf Attribute und auf Methoden einer Klasse a2 % & % & ( ' ' objektorientierte Programmierung (Überblick in Kapitel III) E. Kindler: Technische Informatik für Ingenieure, WS 2006/07, Universität Paderborn 9.4. Gleichheit von Objekten VL 10 25 E. Kindler: Technische Informatik für Ingenieure, WS 2006/07, Universität Paderborn Beispiel University of Paderborn Software Engineering Group E. Kindler a != b a.name = "Kindler"; b.name = a.name; a.vorname = "Ekkart"; b.vorname = a.vorname; a.ort = "Berlin"; b.ort = a.ort; a != b " a = b; E. Kindler: Technische Informatik für Ingenieure, WS 2006/07, Universität Paderborn Gegenbeispiel (Forts.) a Adresse name vorname ort b Adresse name VL 10 27 String ) * E. Kindler: Technische Informatik für Ingenieure, WS 2006/07, Universität Paderborn Gleichheit von Objekten University of Paderborn Software Engineering Group E. Kindler 26 University of Paderborn Software Engineering Group E. Kindler Adresse a, b; a = new Adresse(); b = new Adresse(); Zwei Objektvariablen a und b sind bezüglich == genau dann gleich, wenn sie auf dasselbe Objekt verweisen oder beide den Wert null annehmen. VL 10 ( VL 10 28 University of Paderborn Software Engineering Group E. Kindler Wenn Sie zwei Objekte auf gleichen Inhalt vergleichen wollen, benutzen Sie die Methode „equals“. "Kindler" String "Ekkart" String In unserem Beispiel Gleichheit der Namen: "Paderborn" if (name.equals(liste.adr.name)) müssen Sie für Diese Methode lbst te Klassen se selbstdefinier pitel III). Ka ( n ere implementi aber diese Methode Für Stings ist ut. ba ge breits ein vorname ort E. Kindler: Technische Informatik für Ingenieure, WS 2006/07, Universität Paderborn VL 10 29 E. Kindler: Technische Informatik für Ingenieure, WS 2006/07, Universität Paderborn VL 10 30 5 10. Zusammenfassung Zuweisungen (VL2 & VL4) University of Paderborn Software Engineering Group E. Kindler University of Paderborn Software Engineering Group E. Kindler Primitive Datentypen Zuweisungen Konstanten (Literale) Kontrollstrukturen (Ablaufstrukturen) Variablen und Variablendeklarationen Arrays Operationen Funktionen und Prozeduren Ausdrücke Datenstrukturen Zuweisung E. Kindler: Technische Informatik für Ingenieure, WS 2006/07, Universität Paderborn Kontrollstrukturen (VL3 & VL4) VL 10 31 E. Kindler: Technische Informatik für Ingenieure, WS 2006/07, Universität Paderborn Felder (VL5 – VL7) University of Paderborn Software Engineering Group E. Kindler Bedingte Anweisung VL 10 32 University of Paderborn Software Engineering Group E. Kindler Ansammlung gleichartiger Objekte kurze und lange Deklaration und Initialisierung von Feldern Schleifen while-Schleife for-Schleife do-while-Schleife efinition) BNF (Syntaxd äume / Ableitungsb e um Syntaxbä us Polymorphism Seiteneffekte n Sichtbarkeit vo Gültigkeit und Variablen ) ithmetik (VL5 Gleitkomma-Ar Zugriff auf einzelne Elemente Modifikation einzelner Elemente n sind Arrayvariable se ei Verw onale Mehrdimensi Arrays r Schlüsselwörte isung break-Anwe E. Kindler: Technische Informatik für Ingenieure, WS 2006/07, Universität Paderborn Funktionen und Prozeduren (VL7 – VL9) VL 10 33 E. Kindler: Technische Informatik für Ingenieure, WS 2006/07, Universität Paderborn Einführungsbeispiel University of Paderborn Software Engineering Group E. Kindler VL 10 34 University of Paderborn Software Engineering Group E. Kindler public class Fakultaet { Definition einer Funktion public static void main (String[] args) { Funktionskopf Funktionsrumpf Out.print("Geben Sie eine Zahl ein: "); int n = In.readInt(); int erg = 1; Aufruf einer Funktion while (n > 0) { erg = erg * n; n = n - 1; } Prozedur: Funktion ohne Resultat Werte- und meter Referenzpara Rekursion E. Kindler: Technische Informatik für Ingenieure, WS 2006/07, Universität Paderborn VL 10 } Out.println("Das Ergebnis ist " + erg + "."); } 35 E. Kindler: Technische Informatik für Ingenieure, WS 2006/07, Universität Paderborn VL 10 36 6 Auswertung eines Ausdrucks Für n = 25: Auswertung und Zuweisung University of Paderborn Software Engineering Group E. Kindler n * (n + 1) / 2 erg = n * (n + 1) / 2; h7 / / h5 * h1 + n h4 + h2 n n 1 E. Kindler: Technische Informatik für Ingenieure, WS 2006/07, Universität Paderborn Typ eines Ausdrucks VL 10 int h1 2 + h3 1 h1 h2 h3 h4 h5 h6 h7 = = = = = = = n; n; 1; h2 + h3; h1 * h4; 2; h5 / h6; erg = h7; E. Kindler: Technische Informatik für Ingenieure, WS 2006/07, Universität Paderborn Lange if-Anweisung boolean h7 < wenn wahr < VL 10 38 University of Paderborn Software Engineering Group E. Kindler wenn falsch 2 führe Anweisung 1 aus int h4 + n + werte die Bedingung aus int h6 * int h2 führe Anweisung 2 aus int h3 n 1 E. Kindler: Technische Informatik für Ingenieure, WS 2006/07, Universität Paderborn VL 10 39 E. Kindler: Technische Informatik für Ingenieure, WS 2006/07, Universität Paderborn Semantik University of Paderborn Software Engineering Group E. Kindler if ( <BoolExpression> ) { <Command> } werte die Bedingung aus h6 int int int int int int int if ( <BoolExpression> ) { <Command1> } else { <Command2> } * Kurze if-Anweisung 37 University of Paderborn Software Engineering Group E. Kindler ergibt sich (induktiv) aus dem Typ der Konstanten, der Variablen, und der Operatoren int h5 und Funktionen wenn wahr * n + int n; ... n * (n + 1) < 2 / / * 2 * University of Paderborn Software Engineering Group E. Kindler VL 10 40 University of Paderborn Software Engineering Group E. Kindler while ( <BoolExpression> ) { <Command> } wenn falsch wenn wahr werte die Bedingung aus wenn falsch führe Anweisung 1 aus E. Kindler: Technische Informatik für Ingenieure, WS 2006/07, Universität Paderborn führe die Anweisung aus VL 10 41 E. Kindler: Technische Informatik für Ingenieure, WS 2006/07, Universität Paderborn VL 10 42 7 for-Schleifen (Zählschleifen) Initialisierung der “Zählvariablen” i Deklaration mit Initialisierung University of Paderborn Software Engineering Group E. Kindler Obergrenze für die Zählvariable i! Diese Bedingung wird vor jedem Schleifendurchlauf überprüft. String[] monate = new String[] { "Jan","Feb","Mrz","Apr","Mai","Jun", "Jul","Aug","Sep","Okt","Nov","Dez" }; for ( int i = 1; i <= n; i++ ) { <Command> } 0 Erhöhung der Zählvariablen i um eins (nach jedem Schleifendurchlauf)! E. Kindler: Technische Informatik für Ingenieure, WS 2006/07, Universität Paderborn Summe von Array-Elementen University of Paderborn Software Engineering Group E. Kindler VL 10 monate 43 1 2 3 "Jan" "Feb" "Mrz" "Apr" E. Kindler: Technische Informatik für Ingenieure, WS 2006/07, Universität Paderborn Beispiel: Bubble Sort University of Paderborn Software Engineering Group E. Kindler 11 ... "Dez" VL 10 44 University of Paderborn Software Engineering Group E. Kindler // Eingabe ein Array int[] a; double[] v = { 3.1, 5.3, 7.0, -3.7 }; 0 1 2 boolean sortiert; 3 do { sortiert = true; for ( int i = 0; i < a.length - 1; i++ ) { if ( a[i] > a[i+1] ) { int h = a[i]; a[i] = a[i+1]; a[i+1] = h; sortiert = false; } } } while ( !sortiert ); double summe = 0.0; for (int i = 0; i < v.length; i++) { summe = summe + v[i]; } E. Kindler: Technische Informatik für Ingenieure, WS 2006/07, Universität Paderborn Funktionsdefinition VL 10 45 E. Kindler: Technische Informatik für Ingenieure, WS 2006/07, Universität Paderborn Binomialkoeffizient University of Paderborn Software Engineering Group E. Kindler public static int fak(int n) { VL 10 46 University of Paderborn Software Engineering Group E. Kindler public static void main (String[] args) { int n = In.readInt(); int k = In.readInt(); int ergebnis = 1; int ergebnis = fak(n) / ( fak(k) * fak(n - k) ); for (int i = 1; i <= n; i++) { ergebnis = ergebnis * i; } Out.println("Ergebnis: " + ergebnis); } return ergebnis; } E. Kindler: Technische Informatik für Ingenieure, WS 2006/07, Universität Paderborn VL 10 47 E. Kindler: Technische Informatik für Ingenieure, WS 2006/07, Universität Paderborn VL 10 48 8 Bubble Sort als Prozedur University of Paderborn Software Engineering Group E. Kindler public static void sort (int[] a) { boolean sortiert; do { sortiert = true; for ( int i = 0; i < a.length - 1; i++ ) { if ( a[i] > a[i+1] ) { int h = a[i]; a[i] = a[i+1]; a[i+1] = h; sortiert = false; } } } while ( !sortiert ); } E. Kindler: Technische Informatik für Ingenieure, WS 2006/07, Universität Paderborn VL 10 49 9