a=b

Werbung
Grundlagen der
Programmierung –Teil1
Einheit 1I - 15. Okt. 2010
GDP
DDr. Karl D. Fritscher
basierend auf der Vorlesung
“Grundlagen der Programmierung”
von
DI Dr. Bernhard Pfeifer
Variablen
• Variablen dienen dazu, Daten an einer bestimmten Stelle im Hauptspeicher eines
Programms abzulegen und gegebenenfalls zu lesen oder zu verändern. Eine Variable hat
4 Kennzeichen:
• Variablenname: (mehr oder weniger) beliebiger Name (Tipps zur Benennung
von Variablen beachten!)
• Datentyp: Legt fest, welche Operationen auf einer Variable möglich sind und wie
die Darstellung der Variablen im Speicher erfolgt (mehr dazu auf den
nächsten Folien)
• Wert: Der Wert muss der Variablen in der Regel explizit zugewiesen werden. Es
ist wichtig, dass einer Variable vor Ihrer ersten Verwendung ein Wert
zugewiesen wird (Initialisierung). Wird dies nicht gemacht ist Wert der
Variablen zufällig und kann Fehlfunktionen des Programms führen. (siehe
auch Folie „Definite Assignment“
• Adresse: Nummerierte Speicherzelle im Arbeitsspeicher welche von der Variable
belegt wird. Eine Variable kann natürlich auch mehrere Speicherzellen
belegen
Variablen
• Bevor Variablen ein Wert zugewiesen werden kann, muss die Variable definiert
werden.
Die Definition einer Variablen setzt sich aus Deklaration und
Reservierung des Speicherplatzes zusammen.
 Deklaration: Hier wird dem Compiler mitgeteilt, mit welchem Typ (und
welchem Typmodifikator – mehr dazu später) er einen Namen verbinden
muss
 Bei einfachen Datentypen (siehe nächste Folie) sieht das so beispielsweise so
aus: int i;
Dabei wir automatisch auch im Hauptspeicher Speicherplatz für die Variable
reserviert
 Variablen vom selben Typ können auch in einer einzigen Vereinbarung definiert
werden:
int a,b,c;+
• Variablen können auf zwei unterschiedliche Arten verändert werden
 durch eine Zuweisung : i=5;
 durch einen Inkrement- oder Dekrement-Operator: i++; bzw. i--;
Datentypen
•
•
•
In Java kann man die Datentypen wie folgt klassifizieren:
Java kennt acht elementare Datentypen, die gemäß Sprachspezifikation als primitive
Datentypen bezeichnet werden.
Daneben gibt es die Möglichkeit, Array-Typen zu definieren, und als objektorientierte
Sprache erlaubt Java die Definition von Objekttypen: Interface(Schnittstellen)-Typ und
Klassen Typ. Zusammen werden diese drei Typen als Referenztypen bezeichnet.
Primitive Datentypen
Gleitkommatypen
import java.io.*;
public class Sample
{
public static void main (String[] argument) throws
IOException
{
Ergebnis ??
System.out.println (1/10);
}
}
• Wenn wir das Programm übersetzen und ausführen, so würden wir
erwarten, dass als Ergebnis 0.1 am Bildschirm ausgegeben wird.
• Zu unserer Überraschung wird jedoch 0 ausgegeben. Das ist aber vermeintlich
falsch!
• Aber Achtung! Wir haben im obigen Programm mit Ganzzahlen gearbeitet. Der
Divisionsoperator ist in Java jedoch so definiert, dass die Division zweier
ganzer Zahlen wiederum eine ganze Zahl ist. Und somit stimmt die Division
natürlich: 1 / 10 = 0 mit 1 Rest
Gleitkommatypen
•
Java kennt die beiden Fließkommatypen float (einfache Genauigkeit) und
double (doppelte Genauigkeit). Die Länge beträgt 4 Byte für float und 8
Byte für double.
•
Fließkommaliterale werden immer in Dezimalnotation aufgeschrieben. Sie
bestehen aus einem Vorkommateil, einem Dezimalpunkt, einem
Nachkommateil, einem Exponenten und einem Suffix. Um ein
Fließkommaliteral von einem integralen Literal unterscheiden zu können,
muss mindestens der Dezimalpunkt, der Exponent oder der Suffix vorhanden
sein. Entweder der Vorkomma- oder der Nachkommateil darf ausgelassen
werden, aber nicht beide.
47
Gleitkommatypen
• Vorkommateil und Exponent können wahlweise durch das Vorzeichen +
oder - eingeleitet werden.
• Der Exponent, der durch ein e oder E eingeleitet wird, ist optional.
• Auch der Suffix kann weggelassen werden, wenn durch die anderen
Merkmale klar ist, dass es sich um eine Fließkommazahl handelt. Der Suffix
kann entweder f oder F sein, um anzuzeigen, dass es sich um ein float
handelt, oder d oder D, um ein double anzuzeigen. Fehlt er, so ist das Literal
(unabhängig von seiner Größe) vom Typ double.
Gültige Beispiele: ?????
3.14
2d
1e6
.5f
6.
47
Gleitkommatypen
• Neben diesen numerischen Literalen gibt es noch einige symbolische
Literale in den Klassen Float und Double des Pakets java.lang.
 NaN („not a number“) entsteht beispielsweise bei der Division durch 0,
 POSITIVE_INFINITY bzw. NEGATIVE_INFINITY sind Zahlen, die
größer bzw. kleiner als der darstellbare Bereich sind.
 MAX_VALUE und MIN_VALUE sind Konstanten welche die größte
bzw. kleinste darstellbare Zahl des jeweiligen Datentype
repräsentieren (definiert in „Wrapper-Klassen“ (später mehr
dazu))
Gleitkommatypen
import java.io.*;
public class Sample2
{
public static void
IOException
{
System.out.println
}
}
Ergebnis ??
main
(String[]
(1d/10.);
argument)
throws
Datentyp char
• Will man mit einzelnen Zeichen arbeiten, so steht der Datentyp char zur
Verfügung (2 Byte, UTF -16)
• Literalkonstanten werden dabei unter ein einfaches Hochkomma gestellt
• Daten von diesem Datentyp werden intern mit 16 Bit dargestellt
(unicode)
import java.io.*;
public class Buchstabe
{
public static void
IOException
{
main
(String[]
argument)
char ersterBuchstabe = 'A';
System.out.print("Der erste Buchstabe des
Alphabets ist ein");
System.out.println(ersterBuchstabe);
}
}
throws
Datentyp char
• char wird innerhalb der Java Virtual Machine als Datentyp int betrachtet:
Datentyp char
• char wird innerhalb der Java Virtual Machine als Datentyp int betrachtet:
import java.io.*;
public class AddBuchstabe
{
public
static
void
IOException
{
main
(String[]
argument)
char ersterBuchstabe = 'A';
char zweiterBuchstabe = 'B';
System.out.println(„Die Addition von erstem und
zweitem Buchtaben ergibt");
System.out.println(ersterBuchstabe+zweiterBuchstabe);
}
}
Ergebnis ??
throws
Datentyp boolean
• Beim Programmieren steht man des öfteren vor dem Problem, dass man Werte
miteinander vergleichen muss. Das Ergebnis des Vergleichs liefert dann WAHR oder
FALSCH.
• In Java existieren die Wahrheitswerte true und false
• Die Auswertung von logischen Ausdrücken liefert als Ergebnis Werte des Typs
boolean
Siehe auch Folie „Logische Operatoren“
ImpliziteTypumwandlung
• Es kann vorkommen, dass man einen gewissen Datentyp für eine Operation benötigt,
jedoch einen anderen vorliegen hat .Will man z.B.: eine 64 Bit Zahl mit einer 32 Bit
Zahl addieren, so steht man vor dem Problem, dass die Addition nur für denselben Typ
definiert ist. In einem solchen fall benötigt man also eine Typumwandlung, damit die
Operation überhaupt durchgeführt werden kann.
• Bei der oben beschriebenen Problemstellung muss man gar nichts tun. Denn der
Compiler erkennt, dass die eine Zahl einen Zahlenbereich hat, der den der anderen
Zahl umschliesst. Aus diesem Grund wird einfach die int Zahl in eine long Zahl
umgewandet, und die Addition kann ausgeführt werden.
• Diese automatische Vorgehensweise nennt man implizite Typkonvertierung
(implicit typecast)
• Implizite Typkonvertierungen treten immer dann auf, wenn ein kleinerer Zahlenbereich
in einen größeren Zahlenbereich abgebildet wird.
byte short int long float double
ImpliziteTypumwandlung 2
Eine automatische Konvertierung wird vom Compiler in folgenden
Fällen vorgenommen
Bei einer Zuweisung, wenn der Typ der Variablen und des
zugewiesenen Ausdrucks nicht identisch ist.
Bei der Auswertung eines arithmetischen Ausdrucks, wenn
Operanden unterschiedlich typisiert sind:
int a;
float b,c;
c=a+b;
54
ImpliziteTypumwandlung 3
Eine automatische Konvertierung wird vom Compiler in folgenden
Fällen vorgenommen (Fortsetzung)
 Beim Aufruf einer Methode, falls die Typen der aktuellen Parameter nicht
mit denen der formalen Parameter übereinstimmen (dazu wieder einmal
später mehr)
public double doSomething (double a, double b)
{
....
}
float x,y,z;
Z=doSomething(x,y);
54
Implizite/Explizite Typumwandlung
• Will man beispielsweise eine Variable vom typ double in eine Variable
vom Typ int konvertieren, so kann man das nicht so ohne weiteres tun,
denn es geht ja durch diese einschränkende Konvertierung Information
verloren!
Beispiel:
int a=1;
double b=3.5;
a=b;
•
Daher nimmt der Compiler an, dass es sich um einen Fehler handelt und
gibt eine Fehlermeldung aus:
possible loss of precision
found: double
required: int
•55
Implizite/Explizite Typumwandlung
• Der Grund für dieses Verhalten liegt darin begründet, dass es sich bei einer
solchen Vorgangsweise häufig um einen Programmierfehler handelt. Um jedoch
eine Konvertierung vornehmen zu können, muss man den Compiler dazu mit
Hilfe des Cast-Operators () dazu „zwingen“, es zu tun. Diese Vorgangsweise
nennt man explizite Typkonvertierung (explicit typecast):
int a=1;
double b=3.5;
a=(int)b;
• Eine Umwandlung von boolean in einen anderen Datentyp ist nicht möglich!
•55
Definite Assignment
•
•
In Java gibt es ein Konzept, das sich Definite Assignment nennt. Gemeint ist damit die
Tatsache, dass jede lokale Variable vor ihrer ersten Verwendung definitiv initialisiert sein
muss.
Dazu muss im Quelltext eine Datenflussanalyse durchgeführt werden, die jeden
möglichen Ausführungspfad von der Deklaration einer Variablen bis zu ihrer Verwendung
ermittelt und sicherstellt, dass kein Weg existiert, der eine Initialisierung auslassen würde.
import java.io.*;
public class Test
{
public static void main (String[] argument) throws IOException
{
int a;
System.out.println(a);
}
}
PROBLEM?
Ausdrücke und Operatoren
• Obwohl wir Ausdrücke schon in unseren ersten kleinen Programmen
kennengelernt haben, wollen wir diese jetzt noch einmal etwas genauer
unter die Lupe nehmen.
 Merke: Ein Ausdruck ist die kleinste ausführbare Einheit
eines Programms.
 Ein Ausdruck besteht immer aus mindestens einem Operator und
einem oder mehreren Operanden, auf die der Operator
angewendet wird. Nach den Typen der Operatoren unterscheidet man
zwischen
 arithmetischen / nummerischen,
 relationalen ,
 logischen ,
 (bitweise) Zuweisungs ,
 und sonstigen Operatoren (oft als Methode implementiert zB instanceof)
Arithmetische Operatoren
• Es existiert die Addition, Subtraktion, Multiplikation, Division und der
Restwertoperator
• Zusätzlich gibt es den einstelligen Operator für ein positives oder negatives
Vorzeichen
• Arithmetische Operatoren erwarten numerische Operanden und liefern einen
numerischen Rückgabewert.
• Haben die Operanden unterschiedliche Datentypen, so wird ein automatischer
Type-Cast durchgeführt.
+
+
*
/
%
++
--
positives Vorzeichen
negatives Vorzeichen
Summe
Differenz
Multiplikation
Quotient
Restwert
Prä/Postinkement
Prä/Postdekrement
+n gleichbedeutend mit n
-n kehrt das Vorzeichen um
a+b ergibt Summe von a,b
a-b
a*b
a/b
a modulo b
a=a+1
a=a-1
Relationale Operatoren
•
Relationale Operatoren dienen dazu, Ausdrücke miteinander zu
vergleichen und in Abhängigkeit davon einen logischen Rückgabewert
zu produzieren
==
Gleich
!=
Ungleich
a!=b => true wenn a ungleich b
<
Kleiner
a<b => true wenn a kleiner b
<=
Kleiner gleich
>
>=
Größer
Größer gleich
a==b => true wenn a=b
a<=b => true wenn a kleiner oder gleich b
a>b
a>=b
59
Logische Operatoren
• Logische Operatoren dienen dazu, boolsche Werte miteinander zu verknüpfen. Im
Gegensatz zu relationalen Operatoren, die durch Vergleiche einen boolschen Wert
produzieren, werden logische Operatoren zur Weiterverarbeitung von Wahrheitswerten
verwendet.
• Es gibt die Grundoperationen UND, ODER und NICHT. UND und ODER werden in
zwei Varianten zur Verfügung gestellt:
 Short-Circuit-Evaluation (SCE) && bzw ||:
Bei der Aneinanderreihung mehrerer logische Ausdrücke wird ein logischer
Ausdruck (weiter rechts) wird nur dann ausgewertet, wenn er für das Ergebnis
noch von Bedeutung ist
boolean wert1=false, wert2=true;
if(wert1 == true
&&
wird nicht ausgewertet
wert2 == false) wert1=wert2;
 keine Short-Circuit-Evaluation & bzw |
boolean wert1=false, wert2=true;
if(wert1 == true
&
wird ausgewertet
wert2 == false) wert1=wert2;
Logische Operatoren
!
logisches NICHT
&&
UND mit SCE
||
ODER mit SCE
&
UND ohne SCE
|
ODER ohne SCE
^
Exklusiv-Oder
!a => false, wenn a true und vice versa
a&&b => true wenn a und b true sonst
false
a||b => true, wenn mind. einer der
Ausdrücke true ist, sonst false
a^b => true, wenn beide Ausdrücke
einen unterschiedlichen Wert haben
Bitweise Operatoren
• Mit diesen Operatoren kann auf die Binärdarstellung von
numerischen Operanden zugegriffen werden.
• Ein numerischer Datentyp wird dabei binär (dual) repräsentiert, und es können
die einzelnen Bits direkt manipuliert werden.
~
Einerkomplement
&
bitweises UND
|
bitweises ODER
^
bitweises XOR
>>
rechtsschieben mit Vorzeichen
>>>
rechtsschieben ohne Vorzeichen
<<
linksschieben
~a entsteht aus a, indem alle Bits von a invertiert
werden
a&b ergibt den Wert, der entsteht, wenn die
korrespondierenden Bits von a und b miteinander
UND verknüpft werden
a|b ergibt den Wert, der entsteht, wenn die
korrespondierenden Bits von a und b miteinander
ODER verknüpft werden
a^b ergibt den Wert, der entsteht, wenn die
korrespondierenden Bits von a und b miteinander
Exklusiv-ODER verknüpft werden
a>>b schiebt um b bits in a nach rechts
entspricht Division von a durch 2n
a>>b schiebt um b bits in a nach rechts
Es werden stets Nullen von links eingefügt
a>>b schiebt um b bits in a nach links
Bitweise Operatoren
Beispiele:
14 & 1
14 | 1
14 ^ 1
1110 & 0001 = 1111 = 15
1110 | 0001 = 0000
1110 ^ 0001 = 1111 = 15
8 >>3
00000000 00000000 00000000 00001000
00000000 00000000 00000000 00000001
-7 >> 3
11111111 11111111 11111111 11111001
11111111 11111111 11111111 11111111
-7 >>> 3
11111111 11111111 11111111 11111001
00011111 11111111 11111111 11111111
= abschneidende
Ganzahldivision
durch 8 (=23)
Zuweisungsoperatoren
=
+=
-=
*=
/=
%=
&=
|=
^=
<<=
>>=
Einfache Zuweisung
Additionszuweisung
a+=3; entspricht a=a+3;
Subtraktionszuweisung
Multiplikationszuweisung
Divisionszuweisung
Modulozuweisunng
UND Zuweisung
a&=b weist a den Wert zu von a&b
ODER Zuweisung
XOR Zuweisung
Linksschiebungszuweisung
Rechtsschiebungszuweisung
Sonstige Operatoren
Sonstige Operatoren für primitive Datentypen:
• Type-Cast Operator (): wird für explizite Typumwandlung verwendet
int c = (int) 4.2;
• Fragezeichenoperator ? : mehr dazu in der nächsten Vorlesung
Sonstige Operatoren für Referenztypen:
• InstanceOf – Operator instanceof: mehr dazu in der
übernächstenVorlesung
63
Stelligkeit von Operatoren
Neben dem Typ ist auch die Stelligkeit eines Operators von zentraler
Bedeutung:
•
monadische Operatoren:
benötigen nur einen Operanden. Bsp.: ++ --
•
dyadische Operatoren:
verknüpfen zwei Operanden und werden absolut am häufigsten
verwendet. Bsp.: + - ==
•
triadische/ternäre Operatoren:
verknüpfen drei Operanden. Als einziges Beispiel in Java ist der
Fragezeichen-Operator ? zu nennen
Priorität von Operatoren
• Operatoren sind in Java mit so genannten Prioritäten versehen,
wodurch gewisse Reihenfolgen bei der Auswertung (=operator
ranking) eingehalten werden
• Darüber hinaus gibt es folgende Regeln zur Auswertung eines
Ausdrucks in JAVA:
1. Als erstes werden Teilausdrücke in Klammern ausgewertet.
2. Danach werden Ausdrücke mit unären Operatoren ausgewertet
3. Abschließend werden Teilausdrücke mit mehrstelligen
Operatoren ausgewertet
(Fortsetzung auf der nächsten Folie !)
Priorität von Operatoren 2
• Regeln zur Auswertung (Fortsetzung)
1.
Als erstes werden Teilausdrücke in Klammern ausgewertet.
2.
Danach werden Ausdrücke mit unären Operatoren ausgewertet
3.
Abschließend werden Teilausdrücke mit mehrstelligen Operatoren ausgewertet
4. Bei Operatoren mit gleicher Priorität (siehe auch Tabelle) wird
die Reihenfolge der Auswertung anhand Ihrer Assoziativität
bestimmt
Bsp:
a – b + c ……. Es wird zuerst die Operation a-b durchgeführt bevor die Addition
mit c erfolgt -> linksassoziativ
Beachte: Die Reihenfolge der Auswertung kann durch
Verwendung von Klammern beeinflusst werden: a-(b+c) (siehe
auch Regel 1)
• In Java sind Zuweisungsoperatoren, der Bedingungsoperator und
unäre Operatoren rechtsassoziativ. Alle anderen Operatoren sind
linksassoziativ.
Priorität von Operatoren
•
Wie bereits erwähnt sind Operatoren sind in Java mit so genannten Prioritäten
versehen, wodurch gewisse Reihenfolgen bei der Auswertung eingehalten werden
(Punkt vor Strich)
Übungsfragenzu Datentypen und Operatoren
1. Was versteht man unter Typumwandlung?
2. Wie kann es bei einer Typumwandlung zu unerwünschten
Veränderungen im Wert kommen?
3. Was versteht man unter expliziter bzw. impliziter Typumwandlung?
Nennen sie jeweils ein Beispiel.
4. Was sind Operatoren? In welche Klassen können Operationen
eingeteilt werden?
5. Was versteht man unter der Priorität eines Operators? In diesem
Zusammenhang fällt auch manchmal der Begriff „operator ranking“ .
Was versteht man darunter ?
Ausdrücke & Anweisungen
In Java unterscheidet man zwischen Ausdrücken und Anweisungen:
• Ausdruck:
 Ein Ausdruck ist in Java im einfachsten Fall eine Konstante oder eine
Variable. Ausdrücke haben immer einen Wert, der auch teilweise als
Rückgabewert bezeichnet wird
 Durch Verknüpfung von Operanden durch Operatoren entsteht ein
komplexer Ausdruck
Ausdrücke & Anweisungen
Anweisungen:
 Im Gegensatz zu Ausdrücken haben Anweisungen keinen Rückgabewert. Mann
kann folgende Anweisungen unterscheiden:









Leere Anweisung
Anweisungen zur Deklaration von Variablen
Ausdrucksanweisung (Ausdruck;)
Selektionsanweisung (if, switch)
Iterationsanweisung (while, do, for)
Sprunganweisungen (break, continue)
Try - Anweisung
Throw - Anweisung
Synchronized - Anweisung
Anweisungen
• Eine Reihe von Anweisungen kann in einem Block zusammengefasst
werden
{
Anweisung1;
Anweisung2;
}
• Im Prinzip erlaubt die Blockanweisung eine Zusammenfassung von vielen
Anweisungen zu einer einzigen geblockten (komplexen) Einzelanweisung.
Anweisungen
• Die leere Anweisung
;
ist die einfachste Anweisung und hat auf das laufende Programm keinerlei
Effekt
• Variablendeklaration

Syntax:
Typname VariablenName;
oder
Typname VariablenName

= Initialwert;
die Deklaration einer lokalen Variable gilt in Java als eine Anweisung.
Sie darf überall erfolgen, wo auch eine andere Anweisung stehen
dürfte.
Anweisungen
• Ausdrucksanweisungen
 Syntax
Ausdruck;
 Ausdruckanweisungen dienen dazu, Ausdrücke in einem
Anweisungskontext auszuführen. Sie werden erzeugt, indem man an den
Ausdruck ein Semikolon anhängt. In Java können Anwesiungen nicht aus
allen Ausdrücken erzeugt werden.
In Java zulässige Ausdrucksanweisungen sind:
Zuweisung
a+=b;
Inkrement oder Dekrement
c++;
Methodenaufruf
System.out.println(„Hello“);
Instanzerzeugung
Auto bmw = new Auto();
Anweisungen
•
Verzweigungen


erst aufgrund von Verzweigungen ist es möglich komplexe Programme zu
erstellen. Die Verzweigung ist eine der wichtigsten Anweisungen
überhaupt, da Entscheidungen gefällt und verschiedene Codezweige
ausgeführt werden können.
In Java existiert die if und if-else sowie die switch Anweisung
Hunger ?
nein
GDP
lernen
ja
Essen
Die if-Anweisung
If-Anweisung
 Syntax
if(ausdruck) anweisung;
if(ausdruck)
anweisung;
else
anweisung;

Zuerst wird der Ausdruck (ausdruck) ausgewertet.
 Die Anweisung (anweisung) wird genau dann ausgewertet , wenn der
Ausdruck (ausdruck) true zurückgeliefert hat.
 Liefer (ausruck) hingegen false zurück, so wird nichts gemacht oder
wie in der zweiten Anweisung der else Zweig ausgeführt
79
Dangling Else
•
In fast allen blockorientierten Programmiersprachen können durch die elseAnweisung Mehrdeutigkeiten entstehen. Dann ist es oft schwer möglich zu
sagen zu welchem if das else gehört (dangling else) :
if (a)
if (b)
dothis ();
else
dothat ();
Zu welchem if gehört nun der else Zweig?
Lösung: Der Else Zweig gehört immer zu der innersten Verzweigung (die
noch nicht geschlossen wurde). Hätte man den Code richtig eingerückt, so
wäre dies auch gleich klar ersichtlich:
if (a)
if (b)
dothis
else
dothat
();
();
80
Ergänzung zu ?-Operatoren
Fragezeichenoperator ?
der einzige dreistellige (=ternäre) Operator in Java - er erwartet einen logischen
Ausdruck und zwei weitere, die beide entweder numerisch, vom Typ boolean oder
ein von einem Referenztyp) sein müssen
b = (a > 10) ? 1 : a ; //ist a >10, dann wird b=1, ansonsten b=c gesetzt
Obige Zeile kann auch mit Hilfe von if...else.. formuliert werden:
if (a > 10)
{
b = 1 ;
}
else
{
b = a;
}
80
Herunterladen