3.2 Schleifen und Felder
3.2 Schleifen und FelderSchleifen erlauben die Wiederholungen von Einzelanweisung. Schleifen bestehen typischerweise aus den folgenden Komponenten
- einen Schleifenrumpf mit den auszuführenden Anweisungen
- einem Kopf oder Fuß mit einer Ausführungsbedingung
- oft einer Laufvariablen mit der die Durchläufe kontrolliert werden
Die while Schleife
Die while Schleife überprüft vor dem Schleifeneintritt ob die Ausführungsbedingung (noch) erfüllt ist. Sie enthält die Schleifenbedingung im Kopf der Schleife.
Die Syntax der while Schleife ist die folgende:
while ( Bedingung) { Anweisung ; } oder while ( Bedingung) Anweisung; Beispiel: Arithmetische Summe 1+2+3+4+5 int i = 1; int summe= 0; while (i<=5) { summe = summe + i; i++; } |
Die do-while-Schleife
Die do-while-Schleife überprüft nach dem ersten Schleifendurchlauf ob die Ausführungsbedingung erfüllt ist. Sie enthält die Schleifenbedingung im Fuß der Schleife. Die Syntax der do-while Schleife ist die folgende: do { Anweisung ; } while ( Bedingung ); oder do Anweisung; while ( Bedingung ); Beispiel: Beende Schleife wenn Wert durch 3 ohne Rest teilt int i = 9; int j = 0; // Zählt Schleifendurchläufe do { j++; i--; } while (i%3 != 0); Die Schleife wird dreimal durchlaufen. |
Regel:
- Die while Schleife ist eine abweisende Schleife: Sie wird nicht notwendigerweise durchlaufen.
- Die do-while ist eine nicht abweisende Schleife: Sie wird mindestens einmal durchlaufen.
Diese Unterscheidung ist in verschiedenen Bereichen wichtig
- Variablen werden bei einer abweisenden Schleife eventuell nicht belegt
- Es wird manchmal in der Qualitätssicherung gefordert, dass alle Zeilen eines Programmes duchlaufen werden. Bei abweisenden Schleifen muss man unter Umständen bei der Implementierung der Testabdeckung mehr investieren.
Die for-Schleife
Die for-Schleife überprüft die Schleifenbedingung vor dem Eintritt in die Schleife.
Ihre Syntax ist die anspruchsvollste der drei Schleifenarten:
for (Initialiserung; Bedingung; Veränderung) {Anweisung ;}
oder
for (Initialiserung; Bedingung; Veränderung) Anweisung;
Der Kopf der for-Schleife besteht aus den folgenden drei Teilen:
- Initialisierungsteil: Laufvariable und Startwert werden festgelegt.
- Bedingungsteil: Wird der Wert der Bedingung unwahr (false) wird die Schleife verlassen oder nicht betreten. Ansonsten wird sie weiter fortgesetzt.
- Veränderungsteil: Nach jedem Durchlauf der Schleife wird die Laufvariable entsprechen verändert (Typischerweise inkrementiert oder dekrementiert).
Beispiel einer einfachen for-Schleife
Im folgenden Beispiel wird die for-Schleife "b mal" durchlaufen. Durch das Aufaddieren der Variablen a wird eine Multiplikation von positiven Zahlen ausgeführt.
Ist b gleich Null oder negativ wird die Schleife nicht durchlaufen.
Geschachtelte Schleifen
Oft ist es notwendig Schleifen zu schachteln. Dies kommt oft bei mehrdimensionalen Datenstrukturen vor bei denen jedes Feld bearbeitet werden muss. Bei jedem Durchlauf der äusseren Schleife wird die innere aufgerufen, die ihre eigenen Durchläufe komplett bei jedem Durchlauf der äusseren Schleife durchführt. Anbei ein Beispiel einer naiven Multiplikation die auf Inkrementieren beruht:
class MultiplizierenNaiv { public static void main(String[] args) { int a = 5; int b = 10; int result = 0; for (int i = 1; i <= a; i++) { System.out.println("Äussere Schleife i = " + i); for (int j = 1; j <= b; j++) { System.out.println("Innere Schleife j = " + j); result++; } } System.out.println(a +"*"+b+" = "+result); } }
Geschachtelte Schleifen sind sehr mächtig und sie haben ein viel größeres Potential Rechnerleistung zu binden. Die Aufwände bei zwei geschachtelten Schleifen können quadratisch steigen im Vergleich zum linearen Aufwand einer einfachen Schleife. Generell gilt, dass eine teure Anweisung in einer Schleife n-mal statt einmal durchlaufen werden kann. Es ist daher wichtig auf die folgenden Dinge zu achten:
- Lassen Sie alle Anweisungen die man vor oder nach der Schleife ausführen kann aus dem Schleifenblock draussen
- Definieren und Initialisieren Sie Variablen wenn möglich ausserhalb der Schleife und verwenden Sie die Variablen wieder. Die Variable muss sonst jedes mal neu angelegt und wieder gelöscht werden.
- Verzichten Sie auf unnötige Schleifendurchläufe
- Seien Sie vorsichtig bei mehrfach geschachtelten Schleifen. Die Anzahl der Durchläufe kann theoretisch sehr schnell, sehr groß werden. Eine dreifach geschachtelte Schleife mit jeweils 1000 Durchläufen wird eine Milliarde mal ausgeführt!
Sprunganweisungen und Schleifenabbrüche mit continue und break Schlüsselwörtern
Java verfügt über zwei Möglichkeiten Schleifen in der Mitte von Ausführungsblöcken zu verlassen. Diese Programmiertechnik sollte man normalerweise vermeiden.
In manchen Fällen ist sie jedoch nützlich. Schleifenabbrüche werden durch die beiden folgenden Schlüsselwörter gesteuert:
Die break Anweisung ist schon vom switch Befehl her bekannt. Mit ihr kann man auch eine if Bedingung beenden. Beispiel einer continue Anweisung: ... for (int i=0; i<= 100; i++) { if (i%2 == 0) continue; System.out.println("Die Zahl " + i + " ist ungerade"); } Bei geraden Zahlen wird die Druckanweisung nach der if Anweisung nicht mehr ausgeführt. Die Schleifen werden jedoch alle durchlaufen. |
Beispiel einer break-Anweisung:
... for (int i=1; i<= 100; i++) { if (i== 32) break; System.out.println("Die Zahl " + i + " wurde bearbeitet"); } Die Zahlen von 1 bis 31 werden ausgedruckt. Anschließend wird die Schleife abgebrochen. Die break und continue Anweisungen beziehen sich immer auf die nächst äussere Schleife. Mit Hilfe von Labels (Marken) kann man auch über mehrere geschachtelte Schleifen nach aussen springen. |
Verlassen von Blöcken mit Hilfe von Sprungzielen (Label)
Java erlaubt das Benennen von Blöcken mit Hilfe von "Labeln" (Marken). Mit ihnen kann man mit einer break-Anweisung beliebig viele Blöcke auf einmal verlassen.
Das folgende Beispiel zeigt wie man zum Label "Label1" springt um beide Schleifen auf einmal zu verlassen:
class MultiplizierenNaivLabel { public static void main(String[] args) { int a = 5; int b = 10; int result = 0; Label1: for (int i = 1; i <= a; i++) { System.out.println("Äussere Schleife i = " + i); for (int j = 1; j <= b; j++) { System.out.println("Innere Schleife j = " + j); if ((i == 3) && (j == 3)) break Label1; result++; } } System.out.println(a +"*"+b+" = "+result); System.out.println("Dieses Ergebnis ist falsch..."); } }
Endlosenschleifen
Endlosenschleifen sind Schleifen die nicht terminieren. Ein Programm mit einer Endlosschleife sieht aus wie ein "hängendes" Programm. Es bindet jedoch sehr wahrscheinlich (mindestens) einen physikalischen Prozessor vollständig! Anbei einige Beispiele mehr oder weniger leicht zu erkennende Endloschleifen: while ( true) { /* Anweisung(en) */ } ... for ( ; ; ) { /* Anweisung(en) */ } ... int i=10; while (i>5) i++; ... int i=0; while ( i!=99) {i++; i++;} Der Übersetzer erkennt diverse einfache Endlosschleifen und meldet die darauf folgende Codezeile als "unreachable code". |
Trivia: Welcher Obsthändler hat die Adresse 1 Infinite Loop, Cupertino, CA 95014?
|
Felder (Arrays), Einführung
Die folgende Kurzüberblick von Feldern ist notwendig um die Übungen zu den Kontrollstrukturen zu lösen. Felder werden später noch einmal aufgegriffen und genauer behandelt.
Felder sind Datenbehälter mit einer oder mehreren Dimensionen um eine Anzahl primitive Datentypen gleichen Typs aufzunehmen.
Man kann auf die einzelnen Feldelemente wahlfrei, also direkt mit Hilfe eines Index zugreifen. Java benutzt rechteckige Klammern [] um auf einzelne Elemente eines Feldes zuzugreifen.
Initialisieren und Deklarieren von Feldern
Felder sind im Gegensatz zu Variablen mit primitiven Datentyp Objekte. Dies bedeutet, dass die die Variable nur aus einer Referenz besteht. Das Feld selbst muss dynamisch angelegt werden. Hierfür gibt es eine Reihe von Gründen.
- Der Übersetzer kann nicht wissen wie groß ein Feld werden kann
- Man kann mit einer Feldvariablen dynamisch neue Felder verwalten
- Felder können sehr groß sein. Es ist oft klüger das Feld erst anzulegen wenn man es benötigt und die Größe kennt.
Die Deklaration von Feldern geschieht wie folgt:
int[] x; // Anlegen einer Referenz, es ist noch keine Größe vorgeben, // es können noch keine Feldelemente benutzt werden< double[] y; // Anlegen einer Referenz, es ist noch keine Größe vorgeben, //es können noch keine Feldelemente benutzt werden
Um das eigentliche Feld anzulegen muss der new Operator verwendet werden wie für reguläre Objekte auch um den Speicher zu allozieren. Dies geschieht wie folgt:
int [] x; x = new int[4]; double[] y; y = new double[200];
Jetzt zeigt x auf 4 Datenbehälter für Ganzzahlen. Der Zugriff auf die vier Elemente erfolgt über einen Index im Bereich von 0 (erster Wert) bis 3.
Zugriff auf Felder
Das Feld kann nun wie folgt belegt und bearbeitet werden:
int [] x = new int[4]; x[0] = 99; x[1] = 88; x[2] = x[0]+x[1]; x[3] = x[0]*x[1];
Bestimmen der Länge eines Feldes
...geschieht mit dem Attribut .length. Hier ein Beispiel:
int[] x; int groesse; ... groesse=x.length;
Erweiterte for Schleife (enhanced for-loop)
Seit Java 5 ist es möglich mit der for Schleife Felder komfortabler abzuarbeiten. Man kann mit einer Laufvariable alle Elemente des gegeben Feldes abarbeiten. Wie zum Beispiel:
int [] xxx = { 11, 22, 33, 44, 55}; for ( int position : xxx) // für Element auf Position position in xxx[] System.out.println("Wert: " + position);
Wird das folgende Ergebnis liefern:
Wert: 11 Wert: 22 Wert: 33 Wert: 44 Wert: 55
Die Oracle Java Dokumentation erklärt die Einsatzmöglichkeiten und Grenzen der "enhanced for-loop".
- 16667 views
3.2.1 Schleifentransformationen
3.2.1 SchleifentransformationenDie drei Java Schleifentypen sind für unterschiedliche Zwecke entwickelt worden. Man Sie jedoch ineinander Überführen.
Hier sind einige Regeln
While Schleife in Do-While Schleife überführen
von While Schleife | zu do-While Schleife | |
---|---|---|
Java |
while (Bedingung) {Block A } |
do if (Bedingung) { Block A } while ( Bedingung ) |
UML |
Do-While Schleife in While Schleife überführen
Eine Do-While Schleife führt einen Block mindestens einmal aus. Man kann Sie in eine While Schleife tranformieren in dem man den Block kopiert und voran stellt.
Vorsicht: Durch das duplizieren des Codes wird der Code schlechter wartbar!
von Do-While Schleife | zu While Schleife | |
---|---|---|
Java |
do Block A while ( Bedingung ) |
Block A while (Bedingung) {Block A } |
UML |
For-Schleife in eine While Schleife überführen
von For-Schleife | zu While Schleife | |
---|---|---|
Java |
for (Initialiserung; Bedingung; Veränderung) {Block A} |
Initialisierung while (Bedingung) { Block A; Veränderung } |
While Schleife in For-Schleife überführen
While Schleifen kan man recht einfach in For-Schleifen überführen.
von While-Schleife | zu For-Schleife | |
---|---|---|
Java |
while (Bedingung) { Block A;} |
for (; Bedingung;) {Block A} |
Eine solche Überführung wird aber recht selten angewendet, da der Initialisierungsanteil und die Veränderung der for Schleife irgendwo im Block A verborgen sind.
Do-While Schleife in For-Schleife überführen
Do-While Schleifen kan man auch recht einfach in For-Schleifen überführen.
von While-Schleife | zu For-Schleife | |
---|---|---|
Java |
do { Block A;} while (Bedingung) |
Block A; for (; Bedingung;) {Block A;} |
Eine solche Überführung wird aber recht selten angewendet, da der Initialisierungsanteil und die Veränderung der for Schleife irgendwo im Block A verborgen sind.
- 3916 views
Semikolon
Hallo,
muss bei der Transformation von der For Schleife zu der While Schleife hinter die Initialisierung ein Semikolon?
Und mir ist aufgefallen, dass bei der letzten Transformation die Begriffe in der Tabelle nicht stimmen.Es handelt sich um eine Transformation von einer Do While Schleife zu einer For Schleife, aber in der Tabelle steht von einer While Schliefe zu einer While Schleife.
Mit freundlichen Grüßen!
- Log in to post comments
Endlosschleife
"int i = 10
while (i > 5 ) i++;"
fehlen nach der Bedingung nicht die { }?
Also {i++;} ?
Nein
Das wurde hier in Syntax nicht vollständig korrekt dargestellt.
Die allgemeine Regel für Programmierblöcke ist: Man darf anstatt mehrerer Befehle in einem Block mit geschweiften Klammern immer auch einen einzelnen Befehl ohne geschweifte Klammer schreiben.
Die Syntax müßte wohl als regulärer Ausdruck so aussehen:
while (bedingung) [{ anweisung; {anweisung;}} , anweisung; ]
Bestimmen der Länge eines Feldes
Sollte es nicht heißen
groesse = x.length(); statt groesse = x.length; ?
lg
length ist keine Methode, das Feld ist keine Klasse
das ist ein Spezialfall. Felder sind keine Klassen und haben keine Methoden. length ist ein Attribut welches alle Felder besitzen.
Man kann das auch mal selbst in eine Entwicklungsumgebung eintippen und schauen was passiert...
Mag sein, dass das ein…
Mag sein, dass das ein Erbsenzähler Problem ist, allerdings wird unter dem Punkt 'Bestimmen der Länge eines Feldes' beschrieben, dass die Länge mit der .length()-Methode bestimmt wird.
Sollte hier nicht length-Attribut stehen?
Gut beobachtet
Habe ich verbessert. Danke.
for Schleife
Im Beispiel einer einfachen for Schleife steht, dass sie b mal durchlaufen wird, jedoch ist die Bedingung der for Schleife i
Schon...
Gute Überlegung.
Die Variable i dient zum Schleifenabruch und wird bei jedem Durchlauf imkrementiert. Sie startet bei 1 und endet bei b. Das sollte schon hinkommen.
Semikolon
Ich glaube es fehlt bei der while, do-while und for Schleife immer ein Semikolon hinter Anweisung(en).
while (Bedingung) {Anweisung(en) ; }
do {Anweisung(en) ; } while (Bedingung);
for (Initialisierung; Bedingung; Veränderung) {Anweisung(en) ; }
Stimmt
habe ich verbessert.