Zählschleifen

<-- zurck zur Startseite | <- eine Seite vor | eine Seite weiter ->

  1. Arbeitsweise von Zählschleifen
  2. besondere Verhaltensweisen
  3. Zählschleifen verschachteln
  4. Übung
  5. Lösung

Schleifen dienen dazu, bestimmte Programmteile mehrfach ausführen zu können, aber nur einmal zu tippen. Oft werden alle Schleifen in einen Topf geworfen, aber ich möchte trotzdem eine Unterscheidung vornehmen, die allgemein geläufig ist.
Java kennt 3 verschiedene Arten von Schleifen:

  1. die Zählschleife (for-Schleife)
  2. die abweisende Bedingungsschleife (while-Schlife)
  3. die nicht-abweisende Bedingungsschleife (do-Schleife)

nach oben

2. Arbeitsweise von Zählschleifen

Die Bedingungsschleifen sind Gegenstand des nächsten Kapitels, zunächst sehen wir uns die Zählschleife an: im Gegensatz zu den Bedingungsschleifen muss man bei Zählschleifen schon vorher wissen, wie oft genau das Programm an dieser Stelle wiederholt werden soll. Wie oben angedeutet, wird eine Zählschleife mit dem Schlüsselwort for eingeleitet. Syntax:

for (startwert; bedingung; schrittweite) {
    // eine oder mehrere Anweisungen
}

Wir brauchen für diese Art der Schleife 3 Elemente: die Schrittweite gibt an, wie bei jedem Durchlauf der Startwert geändert werden soll. Die Bedingung schließlich muss einen booleschen Wert zurückgeben, ergo muss sie aus Vergleichsoperatoren (und evtl. logischen Operatoren bestehen).
Achtung: die Bedingung muss so gewählt werden, dass die Schleife auch mal verlassen werden kann und nicht in einer Endlosschleife endet, aus der man nur mit einem gewaltsamen Programmabbruch wieder herauskommt!
Sehen wir uns ein typisches Beispiel einer for-Schleife an und zählen die Ziffern von 0 bis 9 auf:

for (int i=0; i<10; i++) {
  System.out.println("Durchlauf: " + i);
}

Zuerst wird ein Startwert festgelegt, meist ein Integer-Wert wie hier. Natürlich muss diesem auch gleich ein Wert zugewiesen werden. Startwert soll 0 sein, weil die erste Ziffer, die wir auflisten wollen, die 0 sein soll. Als Kriterium haben wir i<10 gewählt: solange i kleiner als 10 ist, wird die Schleife durchlaufen. Erreicht i den Wert 10, wird die Schleife nicht mehr ausgeführt, sondern übersprungen! Jetzt müssen wir natürlich noch dafür sorgen, dass die Bedingung auch mal nicht erfüllt ist, damit die Schleife verlassen werden kann (man sagt auch "terminieren"): wir erhöhen bei jedem Schleifendurchlauf um 1 und wählen daher als Schrittweite i=i+1 (oder kürzer: i++), damit wir auch alle Ziffern erwischen und nicht welche überspringen. Der Wert wird übrigens erst nach jedem Schleifendurchlauf verändert:
Das Programm gelangt an die Stelle der Schleife. Jetzt überprüft es, ob die Bedingung (i<10) erfüllt ist. Da beim ersten Mal i noch 0 ist, ergibt die Bedingung 0<10 und ist damit erfüllt: die Schleife wird durchlaufen und "Ziffer: 0" auf den Bildschirm geschrieben. Am Ende der Schleife wird die Variable i gemäß der Schrittweite um 1 erhöht und hat jetzt den Wert 1.
Die Bedingung wird erneut geprüft und ist wieder erfüllt (1<10): die Schleife wird erneut durchlaufen und wieder der Wert von i ausgegeben, der jetzt schon 1 beträgt. Am Ende wird i wieder inkrementiert (um 1 erhöht) usw. bis i schließlich den Wert 9 hat und zum letzten Mal die Bedingung erfüllt ist (9<10). Jetzt wird die Schleife ein letztes Mal durchlaufen, da am Ende der Wert von i auf 10 erh&#246;ht wird und damit die Bedingung nicht mehr erf&#252;llt wird (<![CDATA[10<10 stimmt nicht!). Jetzt wird die Schleife nicht mehr ausgeführt, sondern das Programm springt an deren Ende und arbeitet den Rest des Programms ab.
Nochmal der Hinweis darauf, dass ein Abbruchkriterium vorliegen muss, damit die Schleife wieder verlassen werden kann. Eine vermurkste Schleife und nicht zur Nachahmung empfohlen wäre:

for (int i=0; i<10; i--) {
   System.out.println("Durchlauf: " + i);
}

i würde hier niemals 10 erreichen, weil es bei 0 startet und dann schrittweise um 1 erniedrigt statt erhöht wird. Dann kann man zusehen, wie das Programm läuft und läuft und läuft...

nach oben

3. besondere Verhaltensweisen

Wenn man, wie in unserem Beispiel, nur eine einzige Anweisung innerhalb der Schleife hat, kann man auch wieder die geschweiften Klammern weglassen:

for (int i=0; i<10; i++)
    System.out.println("Durchlauf: " + i);

Wie wir an unserem Beispiel sehen, wurde bis jetzt die Zählvariable erst bei der Schleifendeklaration angelegt. Das hat folgende wichtige Konsequenz: die Variable ist nur innerhalb der Schleife gültig. Von außen kann daher nicht auf sie zugegriffen werden! Natürlich könnte man auch eine schon vorher deklarierte Variable als Zählvariable verwenden:

int i;
for (i=0; i<10; i++)
    System.out.println("Durchlauf: " + i);

Damit ist die Variable i nicht nur innerhalb der Schleife, sondern auch außerhalb bekannt. Für gewöhnlich wird aber die Zählvariable zusammen mit der Schleife deklariert. So bleibt dessen Verwendung kontrollierbarer. Außerdem sieht man so sofort, um welchen Datentyp es sich bei der Zählvariablen handelt.

In Java ist es zudem möglich, mehrere Variablen für die Schleife zu initialisieren. Diese werden dann durch Kommata getrennt:

for (int i=0, j=5; i<j*3; i+=j)
   System.out.println("Wert von i: " + i);

Allerdings ist dies nur beim Startwert zulässig: einen Kommaoperator, der auch für die Bedinung und die Schrittweite gilt, gibt es in Java im Gegensatz zu C/C++ nicht!
Allerdings dürfen, wie in C/C++, die einzelnen Bestandteile der Schleifeninitialisierung frei bleiben: Startwert und Schrittweite fallen dabei einfach unter den Tisch (es wird keine Zählvariable angelegt, bzw. ihr Wert wird nicht verändert), für die Bedingung setzt der Compiler, wenn sie weggelassen wird, einfach "true" ein, was einer Endlosschleife gleichkommt.
Eine Endlosschleife kann also minimal so geschrieben werden:

for (;;) {
  System.out.println("Hallo!");
}

Hier wird werder eine Zählvariable angelegt noch wird diese verändert. Da auch die Bedingung fehlt, setzt der Compiler "true" ein und die Schleife läuft bis ins Unendliche. Von den ursprünglichen Komponenten, die hier weggelassen werden, zeugen aber noch die beiden Strichpunkte, die Startwert, Bedingung und Schrittweite trennen.
Selbstverständlich kann man auch nur z.B. den Startwert weglassen, wenn dieser schon vorher angelegt wurde:

int i=0;
for (; i<10; i++)
    System.out.println("Durchlauf: " + i);

Hier wurde der Startwert weggelassen, d.h. nicht explizit angelegt und zugewiesen. Die Schleife wird trotzdem auf die Variable i zugreifen und sie bis 10 hochzählen, anschließend die Schleife verlassen. Allerdings ist hier die Variable i auch wieder außerhalb der Schleife sichtbar. Sie könnte nach der Schleife weiter benutzt werden und hätte da den Wert 10.

nach oben

4. Zählschleifen verschachteln

Wie bei bedingten Anweisungen lassen sich auch mehrere Schleifen ineinander schachteln:

for (int i=1; i<=4; i++) {
  for (int j=1; j<=4; j++) {
    System.out.print("Durchlauf der Schleife aussen: " + i + "; ");
    System.out.println("Durchlauf der Schleife innen: " + j);
  }
}

Zum Programmfluss brauche ich kaum mehr Worte verlieren, anhand dieser Ausgabe sollte alles klar sein:

screenshot

Wenn man sich die Ausgabe dieses kleinen Programms ansieht, stellt man fest, dass für jeden Durchlauf der äußeren Schleife die innere Schleife komplett abgearbeitet wird, sprich, bei jedem der 4 Durchläufe der äußeren Schleife wird jedes Mal die innere Schleife neu initialisiert und jedes Mal bis zum Ende durchlaufen. Insgesamt also werden 4*4=16 Zeilen ausgegeben.

nach oben

5. Übung

  1. Schreibe ein Programm, das die Fakultät von 7 berechnet! (7! = 1*2*3*4*5*6*7)
  2. Ändere die von mir vorgestellte, geschachtelte for-Schleife dahingehend, dass jeweils das Produkt von i und j errechnet wird. Versuche, die so entstehende Multiplikationstabelle lesbar zu gestalten.

nach oben

6. Lösung

Aufgabe 1:

public class Fakultaet {

  public static void main(String[] args) {
    int ergebnis = 1;
    for (int i=2; i<=7; i++)
         ergebnis *= i;
    System.out.println("Fakultaet von 7: " + ergebnis);
  }

}

Aufgabe 2:

public class Multiplikationstabelle {

  public static void main(String[] args) {
    for (int i=1; i<=4; i++) {
      for (int j=1; j<=4; j++)
           System.out.print(i*j + "\t");
      System.out.println();
    }
  }

}

nach oben