Bisher haben wir gesehen, dass man den Programmablauf ändern kann und der Benutzer entscheiden kann, ob er beispielsweise eine Multiplikation oder eine Addition durchführen will. Was aber, wenn er nach der ersten Addition eine weitere ausführen möchte, oder dann vielleicht doch mal eine Multiplikation? Was, wenn das Programm nicht einfach nach der ausgeführten Berechnung enden soll?

In diesem Fall müssen wir den Code immer wieder ausführen, bis eine Bedingung nicht mehr erfüllt ist und das Programm dann beendet. D.h. das Programm müsste in einer Schleife laufen. Iterative Anweisungen, auch Schleifen genannt, führen einen Codeblock solange aus, wie eine Bedingung true ist. Es gibt drei verschiedene Varianten von Schleifen. Die while und for Anweisungen prüfen zunächst eine Bedingung, bevor ein Codeblock ausgeführt wird und die do ... while Anweisung führt erst den Codeblock aus und prüft dann die Bedingung.

Die while Anweisung

Eine while Anweisung wiederholt einen Codeblock genau solange, wie eine gegebene Bedingung true ist. Die Syntax sieht so aus:

while (condition) {
    statements ...
}

In einer while Schleife kann der auszuführende Codeblock aus einem oder mehreren Anweisungen bestehen. Es ist aber auch bei nur einer Anweisung eine gute Idee, diese in geschweifte Klammern zu setzen – zumindest habe ich mir das so angewöhnt. Dieser Codeblock wird solange ausgeführt, solange die Bedingung (condition) true ist. Sobald die Bedingung false ist, wird der Codeblock nicht mehr ausgeführt und der Programmablauf geht nach der Schleife weiter.

Die Bedingung kann entweder ein Ausdruck oder eine initialisierte Variable sein. Allerdings muss die Bedingung an sich oder der Codeblock der Schleife irgendetwas tun, damit sich irgendetwas am Wert der Bedingung oder Variablen ändert, ansonsten würde die Schleife endlos laufen.

// whileLoop.cpp

#include <iostream>

using namespace std;

int main() {

    char userSelection = 'm';  // initial value

    while(userSelection != 'x') {

        cout << "Enter the two integers: " << endl;
        int num1 = 0;
        int num2 = 0;
        cin >> num1;
        cin >> num2;

        cout << num1 << " x " << num2 << " = " 
             << num1 * num2 << endl;
        cout << num1 << " + " << num2 << " = " 
             << num1 + num2 << endl;

        cout << "Press x to exit(x) or any other " 
             << "key to recalculate" << endl;
        cin >> userSelection;
    }

    cout << "Goodbye!" << endl;

    return 0;
}
Enter the two integers:
12
23
12 x 23 = 276
12 + 23 = 35
Press x to exit(x) or any other key to recalculate
a
Enter the two integers:
45
34
45 x 34 = 1530
45 + 34 = 79
Press x to exit(x) or any other key to recalculate
x
Goodbye!

Die meiste Programmlogik ist in der while Schleife enthalten. Die while Anweisung kontrolliert die Bedingung (userSelection != 'x') und führt den folgenden Codeblock nur aus, wenn diese Bedingung true ist. Damit diese Bedingung beim ersten Ausführen true ist, haben wir die char Variable userSelection zu Beginn mit einem 'm' initialisiert.

Die do ... while Schleife

Es gibt Fälle (wie auch im vorangegangenen Programm), wo man zunächst wenigstens einmal einen gegebenen Codeblock ausführen möchte und danach erst eine Bedingung prüfen will. Für solche Fälle ist die do ... while Schleife hilfreich. Die Syntax sieht so aus:

do {
    statements...
} while (condition);

Wichtig ist hier, dass die Zeile mit der while (condition) Anweisung mit einem Semikolon abschließt. Das war bei der while Scheife anders, dort würde die Schleife nicht funktionieren, wenn wir die while (condition) Zeile mit einem Semikolon beendet hätten.

// doWhileLoop.cpp

#include <iostream>

using namespace std;

int main() {

    char userSelection = 'm';  // initial value

    do {

        cout << "Enter the two integers: " << endl;
        int num1 = 0;
        int num2 = 0;
        cin >> num1;
        cin >> num2;

        cout << num1 << " x " << num2 << " = " 
             << num1 * num2 << endl;
        cout << num1 << " + " << num2 << " = " 
             << num1 + num2 << endl;

        cout << "Press x to exit(x) or any other " 
             << "key to recalculate" << endl;
        cin >> userSelection;
    } while (userSelection != 'x');

    cout << "Goodbye!" << endl;

    return 0;
}
Enter the two integers:
55
44
55 x 44 = 2420
55 + 44 = 99
Press x to exit(x) or any other key to recalculate
b
Enter the two integers:
687
36
687 x 36 = 24732
687 + 36 = 723
Press x to exit(x) or any other key to recalculate
x
Goodbye!

Das Programm verhält sich genauso, wie unser while Beispiel. Der einzige Unterschied ist das do Schlüsselwort und die Benutzung von while etwas weiter unten.

Die for Schleife

Die for Anweisung ist etwas durchdachter. In ihr kann man eine Variable deklarieren und initialisieren, die dann z.B. als Zähler fungieren könnte. Dann kontrolliert man eine Bedingung und zusätzlich inkrementiert man die Variable. Das alles spielt sich im Kopf der Schleife ab. Die Syntax sieht so aus:

for (initial statement; condition; expression) {
    statements...
}

Die for Schleife wurde speziell für diesen Fall entworfen: Es wird ein Zähler definiert mit einem Startwert, dann wird dieser Wert am Anfang der Schleife gegen eine Bedingung geprüft und am Ende eines Durchlaufs wird dieser Wert geändert …

Was jetzt vielleicht etwas kryptisch klingt, wird in einem Beispiel deutlicher:

// forLoop01.cpp

#include <iostream>

using namespace std;

int main() {

    const int ARRAY_LENGTH = 5;
    int myNums[ARRAY_LENGTH] = {0};

    cout << "Populate array of " << ARRAY_LENGTH 
         << " integers" << endl;
    
    for (int count = 0; count < ARRAY_LENGTH; ++count) {

        cout << "Enter an integer for element " 
             << count << ": ";
        cin >> myNums[count];
    }

    cout << "Displaying contents of the array: " << endl;

    for (int i = 0; i < ARRAY_LENGTH; ++i) {

        cout << "Element " << i << " = "
             << myNums[i] << endl;
    }

    return 0;
}
Populate array of 5 integers
Enter an integer for element 0: 89
Enter an integer for element 1: 54
Enter an integer for element 2: 72
Enter an integer for element 3: 57
Enter an integer for element 4: 90
Displaying contents of the array:
Element 0 = 89
Element 1 = 54
Element 2 = 72
Element 3 = 57
Element 4 = 90

Die Angabe der Initialisierung einer Variablen, Der Bedingung und der Änderung dieser Variablen nach einem Durchlauf ist optional. Man kann auch for Schleifen schreiben, ohne einer dieser Angaben zu benutzen.

//anotherForLoop.cpp

#include <iostream>

using namespace std;

int main() {

    // without loop expression (3rd expression missing)
    for (char userSelection = 'm'; userSelection != 'x';) {

        cout << "Enter the two integers: " << endl;
        int num1 = 0;
        int num2 = 0;
        cin >> num1;
        cin >> num2;

        cout << num1 << " x " << num2 << " = " 
             << num1 * num2 << endl;
        cout << num1 << " + " << num2 << " = "
             << num1 + num2 << endl;

        cout << "Press x to exit or any other "
             << "key to recalculate" << endl;
        cin >> userSelection;
    }

    cout << "Goodbye!" << endl;

    return 0;
}

Dieses Programm verhält sich im Grunde genauso wie unsere while Schleife von eben. Interessant ist, dass wir hier nur die char Variable initialisiert haben und die Bedingung für die Schleife festgelegt haben.

Man könnte übrigens auch mehrere Variablen initialisieren, wenn man diese Initialisierungen mit einem Komma trennt:

for (int counter 1 = 0, counter2 = 5;
     counter1 < ARRAY_LENGTH;
     ++counter1, --counter2) ...

for für einen vorgegebenen Bereich

Seit C++11 hat der Standard eine neue for Schleifen Variante eingeführt, die man aus anderen Programmiersprachen, wie bspw. Python, auch kennt. Die Variante läuft über eine bestimmte Anzahl von Elementen, wie z.B. den Elementen eines Arrays:

for (varType varName: sequence) {
    // use varName that contains an element from sequence
}

Wenn ich z.B. ein Array habe mit Integer Zahlen someNums, könnte ich eine Bereichs-for Schleife nehmen, um die einzelnen Elemente des Arrays auszulesen:

int someNums[] = {1, 101, -1, 40, 2040};

for (int aNum : someNums) { // range based for loop
    cout << "Element: " << aNum << endl;
}

Übrigens: Man könnte die Schleife noch etwas vereinfachen, wenn man den Typ des Elements automatisch bestimmen lässt. Mit dem Schlüsselwort auto kann man quasi eine generische for Schleife schreiben, die für jede Art von Datentyp funktioniert:

for (auto anElement : elements) { // range based for
    cout << "Element: " << anElement << endl;

Schleifen, die niemals enden…

Bisher haben immer Schleifen geschrieben, die eine Bedingung erfüllen mussten, damit sie funktionieren. Beim nicht-Erfüllen dieser Bedingung brach die Schleife ab. Wenn man allerdings eine Bedingung programmiert, die immer true ist, endet die Schleife niemals:

while (true) { // while expression fixed to true
    DoSomethingRepeatedly; ...
}
for (; ;) { // no condition supplied = unending for
    DoSomethingRepeatedly; ...
}

So seltsam es auch scheinen mag, solche unendlichen Schleifen haben ihre Daseinsberechtigung. Man stelle sich ein Betriebssystem vor, dass ständig prüfen muss, ob ein USB Stick im USB Port eingesteckt wurde, oder nicht. Diese Tätigkeit sollte nicht unterbrochen werden, solange das Betriebssystem läuft. Solche Funktionen benötigen eine unendliche Schleife.

Unendliche Schleifen kontrollieren

Um eine unendliche Schleife zu beenden, muss man ein break einfügen, dass wir ja schon bei der <a href="http://tropone.de/2020/04/30/audio-programmierung-06-c-grundlagen-die-kontrolle-des-programmablaufs-switch-case/">switch</a> Verzweigung kennengelernt haben:

while (true) {  // while condition fixed to true
    DoSomethingRepeatedly;
    if (expression) {
        break;  // exit loop when expression is true
    }
}

Das folgende Programm zeigt wie man unendliche Schleifen programmiert und mit continue und break ein Ausstiegskriterium kontrolliert.

//infiniteLoop.cpp

#include <iostream>

using namespace std;

int main() {

    for (;;) {  // an infinite loop

        cout << "Enter two numbers: " << endl;
        int num1 = 0;
        int num2 = 0;
        cin >> num1;
        cin >> num2;

        cout << "Do you wish to correct the numbers? (y/n): ";
        char changeNumbers = '\0';
        cin >> changeNumbers;

        if (changeNumbers == 'y') {
            continue;  // restart loop!
        }

        cout << num1 << " x " << num2 << " = " 
             << num1 * num2 << endl;
        cout << num1 << " + " << num2 << " = "
             << num1 + num2 << endl;

        cout << "Press x to exit or any other "
             << "key to recalculate" << endl;
        char userSelection = '\0';
        cin >> userSelection;

        if (userSelection = 'x') {
            break;  // exit the infinite loop!
        }
    }  // end of infinite for loop

    cout << "Goodbye!" << endl;

    return 0;
}
Enter two numbers:
12
23
Do you wish to correct the numbers? (y/n): y
Enter two numbers:
34
45
Do you wish to correct the numbers? (y/n): n
34 x 45 = 1530
34 + 45 = 79
Press x to exit or any other key to recalculate
x
Goodbye!

Dieses Programm benutzt einen for(;;) Befehl, um eine unendliche Schleife zu erzeugen. Man hätte natürlich genauso gut ein while(true) oder do...while(true) benutzen können.

Soviel erstmal zu den einfachen Schleifen. Das nächste mal spreche ich über verschachtelte Schleifen…