Zusammenfassung Praktische Informatik HWS 09/10 1. Kapitel: Programmierung a) Programme • Ein Progamm ist eine Folge von Anweisungen, die einem Computer sagen, was er tun soll. • Programme werden in einer künstlichen Sprache verfasst und in Textdateien gespeichert. Sie sollen für Menschen lesbar sein und präzise und unmissverständliche Handlungsanweisungen enthalten. • Beispiel Programmiersprachen: Pascal, C, Java, SQL, HTML, Tex b) Compiler • Rechner verstehen nur sehr einfach Kommandos, die als Zahlen im Binärsystem kodiert sind (Maschinensprache). Compiler übersetzen Programme aus einer höheren Sprache in die Maschinensprache des Computers. c) Virtuelle Maschine • Betriebssysteme stellen eine Infrastruktur bereit, die Programme nutzen können. Programme greifen direkt auf die Resourcen des OS zu. Jedes Programm läuft nur auf einem Rechnertyp mit einem Betriebssystem. m*n Compiler (m Sprachen, n Plattformen) • Virtuelle Maschine ist ein gedachter Computer, der auf einem realen Computer simuliert wird. Man kann VM als Zwischensprache auffassen. Anweisungen in der Zwischensprache heißen Bytecode. M Compiler + N Implementierungen der VM • Vorteile: weniger Komplexität Nachteil: Effizienzverlust: Spezielle Stärken von Hardware oder Programmiersprachen werden nicht genutzt. Beispiele: Smalltalk Bytecode Interpreter, Pascal p-Maschine, Java Virtual Machine: Java Runtime-Environment auch als Zielmaschine für andere Sprachen benutzt (JPhyton, JBasic, Smalltalk/JVM) d) Java • Compilation von Java Programmen: Aus einer Textdatei mit der Endung .java erzeugt der Compiler javac(.exe) eine Datei mit gleichem Namen, aber Endung .class. Diese enthält den Bytecode für die JVM. Die Datei mit dem Bytecode wird der JVM java(.exe) übergeben und ausgeführt. 08.11.09! PI1 HWS 2009! 1 • vorsintflutlich: name.java erstellen, in der Konsole Compilieren mit dem Befehl „javac.exe name.java“ , es entsteht name.class, ausführen mit dem Befehl „java.exe name“ • modern: Verwendung von Integrated Development Environment (Programmierungumgebung). IDE integriert Editor, Compiler, VM, Debugging, Dokumentation,... Beispiele: Eclipse, BlueJ 2. Kapitel: Arbeiten mit BlueJ • viel (triviale;-)) Praxis: Video oder Skript • BlueJ: Erstellung, Fähigkeiten, Inspizieren, Entfernen von Objekten virtuell über das Kontextmenü aufrufbar a) Klassen: Rahmen einer Klasse class Klasse { } b) Objekte: • Die Erzeugung von Objekten besteht aus zwei Schritten: 1. Ein Name für das Objekt wird registriert 2. Ein neues Objekt wird erzeugt und unter diesem Namen gespeichert Klasse objekt; ! ! ! Registriere sonne für Objekt der Klasse Circle objekt = new Klasse(); ! Konstruiere ein Objekt der Klasse und nenne es objekt oder kombiniert: Klasse objekt = new Klasse( ); • Java unterscheidet zwischen Groß- und Kleinschreibung. Namen für Objekte beginnen mit kleinbuchstaben. Namen für Klassen beginnen mit Großbuchstaben. c) Methoden: Eine Methode besteht aus: • Kopf: void methodenName( ) void: Typ des Ergebnisses: kein Wert zurückgeben methodenName: Name der Methode: Konvention kleinschreiben ( ) Liste der Parameter, auch ohne Parameter setzen. • Rumpf / Block: { Folge von Anweisungen } z.B. Variabendeklaration, Zuweisungen, Schleifen, Methoden 08.11.09! PI1 HWS 2009! 2 3. Kapitel: Objekte und Klassen a) Algorithmen und Programme • Algorithmen sind Handlungsanweisungen. Elementare Aktionen werden vorausgesetzt. Ein Algorithmus beschreibt eindeutig Reihenfolge und Bedingungen der Ausführung dieser elementaren Aktionen. • Programme sind formale Beschreibungen von Algorithmen. Programme werden in einer der Aufgabe gemäßen Sprache formuliert. Programme können von Menschen oder Maschinen ausgeführt werden. (+ Definiton aus Kapitel 1) • Programme sollen alles können und alle Eventualitäten berücksichtigen. Sie werden immer größer, komplexer und unüberschaubarer. Beispiel: TollCollect, SAP Lösung: Modularisierung Objekte und Klassen b) Klassen und Objekte • Klassen sind Fabriken für Objekte, Jede Klasse kann genau einen Typ von Objekten erzeugen. Jedes Objekt gehört zu genau einer Klasse. Sie umfassen gleichartige Objekte, enthalten den Bauplan für Objekte, erzeugen Objekte. • Objekte sind kleine Programmstücke. Jedes Objekt hat spezifische Fähigkeiten. Objekte kooperieren, um eine umfangreiche Aufgabe gemeinsam zu erfüllen. Objekte modellieren Gegenstände und Akteure. Objekte haben Felder und Methoden. • Praxisbeispiel Bankkonto c) Felder • Felder = Eigenschaften/Zustand eines Objekts. Typen von Feldern: 1) primitiver Typ: der Wert eines primitiven Typen wird direkt in das Feld geschrieben. Beispiele: int, boolean, float usw. 2) Objekttyp: Referenz auf den Wert im Feld gespeichert. ohne Initialisierung: null. Objekttypen sollen großgeschrieben werden. Beispiel: String, Konto, Maler d) Methoden • Observer liefern Objektinformationen und sollen das Objekt nicht verändern. Mutator verändern das Objekt und sollen keine Informationen zurückliefern. Mutator kann man an void erkennen. Klare Entscheidung zwischen den beiden zu treffen. • Methode mit Resultat int getInformation() {return wert;} Methode mit Parameter: void setWert (int neuerWert) { wert = neuerwert;} • Den Kopf einer Methode bestehend aus Name und Parametertypen nennt man auch Signatur. Nicht entscheidend sind Ergebnistyp und Parameternamen. • Beim Aufruf einer Methode werden formale Parameter durch konkrete Werte ersetzt. 08.11.09! PI1 HWS 2009! 3 • Kommunikation zwischen Objekten: (von objekt1 auf objekt2) void methodeA (Klasse empfaenger){ empfaenger.methodeB();} zum Ausführen in objekt1: methodeA (objekt2); • Konstruktoren sind besondere Methoden. Sie dienen dazu Objekte zu erzeugen. Sie gehören zur Klasse und haben den selben Namen. Konstruktoren werden großgeschrieben! Konstruktoren haben keinen Rückgabewert. Ihr Ergebnis ist ein neues Objekt der Klasse. Eine Klasse kann mehrere Konstruktoren haben.(!Signatur) Für jede Klasse gibt es einen Default-Konstruktor. Er erzeugt ein Objekt und alle Felder werden initialisiert. (int 0, Objektfeld <null>) e) Prinzip des information hiding: Felder sind von außen(vom Benutzer) nicht mehr sichtbar/zugreifbar durch private. privater Felder stehen nicht in Javadoc. Dies sollte Standart sein, ansonsten Kommentar. Zugriff nur über kontrollierte Methoden: getter und setter sind spezielle Arten von Observer und Mutator. Vorteil: Kontrolle der Daten, interne Veränderbarkeit der Methoden - weiter nutzbar f) Kommentare • // kurze Erläuterung geht bis zum Zeilenende • /* ausführlichere Kommentare */ stehen zwischen den beiden Klammern /* */ g) Javadoc • /** Javadoc Kommentar */ javadoc.exe erzeugt daraus eine Dokumentation • Mindestkommentierung: 1. Beginn der Klasse: /**Wozu dient sie, was stellt sie bereit * @author Mark Lorch * @version 1.0 */ 2.jedes Feld: /**was wird dadrin gespeichert*/ 3.jede Methode: /**was tut sie * @param parameter1 der erste Parameter * @return rückgabe Rückgabewert der Methode */ 08.11.09! PI1 HWS 2009! 4 4. Kapitel: Klassen und Applikationen a) Klassenfelder und Klassenmethoden • Manche Felder müssen nicht in jedem Objekt gespeichert werden.(aktueller Zinssatz, nächste Kontonummer) Klassenfelder sind jedem Objekt der Klasse jederzeit zugänglich. Klassenfelder heißen in Java static. static int klassenfeld • Klassenmethoden sind nützlich um statische Felder zu manipulieren oder Observer zu implementieren, die unabhängig vom aufrufenden Objekt sind. Konstruktoren sind Klassenmethoden, die aber kein static benötigen. Aufruf möglich ohne Objekt über: Klasse.klassenmethode(); b) eingebaute Klassen benutzen: System, Math, String • Wir können vorhandene Klassen benutzen ohne sie im Detail zu verstehen. • System: Klasse mit systemnahen Feldern und Methoden. Wichtig: das statische Feld out. Es enhält ein Schreibobjekt (Printstream). PrintStreams kennen die Methode println(). System.out.println(); oder PrintStream ausgabe = System.out; dann: ausgabe.println(); • Math: Klasse mit mathematischen Funktionen und Konstanten. Math hat nur statische Felder und Methoden. Beispiele: max,min,sqrt,random,sin,log • String: Objekte sind Zeichenketten. Literale: in “ “ eingeschlossene Zeichen Ausgeben: System.out.println(); | Länge feststellen: length() | Gleichheit testen: equals() | i-tes Zeichen bestimmen: charAt() /n ist ein Zeilenumbruch im String. | Verkettung: “Hallo “ + “Welt“ Alle Java-Typen haben String-Darstellung. Umwandlung automatisch von links nach rechts. Jedes Java-Objekt erbt toString() c) this steht für das aktuelle Objekt. this.objektfeld this(), this(..) für Konstruktoren der aktuellen Klasse d) Applikation • Applikationen sind stand alone Java-Anwendung. Eine Applikation enthält mindestens eine public deklarierte Haupt-Klasse in der sich eine Methode main befindet mit der Signatur: public static void main (String[] args) {} • Starten über den Aufruf der kompilierten Klasse, die main enthält. args ist ein Array vom Typ String, der die Parameter enthält. args[0] usw. • java.exe im path, benutzte Klassen im classpath 08.11.09! PI1 HWS 2009! 5 e) jar Archiv • Man kann Verzeichnisse in ein komrimiertes jar-Archiv packen. grossprojekt.jar .jar können unausgepackt ausgeführt werden ohne das die Klassen verfügbar sind. f) Pakete • Java Klassen, die zusammengehören, sind in Pakete organisiert. Pakete sind hierarchisch organisiert. Bsp. java.lang, java.io, java.util, java.net • import paket.Klasse öffnet den Namensraum der Klasse. Alle als public deklarierten Klassen, Felder, Methoden werden sichtbar. import paket.* öffnet den Namensraum alles Klassen im Paket. import muss erste Anweisung sein noch vor class. Es macht lediglich Namen sichtbar und benutzbar, importiert aber keine Daten. • import java.util.Scanner; [...] Scanner sc = new Scanner(System.in); String name = sc.next(); int zahl = scn.nextInt(); 5. Kapitel: Daten und Operationen a) BlueJ als Taschenrechner div, mod • 26 / 7 = 3 • 26 % 7 = 5 Ganzzahl-Division div Rest der Ganzzahldivision mod • (n div d)*d + (n mod d) = n (n,d natürliche Zahlen) b) Bits, Bytes • Eine physikalische Speicherzelle kann nur einen von zwei Zuständen annehmen. Die beiden zustände werden als 0 und 1 interpretiert. Eine Gruppe von Speicherzellen kann viele Kombinationen von Zuständen speichern. ( 2 4; 4 26; 8 256;) • Die kleinste Einheit mit dem eine Computer heute rechnet ist ein Byte(8 Bit). Zwei Byte ist Wort, 4 Byte Doppelwort, 8 Byte ist Quad-Wort. Üblicherweise rechnen Computer heute intern mit 4 Byte großen Daten. (32-Bit). c) Zahlen und Zahlendarstellung • Eine Zahl (ein Zahlenwert) kann unterschiedlich dargestellt werden. Die Darstellung ist immer eine Folge von Ziffern aus einem Ziffernalphabet. Allgemein: Sei Z das Ziffernalphabet dann kann man eine Zahl als Folge von Ziffern dargestellt werden: zn zn-1 ... z2 z1 z0 mit zi aus Z • Eine Zahlendarstellung kann unterschiedliche Zahlenwerte besitzen. Übliche Umrechnung: Ziffer zi an Position i hat die Wertigkeit zi * Bi • Man kann den Speicherzuständen Zahlen zuordnen. z.b. im Binärsystem oder im Zweierkomplement. 08.11.09! PI1 HWS 2009! 6 0001 1 • Binärsystem: 0010 2 • Ziffernalphabet {0,1}, Binärzahl ist eine Folge von Binärziffern. Missverständnisse (x)2 Berechnung des Zahlenwertes anhand der 0011 3 0100 4 Ziffer an der Position i hat die Wertigkeit zi * 2i 0101 5 0 ≤ x ≤ 28-1 (255); 2 Byte 0110 6 0111 7 1000 8 1001 9 1010 10 = A 1011 11 = B 1100 12 = C 1101 13 = D 1110 14 = E 1111 15 = F d) Binärzahlen, Hex-Zahlen, Dezimalzahlen Wertigkeit der einzelnen Ziffern: 1 Byte 0 ≤ x ≤ 216-1 • Zweierkomplement: Darstellung von negativen Zahlen im Binärsystem. oberstes/linkstes Bit gibt das Vorzeichen an Umwandlung: Negation und +1 1 Byte(28) -27 ≤ x ≤ 27-1 (-128,127); 2 Byte(216) -215 ≤ x ≤ 215 -1 byte,short,int,long sind als Zweierkomplement gespeichert. führende Einsen statt führenden Nullen 210 29 28 27 26 25 24 23 22 21 20 1024 512 256 128 64 32 16 8 4 2 1 • Hexadimalzahlen Ziffernalphabet {0-9,A,B,C,D,E,F}, Missverständnisse ()16 Berechnung des Zahlenwertes anhand der Wertigkeit der einzelnen Ziffern: Ziffer an der Position i hat die Wertigkeit zi * 16i • Umrechnungen B-System Dezimalsystem (zn,zn-1,..,z1,z0)B = zn * Bn + zn-1 * Bn-1 + ... + z1 * B1 + z0 * B0 = (x)10 • Umrechnung Dezimalsystem div B (x)10 B-System mod B xneu z0 xneu ... • Umrechnung 2 ... 0 zn 8 (23) bzw. 16(24) jeweils 3 bzw 4 Zeichen zusammenfassen und ins neue System führen • Umrechnung 8 (23) bzw. 16(24) 2 ein Zeichen auf 3 bzw. 4 Zeichen im Binärsystem schreiben • Rechnen in anderen Zahlensystemen 08.11.09! PI1 HWS 2009! 7 e) ganzzahlige Datentypen • Ganze Zahlen in Java (gespeichert im Zweierkomplement) Die Datentypen sind mit unterschiedlich viel Speicher abgespeichert. Sie haben einen begrenzten Zahlenbereich. Dies kann zu Bereichsüberschreitungen führen. byte 1 Byte = 8 bit -27 ≤ x ≤ 27-1 27 = 128 short 2 Byte = 16 bit -215 ≤ x ≤ 215-1 215 = 32768 int 4 Byte = 32 bit -231 ≤ x ≤ 231-1 231 = 2147483648 long 8 Byte = 64 bit -263 ≤ x ≤ 263-1 9223372035854775808 • Konversion: Werte aus einem Bereich können in Werte des anderen konvertiert werden. • Implizite Konversion: (Ganze Zahlen) Konversion immer mindestens nach int. Verknüpfung von Werten aus verschiedenen Bereichen konvertiert automatisch in den größeren. x++/x-- wird nicht auf Bereichsüberschreitung kontrolliert. (kein impliziter Cast) Implizite Konversion erfolgt, wenn kein Werteverlust zu befürchten ist. • Explizite Konversion: (Ganze Zahlen) Konvertierung in einen zu kleinen Bereich ist möglich. Gefahr: Informationsverlust muss durch Voranstellen des gewünscht Typs „autorisiert“ werden Interne Regel der JVM: Bytes werden abgeschnitten. • Konversion negativer Zahlen (Zweierkomplement) Implizite Konversion: Vorzeichen wird erweitert (1 oder 0 „gestreckt“) Explizite Konversion: Vorzeichen entsteht aus dem obersten Bit der neuen Binärzahl f) Datentypen für Dezimalzahlen • Man speichert explizit: das Vorzeichen, die Folge der Ziffern (Mantisse), die Position des Kommas(Exponent) im Binärensystem. float 4 Byte = 32 bit Vorzeichen 1 bit Mantisse 23 bit Exponent 8 bit double 8 Byte = 64 bit Vorzeichen 1 bit Mantisse 52 bit Exponent 11 bit • Literale: 3.14 0.14 .14 1.0 243E-12 1.5E17 standard: double • Implizite Konversion (Dezimalzahlen) automatische Umwandlung in den gemeinsamen Type (z.B. int-->double) • Explizite Konversion (Dezimalzahlen) cast: schneidet Nachkommastellen ohne Prüfung ab, Informationsverlust! 08.11.09! PI1 HWS 2009! 8 • Fehler bei Dezimalarithmetik. Werte werden approximiert. 0.1 + 0.2 ≠ 0.3 • Vergleich von Dezimalzahlen mit == sind ungenau Rundungsfehler einrechnen: double wert = 0.1 + 0.2; // Ergebnis einer komplexen Berechnung double zielwert = 0.3; // Wert, mit dem verglichen werden soll // erlaubte Abweichung double epsilon = 0.001; if ( Math.abs( wert - zielwert ) < epsilon ) { ... } Falls Größenordnung des Zielwertes unbekannt, Abweichung als Prozentsatz des Ziel wertes angeben : if ( Math.abs( wert - zielwert ) < epsilon * zielwert ) g) Boolesche Werte, Boolesche Algebra (sh auch Kapitel 6 Aussagenlogik) • Java Datentyp boolean : Literale true, false also genau 2 Werte Operationen: ! not, && und , || oder || und && werden verkürzt (lazy) ausgewertet also false && xx und true || xx • Basisoperationen NOT, AND, OR ¬ ⋀ F W ⋁ F W W F F F F F F F F W W F W W F W • abgeleitete Operationen WENN DANN, GENAU DANN WENN, XOR x y := ¬ x ⋁ y F W F W x ⊕ F W y := (x ⋀ y) ⋁ (¬x ⋀ ¬y) F W W F W F F F W x⊕y := (x ⋀ ¬y) ⋁ (¬x ⋀ y) W F W W F W W W F • Rechenregeln der Boolschen Algebra idempotent x⋁x=x x⋀x=x kommutativ x⋁y=y⋁x x⋀y=y⋀x assoziativ x ⋁ (y ⋁ z) = (x ⋁ y) ⋁ z x ⋀ (y ⋀ z) = (x ⋀ y) ⋀ z absorptiv x ⋁ (x ⋀ y) = x x ⋀ (x ⋁ y) = x de Morgan ¬ (x ⋁ y) = ¬x ⋀ ¬y ¬ (x „and“ y) = ¬x ⋁ ¬y Komplement x ⋁ ¬x = true x ⋀ ¬x = false doppelte Negation ¬¬x=x 08.11.09! PI1 HWS 2009! 9 • Bitoperationen: Variante der boolschen Operationen, die auf den Bits von Werten arbeitet. Auf bollschen Werten stimmt das Ergebnis mit den normalen Operationen überein, allerdings wird nicht lazy ausgewertet. 13 & 6 = 4 13 | 6 = 15 13 ^ 6 = 11 1 << 2 = 4 8 >> 2 = 2 (1101)2 (1101)2 (1101)2 (0001)2 (1000)2 & (0110)2 | (0110)2 ^ (0110)2 << 2 >> 2 (0100)2 (1111)2 (1011)2 (0100)2 (0010)2 h) Zeichen, Unicode, Fonts • Zeichen dienen nicht nur zur Darstellung von Text Buchstaben, Ziffern, Sonderzeichen, nichtdruckbare Zeichen: z.B.Zeilenumbruch, Tab • Unicode benutzt eine 2-Byte Codierung für Zeichen. 216 Zeichen z.B. europäische Zeichen, griechisch, kyrillisch, arabisch. Java unterstützt Unicode. • Im Java Datentyp char werden Zeichen abgespeichert. Literale: ʻaʻ ʻAʻ ʻ\nʻ neue Zeile ʻ\tʻ Tab ʻ\bʻ backspace ʻ\rʻ return ʻ\\ʻ backslash Unicode: 4 Hex oder 3 Oktalziffern: ʻ\uFFFFʻ char wird bei Bedarf zu int implizit konvertiert. char kann als vorzeichenloses short gesehen werden, da keine Vorzeichenerweiterung bei der impliziten Konversion. (byte) -1 (char) (int) 1111 1111 „-1“ 1111 1111 1111 1111 „-1“ 0000 0000 0000 0000 1111 1111 1111 1111 216-1 = 65535 1111 1111 „-1“ 1111 1111 1111 1111 „-1“ 1111 1111 1111 1111 1111 1111 1111 1111 „-1“ (byte) -1 (short) (int) 08.11.09! PI1 HWS 2009! 10 6. Kapitel: Ausdrücke a) Variable, Deklaration & Initialisierung • In Variablen kann man Werte speichern und den Wert lesen. Sie sind temporäre Behälter. • Variablennamen sind weitgehend frei wählbar. Schlüsselwörter sind zu vermeiden (class, public, static, int...) keine Ziffer an der ersten Stelle. Groß-und Kleinschreibung beachten. Konventionen: Variablennamen beginnen mit Kleinbuchstabend, zusammengesetzt wortWort • Variablentyp beschreibt den Wertebereich d.h. die Menge von Werten die angenommen werden dürfen. Variablen verschiedener Typen brauchen verschieden viel Speicherplatz. Die Typen erlauben dem Rechner Speicherplatz zu reservieren. Typen helfen Programmierfehler zu vermeiden. z.B. age = thisYear * 3.14 • Deklaration Syntax: Typname Variablenname ; Typ Name, Name, Name ; • Deklaration mit Initialisierung: Syntax: Typname Variablenname = Wert; Typ Name = Wert, Name = Wert; • null = Nullreferenz (für jeden Objekttyp) • Felder in Klassen sind spezielle Arten von Variablen. Sie werden auf die selbe Art deklariert, aber automatisch initialisiert. b) Kontext • Für jede Variable gibt es einen Kontext (Umgebung). Ein Kontext wird durch eine aktuelle Belegung von Variablen gegeben. Für jede Variable benötigt man Typ und Wert. • Typ und Wert eines Ausdrucks hängt vom gegenwärtigen Kontext ab, in den man ihn schreibt. Bsp: Ausdruck x/y int x = 2, y = 10; x/y = 0 int x = 2; double y = 10.0; x/y = 0.2 • In Java begrenzen {...} einen Kontext. Variablen sind nur in ihrem Kontext gültig. Bei einem geschachtelten Kontext sind äußere Variablen innen sichtbar und dürfen nicht neu deklariert werden. Innere Variablen sind von außen unsichtbar. c) Ausdruck • Ein Ausdruck ist eine korrekt gebildete Formel aus Konstanten, Variablen, Operationszeichen und Klammer (Syntax). In einem Kontext, der alle Variablen des Ausdrucks enthält, lieder ein Ausdruck einen eindeutigen Wert mit eindeutigem Typ (Semantik). 08.11.09! PI1 HWS 2009! 11 • Rekursive Defintion eines int-Ausdrucks und eines boolschen Ausdrucks in Java ➝ Kap 8! • Definition eines Baumes (mathematisch) • Syntaxbaum nutzt man zur Korrektheitsanalyse eines Ausdrucks. • Präzendenzen sind Regeln um Klammern zu sparen. Sie sagen aus, welche Operatoren stärker binden, das heißt welche Operanten zu erst berechnet werden. In Java: • Punkt vor Strich • && vor || • einstellige Operatoren (!x, -x) vor zwei Operatoren • Linksklammerung bei gleicher Präzendenz 08.11.09! PI1 HWS 2009! 12 • Präzedenztabelle d) Syntax und Semantik • Syntax regelt die Bildung korrekter Ausdrücker. Legalität des Ausdrucks. • Semantik regelt die Bedeutung(=Wert) korrekt gebildeter Ausdrücke. definiert über eine Funktion W: Ausdruck Wert • Bedingte Ausdrücke: Falls B dann E1 sonst E2: B ? E1 : E2 B boolscher Ausdruck, E1, E2, beliebiger Typ aber gleich • Semantik boolscher Operationen W(E1 || E2) := (W(E1) ? true : W(E2) W(E1 && E2) 08.11.09! := (!W(E1) ? false : W(E2) PI1 HWS 2009! 13 e) Seiteneffekte • Von Seiteneffekten spricht man, wenn die Ausdrucksauswertung den Kontext verändert, d.h eine Variable während der Auswertung verändert wird. Dadurch werden mathematische Regeln verletzt, die nur in einem festen Kontext gelten. Bsp x++ Seiteneffekte in Ausdrücken sind in Java erlaubt aber für die Programmierung in der Vorlesung verboten. f) Exkurs in die Aussagenlogik • Die Aussagenlogik behandelt einfache Verknüpfungen wie „und“ und „oder“ zwischen atomaren sprachlichen Gebilden. • Syntax: Literale: WAHR und FALSCH Variablen A,B,C als Symbole für atomare Aussagen Die Operatoren sind die der Boolschen Algebra. Rekursive Definition einer Formel: Literale und Aussagenvariablen sind Formeln Wenn F ist Formel, ¬F ist Formel F und G Formeln, dann F⋀ G und F ⋁ G Formeln F Formel dann (F) Formel F G sei ¬F ⋁ G und F G sei ( F ⋀ G) ⋁ (¬F ⋀ ¬G) • Semantik Elemente der Menge {0,1} heißen Wahrheitswerte. Eine Belegung bildet die Aussagenvariable auf Wahrheitswerte ab. Semantik einer Formel durch Funktion W: Formel ➝ {0,1} : Für A ist W(A) die Belegung von A. Für E,F beliebige Formeln gilt: W (E ⋀ F) = 1 wenn W(E) und W(F)=1 sonst 0 W (E ⋁ F) = 1 wenn W(E) oder W(F)=1 sonst 0 W (¬E) = 1 wenn W(E) = 0 sonst 0 • Beispiel g) X fährt nach Spanien-Beispiel in Video 6b ab ca. 1:02:40 08.11.09! PI1 HWS 2009! 14 7. Kapitel: Algorithmische Kernsprache a) Ausdrücke und Anweisungen • Ausdrücke bezichnen einen Wert. Der Kontext legt den Wert von Variablen fest. Werte werden mit Operationen verknüpft. Der Kontext soll durch Ausdrücke nicht verändert werden. • Anweisungen verändern den Kontext. Anweisungen liefern keinen Wert. Anweisungen haben einen Effekt. Anweisungen enden mit Semikolon. • Zuweisung als eine primitive anweisung. Syntax: v = E; v eine vorher deklarierte Variable. E ein zum Typ v kompatibler Ausdruck Semantik: Berechne den Wert von E im Kontext und speichere ihn in v. Varianten: v += E; v -= E; v *= E; v /= E; v %= E; v++; v--; v = v + E; v = v - E; v=v*E v = v / E; v = v % E; v = v +1; v = v - 1; • Einfache Ausdrücke sind Ausdrücke mit Seiteneffekt. z.B. x = 15 oder x++ . Sie dürfen überall stehen, wo Ausdrücke erlaubt sind. Java vermischt Anweisungen und Ausdrücke. Einfache Ausdrücke werden als Fehler gewertet. Semikolon macht aus einem einfachen Ausdruck eine Anweisung. • Deklaration ist Anweisung. Eine Deklaration erweitert den Kontext. Sie werden mit ; beendet. • Initialisierung ist eine Zuweisung. Empfehlung: auch Felder initialisieren. b) Anweisungsformen: Blöcke, Alternativ- und bedingte Anweisungen, Schleifen • Block ist eine Folge von Anweisung. Ein Block ist selbst eine Anweisung, daher auch Schachtelung möglich. Block definiert einen neuen Kontext. Variablen, die in einem Block deklariert werden, sind nur dort gültig. Block: {Anw1 Anw2 Anw3} • Bei Alternativanweisungen wird eine der Anweisungen ausgeführt, je nachdem ob die Bedingung wahr oder falsch ist. Syntax: if (Bedingung) Anw1 else Anw2 Bedingung boolscher Ausdruck | Anw sind Zuweisungen, Blöcke, bedingte Anweisungen... • Bedingte Anweisung ist ein Sonderfall der Alternativanweisung. Nur bei wahrer Bedingung wird die Anweisung ausgeführt. Syntax: if (Bedingung) Anw • Schachtelung bedingter Anweisungen: else bezieht sich in der Regel auf das letzte vorhergende unergänzte if. 08.11.09! PI1 HWS 2009! 15 • while-Schleife: solange eine Bedingung wahr ist, wird eine Anweisung wiederholt. Syntax: while (Bedingung) Anweisung Anweisung wird auch Rumpf oder Körper genannt. Schleifen können 0, endlich oder unendlich mal ihren Rumpf ausführen. • Methoden: Deklaration: Resultattyp Name ( Parameterliste) { Anw } Aufruf: Name(Parameterwerte); Aufruf von Methoden mit Rückgabewert sind Ausdrücke. Sie können stehen wo Ausdrücke des Rückgabewertes möglich sind. • Prozeduren: Methoden ohne Rückgabewert, Ziel ist es Effekt zu erzeugen. Deklaration: void Name ( Parameterliste) { Anw } Aufruf: Name( Parameterwerte); Aufruf einer Prozedur ist eine Anweisung. Sie können überall stehen wo Anweisungen möglich sind. • return beendet eine Methode sofort und liefert den Rückgabewert. Methoden mit Rückgabewert müssen return-anweisung haben, Prozeduren können eine return-Anweisung haben (return ;) c) degugging • Klick in die linke Spalte des Editors (nach dem Compilieren) ➝ Breakpoint Beim Ausführen öffnet sich Debugger mit dem man schrittweise durch das Programm gehen kann. Im Debuggerfenster sieht man den aktuellen Inhalt aller Variablen. Schritt hinein: geht in Methode hinein | Schritt über: geht in die nächste Zeile 8. Sprachbeschreibung und Erweiterung a) Worte, Sprachen • Formale Sprachen haben 3 Facetten: Syntax: textuell akzeptable Elemente der Sprache Semantik: Was leistet ein Programm? möglichst mathematisch definierbar Pragmatik: Wie sollte man ein Programm schreiben? (keine Pflicht) Programmiersprachen sind zwar seh präzise aber nicht besonders ausdrucksstark. • natürliche Sprache: syntaktisch falsche Sätze, die semantisch erkennbar sind oder syntaktisch richtig Sätze, die falsch sind ➝ sehr flexibel, ausdrucksstark, aber unpräzise • Die lexikalische Ebene definiert die erlaubten Worte der Sprache. (BNF, Automaten) Die grammatische Ebene definiert, wie Worte zu korrekten Sätzen zusammgefügt werden dürfen. (EBNF, Syntaxdiagramme) 08.11.09! PI1 HWS 2009! 16 b) reguläre Ausdrücke, BNF (Backus-Naur-Form), Automaten • Ein Alphabet Σ ist eine Menge von Zeichen (lateinisches Alphabet, ASCII, Unicode) Ein Wort über Σ ist eine beliebige Folge von Zeichen aus Σ. ( abcdjfkd, 0111001) Das Wort der Länge 0 heißt leeres Wort oder ε. Eine Sprache über Σ ist eine Menge von Worten über Σ. (alle deutschen Wörter, floatLiterale) • Reguläre Ausdrücke dienen zur kompakten und präzisen Beschreibung der Wörter einer Sprache. • Rekursive Definition der Syntax: Literal: Jedes Zeichen aus dem Alphabet Σ. Wenn A und B reg. Ausdrücke dann auch: (A) A* A? A.B A|B • Die Semantik eines regulären Ausdrucks ist eine Sprache also Menge von Worten über Σ Rekursive Definition der Semantik: W: regulärer Ausdruck ➝ Sprache über Σ a∈Σ dann W(a) = {a}. Sei A ein regulärer Ausdruck dann: W((A)) = W(A) W(A*) W(A?) = = W(A) beliebig häufig W(A) optional W(A.B) = W(A) konkateniert W(B) W(A|B) = W(A) oder W(B) • Präzedenz * ? (einstellig) ➝ . („und“) ➝ | („oder“) (hoch➝ tief) • Reguläre Definitonen (BNF) sind eine Erweiterung der regulären Ausdrücke um einen Makro-Mechanismus. Eine reguläre Definition ist eine Gleichung: < def > ::= regulärer Ausdruck <float-literal> ::= <ziffer>* , <zahl>(e(+|-)?<Zahl>)? def kann danach wie ein Zeichen verwendet werden, rekursive Definitionen nicht erlaubt! • Reguläre Definition eigenen sich gut als Formalismus um die zulässigen Worte einer Sprache zu beschreiben. Es gibt aber Sprachen die nicht durch reguläre Definitionen beschreibbar sind. Beispiel: korrekte Klammerung, anbn • Automaten sind eine alternative zu regulären Definitionen. Automaten bestehen Knoten und Pfeilen als Übergänge. Es gibt einen Anfangsknoten und einen oder mehrere Endknoten. 08.11.09! PI1 HWS 2009! 17 c) Kontextfreie Grammatik(EBNF), Syntax-Diagramme • Zur Beschreibung von Programmen benötigt man einen mächtigeren Formalismus als reguläre Definitionen. Bei der Kontextfreien Grammatik ist die Rekursion erlaubt. EBNF = BNF + Rekursion , Syntaxdiagramme = Automaten + Rekursion < def > ::= regulärere Definition • Syntax-Diagramme Grafische Darstellung für kontextfreien Grammatiken. Sie ähneln Automaten, aber die Zustände tragen die Beschriftung. Pfeile ohne Beschriftung rund: terminal, eckig: nonterminal ein Eingang, ein Ausgang, Rekursion erlaubt d) Java-Spracherweiterung: do, for, break, continue, switch • Prinzipiell benötigt man nur Zuweisung, Blöcke, Bedingte Anweisung, While-Schleife. Jeder Algorithmus ist damit programmierbar. • do-while-Schleife: Schleifen, deren Körper mindestens einmal ausgeführt wird. Syntax: do anweisung while (bedingung); • for-Schleife Schleifen mit Zähler Syntax: for ( int i = 0; bedingung; i++;) anweisung Sonderfall: for (;B;)A entspricht while(B)A Beispiel mit geschachtelten Schleifen 08.11.09! PI1 HWS 2009! 18 • break Semantik: beendet sofort die Schleife bzw switch-Anweisung (erlaubt: while,do,for,switch) Syntax: break; sinnvoll, wenn z.B. ein Element gefunden wurde oder der Rest keinen Sinn mehr macht • continue Semantik: bricht den Schleifendurchlauf ab und beginnt den nächsten Schleifendurchlauf Syntax: continue; Beispiel • Fallunterscheidung switch Syntax: switch (<expr>) { <fall>* default? } <fall> ::= case <wert> : <anweisung>* (incl break;/return; in der Regel) <default> ::= default: <anweisung>* <expr> vom Typ byte, short, int, long, char Semantik: Wenn ein case passt, werden die dazugehörigen Anweisungen und die der folgenden Fälle ausgeführt, bis ein break; oder return; angetroffen wird. 08.11.09! PI1 HWS 2009! 19 9. Kapitel: Objekttypen a) Referenzen, Objekte • Primitive Datentypen benötigen einen vorher genau bekannten Speicherplatz. Es gibt aber Objekte, die unvorhersehbar viel Speicherplatz verbrauchen. (z.B. String) • In einer Objektvariable wird nur Verweis (Referenz) auf das wirkliche Objekt gespeichert. Die Java VM verwaltet den Platz für Objekte (zusätzlicher Platz, Garbage Collection) Müll entsteht wenn keine Verweis mehr auf ein Objekt zeigt. • Der Programmierer hat stets nur einen Verweis auf das Objekt zur Verfügung. Beim Zugriff auf Objektfelder folgt Java automatisch dem Verweis. b) Gleichheit • Beim Zuweisen ganzer Objekte werden nur die Referenzen übernommen. Wenn zwei Referenzen auf das selbe Objekt zeigen, kann jeder die Felder des anderen beeinflußen. Ein Name ist ein Alias für den anderen. • Der Vergleich mit == oder != prüft nur, ob die Verweise auf das selbe Objekt zeigen. • Für den inhaltlichen Vergleich ist eine Methode equals vorgesehen. Mit Signatur public boolean equals(Object z) wird von sie vom Object geerbt und ist für alle Objekte verfügbar. c) Wrapper-Klassen • Basis-Datentypen sind keine Klassen. Objekte dieser Basis-Klassen sind keine Objekte im Sinne des OO-Progammierens Vorteil: direkter Zugriff ohne Referenz und vereinfachte Erzeugung ohne new Nachteil: keine Objekte, viele Behälter-Strukturen(ArrayList) können nur Objekte aufnehmen. ➝ Für jede Basisklasse gibt es eine entsprechende Wrapper-Klasse. Eine Wrapper-Klasse „verpackt“ den Wert des Basistyps in ein Objekt. Ein Objekt der Wrapper-Klasse hat genau ein Feld des entsprechenden Datentyps. Integer i = new Integer(10); i.intValue() ➝ 10 • Autoboxing: Automatische Umwandlung zwischen Basisklassen und Wrapperklassen. 08.11.09! PI1 HWS 2009! 20 d) Arrays • Arrays sind Objekte, die Folgen fester Länge, die gleichartige Variablen enthalten. • Deklaration: int[] zahlen; char[] wort; Deklaration mit Initialisierung: int[] x = {1,2,3,4}; Deklaration mit Erzeugung: int[] intArray = new int[10]; • Länge eines Arrays: int lang = intArray.length; • Suche im Array int position = 0; • Array durchlaufen: Wuerfel W = new Wuerfel(); for (int k=0; k<lang; k++) { for (int k=0; k<lang;k++) { W.wuerfeln(); if (intArray[k] == 6) { intArray[k] = position = k; break; W.getAugenzahl(); } . } e) mehr-dimensionale Arrays • Deklaration: int[][] matrix; Deklaration mit Initialisierung: int[][] x = {{1,2,3},{2,3,4}}; Deklaration mit Erzeugung: int[] intArray = new int[2][3]; • Mehrdimensionale Arrays sind Arrays von Arrays. Bsp: ein zweidimensionaler Array ist ein Array von Zeilen ( array[zeile][spalte] ) f) krumme Arrays • verschieden lange Arrays können den gleichen Typ haben, z.B. int[] für int[3]int[17] ➡ Eine Matrix kann verschieden lange Zeilen haben. (Array von Array ➝ int [] []) • Durchlaufen eines Schief-Arrays: ! for (int zeile = 0; zeile < schiefArray.length; zeile ++) " " for (int spalte = 0; spalte < schiefArray[zeile].lenght;spalte++) " machwasmit (schiefArray[zeile][spalte]); • Arrays sind Objekte. Array-Variablen verweisen auch auf Referenzen. Die Zuweisung = ändert also auch nur die Zuweisung. Selber Effekt wie bei z.B. String ➝ „Alias“ 08.11.09! PI1 HWS 2009! 21