SWE-10b 1.1. Aufgabenbeschreibung und Algorithmus wohl-spezifizierte Aufgabenbeschreibung: legt das gewünschte Eingabe-/Ausgabe-Verhalten fest Eingabe: Zahl1 und Zahl2 Ausgabe: zuerst die Summe und danach das Produkt beider Zahlen Algorithmus: Berechnungsverfahren für wohl-spezifizierte Aufgabenbeschreibung lies Eingabe Zahl1 und lies Eingabe Zahl2 berechne Summe beider Zahlen gib berechnete Summe aus berechne Produkt aus Zahl1 und Zahl2 gib berechnetes Produkt aus SWE-10c Programm: Codierung eines Algorithmus in einer Programmiersprache class Summe_und_Produkt { public static void main ( String[ ] args ) { int zahl1 , zahl2 , summe , produkt ; } } // nötiger Rahmen // hier geht es los // Variablen deklarieren // ... Hier zahl1 und zahl2 einlesen ... // einlesen summe = zahl1 + zahl2 ; System . out . println ( summe ) ; produkt = zahl1 * zahl2 ; System.out.println ( produkt ) ; // Summe berechnen // Summe ausgeben // Produkt berechnen // Produkt ausgeben SWE-11 Warum Java als erste Programmiersprache? • konsequent objektorientiert, klassenbasiert • statisch typisiert: Übersetzer prüft typkorrekte Benutzung der Sprachkonstrukte (wie z. B. in Pascal, C++) • Java ist weit verbreitet und leicht verfügbar; Java-Programme sind portabel. Übersetzung in die Zwischensprache (Java Bytecode) einer abstrakten Maschine (JVM: Java Virtual Machine). Sie interpretiert das Programm (wie in Smalltalk). Das ist portabel aber weniger effizient als die Ausführung von Maschinen-Code. • Umfangreiche Klassenbibliotheken (API: Application Programming Interface). • Programmierung für das WWW (Applets, Netzzugriffe, Laden von Modulen) • Aber: Java ist noch jung und verbreitet sich stürmisch. © 1999 bei Prof. Dr. Uwe Kastens Zukünftig notwendige Sprachänderungen können teuer werden. SWE-12 Beispiel: Welcome class Welcome { - Rahmen /* Welcome to Java! Program by J M Bishop Dec 96 Illustrates a simple program displaying a message. */ - zweizeiliger Kommentar public static void main (String [] args) { System.out.println(”Welcome to Java”); } } © 1999 bei Prof. Dr. Uwe Kastens Figure 2.1 Welcome to Java! - Hauptprogramm - Aufruf einer Ausgabefunktion SWE-16 Ausführung von Java-Programmen Editor Quellmodul m1.java JavaÜbersetzer m2.class m1.class m3.class Java Modulbibliotheken auf Rechnern am Internet Zielmodule in Java-Bytecode Internet © 1999 bei Prof. Dr. Uwe Kastens Browser Eingabe Java-Bytecode Interpretierer Ausgabe Java-Bytecode ist maschinenunabhängig und wird von einem Interpretierer-Programm ausgeführt SWE-17 Variable und Zuweisung Eine Variable ist ein Name im Programm für eine Stelle im Speicher, die einen Wert enthält. Eine Zuweisung bestimmt oder ändert den Wert einer Variablen. Eine Deklaration bindet Namen an neue Variable. Sie können nur Werte des angegebenen Typs aufnehmen. Die Bindung gilt nur in einem bestimmten Bereich des Programms (Gültigkeitsbereich). Die Variablen existieren im Speicher nur für eine bestimmte Zeit (Lebensdauer). Formen von Variablendeklarationen: Typ Name; Typ Name1, Name2, ...; int year; double cDegree, fDegree; © 1999 bei Prof. Dr. Uwe Kastens Zuweisungen: Variable = cDegree = fDegree = cDegree = Typ int Name = Initialwert; msgNo = 1; Ausdruck; 10.0; cDegree * 9 / 5 + 32; cDegree + 10; Variable und Zuweisungen sind das Grundprinzip imperativer Sprachen: Der Programmzustand wird bestimmt durch eine Menge von Variablen mit ihren Werten. Zuweisungen im Programmablauf verändern den Zustand. SWE-24 Datentypen Ein Datentyp bestimmt eine Wertemenge und Operationen darauf. Datentypen in Java: numerische Werte: logische Werte: Zeichen: Objektreferenzen: byte, short, int, long, float, double boolean char Name einer Klasse (oder eines Interface) Eine Variable hat einen Typ, d. h. sie kann Werte aus der Wertemenge aufnehmen. Ein Ausdruck hat einen Typ, d. h. seine Auswertung liefert einen Wert aus der Wertemenge. © 1999 bei Prof. Dr. Uwe Kastens Literale: Notation für Werte im Programmtext, z. B. 127 ’?’ null Operatoren verknüpfen Werte bestimmter Typen, z. B. Operator Signaturen Typen der Operanden -> Ergebnistyp + int × int -> int long × long -> long float × float -> float double × double -> double String × String -> String Der Operator + ist hier mit fünf Bedeutungen überladen; sie werden an den Operandentypen unterschieden. SWE-25 Logische Werte Typname: Werte: boolean true false Vergleichsoperatoren liefern Werte vom Typ boolean: == != > < >= <= logische Operatoren verknüpfen Werte vom Typ boolean: und oder ausschließendes oder nicht & | ^ ! Beispiele: © 1999 bei Prof. Dr. Uwe Kastens boolean istRentner, istJugendlich, hatArbeit, freierEintritt; int alter; ... istRentner = alter >= 65; freierEintritt = (istRentner | istJugendlich) & !hatArbeit; Operatoren und, oder mit Kurzauswertung, d. h. wenn der linke Operand das Ergebnis bestimmt, wird der rechte nicht mehr ausgewertet: && || Beispiel: anzahl != 0 && summe / anzahl > 10 Ausgabe logischer Werte: System.out.println ("It is " + hatArbeit + " that he is employed"); It is true that he is employed SWE-26 Zeichen Typname: Wertemenge: Literale: char einzelne Zeichen aus einem Zeichensatz (Unicode) ’a’ ’?’ Der Zeichensatz enthält Buchstaben, Ziffern, Sonderzeichen, z. B. ’B’ nicht druckbare Zeichen mit spezieller Bedeutung, z. B. ’\b’ und viele Zeichen aus nicht-lateinischen Schriften, z. B. Der Zeichensatz ist geordnet, z. B. ’\t’ ’⊗’ ’6’ ’#’ ’ ’ ’\n’ ’\u2297’ für ⊗ ’a’ < ’b’ © 1999 bei Prof. Dr. Uwe Kastens Werte vom Typ char nicht verwechseln mit Zeichenreihen! Das sind Objekte der Klasse String. Es gibt Literale für String-Objekte, z. B. "Welcome" "#" SWE-27 Numerische Typen Typname byte short int long float double Literale: Speicher (Bits) 8 16 32 64 32 64 kleinster Wert -128 -32768 -2147483648 < - 1018 < -1038 < -10308 int: 123 077 0xff float: 3.14f 6.022e+23f größter Wert 127 32767 2147483647 > 1018 > 1038 > 10308 long: 21L double: 3.14 1e137 1e-9d numerische Operatoren: + - * / % (modulo) - (unär) Signaturen: int × int -> int float × float -> float long × long -> long double × double -> double © 1999 bei Prof. Dr. Uwe Kastens Konversion (allgemein, nicht nur numerisch): Wandlung eines Wertes eines Typs in einen entsprechenden Wert eines anderen Typs. implizite Konversion, wenn nötig: byte -> short -> int -> long -> float -> double explizite Konversion durch Type Cast: float kilograms; double estimate = 45; kilograms = (float) (estimate * 1.2); SWE-29 Iteration mit for-Schleifen for-Schleifen dienen zur Formulierung iterativer Berechnungen. Sie haben die Form: for ( Initialisierung; Bedingung; Fortschaltung) { Schleifenrumpf } Ausführung: Initialisierung: Deklaration(en) oder Zuweisung(en) für Schleifenvariable; Deklarationen sind in der ganzen Schleife gültig. Initialisierung Bedingung Bedingung: logischer Ausdruck, Vorbedingung für die (erneute) Ausführung des Schleifenrumpfes Schleifenrumpf Fortschaltung: Anweisungen, die die Werte der Schleifenvariable(n) ändern Fortschaltung © 1999 bei Prof. Dr. Uwe Kastens Beispiel: for (int zaehler = 0; zaehler < 5; zaehler++) { System.out.println ("******"); } Eine Schleife terminiert, wenn es einen Wert gibt, der in jeder Iteration monoton wächst (fällt) und nach oben (unten) begrenzt ist. SWE-30 Präzedenz von Operatoren © 1999 bei Prof. Dr. Uwe Kastens Die Präzedenz von Operatoren bestimmt die Struktur von Ausdrücken. Ein Operator höherer Präzedenz bindet die Operanden stärker als ein Operator geringerer Präzedenz. Mit der Tabelle unten gilt z. B. a + b * c ist gleichwertig zu a + (b * c). unäre Operatoren ~ ! -- ++ + - cast * / % + >> << >>> < > <= >= instanceof == != & ^ | && || bedingter Ausdruck b ? e1: e2 Zuweisung hohe Präzedenz geringe Präzedenz Bei gleicher Präzedenz bindet der linke Operator stärker als der rechte (außer bei Zuweisungen und bedingten Ausdrücken), z. B. a - b + c ist gleichwertig zu (a - b) + c SWE-31 Elementare Anweisungsformen • Zuweisung: Variable = Ausdruck; • Alternative: if (Bedingung) Anweisung else Anweisung Die Bedingung wird ausgewertet; ergibt sie wahr, so wird die erste sonst die zweite Anweisung ausgeführt. if (Bedingung) Anweisung Die Anweisung wird nur ausgeführt, wenn die Bedingung Beispiel: wahr liefert. Größter gemeinsamer Teiler © 1999 bei Prof. Dr. Uwe Kastens • Schleife: while (Bedingung) Anweisung { int a, b; Solange die Auswertung der Bedingung wahr ergibt, a = Text.ReadInt(in); wird die Anweisung ausgeführt. b = Text.ReadInt(in); do Anweisung while (Bedingung); Die Anweisung wird ausgeführt und solange wiederholt, while (a != b) wie die Bedingung wahr liefert. { • Folge (Block): { Anweisung ... Anweisung } if (a > b) Die Anweisungen (und Deklarationen) werden a = a - b; nacheinander ausgeführt. Der Block kann für eine else b = b - a; Anweisung stehen. } • Aufruf: Funktionsname (Parameterausdrücke); System.out.println(a); Die Ausdrücke werden ausgewertet und } die Funktion mit den Parameterwerten aufgerufen. SWE-32 Funktionen (Methoden) Übersicht: • Funktionen dienen zur Gliederung von Programmen. Eine Funktion soll eine übersichtliche Teilaufgabe erledigen. • Eine Funktion kann Parameter verwenden, deren Werte erst im Aufruf angegeben werden. • Eine Funktion berechnet ein Ergebnis und/oder verändert den Zustand in ihrer Umgebung. • Methoden sind Funktionen, die auf den Variablen von Objekten (oder Klassen) operieren. Funktionsdeklaration: Modifizierer Ergebnistyp Funktionsname static double (formale Parameter) Block toFahrenheit (double celsius) { return celsius * 9 / 5 + 32;} © 1999 bei Prof. Dr. Uwe Kastens Funktionsaufruf: Funktionsname (aktuelle Parameter) double cDegree = 10; double fDegree; fDegree = toFahrenheit (cDegree); System.out.println (toFahrenheit (cDegree+10)); SWE-33 Aufruf, Parameter, Ergebnis • Zur Ausführung eines Aufrufes wird Speicher angelegt für die formalen Parameter, das Ergebnis und die lokalen Variablen der Funktion. • Parameterübergabe call-by-value: Die formalen Parametervariablen werden mit den Werten der entsprechenden aktuellen Parameter initialisiert. • Eine Anweisung return Ausdruck; beendet den Aufruf und bestimmt sein Ergebnis. © 1999 bei Prof. Dr. Uwe Kastens Beispiel GGT als Funktion: Aufrufe: int ggt (int a, int b) int g; { while (a != b) { if (a > b) a = a - b; else b = b - a; } return a; } g = ggt(90, 54); System.out.print(ggt(36, 54)); g = ggt(g, 4); SWE-34 Funktionen ohne Ergebnis (Prozeduren) © 1999 bei Prof. Dr. Uwe Kastens Funktionen können eine Änderung ihrer Umgebung (Zustand, Ein-, Ausgabe) bewirken, statt ein Ergebnis zu berechnen. Sie werden dann als Anweisungen aufgerufen. (Zustandsändernde Funktionen mit Ergebnis sind möglich aber fragwürdiger Stil.) Beispiel: Aufrufe und Ausgabe: void aLine (int width, char c) { System.out.print (’=’); int i = 2; aLine(7, ’5’); while (i < width) =55555= { System.out.print (c); i = i+1; } System.out.println (’=’); } void aTicket (int width, int depth, char c) { aLine (width, ’=’); aTicket(7, 6, ’5’); int i = 2; ======= while (i < depth) =55555= { aLine (width, c); i = i+1; } =55555= =55555= aLine (width, ’=’); =55555= } =======