Teil 12 „Looping“

Der C-Kurs
Antworten
Benutzeravatar
bodo
User
Beiträge: 322
Registriert: 14.02.2007, 17:21
Kontaktdaten:

Teil 12 „Looping“

Beitrag von bodo » 30.10.2010, 17:05

C für BASIC-Programmierer

Arbeiten mit dem z88dk Cross-Compiler

von Jens Sommerfeld und Bodo Wenzel

Teil 12

Bisher waren unsere C-Programme ja eher langweilig, weil sie immer nur geradeaus liefen, vielleicht einmal aufgelockert durch eine Verzweigung. In diesem Teil kommen wir endlich zum „Looping“!

Kurzschreibweisen für Berechnungen

Bevor es aber damit losgeht, sollt ihr noch ein paar nette Kurzschreibweisen für häufige Anweisungen kennen lernen.

Solche Anweisungen sind Berechnungen, die z. B. so aussehen:

Code: Alles auswählen

    variable = variable + 23;
Der Inhalt der Variablen wird also mit einem Wert verknüpft und das Ergebnis wieder der Variablen zugewiesen. Zunächst ist das problemlos, aber das doppelte Eintippen des Variablennamens ist zum einen lästig, zum anderen auch etwas fehlerträchtig, wenn ich mich vertippe. Daher kennt C eine Kurzform solcher Berechnungen:

Code: Alles auswählen

    variable += 23;
Der Operator kann jeder der binären Operatoren sein, außer den logischen („&&“ und „||“). Warum die gerade nicht, tja, wer weiß das schon?! Der Ausdruck auf der rechten Seite muss auch nicht unbedingt eine Konstante sein, sondern kann auch komplex sein.

Und für die häufigsten dieser Berechnungen gibt es noch eine weitere Vereinfachung.

Code: Alles auswählen

    variable += 1;
    variable -= 1;
... könnt ihr jeweils verkürzen zu den Inkrement- und Dekrement-Operatoren:

Code: Alles auswählen

    variable++;
    variable--;
Jetzt ahnt ihr auch, warum C++ so heißt: es ist die nächste Stufe nach C, also C erhöht um eins. Warum heißt es nicht D? Das müsst ihr Bjarne Stroustrup fragen, seinen Erfinder. Es gibt übrigens tatsächlich eine Sprache D (http://www.digitalmars.com/d/index.html), die auch von C abgeleitet ist...

Eventuell habe ich euch das schon erzählt: jede Zuweisung ist auch gleichzeitig ein Ausdruck. Er hat den Datentyp und den Wert des zugewiesenen Ergebnisses. Ebenso ist es mit dem Inkrement und dem Dekrement. Hier gibt es allerdings zwei Varianten zu unterscheiden:

Code: Alles auswählen

    var1 = 42;
    var2 = ++var1; /* var1 ist danach 43, ebenso var2 */

    var1 = 81;
    var2 = var1--; /* var1 ist danach 80, var2 aber 81! */
Es kommt also auf die Position des Operators an: steht er vor der Variablen, wird erst die Berechnung ausgeführt, und dann der Wert des Gesamtausdrucks bestimmt. Steht der Operator nach der Variablen, gilt der „alte“ Variablenwert als Wert des Gesamtausdrucks.

Schleifen... endlich!

Die bekannte FOR-Schleife kennt C natürlich auch. Sie kommt mit einem einzigen Schlüsselwort aus:

Code: Alles auswählen

#include <stdio.h>

int main(void) {
    int i;

    for (i = 1; i <= 10; i++) {
        printf("%d\n", i);
    }

    return 0;
}
Wie bei „if“ kommt nach dem Schlüsselwort ein Paar runder Klammern. Darin stehen drei Teile, durch Semikolons getrennt: die Initialisierungsanweisung, die Schleifenbedingung (ein Ausdruck, der als wahr oder falsch bewertet wird), und die Schleifenanweisung. Jeder dieser Teile darf auch leer sein. Wenn die Schleifenbedingung leer ist, wird die for-Schleife zu einer Endlosschleife. Mit folgendem Konstrukt tut das Programm gar nichts mehr, außer „sich im Kreis zu drehen“:

Code: Alles auswählen

    for (;;);
Nach den runden Klammern kommt eine einzelne Anweisung oder ein Anweisungsblock, der in geschweiften Klammern steht. Das ist der Teil, der beim BASIC zwischen FOR-TO und NEXT steht.

Im Beispiel oben seht ihr eine simple Zählschleife, die von 1 bis 10 zählt und den jeweiligen Zählwert ausgibt. Aber es gibt auch ziemlich raffinierte Schleifen, die trotzdem prima lesbar sind. Im folgenden Beispiel ist die Anordnung der einzelnen Teile aufgelockert, um den Aufbau deutlich zu machen:

Code: Alles auswählen

    for (datei = finde_erste_datei();       /* 34 */
         datei != KEINE_DATEI;              /* 35 */
         datei = finde_naechste_datei()) {  /* 36 */
        bearbeite_datei(datei);             /* 37 */
    }
Anmerkung 34: Diese Funktion ermittelt die erste Datei aus einer Menge von Dateien, z.B. dem aktuellen Verzeichnis.
Anmerkung 35: Dies ist eine symbolische Konstante, die den Fall „Keine Datei gefunden“ repräsentiert. Dieser Wert wird von den beiden Funktionen zurückgegeben, wenn keine Datei (mehr) in der Menge ist.
Anmerkung 36: Diese Funktion ermittelt die nächste Datei aus einer Menge von Dateien, z.B. dem aktuellen Verzeichnis.
Anmerkung 37: Diese Funktion macht schließlich etwas mit der gefundenen Datei.

C kennt noch zwei weitere Schleifen, die häufig verwendet werden; eine kopfgesteuerte Schleife und eine fußgesteuerte Schleife. Beginnen wir mit der kopfgesteuerten Schleife:

Code: Alles auswählen

#include <stdio.h>

int main(void) {
    int i;

    i = 1;
    while (i <= 10) {
        printf("%d\n", i);
        i++;
    }

    return 0;
}
Sie heißt so, weil ihre Schleifenbedingung am Anfang steht, also am Kopf. Falls diese Bedingung bereits beim ersten Mal falsch ist, wird der zugehörige Anweisungsblock noch nicht einmal ausgeführt!

Das Beispiel ist übrigens vollständig gleichwertig mit dem Beispiel zur for-Schleife. Damit seht ihr auch, wann welcher Teil der for-Schleife ausgeführt wird. Die Initialisierungsanweisung wird genau einmal als allererstes ausgeführt. Vor jedem Schleifendurchlauf (auch dem ersten!) wird die Schleifenbedingung berechnet und bewertet. Wenn die Schleifenbedingung wahr ist, wird zunächst der Anweisungsblock ausgeführt. Erst als letztes wird die Schleifenanweisung ausgeführt.

Kommen wir jetzt zur fußgesteuerten Schleife. Hier wird die Schleifenbedingung erst am Fuß der Schleife abgefragt, wenn der zugehörige Anweisungsblock bereits durchlaufen wurde:

Code: Alles auswählen

#include <stdio.h>

int main(void) {
    int zahl;

    do {
        char zeile[10];

        printf("EINE ZAHL (0 = ENDE): ");
        gets(zeile);
        sscanf(zeile, "%d", &zahl);
        printf("\nDAS DOPPELTE VON %d IST %d\n", zahl, 2 * zahl);
    } while (zahl != 0);

    return 0;
}
So weit, so gut! C kennt noch zwei Schlüsselworte, die den Ablauf einer Schleife verändern:
  • „break“ beendet eine Schleife sofort, bei einer for -Schleife wird auch die Schleifenanweisung nicht mehr ausgeführt.
  • „continue“ bricht die Abarbeitung der Anweisungen im Anweisungsblock ab und macht mit der Schleifenbedingung weiter. Bei der for-Schleife wird aber vorher noch die Schleifenanweisung ausgeführt.
Ein Beispiel hilft sicher beim Verständnis. Bitte versucht vorherzusagen, was das Programm ausgibt, bevor ihr es ausprobiert:

Code: Alles auswählen

#include <stdio.h>

int main(void) {
    int i;

    for (i = 0; i < 200; i++) {
        if (i < 10) {
            continue;
        }
        printf("INNERHALB: %d\n", i);
        if (i > 20) {
            break;
        }
    }
    printf("ENDE MIT %d\n", i);

    return 0;
}
Die Sprunganweisung goto

Ja ja, es gibt auch in C Sprünge. Zum Glück sind aber die ganzen Steuerstrukturen wie Verzweigungen und Schleifen praktisch immer ausreichend, so dass ein Sprung fast nie benutzt werden muss. Er zerstört eigentlich auch immer den schönen Programmaufbau.

Aber sei's drum, wir wollen uns das trotzdem einmal ansehen! Bloß, wohin soll der Sprung gehen? C hat ja keine Zeilennummern... Die Antwort: C hat Labels, wie sie den Assemblerfreaks unter euch schon bekannt sind:

Code: Alles auswählen

#include <stdio.h>

int main(void) {
    int i;

    i = 1;
marke1:
    printf("%d\n", i);
    i++;
    if (i <= 10) {
        goto marke1;
    }

    return 0;
}
Hausaufgaben
  1. Schreibt das Zählprogramm mit der do-while-Schleife.
  2. Welchen Wert hat die Variable i nach der Schleife?

    Code: Alles auswählen

        for (i = 30; i > 7; i -= 12) {
            i += 4;
        }
  3. Schreibt das Zählprogramm so um, dass es rückwärts zählt. Versucht es mit allen drei Schleifenvarianten (for-, while- und do-while-Schleife).
  4. Schreibt ein Programm, das die Summe aller ganzen Zahlen zwischen 10 und 20 (jeweils inklusive) berechnet.
  5. Was ist falsch am folgenden Programmausschnitt?

    Code: Alles auswählen

        for (zaehler = 0; zaehler < 10; zaehler++);
            printf("ZAEHLER = %d\n", zaehler);
  6. Was ist falsch am folgenden Programmausschnitt?

    Code: Alles auswählen

        Index = 1;
        while (index <= 10)
            printf("INDEX = %d\n", index);
B0D0: Real programmers do it in hex.

Antworten