Die for -Schleife
Wir haben schon eine Zählschleife mit »while« gesehen.
- Zählschleife mit while
{ int i = 10; /* Schleifenvorbereitung (Teil der Schleifensteuerung) */
while( i < 15 /* Schleifenpruefung (Teil der Schleifensteuerung) */ )
{ java.lang.System.out.println( i );
i += 2; /* Schleifenschritt (Teil der Schleifensteuerung) */ }}
Eine while -Schleife kann im allgemeinen aus einer Schleifenvorbereitung, einer Schleifenprüfung und einem Schleifeninhalt mit einem Schleifenschritt (Übergang zum nächsten Durchlauf) bestehen.
Schleifenvorbereitung, Schleifenprüfung und Schleifenschritt können bei einer for -Schleife übersichtlich im Schleifenkopf zusammengefaßt werden, während der Schleifenrumpf dann nur aus der Nutzlast (dem Schleifeninhalt ohne Schleifenschritt) besteht.
Die folgende for -Schleife hat dieselbe Bedeutung wie die oben stehende while -Schleife.
- Zählschleife mit »for«
for( int i = 10; i < 15; i += 2 )
java.lang.System.out.println( i );
Die voranstehende for -Schleife enthält eine Variablendeklaration vor dem ersten Semikolon. Statt dessen darf dort auch eine Liste von Anweisungsausdrücken stehen, genauso wie nach dem zweiten Semikolon. So gibt das folgende Programm eine Tabelle von Zweierpotenzen aus.
Main.java
public final class Main
{ public static void main( final java.lang.String[] args )
{ int i; int j;
for( i = 0, j = 1; i < 10; i += 1, j *= 2 )
java.lang.System.out.printf
( "%d %3d%n", i, j ); }}transcript
0 1
1 2
2 4
3 8
4 16
5 32
6 64
7 128
8 256
9 512
Allerdings wird von der Möglichkeit, auf die gezeigte Weise mit einem Komma mehrere Anweisungsausdrücke im Kopfe einer for -Schleife hintereinander zu schreiben, selten Gebrauch gemacht.
Syntax (vereinfacht)
Anweisung .-----------. .---------------. .--------------.
| | | | | |
.'''. .-. | .------. v .-. | .----------. v .-. | .---------. v .-. .-----------.
->( for )->( ( )-'->| Init |-'->( ; )-'->| Ausdruck |-'->( ; )-'->| Schritt |-'->( ) )->| Anweisung |->
'...' '-' '------' '-' '----------' '-' '---------' '-' '-----------'Init .--------------------.
---.-------.--->| Anweisungsausdruck |---.-------.--->
| ^ '--------------------' | ^
| | .-. | |
| '-------------( , )-----------' |
| '-' |
| .-----------------------------. |
'------->| Variablendeklaration |------'
'-----------------------------'Schritt
.--------------------.
---.--->| Anweisungsausdruck |---.--->
^ '--------------------' |
| .-. |
'-------------( , )-----------'
'-'
Typanforderungen
Genau wie bei der while -Anweisung muß auch hier der Ausdruck den Typ »boolean« haben.
Semantik
Zunächst wird die Init -Deklaration ausgeführt beziehungsweise die Init-Ausdrücke werden ausgewertet, falls vorhanden.
Nun wird die folgende Schleifensequenz einmal oder wiederholt ausgeführt:
- Schleifensequenz
- Der Ausdruck wird ausgewertet. (Falls kein Ausdruck vorhanden ist, so ist dies als würde der Ausdruck »true« dastehen.)
- Falls der Ausdruck wahr ist, wird die Anweisung ausgeführt, dann werden alle Ausdrücke des Schritts der Schleife hintereinander ausgewertet und schließlich wird eine weitere Schleifensequenz ausgeführt.
- Falls der Ausdruck nicht wahr ist, wird nichts weiter gemacht.
Beispiel Tabellieren einer deterministischen einparametrigen Wertmethode
Das folgende Programm gibt eine Tabelle einiger Werte der Betragsfunktion aus.
Main.java
public final class Main
{ public static void main( final java.lang.String[] args )
{ for( int i = -3; i < 4; ++i )
java.lang.System.out.println
( "|" +( i < 0 ? "" : "+" )+ i + "| = " + java.lang.Math.abs( i )); }}java.lang.System.out
|-3| = 3
|-2| = 2
|-1| = 1
|+0| = 0
|+1| = 1
|+2| = 2
|+3| = 3
Schleifen mit double-Werten
Die folgende Schleife zeigt einen typischen Programmierfehler (der genausogut auch mit einer while -Schleife gezeigt werden könnte): Der Programmierer will Werte bis 0.3 (ausschließlich) ausgeben. Durch Darstellungsfehler bei den Nachkommastellen wird aber der Wert 0.3 nicht genau erreicht, und die Schleife endet nicht wie gewünscht.
Main.java
public final class Main
{ public static void main( final java.lang.String[] args )
{ for( double x = 0; x != 0.3; x += 0.1 )java.lang.System.out.println( x ); }}java.lang.System.out
0.0
0.1
0.2
0.30000000000000004
0.4
0.5- u.s.w.
Die folgende Schleife zeigt eine Variante, bei der Zahlen bis 0.3 (einschließlich) ausgegeben werden soll, aber dann 0.3 selber schon nicht mehr ausgegeben wird.
Main.java
public final class Main
{ public static void main( final java.lang.String[] args )
{ for( double x = 0; x <= 0.3; x += 0.1 )java.lang.System.out.println( x ); }}java.lang.System.out
0.0
0.1
0.2
Während die erste Schleife zu viele Werte ausgab, gibt die zweite Schleife zu wenige aus.
Schleifen mit int-Werten
Bei aufwärts zählenden Zählschleifen mit int -Werten ist es der übliche Stil, das Minimum und den Deckel der Werte in die Schleife zu schreiben. Unter dem Deckel einer endlichen Menge ganzer Zahlen verstehen wir hier den auf das Maximum folgenden Wert. Dann wird »<« und nicht »<=« zum Vergleich verwendet.
Main.java
public final class Main
{ public static void main( final java.lang.String[] args )
{ for( int i = 0; i < 3; ++i )
java.lang.System.out.println( i ); }}java.lang.System.out
0
1
2
Einer der Vorteile dieses Verfahrens ist es, daß die Differenz zwischen den beiden geschriebenen Werten gerade die Anzahl der Durchläufe der Schleife angibt: 3 − 0 = 3.
Nachbildung von while mit for
Eine while -Schleife kann durch eine for -Schleife nachgebildet werden, indem der Bereich vor dem ersten und nach dem letzten Semikolon leer gelassen wird.
Main.java
public final class Main
{ public static void main( final java.lang.String[] args )
{ int i = 0; while( i < 3 )
java.lang.System.out.println( i++ ); }}java.lang.System.out
0
1
2Main.java
public final class Main
{ public static void main( final java.lang.String[] args )
{ int i = 0; for(; i < 3 ;)
java.lang.System.out.println( i++ ); }}java.lang.System.out
0
1
2
Endlosschleife
Eine Endlosschleife kann mit »while(true)« oder mit »for(;;)« als Schleifenkopf formuliert werden.
Iterative Implementation der Fakultät
Main.java
public final class Main
{public static int f( final int n )
{ int r = 1;
for( int i = 1; i <= n; ++i )r *= i;
return r; }public static void main( final java.lang.String[] args )
{ for( int i = 0; i < 6; ++i )
java.lang.System.out.println( i + " " + f( i ) ); }}java.lang.System.out
1 1
2 2
3 6
4 24
5 120
Struktogramm für for
f( n )
.---------------------------------.
| r := 1 |
|---------------------------------|
| for( int i = 1; i <= n; ++i ) |
| .------------------------------|
| | r := r * i |
|---------------------------------|
| return r |
'---------------------------------'
Ein Struktogramm muß nicht mit Java -spezifischen Bestandteilen formuliert werden. Wenn aber ein Struktogramm speziell für die Java -for -Schleife erstellt werden soll, dann ist es vielleicht am besten, den Schleifenkopf auch direkt in das Struktogramm zu schreiben, da ein Struktogramm keine spezielle graphische Form der Darstellung einer Java -for -Schleife vorsieht. Alternativ könnte die Java -for -Schleife auch in eine while -Schleife umformuliert werden, welche dann eine Basis für ein Struktogramm sein kann.
f( n )
.---------------------------------.
| r := 1 |
|---------------------------------|
| i := 1 |
|---------------------------------|
| i <= n |
| .------------------------------|
| | r := r * i |
| |------------------------------|
| | i := i + 1 |
|---------------------------------|
| return r |
'---------------------------------'
Durchlaufen von Reihungen mit einer Doppelpunkt-Schleife
Eine spezielle for -Schleife mit einer Deklarationen einer Laufvariablen für die Komponente, einem Doppelpunkt und der Reihung erlaubt es, alle Komponenten der Reihung nacheinander an die Laufvariable zuzuweisen.
- Startkommando
java Main alpha beta gamma
Main.java
public class Main
{ public static void main( final java.lang.String[] args )
{ for( final java.lang.String word : args )
java.lang.System.out.println( word ); }}- java.lang.System.out
alpha
beta
gammaMain.java
public final class Main
{
public static void p( final java.lang.String text )
{ java.lang.System.out.println( text ); }public static void trg( final java.lang.String wort )
{ p( "Tomaten" ); p( "Rotkohl Gruenkohl" ); p( wort ); }public static void main( final java.lang.String[] args )
{ for
( final java.lang.String word:
new java.lang.String[]{ "Gurken", "Spinat", "Kohlrabi" })
trg( word ); }}transcript
Tomaten
Rotkohl Gruenkohl
Gurken
Tomaten
Rotkohl Gruenkohl
Spinat
Tomaten
Rotkohl Gruenkohl
Kohlrabi
Durchlaufen von Reihungen mit einer klassischen for -Schleife
So ist es auch möglich, die Reihung mit einer klassischen for -Schleife zu durchlaufen. Dies geht auch manchmal nicht anders, wenn die Reihung in einer speziellen Weise durchlaufen werden soll (etwa von hinten nach vorne) oder der Index in der Schleife benötigt wird.
- Startkommando
java Main alpha beta gamma
- Main.java
public class Main
{ public static void main( final java.lang.String[] args )
{ for( int i = args.length - 1; i >= 0 ; i = i - 1 )
java.lang.System.out.println( i + ": " + args[ i ]); }}- java.lang.System.out
2 gamma
1 beta
0 alpha
Übungsfragen
Main.java
public class Main
{public static void f(){ java.lang.System.out.println( "f" ); }
public static void g(){ java.lang.System.out.println( "g" ); }
public static void main( final java.lang.String[] args )
{ for( int i = 0; i == 0; f() ){ g(); i = i + 1; }}}
Übungsaufgaben
Übungsaufgaben, zu deren Lösung auch Schleifen geschrieben werden können, finden sich in einer separaten Lektion mit Übungsaufgaben am Ende des Grundkurses.