3. Datentypen Algorithmen und Datenstrukturen 3. Datentypen Prof. Dr. Christoph Pflaum Department Informatik • Martensstraße 3 • 91058 Erlangen Wdh. 1.4 Programmgesteuerter Rechner (Babbage, 1833) ZwischenErgebnisse Zustand Programm Verarbeitung Idee der Programmgesteuerten Rechner: Die Verarbeitung nicht ein für allemal festlegen, sondern die Verarbeitungsschritte durch ein austauschbares Programm variabel bestimmen. Programm extern (auf Lochkarten) Algorithmen und Datenstrukturen • Philippsen/Stamminger/Pflaum • WS 2008/09 • Folie 03-3 © Michael Philippsen Algorithmen und Datenstrukturen • Philippsen/Stamminger/Pflaum • WS 2008/09 • Folie 03-2 Wdh. 1.4 Von-Neumann-Rechner Speicher, konzeptionell Speicher EingabeDaten, 3.1 Variablen einfachen Typs 3.2 Ausdrücke 3.3 Referenzvariablen 3.4 Zusammengesetzte Datentypen Adresse 0 Adresse 4 0100 0100 0100 0100 0100 0100 0101 0101 0100 1101 0011 0001 1100 1000 1100 0000 0011 1110 0100 0100 0100 0101 0100 0100 0101 0100 1001 1000 0101 0000 1001 1001 0000 0101 4D 43 41 4C 48 4C 50 53 4E 49 48 45 50 49 49 50 45 Sedezimale Darstellung „Hex-Dump“ Nur mit Interpretationsvorschrift ist Menschen klar, was die Werte im Speicher bedeuten. Binär codierter Zeichenvorrat, Binärdarstellung von Zahlen aber auch: „Nummern“ von Maschinenbefehlen Æ nicht „benutzerfreundlich“ Algorithmen und Datenstrukturen • Philippsen/Stamminger/Pflaum • WS 2008/09 • Folie 03-4 1 3.1 Variablen einfachen Typs 3.1 Variablen einfachen Typs Eigenschaften einer Speicherzelle: Ablauf des Zugriffs über den Namen: □ Sie stellt einen Behälter dar, der über eine Adresse angesprochen wird und einen Inhalt (Wert) aufnimmt. □ Wir sagen: „Die Zelle mit Adresse a hat den Wert w zum Inhalt“. Abstraktion für den Programmierer: Adresse interessiert nicht. □ Verwendung einer die Zelle identifizierenden Zugriffsfunktion: Name. □ Ergebnis der Berechnung der Adresse über die Zugriffsfunktion: Referenz. Beispiel: Ausführende Operation: 1/pi Adresse: 003 Name: pi Wert: 3.141 Referenz von pi ist die Adresse 003. Der Wert der Referenz ist 3.141. Anderes übliches Wort für Name: Bezeichner □lesend: Vorgabe des Namens Æ Beschaffung der Referenz Æ Zugriff auf den Behälter Æ Lieferung des Wertes als Ergebnis. □schreibend: Vorgabe des Namens Æ Beschaffung der Referenz Æ Zugriff auf den Behälter Æ Ersetzen des Wertes. Variablen sind Namen, die lesenden und schreibenden Zugriff erlauben. Konstanten erlauben nur Lesezugriffe. Beachte: Der schreibende Zugriff hat einen sogenannten Seiteneffekt, das ist eine Veränderung des Zustands (im Speicher) des Rechners. Algorithmen und Datenstrukturen • Philippsen/Stamminger/Pflaum • WS 2008/09 • Folie 03-5 Algorithmen und Datenstrukturen • Philippsen/Stamminger/Pflaum • WS 2008/09 • Folie 03-6 3.1 Variablen einfachen Typs 3.1 Variablen einfachen Typs Ein Name ist eine beliebig lange Folge von „JavaBuchstaben“ und „Java-Ziffern“, beginnend mit einem „JavaBuchstaben“, wobei: Jede Variable oder Konstante besitzt einen Typ. □ Java-Ziffer = Zahl zwischen 0 und 9 □ Java-Buchstabe: Buchstabe aus dem gesamten sog. Unicode Zeichenvorrat, in dem die meisten auf der Welt verwendeten Schriftzeichen enthalten sind. □Festlegung des gültigen Wertebereichs □Festlegung der anwendbaren Grundoperationen (später mehr) Numerischer Typ Ein Name darf also nicht mit einer Ziffer beginnen. Beispiele: □ gültige Bezeichner: □ ungültige Bezeichner: Primitiver Typ Einfache Typen: i3, aud_1, MAX_WERT 1aud, 12HUNDERT, 0nixgut Ganzzahliger Typ Gleitkomma-Typ Wichtig: Groß- und Kleinschreibung wird unterschieden. AuD1 und aud1 sind also zwei verschiedene Bezeichner. byte Algorithmen und Datenstrukturen • Philippsen/Stamminger/Pflaum • WS 2008/09 • Folie 03-7 © Michael Philippsen char long int short float double boolean Algorithmen und Datenstrukturen • Philippsen/Stamminger/Pflaum • WS 2008/09 • Folie 03-8 2 3.1 Variablen einfachen Typs 3.1 Variablen einfachen Typs Basistyp Beschreibung boolean Wahrheitswert Wertebereiche true, false Art byte, short, int, long vorzeichenbehaftete Ganzzahlen von 8, 16, 32, 64 Bit Länge. -27 = -128 ≤ byte ≤ 127 = 27-1 -215 = -32 768 ≤ short ≤ 32 767 = 215-1 -231 = -2 147 483 648 ≤ int ≤ 2 147 483 647 = 231-1 -263 = -9 223 372 036 854 775 808 ≤ long long ≤ 9 223 372 036 854 775 807 = 263-1 float, double Gleitpunktzahlen von 32 bzw. 64 Bit gemäß IEEE 754-1985. Kleinste float Zahl >0: 1.40239846e-45 Größte float Zahl >0: 3.40282347e+38 Kleinste double Zahl >0: 4.94065645841246544e-324 Größte double Zahl >0: 1.79769313486231570e+308 char Einzelzeichen Unicode, 16 Bits, http://www.unicode.org Syntaktische Form <Wert> 1, true, 'c' Variablenvereinbarung (Deklaration) <Typ> <Name>; int a; lesender Zugriff <Name> a + 1 schreibender Zugriff (Zuweisung) <Name> = <Wert>; a = 1; Algorithmen und Datenstrukturen • Philippsen/Stamminger/Pflaum • WS 2008/09 • Folie 03-9 3.1 Variablen einfachen Typs 3.1 Variablen einfachen Typs Wert von a nach der Anweisung Beispiele Variablenvereinbarung mit Vorbesetzung (Deklaration mit Initialisierung) <Typ> <Name> = <Wert>; int a = 1; Vereinbarung einer benannten Konstanten mit Einmaldefinition final <Typ> <Name> = <Wert>; final float pi = 3.14159; Der Übersetzer stellt sicher, dass es nur eine Definition im Programm gibt. Algorithmen und Datenstrukturen • Philippsen/Stamminger/Pflaum • WS 2008/09 • Folie 03-11 © Michael Philippsen Initialwert der Variable ist typspezifisch. Meist 0. Algorithmen und Datenstrukturen • Philippsen/Stamminger/Pflaum • WS 2008/09 • Folie 03-10 Beispiele Syntaktische Form Beispiele unbenannte Konstante (Literal) <Wert> kann auch ein zu berechnender Ausdruck sein. Art restlicher Text muss exakt wie angegeben im Programm erscheinen. <XXX> ist ein Platzhalter; im Programm zu ersetzen. int a = 1; //Deklaration //Initialisierung mit //Literal 1 1 a = a + 1; //Inkrementierung 2 a++; //Inkrementierung 3 3 3 a; //Lesezugriff final int b = a; //Deklaration //einer Konstanten float c = 1.0f; //float-Literal int d, e = 5; //mehrere Deklarationen //von einem Typ (d=0,e=5) Komma vereinfacht Deklarationsschreibweise später: d bleibt als lokale Variable uninitialisiert. 3 3 Folge der Zugriffsfunktion: Es wird immer der (einzig verfügbare) aktuelle Wert gelesen. Algorithmen und Datenstrukturen • Philippsen/Stamminger/Pflaum • WS 2008/09 • Folie 03-12 3 3.2 Ausdrücke 3.2 Ausdrücke Bei Zuweisungen dürfen auch Ausdrücke stehen z.B.: Grundoperationen für primitive Typen int a = 1; int b = 2 * a + 1; int c = 3 * (a + b) double d = a / b; double e = 1.0, f = 3.0; double g = e / f; boolean b = e < f; int i = a++; int j = ++a; // // // // // // // // // a b c d e g b i j = = = = = = = = = 1 3 12 0.0 (!) 1.0, f = 3.0 0.333333333 true; 1, a = 2 3; a = 3 Algorithmen und Datenstrukturen • Philippsen/Stamminger/Pflaum • WS 2008/09 • Folie 03-13 3.2 Ausdrücke Unäre/binäre „Strichrechung“ am Beispiel a + b Addition von a und b zwei Operanden Æ binärer Operator a++ ++a Inkrementiere a um 1 (nach der Auswertung von a) Inkrementiere a um 1 (vor der Auswertung von a) ein Operand Æ unärer Operator Basistyp Grundoperationen (Auswahl) boolean ==, !=, !(not), &(and), |(inkl. or), ^(exkl. or), &&(and), ||(inkl. or) Test auf gleich/ungleich Strikte Auswertung s.u. Faule Auswertung byte, short, int, long ==, !=, <, >, <=, >=, +, -, ++ (unär), -- (unär), *, /, % (mod), ~(compl.), &(and), |(inkl.or), ^(exkl.or), << (left shift), >> (right shift sign), >>> (right shift no-sign) Vergleiche, liefern boolean „Strichrechnung“ „Punktrechnung“ Operationen auf der Binärdarstellung float, double ==, !=, <, >, <=, >=, +, -, ++ (unär), -- (unär), *, /, % (mod) Vergleiche, liefern boolean „Strichrechnung“ „Punktrechnung“ Algorithmen und Datenstrukturen • Philippsen/Stamminger/Pflaum • WS 2008/09 • Folie 03-14 3.2 Ausdrücke Pre- und Postinkrement sowie Zuweisung am Beispiel Ausdruck Änderung des Vorzeichens von a ein Operand Æ unärer Operator Wert von a, nachher b = ++a; Wert von b, nachher 2 b = a++; b = (a = a + 1); -a Wert von a, vorher 2 3 3 D.h. eine Zuweisung „a = a + 1“ ist wieder ein Ausdruck. Der Wert der Zuweisung ist auch der Wert des Ausdrucks. Anderes Beispiel: a = b = c = 1 setzt a, b und c auf 1 Algorithmen und Datenstrukturen • Philippsen/Stamminger/Pflaum • WS 2008/09 • Folie 03-15 © Michael Philippsen Algorithmen und Datenstrukturen • Philippsen/Stamminger/Pflaum • WS 2008/09 • Folie 03-16 4 3.2 Ausdrücke 3.2 Ausdrücke Operationen auf der Binärdarstellung am Beispiel 15 << 3: (15 =) 00001111 wird zu 01111000 (= 120) 15 >> 3: (15 =) 00001111 wird zu 00000001 (= 1) -1 >>> 3: (-1 =) 11111111 wird zu 00011111 (= 31) Grundoperatoren kombiniert mit Zuweisung Speicherung negativer Zahlen im 2er >>> ignoriert Vorzeichen: von Komplement: Invertiere jede links neue Nullen einfügen Bitposition und addiere dann 1 -1 >> 3: (-1 =) 11111111 wird zu 11111111 ( = -1) Vorzeichen-Bit 14 & 13: (14 =) 00001110 >> beachtet Vorzeichen: von (13 =) 00001101 links altes Vorzeichen-Bit einf. „und“ 00001100 (= 12) 14 | 13: (14 =) 00001110 (13 =) 00001101 „oder“ 00001111 (= 15) Algorithmen und Datenstrukturen • Philippsen/Stamminger/Pflaum • WS 2008/09 • Folie 03-17 = += -= *= /= %= |= &= ^= <<= >>= >>>= Zuweisung Inkrementierung, z. B. alter += 80 (entspricht alter = alter + 80) Dekrementierung, z. B. alter -= 80 (entspricht alter = alter - 80) Skalierung, z. B. alter *= 2 (entspricht alter = alter * 2) Division, z. B. alter /=2 (entspricht alter = alter / 2) Restebildung, z. B. alter %= 10 (entspricht alter = alter % 10) bitweises Oder bitweises Und bitweises Exklusives Oder (Entweder-Oder) Verschieben nach links, z. B. alter <<= 2 (entspricht alter = alter << 2) Verschieben nach rechts (mit Vorzeichenerhalt), z. B. alter >>= 2 (entspricht alter = alter >> 2) Verschieben nach rechts (ohne Vorzeichenerhalt) z. B. alter >>>= 2 (entspricht alter = alter >>> 2) Algorithmen und Datenstrukturen • Philippsen/Stamminger/Pflaum • WS 2008/09 • Folie 03-18 3.2 Ausdrücke 3.2 Ausdrücke Jede Variable, jede Konstante und jedes Literal besitzt einen Typ: Beispiele für Typfehler □ Festlegung des gültigen Wertebereichs □ Festlegung der anwendbaren Operationen Typsicherheit: Auf Operanden können nur die ihrem Typ entsprechenden Operationen angewandt werden. In typsicheren Programmiersprachen kann der Übersetzer für jeden Operanden zu jeder Zeit den zugehörigen Typ ermitteln und damit feststellen, ob eine Operation anwendbar ist. □ Wenn nicht liefert der Übersetzer eine Fehlermeldung. □ Somit lassen sich mit Typen manche Fehler ermitteln, bevor ein Schaden angerichtet wird: Verbesserte Korrektheit von Programmen (statische Typsicherheit). 5 + true binärer +-Operator ist nur für numerische Typen erklärt. Der Übersetzer stellt fest, dass true ein Wahrheitswert und damit kein numerischer Wert ist Æ Fehlermeldung Name der Quellcode-Datei und Zeilennummer des Fehlers Übersetzerlauf: > javac Test.java ... Test.java:4: operator + cannot be applied to int,boolean a = 5 + true; ^ ... Stelle des Fehlers Algorithmen und Datenstrukturen • Philippsen/Stamminger/Pflaum • WS 2008/09 • Folie 03-19 © Michael Philippsen Quellcode-Zeile Algorithmen und Datenstrukturen • Philippsen/Stamminger/Pflaum • WS 2008/09 • Folie 03-20 5 3.2 Ausdrücke 3.2 Ausdrücke (Statischer) Typ eines Ausdrucks (Statischer) Typ einer Zuweisung Der Typ eines Ausdrucks kann zur Übersetzungszeit bestimmt werden und leitet sich im wesentlichen aus den Typen der Teilausdrücke und des angewendeten Operators ab. Beispiel: Die Typen der linken und der rechten Seite einer Zuweisung müssen zusammenpassen. Nicht nur Ausdrücke haben einen Typ, sondern auch Zuweisungen. Zuweisungen liefern als Wert das jeweilige Ergebnis der rechten Seite. Beispiel: int i, j; i = j = 0; // i und j wird der // Wert 0 zugewiesen, // da j = 0 den Wert 0 liefert int a = 0; float b = 2; boolean c; c = a == b; // // // c = a * b; // // // c = c * c; // Typ des Ausdrucks a == b ist boolean, a wird implizit in float gewandelt (s.u.), alles ok. Typ des Ausdrucks a * b ist float, a wird implizit in float gewandet (s.u.), Fehler bei der Zuweisung! Fehler, da * nicht auf boolean anwendbar. Algorithmen und Datenstrukturen • Philippsen/Stamminger/Pflaum • WS 2008/09 • Folie 03-21 Algorithmen und Datenstrukturen • Philippsen/Stamminger/Pflaum • WS 2008/09 • Folie 03-22 3.2 Ausdrücke 3.2 Ausdrücke Faule versus strikte Auswertung Beispiel: Wert des gesammelten Kleingelds Die Operatoren && und || heißen auch bedingte logische Operatoren, da sie ihren rechten Operanden nur dann auswerten, wenn dies wirklich nötig ist. Sie sind in diesem Sinne „faul“. □ In ((b=false) && (c=true)) wird also die Zuweisung zu c nicht ausgeführt, da der Wert der Zuweisung zu b false ist. Da der linke Operand von && schon falsch ist, kann der Gesamtausdruck nicht mehr wahr werden, die Auswertung des rechten Operanden wird eingespart. Im Gegensatz dazu evaluieren die symmetrischen logischen Operatoren &, | und ^ stets (strikt) beide Operanden. Beispiel: □ Durch faule Auswertung führt folgender Ausdruck nicht zur Division durch Null: (x != 0) && ((1-x)/x > 1) □ Durch strikte Auswertung gibt es hier bei x=0 einen Fehler: (x != 0) & ((1-x)/x > 1) Algorithmen und Datenstrukturen • Philippsen/Stamminger/Pflaum • WS 2008/09 • Folie 03-23 © Michael Philippsen int int int int int int int int cents zweiCentStücke fünfer zehner fünfziger euro zweiEuro gesamt; = = = = = = = 10; 2; 0; 4; 1; 3; 1; gesamt = cents + 2 * zweiCentStücke + 5 * fünfer + 10 * zehner + 50 * fünfziger + 100 * euro + 200 * zweiEuro; Ausdruck mit Punkt-vor-Strich-Rechnung. Der Typ des Ausdrucks ist int. Algorithmen und Datenstrukturen • Philippsen/Stamminger/Pflaum • WS 2008/09 • Folie 03-24 6 3.2 Ausdrücke 3.2 Ausdrücke Auswertungsreihenfolge für Ausdrücke Typumwandlung auf primitiven Typen Erforderlich, wenn der geforderte Typ eines Wertes nicht mit dem tatsächlichem Typ übereinstimmt. Bedingte Freizügigkeit wegen Typsicherheit! Implizite Umwandlung bei Zuweisung a = b, wenn Wertebereich nicht verkleinert wird („widening“) Gemäß Präzedenz/Vorrangregeln, innerhalb dieser: links vor rechts. Präzedenz in Java: (mit expliziter Klammerung zu umgehen) □ Postfix-Operatoren [] . (params) expr++ expr-□ unäre Operatoren ++expr --expr +expr -expr ! ~ □ Erzeugung oder Typumwandlung new (type) expr □ Multiplikationsoperatoren */% „Punkt-vor-Strich“ □ Additionsoperatoren +□ Verschiebeoperatoren << >> >>> □ Vergleichsoperatoren < > <= >= instanceof (später mehr) □ Gleichheitsoperatoren == != □ Bitoperator Und & □ Bitoperator exklusives Oder ^ □ Bitoperator inklusives Oder | □ logisches Und && □ logisches Oder || □ Fragezeichenoperator ?: □ Zuweisungsoperatoren = += -= *= /= %= >>= <<= >>>= &= ^= |= Reihenfolge beachten! Zuweisungen haben Seiteneffekte. Algorithmen und Datenstrukturen • Philippsen/Stamminger/Pflaum • WS 2008/09 • Folie 03-25 Typ von b Typ von a byte short, int, long, float, double short, char int, long, float, double int long, float, double Genauigkeitsverluste möglich! long float, double Genauigkeitsverluste möglich! float double Algorithmen und Datenstrukturen • Philippsen/Stamminger/Pflaum • WS 2008/09 • Folie 03-26 3.2 Ausdrücke 3.2 Ausdrücke Typumwandlung auf primitiven Typen Typumwandlung auf primitiven Typen Implizite Umwandlung in Ausdrücken, um definierten Operator anzuwenden, wenn Wertebereich nicht verkleinert wird. □ Beispiel: int a = 0; float b = 2; boolean c; c = a == b; // a wird implizit in float gewandelt Bei ++, -- auf byte, short, char wird Wert zu int. Explizite Typwandlung („casting“). □ Voranstellen des Zieltyps, z.B. long a = 35; int b = (int) a; wandelt eventuell unter Informationsverlust. □ Einschränkungen beachten, jedoch Wandlungen zwischen allen numerischen Typen erlaubt. Algorithmen und Datenstrukturen • Philippsen/Stamminger/Pflaum • WS 2008/09 • Folie 03-27 © Michael Philippsen double pi = 3.14; int i = 8; //3.14 implizit geweitet floatÆdouble double k = pi * i; //i implizit geweitet intÆdouble //k = 25.12 int k1 = (int) (pi * i); //25.12 explizit auf int verkleinert //Informationsverlust: k1=25 int k2 = ((int) pi) * i; //pi wird auf int verkleinert (3) //Informationsverlust: k2=24 long l = (int) k * 2000; //k wird auf int verkleinert (25) //l = 50000 //Sedezimaldarstellung: 000000000000C350 short s = (short) l; //Informationsverlust: //Binärdarstellung: 1100 0011 0101 0000 //2er Komplement -1 1100 0011 0100 1111 // invertieren 0011 1100 1011 0000 Algorithmen und Datenstrukturen • Philippsen/Stamminger/Pflaum • WS 2008/09 • Folie 03-28 //s = -15536 7 3.3 Referenzvariablen 3.3 Referenzvariablen Variablen einfachen Typs Veranschaulichung □ Mit Variablen einfachen Typs wird bei deren Vereinbarung zugleich ein Behälter für den Wert bereitgestellt (und in Java mit dem Default-Wert für diesen Typ initialisiert. Später: keine Initialisierung bei lokalen Variablen.) □ Mit Angabe des Namens wird unmittelbar der Wert angesprochen (Wertsemantik). a 5 Wert eingebracht z.B. durch int Behälter a Zugriffsfunktion Wert • Referenzsemantik □ Mit Objektvariablen wird nur ein Behälter für einen Zeiger auf ein Objekt des entsprechenden Typs angelegt (Referenzsemantik) □ Der eigentliche Speicherplatz für die Objektinstanz muss dann noch angelegt werden und ist somit nicht fest angebunden Objekt nicht zugewiesen Name a = 5; Referenzvariablen c • Wertsemantik c Objekt Objekt zugewiesen Algorithmen und Datenstrukturen • Philippsen/Stamminger/Pflaum • WS 2008/09 • Folie 03-29 Name a Zugriffsfunktion Behälter Adresse d. Objektbehälters Behälter Objektwert Über die Darstellung von Referenzen ist dem Programm nichts bekannt, mit Referenzen kann man nicht rechnen. Algorithmen und Datenstrukturen • Philippsen/Stamminger/Pflaum • WS 2008/09 • Folie 03-30 3.3 Referenzvariablen 3.4 Zusammengesetzte Datentypen In Java sind Variablen mit primitiven Typen immer Wertevariablen, für die folgenden zusammengesetzten Typen aber immer Referenzvariablen! Alle Programmiersprachen bieten neben primitiven Typen auch zusammengesetzte Typen an. Algorithmen und Datenstrukturen • Philippsen/Stamminger/Pflaum • WS 2008/09 • Folie 03-31 © Michael Philippsen □ Verbund □ Zeichenfolge („dies ist eine Zeichenfolge“) □ Reihung („array“) Algorithmen und Datenstrukturen • Philippsen/Stamminger/Pflaum • WS 2008/09 • Folie 03-32 8 3.4 Zusammengesetzte Datentypen Verbund: generiere neuen Datentyp durch Zusammenfügen mehrerer Daten. Schlüsselwort: class Zugriff auf die einzelnen Elemente mit dem Punkt „.“ Beispiel: class Vec3 { double x, y, z; }; 3.4 Zusammengesetzte Datentypen class definiert einen neuen Typ. Es können Variablen mit diesem Typ deklariert werden. Solche Variablen sind automatisch Referenzvariablen. Referenz zeigt am Anfang auf null = undefiniert: class Vec3 { double x, y, z; }; Vec3 p; p.x = 1; Vec3 p,q; ... p.x = 3; p.y = q.y * 2; ... Æ Exception in thread "main" java.lang.NullPointerException Fehler beim Zugriff über null-Referenz. Algorithmen und Datenstrukturen • Philippsen/Stamminger/Pflaum • WS 2008/09 • Folie 03-33 Algorithmen und Datenstrukturen • Philippsen/Stamminger/Pflaum • WS 2008/09 • Folie 03-34 3.4 Zusammengesetzte Datentypen 3.4 Zusammengesetzte Datentypen Richtig: Objekt erzeugen mit new Das liefert Referenz auf ein neues Objekt. Referenzen können auf dasselbe Objekt zeigen: class Vec3 { double x, y, z; }; Vec3 p = new Vec3(); p.x = 1; Die Bedeutung der Klammern folgt noch. class Vec3 { double x, y, z; } ... Vec3 p = new Vec3(); p.x = 1; p.y = 2; p.z = 3; Vec3 q = p; q.x = 4; q.y = 5; q.z = 6; // hier gilt: p.x == 4! p Ab hier zeigen p und q auf das selbe Objekt. Damit sind auch p.x und q.x identisch! Objekt vom Typ Vec3 q Algorithmen und Datenstrukturen • Philippsen/Stamminger/Pflaum • WS 2008/09 • Folie 03-35 © Michael Philippsen Algorithmen und Datenstrukturen • Philippsen/Stamminger/Pflaum • WS 2008/09 • Folie 03-36 9 3.4 Zusammengesetzte Datentypen 3.4 Zusammengesetzte Datentypen Zeichenfolgen Einzelzeichen des Unicodes werden in Java durch einzelne Anführungszeichen abgegrenzt: Spezialzeichen □ char Einzelzeichen = 'x'; Zeichenfolgen werden durch (doppelte) Gänsefüßchen abgegrenzt: □ "" □ "hello" //leere Zeichenfolge //normale Zeichenfolge Es gibt spezielle Operatoren für diesen zusammengesetzten Datentyp: □ Konkatenation: "hello " + "students" □ Zeichenfolgenvergl. "hello " + "students" == "hello students" Vorgriff: Zeichenfolgen sind Objekte der bereits im Sprachumfang vereinbarten Klasse String (genauer: java.lang.String). Algorithmen und Datenstrukturen • Philippsen/Stamminger/Pflaum • WS 2008/09 • Folie 03-37 Für manche Zeichen des Unicodes gibt es besondere Schreibweisen. Spezialzeichen Unicode Ersatzdarstellung Rückschritt („backspace") horizontaler Tabulator („TAB“) neue Zeile („line feed") Seitenvorschub („form feed“) Wagenrücklauf („carriage return“) doppeltes Anführungszeichen einfaches Anführungszeichen Rückstrich („backslash“) \u0008 \u0009 \u000a \u000c \u000d \u0022 \u0027 \u005c \b \t \n \f \r \" \‘ \\ Siehe ASCII-Tabelle, Abschnitt 1.1 Escape-Zeichen Algorithmen und Datenstrukturen • Philippsen/Stamminger/Pflaum • WS 2008/09 • Folie 03-38 3.4 Zusammengesetzte Datentypen 3.4 Zusammengesetzte Datentypen Reihung („array“) = geordnete Menge typgleicher Variablen. Vereinbarung: <Typ> [] <Name> Reihungen sind Objekte einer bereits im Sprachumfang vereinbarten (anonymen) Klasse. Es gibt zusätzliche sprachliche Möglichkeiten für Zugriffe auf die Variablen von Reihungsobjekten. □ Beispiele: int[] ai; Die Größe (= Anzahl der Elemente) wird bei Erzeugung des Arrays festgelegt, kann dann aber nicht mehr geändert werden. Die Erzeugung kann bei oder nach der Variablendeklaration stattfinden. □ Beispiel für die Erzeugung eines int-Arrays der Größe 10: int[] ai; //ai ist noch null-Referenz ai = new int[10]; //ai ist initialisiert oder: int[] ai = new int[10]; Algorithmen und Datenstrukturen • Philippsen/Stamminger/Pflaum • WS 2008/09 • Folie 03-39 © Michael Philippsen □ Im Attribut length eines Reihungsobjekts kann die Größe der erzeugten Reihung abgelesen werden. □ Beispiel: ai.length == 10 //liefert (nach der //Erzeugung von oben) true Nach der Erzeugung gibt es Zugriffsfunktionen („Namen“) für jedes Element der Reihung: ai[0], ai[1], ... , ai[ai.length-1] □ Beispiel Zugriffe: ai[1] = ai[3 + 1]; //schreibt 2. Array-Element (Nr.1) //und liest 5. Array Element (Nr.4) Algorithmen und Datenstrukturen • Philippsen/Stamminger/Pflaum • WS 2008/09 • Folie 03-40 10 3.4 Zusammengesetzte Datentypen 3.4 Zusammengesetzte Datentypen Mehrdimensionale Reihungen: Mehrdimensionale Reihungen Der Typ eines Arrays kann beliebig sein (Klasse, primitiver Typ oder wiederum ein Array-Typ). Daher sind mehr-dimensionale Arrays möglich: gibt es in den meisten Programmiersprachen. Aber meistens nicht als Reihungen von Reihungen, sondern als „rechteckige“ mehrdimensionale Datenfelder. □ Mehrdimensionales Datenfeld (C, C++, Fortran, ...) int[][] aai; Exemplar[] geliehen; // Array aus int-Arrays // Array aus Objektreferenzen Auch im mehrdimensionalen Fall müssen die Arrays jeweils einzeln erzeugt werden: aai = new int[2][]; aai[0] = new int[1]; aai[1] = new int[2]; // // // // // // Erzeuge Array zur Speicherung v. 2 int-Arrays Erzeuge erstes intArray der Länge 1 Erzeuge zweites Array der Länge 2 Algorithmen und Datenstrukturen • Philippsen/Stamminger/Pflaum • WS 2008/09 • Folie 03-41 … Bei linearer Abbildung in den HauptSpeicher kann aus dem Index (i,j) und dem Platzbedarf des Grundtyps die Speicheradresse ermittelt werden. □ Reihung von Reihung (Java) Nicht-“rechteckige“ mehrdimensionale Reihungen sind möglich (fehlende Zeilen, doppelt genutzte Zeilen, unterschiedlich lange Zeilen). Algorithmen und Datenstrukturen • Philippsen/Stamminger/Pflaum • WS 2008/09 • Folie 03-42 3.4 Zusammengesetzte Datentypen Mehr über Reihungen: Bei der Erzeugung dürfen die Array-Größen aus Ausdrücken berechnet werden: int a = b = 10; Exemplar[] geliehen = new Exemplar[a + b]; Es sind auch direkte Array-Initialisierungen möglich: int[] quadrat = {1, 4, 9, 16, 25, 36, 49}; int[][] aai = { { 1, 2 }, { 3, 4 } }; Bei nicht initialisierten Arrays werden die Elemente implizit auf Standardwerte gesetzt: □ 0 bei int, short, byte, float, double □ false bei boolean □ null bei Referenzen Algorithmen und Datenstrukturen • Philippsen/Stamminger/Pflaum • WS 2008/09 • Folie 03-43 © Michael Philippsen 11