Kontrollstrukturen (1) Selektionen, if ermöglicht das alternative Ausführen von Programteilen in Abhängigkeit einer Bedingung if (Bedingung) Block 1 else Block 2 Ist die Bedingung wahr, also ungleich 0, so wird der erste Block (if- Block) ausgeführt, andernfalls der zweite Block (else-block) ein Block ist entweder eine einzelne Anweisung oder eine durch geschweifte Klammern zusammengefasste Gruppe von Anweisungen
Kontrollstrukturen (2) Selektionen, if Wird der else-zweig nicht benötigt, bleibt dieser leer if (Bedingung) Block ist nur der else-zweig relevant, muss die Bedingung invertiert und der entsprechende Block im if-zweig untergebracht werden, z.b. if (!Bedingung) Block
Kontrollstrukturen (3) Selektionen, if Die if-anweisungen können auch geschachtelt werden eine else-anweisung gehört immer zum nächstliegenden if, nur diese Regel ist für den Compiler wichtig Einrückungen dienen nur der Lesbarkeit, der Compiler beachtet sie nicht; auf eine korrekte Einrückung ist zu achten if (Bedingung 1) if (Bedingung 2) Block 1 else Block 2 else if (Bedingung 3) Block 3 else Block 4
Kontrollstrukturen (4) Selektionen, if Verschachtelte if-anweisungen können zu einer kaskadenförmigen Einrückung führen stattdessen wird oft eine rechenförmige Einrückung verwendet, mit der entsprechend zusammengehörige Bedingungen visualisiert werden if (a == b) printf("a und b sind gleich groß.\n"); else if (a < b) printf("a ist kleiner als b.\n"); else if (a > b) printf("a ist größer als b.\n );
Kontrollstrukturen (5) Selektionen, if Rechenförmige Einrückung if (a == b) printf("a und b sind gleich groß.\n"); else if (a < b) printf("a ist kleiner als b.\n"); else if (a > b) printf("a ist größer als b.\n ); letzte Bedingung ist redundant, sie kann also weggelassen werden
Kontrollstrukturen (6) Selektionen, if if (a == b) printf("a und b sind gleich groß.\n"); else if (a < b) printf("a ist kleiner als b.\n"); else printf("a ist größer als b.\n ); Wichtig: ersten else-zweig nicht weglassen, da danach nur noch auf kleiner abgeprüft wird und dann keine korrekte Auswertung erfolgt
Kontrollstrukturen (7) Selektionen, switch ermöglicht selektive Ausführung von beliebig verschiedenen Programmteilen switch wertet die Bedingung aus und führt den Programmteil aus, dessen Sprungmarke mit dem Ergebnis übereinstimmt break sorgt für die Beendigung des Programmteils, der durch die Marke adressiert wird ein Programmteil kann mehrere Marken haben, die einfach untereinander geschrieben werden existiert keine passende Marke, wird zu default verzweigt existiert auch default nicht, so wird switch ohne weitere Aktionen beendet
Kontrollstrukturen (8) Selektionen, switch switch (Ausdruck) {case Marke1: Anweisungen break; case Marke2: Anweisungen break;... default: Anweisungen break;
Kontrollstrukturen (9) Selektionen, switch Beispiele für die switch-anweisung switch (zahl) {case 1: } case 2: case 3: default: printf("eins\n"); break; printf("zwei\n"); break; printf("drei\n"); break; printf("sonst\n"); break; switch (zahl) {case 0: zahl = zahl + 1; case 1: zahl = zahl + 1; case 2: zahl = zahl + 1; case 3: zahl = zahl + 1; case 4: zahl = zahl + 1; case 5: zahl = zahl + 1; case 6: zahl = zahl + 1; case 7: zahl = zahl + 1; case 8: zahl = zahl + 1; case 9: zahl = zahl + 1; }
Kontrollstrukturen (10) Iterationen, for vorprüfende Schleife Verwendung von Iteratoren Syntax und Beispiel: for (Initialisierung; Bedingung; Inkrement) Block for (i = 0; i < 10; i = i + 1) printf("%ld\n", i); Initialisierungsteil wird vor Schleifeneintritt durchlaufen Bedingungsteil wird vor jedem Schleifendurchlauf geprüft, Schleifenblock wird durchlaufen, solange die Bedingung wahr ergibt Vorteil: Verhalten der Schleife wird in einer einzigen Zeile ausgedrückt
Kontrollstrukturen (11) Iterationen, while vorprüfende Schleife, d.h. vor jeder Ausführung der Schleifenblocks wird die Bedingung geprüft. Syntax: while (Bedingung) Block Ändert sich die Schleifenbedingung im Block so dass sie zum Abbruch führen würde, so wird dies erst bei der nächsten regulären Prüfung festgestellt Verwendung der While-Schleife genau dann, wenn sich die bedingungsrelevanten Variablen im Schleifenblock ändern Mögliche Fehler: while (Bedingung); Block
Kontrollstrukturen (12) Iterationen, do... while nachprüfende Schleife Syntax: do Block while (Bedingung); Unterschied zur while-schleife: der Block wird mindestens einmal durchlaufen, bevor die Schleife aufgrund der Bedingung abgebrochen wird wenn die Bedingung wahr ist, wird die Schleife wiederholt Mögliche Fehlerquelle: das Semikolon am Ende der Anweisung ist zwingend erforderlich ein gern gemachter Fehler ist, dass es weggelassen wird
Kontrollstrukturen (13) Iterationen, Besonderheiten der for-anweisung die drei durch Semikolon getrennten Teilausdrücke müssen nicht zwingend präsent sein, falls sie nicht gebraucht werden die Semikolons müssen auf jeden Fall vorhanden sein war der Schleifenzähler vor Eintritt richtig gesetzt, kann man dessen Initialisierung auch weglassen for (; i <= 10; i = i + 1) printf("%ld\n", i); Nachteil: die Anzahl der Schleifendurchläufe ist nicht mehr klar ersichtlich
Kontrollstrukturen (14) Iterationen, Besonderheiten der for-anweisung for-schleife kann prinzipiell auch als while-schleife dargestellt werden: i = 1; for (; i <= 10;) { printf("%ld\n", i); } i = i + 1; der Inkrement-Ausdruck steht jetzt im Schleifenrumpf, was semantisch unklug ist die Schleife ist vollkommen äquivalent zu i = 1; while (i <= 10) { printf("%ld\n", i); } i = i + 1;
Kontrollstrukturen (15) Iterationen, Besonderheiten der for-anweisung bei Weglassen der Bedingung entsteht eine Endlosschleife for (i = 0; ; i = i + 1) printf("%ld\n", i); falls unabhängig von Variablen ein Vorgang immer wieder wiederholt werden muss, kann dies durch folgende Konstrukte erfolgen: for (;;) //... while (1) //...
Kontrollstrukturen (16) Iterationen, Besonderheiten der for-anweisung Sollen mehrere Initialisierungen vorgenommen werden, können diese im Initialisierungsteil durch Kommas getrennt aufgeführt werden entsprechend ist das für mehrere Inkrement-Ausdrücke im Inkrement- Teil möglich Beispiel für eine Berechnung der Potenzen von 1 bis 2 10 : for (i = 0, n = 1; i <= 10; i = i + 1, n = n * 2) printf("%2ld ^ %2ld = %4ld\n", 2L, i, n); Falls das zu unübersichtlich wird, kann man die zweite Laufvariable auch extra behandeln n = 1; for (i = 0; i <= 10; i = i + 1) { printf("%2ld ^ %2ld = %4ld\n", 2L, i, n); n = n * 2; } // end for
Kontrollstrukturen (17) Iterationen, continue wird verwendet, um vorzeitig zur nächsten Schleifeniteration überzugehen Beispiel: const long teiler = 3; long i; for (i = 0; i <= 10; i = i + 1) { if ((i % teiler) == 0) continue; // Abbruch, Übergang zum nächsten // Schleifendurchlauf printf("die Zahl %ld ist durch %ld nicht teilbar.\n", i, teiler); }
Kontrollstrukturen (18) Funktionen, Definition beinhaltet Angabe des Funktionsnamens, des Rückgabetyps, der Parameter und des kompletten Funktionsrumpfes (die eigentliche Funktion) Typ Funktionsname (Parameterliste) { Funktionsrumpf } //end Funktionsname nicht zu verwechseln mit einer Funktionsdeklaration, die nur die Existenz der Funktion anzeigt, welche an anderer Stelle definiert ist
Kontrollstrukturen (19) Funktionen, Definition zur Übersicht sollte der Funktionsname noch einmal am Ende der Funktionsdefinition als Kommentar erscheinen Funktionsnamen unterliegen denselben Einschränkungen wie Namen von Variablen und Konstanten. Ist ein Name schon für eine Variable oder Konstante vergeben, kann er nicht mehr für eine Funktion verwendet werden Konvention ist oft, Funktionsnamen mit einem Großbuchstaben zu beginnen
Kontrollstrukturen (20) Funktionen, Parameter Funktionen können eine beliebige Anzahl von Parametern haben, werden in einer Parameterliste innerhalb von runden Klammern nach dem Funktionsnamen durch Kommas getrennt angegeben für jeden Parameter wird sein Typ festgelegt summe(double x, double y) { printf("die Summe von %g und %g lautet %g\n", x, y, x+y) } // end summe main() { double wert1, wert2; // lokale Var.m existiert nur in dieser Fkt. printf("erste Zahl: "); scanf("%lf", &wert1); printf("zweite Zahl: "); scanf("%lf", &wert2); summe(wert1, wert2); } // end main
Kontrollstrukturen (21) Funktionen, Parameter Reihenfolge der Parameter ist signifikant hat eine Funktion keine Parameter, so bleibt die Parameterliste leer Ausgabe() { printf("hallo Welt!\n"); } // end Ausgabe es kann auch der Typ void verwendet werden, der angibt, dass die Parameterliste leer ist Ausgabe(void)
Kontrollstrukturen (22) Funktionen, Rückgabewerte Funktionen können einen Rückgabewert haben Typ des Rückgabewertes muss bei Funktionsdefinition genannt werden wird der Rückgabetyp weggelassen so wird automatisch der Rückgabetyp int angenommen falls kein Rückgabewert benötigt wird, kann dies explizit durch void angegeben werden der Wert selbst wird durch den return-befehl an den Aufrufer zurückgegeben double Summe(double x, double y) { double ergebnis; // lokale Var., nur in Fkt. sichtbar ergebnis = x + y; return ergebnis; } // end Summe
Kontrollstrukturen (23) Funktionen, Rückgabewerte ist der zurückgegebene Typ nicht gleich dem im Funktionskopf angegebenen Typ, so findet eine Typumwandlung statt auch die Funktion main liefert einen Rückgabewert: int Signalisierung, ob ein Fehler aufgetreten ist Bedeutung der Rückgabewerte ist betriebssystemabhängig
Kontrollstrukturen (24) Funktionen, Rückgabewerte Unix/Linux: bei normaler Funktionsbeendigung wird 0 als Rückgabewert gegeben ist der Rückgabewert nicht null, so wird durch den zurückgegebenen Wert eine Fehlernummer zurückgegeben, die Rückschluss auf den Fehler gibt MSDOS, MS Windows 1 bedeutet, dass das Programm erfolgreich ausgeführt wurde 0 signalisiert einen Fehler Makro EXIT_SUCCESS liefert den Wert für eine erfolgreiche Ausführung Makro EXIT_FAILURE liefert den Wert für eine fehlerhafte Ausführung beide Makros sind in der stdlib.h definiert