Bisher: Strikte Ablauf des Programms von oben nach unten (sequenziell)
Jetzt: Abhängig von der Eingabe anderes Programmverhalten
Heute: Einfache Wiederholung von Befehlen und alternative Programmabläufe
if und else#include <stdio.h>
int main() {
int eingabe = 2, ergebnis = 0;
if (eingabe % 2 == 0) {
ergebnis = eingabe * eingabe;
} else {
ergebnis = eingabe + eingabe;
}
printf("ergebnis = %d\n", ergebnis);
return 0;
}
Was genau ist (eingabe % 2 == 0) eigentlich?
Logischer Datentyp (bool)
true und falsebool b;b = true;Logische Operatoren
| Name | Symbol | Beispiel |
|---|---|---|
| UND (AND) |
&& | b && (x < 7) |
| ODER (OR) |
|| | b || x > 8 |
| Negation (NOT) |
! | !b |
(Die logischen Operatoren werden in Kapitel 5 noch einmal im Detail besprochen.)
Welche Kombination von booleschem Ausdruck und Wert wird angenommen?
#include <stdio.h>
int main() {
int x = 10;
if (x = 9) {
printf("Evaluiert zu 'true' (x: %d)", x);
} else {
printf("Evaluiert zu 'false' (x: %d)", x);
}
}
true und 10true und 9false und 10false und 9C kennt nur 0 oder 1 (bzw. nicht 0)
→ Falls Ausdruck genau 0, dann false
→ Falls Ausdruck ungleich 0, dann true
Im Hintergrund implizite Umwandlung von skalarem Typ zu booleschem Ausdruck
Historie
true/false nicht (wurde mit C++ eingeführt), stattdessen nur 0/10/1 warentrue/false feste Schlüsselwörterint main() {
int x = 10;
char c = 'c';
if (x);
if (0.000001);
if (0.0);
if (c);
if ("Hello World");
if ("");
}
int main() {
int x = 10;
char c = 'c';
if (x); // true
if (0.000001); // true
if (0.0); // false (das entspricht genau 0)
if (c); // true
if ("Hello World"); // true
if (""); // true (Literal enthält immer das NULL-Byte)
}
Zurück zum Kontrollfluss!
#include <stdio.h>
int main() {
int eingabe = 6, ergebnis = 0;
if (eingabe % 2 == 0) {
ergebnis = eingabe * eingabe;
} else if (eingabe % 3 == 0) {
ergebnis = eingabe - 3;
} else {
ergebnis = eingabe + eingabe;
}
printf("ergebnis = %d\n", ergebnis);
return 0;
}
else if möglich → Kette aus OptionenBedingungen müssen in Klammern gesetzt werden → if (...)
Schließt die Verkettung mit else unbedingt ab
→ else hat daher keinen zugehörigen Ausdruck
Der erste if-Ausdruck wird immer evaluiert
Die erste Verzweigung mit wahrer Bedingungen wird genommen
→ Reihenfolge der Abfragen ist relevant!
Ein if kann alleine stehenn; else if und else sind optional
Achtung: Ein else bezieht sich nur auf das letzte if
#include <stdio.h>
int main() {
int sum = 0;
if (sum < 0) {
sum += 10;
}
if ((sum + 10) > 100) {
sum += 100;
}
else {
printf("%d", sum);
}
return 0;
}
else bezieht sich nur auf das letzte if#include <stdio.h>
int main() {
int sum = -1;
if (sum < 0)
sum += 10;
printf("Sum wurde um 10 erhöht");
return 0;
}
if-Statement gehört nur die erste Anweisung danach#include <stdio.h>
int main() {
int sum = -1;
if (sum < 0) {
sum += 10;
printf("Sum wurde um 10 erhöht");
}
return 0;
}
if-Anweisung wird immer noch nur eine Anweisung ausgeführtif und else können mehrere Bedingungen geprüft werdensum auf zehn verschiedene Werte prüfen#include <stdio.h>
int main() {
int sum = -1;
if (sum == 0) {
sum += 10;
printf("Sum wurde um 10 erhöht");
} else if (sum == 1) {
sum += 10;
} else if (sum == 2) {
sum += 20;
} else if (sum == 3) {
sum += 21;
} else if (sum == 4) {
sum += 3;
} else if (sum == 5) {
sum +=11;
} else {
sum = -10;
}
return 0;
}if-else gut für wenige Fälle geeignetswitch und casecase 4711#include <stdio.h>
int main() {
int sum = 0;
switch (sum) {
case -1:
printf("-1\n");
break;
case 0:
printf("0\n");
break;
default:
printf("Kein passender Wert\n");
break;
}
return 0;
}
#include <stdio.h>
int main() {
int sum = 0;
switch (sum) {
case 0:
printf("0");
case 1:
printf("1");
case 2:
printf("2");
break;
default:
printf("Kein passender Wert");
break;
}
return 0;
}
break-Anweisung#include <stdio.h>
int main() {
int sum = -1;
if (sum == 0) {
sum += 10;
} else if (sum == 1) {
sum += 10;
} else if (sum == 2) {
sum += 20;
} else if (sum == 3) {
sum += 20;
} else if (sum == 4) {
sum += 3;
} else if (sum == 5) {
sum += 3;
} else {
sum = -10;
}
printf("sum = %d\n", sum);
return 0;
}switch-Anweisung verbessern?#include <stdio.h>
int main() {
int sum = -1;
switch (sum) {
case 0:
case 1:
sum += 10;
break;
case 2:
case 3:
sum += 20;
break;
case 4:
case 5:
sum += 3;
break;
default:
sum = -10;
}
printf("sum = %d\n", sum);
return 0;
}
Für ein einfaches if-else gibt es in C den ternären/konditionalen Operator
Braucht als einziger Operator 3 Bestandteile (→ Namensherkunft)
Syntax: expression1 ? expression2 : expression3
expression1 wird ausgewertet und als bool betrachtet
expression1 == true → wird expression2 ausgeführtexpression1 == false → wird expression3 ausgeführtexpression2/expression3: Beliebiger Ausdruck (Zahl/Wert, Code-Schnipsel, …)
#include <stdio.h>
int main() {
bool b = true;
int i = 0;
b ? printf("1\n") : printf("2\n");
i = b ? 3: 4;
printf("%d\n", i);
return 0;
}
if-else dient der bedingten Ausführung von Code-Blöckenswitch-case vereinfacht den Umgang mit vielen Verzweigungengoto#include <stdio.h>
int main() {
int sum = 0;
ziel: // Label wie bei Switch-Case
sum += 10;
if (sum > 4711) {
printf("%d", sum);
return 0; // Ende von main()
}
else {
goto ziel; // Sprung zum benannten Label
}
return 0;
}
gotogoto sieht auf den ersten Blick relativ harmlos und nützlich aus🚨 Verwendet niemals goto! 🚨
goto → Schleifentrue istwhiledo-whilefor#include <stdio.h>
int main() {
int i = 0; // Laufvariable
while (i < 10) { // Auswertung *vor* Betreten des Rumpfes
++i; // Fortschritt
printf("%d\n", i);
} // Springt zurück zum Kopf
return 0;
}
Vorzeitiges Verlassen von Schleifen ist möglich mithilfe von break
(→ Kennt Ihr schon von switch-case)
#include <stdio.h>
int main() {
int i = 0;
while (i < 10) {
++i;
if (i == 3) {
break;
}
}
printf("%d\n", i);
return 0;
}
#include <stdbool.h> // Für C-Standard < C23
#include <stdio.h>
int main() {
int i = 0;
while (true) { // Potenziell unendlich
++i;
if (i >= 3) {
break; // Stattdessen Kontrolle mit break
}
}
printf("%d\n", i);
return 0;
}
#include <stdio.h>
int main() {
int i = 0;
do {
++i;
} while (i < 2);
printf("%d\n", i);
return 0;
}
while-Schleife
while-Schleife ist gut, im Allgemeinen aber mehr Schreibaufwandfor-Schleife bietet etwas andere und lesbarere Schreibweisefor(init-clause; cond-expression; iteration-expression) { loop-statement }
#include <stdio.h>
int main() {
for (int i = 0; i < 10; ++i) {
printf("%d ", i); // 0 1 2 3 4 5 6 7 8 9
}
// Laufvariable i ist ab hier nicht mehr bekannt
}
#include <stdio.h>
int main() {
for (int i = 0, j = 2; i < 10; ++i, j += 2) {
j -= 1;
printf("%d %d, ", i, j);
}
}
for und while sind funktionsgleich!#include <stdio.h>
int main() {
for (int i = 0; i < 10; ++i) {
printf("%d ", i);
}
}
#include <stdio.h>
int main() {
int i = 0;
while (i < 10) {
printf("%d ", i);
++i;
}
}
if-else bestimmen, welcher Code ausgeführt wirdswitch-case als sinnvolle Alternative zu langen if-else-Kettenwhile- und do-while-Schleifenfor-Schleifen zur Kapslung der relevanten Teil in einer ZeileWir müssen dank Schleifen nicht mehr jeden Schleifendurchlauf manuell tippen 🎉
… aber: Was ist, wenn wir die Schleife mehrfach nutzen wollen?
Wir haben das Problem teilweise gelöst:
Für unterschiedliche Startwerte muss trotzdem jedes Mal neu getippt werden (✅)