Grundlagen der Programmiersprache C für Studierende der Naturwissenschaften

Ähnliche Dokumente
Grundlagen der Programmiersprache C für Studierende der Naturwissenschaften

Einführung in die Programmierung für Physiker. Die Programmiersprache C Kontrollstrukturen

S. d. I.: Programieren in C Folie 4-1. im Gegensatz zu Pascal gibt es in C kein Schlüsselwort "then"

3. Anweisungen und Kontrollstrukturen

Java Anweisungen und Ablaufsteuerung

C-Propädeutikum Anweisungen

C- Kurs 04 Anweisungen

Objektorientierte Programmierung

Dr. Monika Meiler. Inhalt

Einstieg in die Informatik mit Java

Wintersemester Maschinenbau und Kunststofftechnik. Informatik. Tobias Wolf Seite 1 von 25

Schleifen in C/C++/Java

Einstieg in die Informatik mit Java

Java 8. Elmar Fuchs Grundlagen Programmierung. 1. Ausgabe, Oktober 2014 JAV8

4.4 Imperative Algorithmen Verzweigung und Iteration

4. Einfache Programmstrukturen in C Einfache Programmstrukturen in C

Wiederholungen / Schleifen

Kontrollfluss. man Verzweigungen und Sprünge. o bisher linear (von oben nach unten) o Für interessante Programme braucht

Schleifen in C/C++/Java

Schleifenanweisungen

Einstieg in die Informatik mit Java

Webbasierte Programmierung

FACHHOCHSCHULE AUGSBURG Hochschule für Technik, Wirtschaft und Gestaltung

Kontrollstrukturen -- Schleifen und Wiederholungen

Kontrollstrukturen (1)

2 Teil 2: Nassi-Schneiderman

Programmiersprache 1 (C++) Prof. Dr. Stefan Enderle NTA Isny

Dr. Monika Meiler. Inhalt

Java Ablaufsteuerung (Beispiele)

Grundlagen der Programmierung Teil1 Einheit III Okt. 2010

Einstieg in die Informatik mit Java

Modellierung und Programmierung 1

4.4 Imperative Algorithmen Prozeduren

Algorithmen & Programmierung. Steuerstrukturen im Detail Selektion und Iteration

Abschnitt 5. Grundlagen der funktionalen & imperativen Programmierung

Angewandte Mathematik und Programmierung

Intensivübung zu Algorithmen und Datenstrukturen

C++ Teil 2. Sven Groß. 16. Apr IGPM, RWTH Aachen. Sven Groß (IGPM, RWTH Aachen) C++ Teil Apr / 22

Bei der Und-Verknüpfung müssen beide Ausdrücke wahr sein, dass der gesamte Ausdruck wahr wird. a=1; b=2; a=1; b=3; else. endif

Einführung in die Programmierung II. 3. Kontrollstrukturen

Einstieg in die Informatik mit Java

Tagesprogramm

Kompaktkurs Einführung in die Programmierung. 4. Kontrollstrukturen

Tag 3 Repetitorium Informatik (Java)

4.2 Gleitkommazahlen. Der Speicherbedarf (in Bits) ist üblicherweise. In vielen Anwendungen benötigt man gebrochene Werte. Physikalische Größen

Praxisorientierte Einführung in C++ Lektion: "Kontrollstrukturen"

Grundlagen der Programmierung

Java - Schleifen. Bedingung. wiederhole. Anweisung Anweisung Anweisung. Leibniz Universität IT Services Anja Aue

Programmieren für Wirtschaftswissenschaftler SS 2015

ModProg 15-16, Vorl. 5

2.5 Programmstrukturen Entscheidung / Alternative

Kapitel 5. Programmierkurs. Kontrollstrukturen. Arten von Kontrollstrukturen. Kontrollstrukturen Die if-anweisung Die switch-anweisung

Wo sind wir? Kontrollstrukturen

Java: Eine kurze Einführung an Beispielen

Kontrollstrukturen. Wo sind wir? Anweisung mit Label. Block. Beispiel. Deklarationsanweisung

Übung zu Algorithmen und Datenstrukturen (für ET/IT)

Javakurs für Anfänger

Nachklausur: Grundlagen der Informatik I, am 02. April 2008 Dirk Seeber, h_da, Fb Informatik. Nachname: Vorname: Matr.-Nr.

Nachklausur: Grundlagen der Informatik I, am 02. April 2008 Dirk Seeber, h_da, Fb Informatik. Nachname: Vorname: Matr.-Nr.

EINI LW. Einführung in die Informatik für Naturwissenschaftler und Ingenieure. Vorlesung 2 SWS WS 11/12

Übung zu Algorithmen und Datenstrukturen (für ET/IT)

Prof. Dr. Oliver Haase Karl Martin Kern Achim Bitzer. Programmiertechnik Kontrollstrukturen

Einführung in die Programmierung Wintersemester 2011/12

Übung zur Vorlesung Wissenschaftliches Rechnen Sommersemester 2012 Auffrischung zur Programmierung in C++, 1. Teil

Grundlagen der Programmierung Teil1 Einheit III Okt. 2009

Grundlagen der Programmierung in C++ Kontrollstrukturen

JavaScript. Dies ist normales HTML. Hallo Welt! Dies ist JavaScript. Wieder normales HTML.

Gedächtnis. Während der Abarbeitung eines Algorithmus müssen sich Dinge gemerkt werden bzw. auf Dingen wird gerechnet. Zugriff.

Programmiertechnik Kontrollstrukturen

6. Kontrollanweisungen II

5. Kontrollanweisungen II

Einleitung Entwicklung in C Hello-World! Konstrukte in C Zusammenfassung Literatur. Grundlagen von C. Jonas Gresens

Übungen zur Vorlesung Wissenschaftliches Rechnen I. Grundelemente von Java. Eine Anweisung. wird mit dem Wertzuweisungsoperator = geschrieben.

3. Grundanweisungen in Java

Übung zur Vorlesung Wissenschaftliches Rechnen Sommersemester 2012 Auffrischung zur Programmierung in C++, 1. Teil

Bedingte Anweisungen

Einführung in die Programmierung

C- Kurs 03 Ausdrücke und Operatoren

Programmieren I. Kontrollstrukturen Heusch 8 Ratz Institut für Angewandte Informatik

Kapitel 4. Kontrollstrukturen

Labor Software-Entwicklung 1

Entscheidungen. INE1, Montag M. Thaler, Office TG ZHAW, M. Thaler, K. Rege, G. Burkert

Java Einführung ABLAUFSTEUERUNG Kapitel 3 und 4

Schachtelung der 2. Variante (Bedingungs-Kaskade): if (B1) A1 else if (B2) A2 else if (B3) A3 else if (B4) A4 else A

Grundlagen der Programmiersprache C für Studierende der Naturwissenschaften

5. Elementare Befehle und Struktogramme

C++ - Einführung in die Programmiersprache Schleifen

6. Kontrollanweisungen II

Grundlagen der Programmierung in C++ Kontrollstrukturen

Programmierkurs Java

Programmieren in C. Eine Einführung in die Programmiersprache C. Prof. Dr. Nikolaus Wulff

Transkript:

Grundlagen der Programmiersprache C für Studierende der Naturwissenschaften Teil 3: Schleifen- und Sprunganweisungen Patrick Schreier Abteilung für Angewandte Mathematik Vorlesung vom 03. Mai 2015

Gliederung Bedingte Anweisungen II Motivation Schleifenanweisungen for-schleife while, do-while-schleifen Sprunganweisungen Lösung gewöhnlicher Differentialgleichungen

Gliederung Bedingte Anweisungen II Motivation Schleifenanweisungen for-schleife while, do-while-schleifen Sprunganweisungen Lösung gewöhnlicher Differentialgleichungen

Programmbeispiel Quelltext (Wurzelberechnung mit Fehlerbehandlung) 1 #include <math.h> 2 #include <stdio.h> 3 4 int main(void) 5 { 6 /* declare floating point variable */ 7 double x; 8 9 /* read from user input */ 10 printf ("x = "); 11 scanf("%lf", &x); 12 13 if( x < 0 ) 14 { 15 printf("value x is less than zero\n"); 16 } 17 else 18 { 19 printf ("x = %f\n", x); 20 printf ("sqrt(x) = %f\n", sqrt(x)); 21 } 22 23 return 0; 24 }

if-else-anweisung Syntax: if(expr) statement else statement Ob die Anweisungen des if- oder des else-zweigs bearbeitet werden, hängt vom Kontrollausdruck ab: Ist der Kontrollausdruck wahr, so wird der if-zweig bearbeitet, sonst werden die Anweisungen des else-zweigs bearbeitet. Sowohl im if- als auch im else-zweig können mehrere Anweisungen zu jeweils einem Block zusammengefasst werden.

Dangling else Vorsicht bei verschachtelten Fallunterscheidungen: Der else-zweig gehört immer zum vorangehenden if-zweig! Beispiel: int a;... if(a >= 0) if(a == 0) printf("a equals 0\n"); else printf("a is negative number\n"); Der Code liefert eine falsche Ausgabe für a > 0. Man spricht vom dangling else.

Dangling else vermeiden Lösungsmöglichkeit 1 (leere Anweisung): int a;... if(a >= 0) if(a == 0) printf("a equals 0\n"); else ; else printf("a is negative number\n");

Dangling else vermeiden Lösungsmöglichkeit 1 (leere Anweisung): int a;... if(a >= 0) if(a == 0) printf("a equals 0\n"); else ; else printf("a is negative number\n"); Lösungsmöglichkeit 2 (Blöcke): int a;... if(a >= 0) { if(a == 0) printf( "a equals 0\n" ); } else printf("a is negative number\n");

if-else if Schreibweise Für komplexe, verschachtelte Fallunterscheidungen ist die folgende Schreibweise üblich: if(expr) statement else if(expr) statement else if(expr) statement... else statementn Der else-zweig und die Zusammenfassung von Anweisungen zu Blöcken ist wieder optional.

Vorsicht, Falle I Gleitpunktoperationen sind immer mit einem kleinen Fehler behaftet. Gleitpunktzahlen sollten daher nie auf exakte Gleichheit überprüft werden: double x = (0.1 + 0.2) + 0.3; double y = 0.1 + (0.2 + 0.3); if(x == y) /* will be false */... Stattdessen kann man prüfen, ob zwei Gleitpunktzahlen hinreichend nah beieinander liegen: if(fabs(x-y) < 1e-12)...

Vorsicht, Falle II Ein häufiger Fehler bei Vergleichen auf Gleichheit ist der folgende: if(x = 1) /* always true */... Der Kontrollausdruck besteht aus einer Zuweisung. Ihr Wert entspricht dem der linken Seite nach der Zusweisung (hier 1). Dies entspricht einer wahren Aussage. Analog ist der folgende Kontrollausdruck immer unwahr : if(x = 0) /* always false */...

switch-anweisung Die switch-anweisung prüft einen ganzzahligen Ausdruck auf mehrere konstante Alternativen hin ab. Syntax: switch(expr) { case const_expr1 : statement case const_expr2 : statement... } default : statementn Alle case-konstanten müssen unterschiedliche Werte haben. Stimmt der switch-ausdruck expr mit einer der case-marken überein, wird der Programmfluss hinter der Marke fortgesetzt. Die default-marke ist optional; stimmt der switch-ausdruck mit keiner der angegebenen Konstanten überein, wird die default-marke angesprungen.

break in switch-anweisungen Stimmt der switch-ausdruck mit einer der case-marken überein, werden alle Anweisungen danach ausgeführt auch solche, die hinter späteren Marken stehen. Sollen nur die Anweisungen ausgeführt werden, die zu einer case-marke gehören, muss dies explizit durch eine break-anweisung erzwungen werden: int n = 1; switch(n) { case 1: printf("n = 1\n"); break; case 3: printf("n = 3\n"); break; case 2: printf("n = 2\n"); break; default: printf("n >= 4\n"); }

Konditionaloperator Der einzige ternäre Operator ist der Konditionaloperator?: expr1? expr2 : expr3 Der Wert des Typ und Wert des Ausdrucks stimmt entweder mit dem von expr2 oder expr3 überein und zwar abhängig von expr1: Zuerst wird der Ausdruck expr1 ausgewertet. Ist expr1 ungleich Null, so heißt der Ausdruck wahr. Ist expr1 wahr, wird der Ausdruck expr2 ausgewertet, sonst expr3. Nur genau einer der Ausdrücke expr2, expr3 wird ausgewertet! Beispiel: c = (a < b)? a : b /* c = min{a, b} */

Inkrement- und Dekrement-Operatoren Um eine Variable um den Wert 1 zu erhöhen oder um den Wert 1 zu erniedrigen gibt es in C die unären Operatoren ++ (Inkrementoperator) und -- (Dekrementoperator). Die Operatoren können auf alle arithmetischen Typen angewandt werden, und stehen entweder vor (Präfix-Notation) oder hinter (Postfix-Notation) der Variablen: ++x x++ x x x wird um den Wert 1 erhöht, bevor x im Ausdruck weiterverwendet wird x wird um den Wert 1 erhöht, nachdem x im Ausdruck verwendet wurde x wird um den Wert 1 erniedrigt, bevor x im Ausdruck weiterverwendet wird x wird um den Wert 1 erniedrigt, nachdem x im Ausdruck verwendet wurde Beispiel: int a = 0, b = 2; ++a; /* a = 1 */ b--; /* b = 1 */

Seiteneffekte Jeder Zuweisungsausdruck darf selbst wieder in einem Ausdruck auftauchen: int a = 1, b; b = (a += 1) + 1; /* a = 2, b = 3 */ Solche verschachtelten Ausdrücke verursachen sog. Seiten- oder Nebeneffekte, d. h. neben der Auswertung des Ausdrucks wird durch die Zuweisung auch der Wert einer Variablen geändert. Seiteneffekte machen den Code schwer lesbar und sind damit potentielle Fehlerquellen. Beispiel (Inkrement-Operatoren): int i, j, k; i = 1; j = i++; /* j = 1, side effect: i = 2 */ k = ++i; /* k = 3, side effect: i = 3 */

Komma-Operator Das Komma kennen wir bislang als Trennzeichen in Variablendefinitionen: int a1, a2, a3, a4; Es gibt auch den Komma-Operator: expr1, expr2 Seine Semantik ist etwas gewöhnungsbedürftig: Zuerst wird der Ausdruck expr1 ausgewertet, dann expr2. Der Typ und Wert des Gesamtausdrucks ist der Typ und der Wert des zweiten Operanden expr2. Beispiel: int a; double x; a = 1, x = 2.; /* value of expression is 2. */

Gliederung Bedingte Anweisungen II Motivation Schleifenanweisungen for-schleife while, do-while-schleifen Sprunganweisungen Lösung gewöhnlicher Differentialgleichungen

Schleifenanweisungen Schleifenanweisungen... sind Kontrollanweisungen, die die sonst sequentielle Verarbeitung der Programmanweisungen ändern. führen eine Anweisung (oder mehrere Anweisungen in einem Block) wiederholt aus. werden erst beendet, wenn ein vorher angegebenes Abbruchkriterium erreicht ist (oder die Schleife mit einer Sprunganweisung verlassen wird). In C gibt es mehrere Schleifenanweisungen zur Verfügung (for-, while- und do-while-schleife).

Auswertung monomialer Ausdrücke Wir wollen ein Programm schreiben, dass die n-potenz x n einer reellen Zahl x berechnet. Der Definition eines Ausdrucks lässt sich nicht immer auch gleich ein geeigneter Algorithmus zu seiner Auswertung entnehmen: n x n = x, i=1 n x = x }. {{.. x }, n Mal i=1 0 x = 1. i=1 Für unsere Zwecke besser geeignet ist die Darstellung in rekursiver Form: x n+1 = x x n, x 0 = 1.

Algorithmus in Pseudo-Code Wir halten den der rekursiven Formulierung oben entsprechenden Algorithmus in Form von Pseudo-Code fest. Pseudo-Code (n-te Potenz): y 1 for i = 0, 1,..., n-1 y x*y return y % initialization % number of iterations is fixed % loop body, y is updated in each step Im obigen Verfahren wird der Wert von y in jedem Iterationsschritt überschrieben. Damit kommt dem Startwert y 1 besondere Bedeutung zu.

Gliederung Bedingte Anweisungen II Motivation Schleifenanweisungen for-schleife while, do-while-schleifen Sprunganweisungen Lösung gewöhnlicher Differentialgleichungen

for-schleife Die for-schleife hat von allen Schleifenanweisungen die aufwändigste Syntax. Syntax: for(expr1; expr2; expr3) statement Der erste Ausdruck expr1 heißt Initialisierungsausdruck. Er wird vor dem Kontrollausdruck und nur ein einziges Mal ausgewertet.

for-schleife Die for-schleife hat von allen Schleifenanweisungen die aufwändigste Syntax. Syntax: for(expr1; expr2; expr3) statement Der erste Ausdruck expr1 heißt Initialisierungsausdruck. Er wird vor dem Kontrollausdruck und nur ein einziges Mal ausgewertet. An zweiter Stelle steht der Kontrollausdruck. Er wird vor dem ersten und dann nach jedem weiteren Schleifendurchlauf bewertet. Die Schleife wird beendet, sobald der Kontrollausdruck unwahr ist.

for-schleife Die for-schleife hat von allen Schleifenanweisungen die aufwändigste Syntax. Syntax: for(expr1; expr2; expr3) statement Der erste Ausdruck expr1 heißt Initialisierungsausdruck. Er wird vor dem Kontrollausdruck und nur ein einziges Mal ausgewertet. An zweiter Stelle steht der Kontrollausdruck. Er wird vor dem ersten und dann nach jedem weiteren Schleifendurchlauf bewertet. Die Schleife wird beendet, sobald der Kontrollausdruck unwahr ist. Der dritte Ausdruck wird nach jedem Schleifendurchlauf ausgewertet. Normalerweise werden hier Schleifenvariablen inkrementiert oder dekrementiert.

Programmbeispiel (n-te Potenz) In einer for-schleife lässt sich die n-te Potenz wie folgt berechnen: int i, n; double x, y;... /* initialize x, n */ y = 1.; for(i = 0; i < n; ++i) y *= x; Zur Wahl der einzelnen Ausdrücke in der Schleife: for( i = 0 ; i < n; ++i) An erster Stelle steht der Initialisierungsausdruck. In C beginnen Laufindizes in der Regel bei 0.

Programmbeispiel (n-te Potenz) In einer for-schleife lässt sich die n-te Potenz wie folgt berechnen: int i, n; double x, y;... /* initialize x, n */ y = 1.; for(i = 0; i < n; ++i) y *= x; Zur Wahl der einzelnen Ausdrücke in der Schleife: for(i = 0; i < n; ++i ) Nach jedem Schleifendurchlauf muss der Laufindex i inkrementiert werden.

Programmbeispiel (n-te Potenz) In einer for-schleife lässt sich die n-te Potenz wie folgt berechnen: int i, n; double x, y;... /* initialize x, n */ y = 1.; for(i = 0; i < n; ++i) y *= x; Zur Wahl der einzelnen Ausdrücke in der Schleife: for(i = 0; i < n ; ++i) Der Kontrollausdruck sorgt dann dafür, dass die Schleife soll nach n Iterationen beendet wird.

Auswertung der Fakultät Ein weiteres einfaches Beispiel zur Verwendung der for-schleife ist die Auswertung der n-ten Fakultat: n! = n i = 1 2... n. i=1 Dieser Ausdruck lässt sich leicht in Pseudo-Code übertragen: Pseudo-Code (Fakultät): y 1 for i = 1, 2,..., n y i*y return y % initialization % range based iteration % index i is used in loop statement

Programmbeispiel (Auswertung der Fakultät) Wie das folgende Programmbeispiel illustriert, ist es ohne weiteres möglich, den Laufindex i im Schleifenkörper zu verwenden: int factorial, i, n;... /* initialize n */ for(factorial = 1, i = 1; i <= n; ++i) factorial *= i; Es kann mehr als eine Variable im ersten Ausruck der Schleife initialisiert werden (Komma-Operator). Analog können auch die übrigen Ausdrücke komplexer gestaltet werden: for(factorial = 1, i = 1; i <= n; factorial *= i++) ;

Gliederung Bedingte Anweisungen II Motivation Schleifenanweisungen for-schleife while, do-while-schleifen Sprunganweisungen Lösung gewöhnlicher Differentialgleichungen

Beispiel: Der Euklidische Algorithmus Der Euklidische Algorithmus ein klassisches Verfahren zur Berechnung des größten gemeinsamen Teilers zweier natürlicher Zahlen a, b. In Pseudo-Code lautet der Algorithmus: Pseudo-Code (Euklidischer Algorithmus): if a = 0 return b while b 0 if a > b a a - b else b b - a return a Die Anzahl der Iterationsschritte (Anweisungen innerhalb von while und return) hängt von den Eingabegrößen a und b ab und ist nicht a-priori bekannt.

while-schleife Die while-schleife hat von allen drei C-Schleifen die einfachste Syntax: while(expr) statement Der Ausdruck expr heißt Kontrollausdruck. Er muss von einem arithmetischen Typ (oder ein Zeiger) sein. Der Kontrollausdruck wird mit allen Seiteneffekten ausgewertet. Ist er wahr (d. h. ungleich 0), wird die folgende Schleifenanweisung statement wiederholt ausgeführt.

while-schleife Die while-schleife hat von allen drei C-Schleifen die einfachste Syntax: while(expr) statement Der Ausdruck expr heißt Kontrollausdruck. Er muss von einem arithmetischen Typ (oder ein Zeiger) sein. Der Kontrollausdruck wird mit allen Seiteneffekten ausgewertet. Ist er wahr (d. h. ungleich 0), wird die folgende Schleifenanweisung statement wiederholt ausgeführt. Nach jedem Schleifendurchlauf wird der Kontrollausdruck erneut ausgewertet.

while-schleife Die while-schleife hat von allen drei C-Schleifen die einfachste Syntax: while(expr) statement Der Ausdruck expr heißt Kontrollausdruck. Er muss von einem arithmetischen Typ (oder ein Zeiger) sein. Der Kontrollausdruck wird mit allen Seiteneffekten ausgewertet. Ist er wahr (d. h. ungleich 0), wird die folgende Schleifenanweisung statement wiederholt ausgeführt. Nach jedem Schleifendurchlauf wird der Kontrollausdruck erneut ausgewertet. Ist der Kontrollausdruck unwahr, wird die Schleife beendet.

Abweisende Schleife Ob und wie häufig der Schleifenkörper (auch Schleifenrumpf genannt) durchlaufen wird, hängt vom Kontrollausdruck ab. In einer while-schleife wird der Kontrollausdruck vor dem Eintritt in die Schleife und bei jedem erneuten Schleifendurchlauf ausgewertet. Die while-schleife heißt auch abweisende Schleife: Ist der Kontrollausdruck bereits vor Eintritt in die Schleife unwahr, wird der Schleifenkörper nie durchlaufen (d. h. die nach while folgende Anweisung wird nicht ausgeführt).

Programmbeispiel (Euklidischer Algorithmus) Quelltext #include <stdio.h> int main(void) { int a, b; printf("enter a: "); scanf("%d", &a); printf("enter b: "); scanf("%d", &b); if(a == 0) { printf("greatest common divisor(a,b) = %d\n", b); return 0; } while(b!= 0) { if(a > b) a -= b; else b -= a; } printf("greatest common divisor(a,b) = %d\n", a); return 0; }

Endlosschleifen Eine Schleife wird erst verlassen, wenn der Kontrollausdruck unwahr ist. Wird das Abbruchkriterium nie erreicht (d. h. bleibt der Kontrollausdruck immer wahr), kommt es zu einer Endlosschleife: while(1) ; /* results in infinite loop */ Hängt ein Programm in einer Endlosschleife fest, muss es vom User oder vom System abgebrochen werden. Der Compiler kann eine Endlosschleifen nicht entdecken: das Programm ist syntaktisch korrekt!

Gleitpunktzahlen in Kontrollausdrücken Auch das folgende Beispiel liefert eine Endlosschleife: float x = 1./9.; while(x!= 1.) x += 1./9.; Aufgrund von unvermeidbaren Approximationsfehlern liefert der Kontrollausdruck x!= 1. stets den Wert 0 ( Unwahr ). Eine Lösung dieses Problems könnte so aussehen: float x = 0.1; while(x <= 1.0) x += 0.1;

do-while-schleife Die do while-schleife funktionert ähnlich wie eine while-schleife mit dem Unterschied, dass der Schleifenkörper mindestens einmal durchlaufen wird. Syntax: do statement while(expr); Die Anweisung statement (auch ein Block ist erlaubt) wird ausgeführt, danach wird der Kontrollausdruck expr ausgewertet.

do-while-schleife Die do while-schleife funktionert ähnlich wie eine while-schleife mit dem Unterschied, dass der Schleifenkörper mindestens einmal durchlaufen wird. Syntax: do statement while(expr); Die Anweisung statement (auch ein Block ist erlaubt) wird ausgeführt, danach wird der Kontrollausdruck expr ausgewertet. Dies wird solange wiederholt ausgeführt, wie der Kontrollausdruck wahr ist.

do-while-schleife Die do while-schleife funktionert ähnlich wie eine while-schleife mit dem Unterschied, dass der Schleifenkörper mindestens einmal durchlaufen wird. Syntax: do statement while(expr); Die Anweisung statement (auch ein Block ist erlaubt) wird ausgeführt, danach wird der Kontrollausdruck expr ausgewertet. Dies wird solange wiederholt ausgeführt, wie der Kontrollausdruck wahr ist. Ist der Kontrollausdruck unwahr, wird die Schleife verlassen.

Äquivalenz von for- und while-schleife Alle Schleifenanweisungen sind äquivalent, d. h. man kann jede der drei Schleifen durch jede der jeweils anderen beiden in Verbindung mit bedingten Anweisungen ersetzen. Eine for-schleife beispielsweise for(expr1; expr2; expr3) statement lässt sich stets äquivalent als while-schleife formulieren: expr1 while(expr2) { statement expr3 }

Gliederung Bedingte Anweisungen II Motivation Schleifenanweisungen for-schleife while, do-while-schleifen Sprunganweisungen Lösung gewöhnlicher Differentialgleichungen

Sprunganweisungen Sprunganweisungen ändern den sequentiellen Programmablauf, indem ohne weitere Bedingungen an eine andere Stelle im Programm (im Quellcode) gesprungen wird. In C gibt es die folgenden Sprunganweisungen: break continue goto return Sprunganweisungen werden gebraucht... um Schleifen oder eine switch-anweisung (s. u.) zu verlassen oder um ein Programm oder eine Funktion zu beenden.

break-anweisung Die break-anweisung bewirkt, dass die innerste umgebende Schleife einer for-, while- oder do while-anweisung oder eine switch-anweisung sofort verlassen wird. Syntax: break; Beispiel: int i = 0; while(1) /* no infinite loop due to break */ { i++; if(i > 99) break; }

continue-anweisung Die continue-anweisung darf nur innerhalb einer for-, whileoder do while-schleife verwendet werden. Sie bewirkt, dass der aktuelle Schleifendurchlauf beendet wird und die Schleife mit der nächsten Iteration fortgesetzt wird. Syntax: continue; Beispiel: int i; for(i = 0; i < 10; ++i) { if(i%2) continue; printf("%d is an even number\n", i); }

return-anweisung Die return-anweisung beendet eine Funktion. Handelt es sich bei dieser Funktion um main, so wird das Programm beendet. Syntax: return expr; Manche Funktionen (z. B. main) geben einen Wert zurück. Dies geschieht im Quellcode durch den Aufruf von return. Rückgabetyp und -wert stimmen dann mit expr überein. Auch return gehört zu den Sprunganweisungen: der Programmfluss wird an der Stelle fortgesetzt, an der die Funktion aufgerufen wurde.

DIE Sprunganweisung goto Mit der Sprunganweisung goto kann an eine beliebige andere, mit einer Marke ausgezeichnete Stelle (innerhalb derselben Funktion) gesprungen werden: 11: printf( "First I'm here." ); 12: goto label; 126: label: 127: printf( "Now I'm here.");

Marken und Sprunganweisung Eine Marke (engl. label) zeichnet eine mögliche Einsprungstelle im Quellcode für die goto-anweisung aus. Marken können an jeder beliebigen Stelle im Quellcode stehen. Eine Marke besteht aus einem Bezeichner und einem Doppelpunkt: label: statement Dem Standard nach muss auf eine Marke mindestens eine Anweisung (auch eine leere Anweisung) folgen. Mit der Sprunganweisung goto label; wird eine Marke innerhalb derselben Funktion angesprungen.

Kritik an goto Die goto-anweisungen wird häufig kritisch kommentiert. Das Urteil ist nicht immer einheitlich. Pro: + Tief verschachtelte Schleifen können z. B. im Fehlerfall gezielt verlassen werden. Contra: - Die Sprunganweisung kann immer mit anderen Sprachmitteln vermieden werden. - Extensiver Gebrauch macht Programme schwer lesbar und damit fehleranfällig. Manche Programmiersprachen unterbinden die Verwendung von goto (z. B. Java). Im Handbuch der Skriptsprache Lua hingegen werden die Vorteile unter bestimmten Bedingungen betont.

Akademisches Beispiel: Schleifen mit goto Mit bedingten Sprunganweisungen (d. h. Kombination von if + goto) lassen sich die oben vorgestellten Schleifenanweisungen simulieren. Beispielsweise ist der folgende Code int i; i = 0; loop: if(i < 10) { printf("i = %d\n", i); ++i; goto loop; } äquivalent zu der for-schleife: int i; for(i = 0; i < 10; ++i) printf("i = %d\n", i);

Gliederung Bedingte Anweisungen II Motivation Schleifenanweisungen for-schleife while, do-while-schleifen Sprunganweisungen Lösung gewöhnlicher Differentialgleichungen

Bakterienwachstum Obwohl wir erst wenige Sprachmittel zur Verfügung haben, können wir bereits einige interessante Fragestellungen praktisch untersuchen. Wir betrachten das Wachstum eines Bakterienkultur über einen Zeitraum [0, T ]. Zu Beginn der Beobachtung t = 0 werden p 0 Bakterien geschätzt. Wir möchten ein Programm näherungsweise bestimmen lassen, wie groß die Bakterienpopulation p in der Probe zum Zeitpunkt t [0, T ] ist.

Mathematische Modellierung I Angenommen, die Zahl der Bakterien p(t) zum Zeitpunkt t ist bekannt. Wir beobachten, dass sich kurze Zeit später, zum Zeitpunkt t + t, die Population wie folgt verändert hat: p(t + t) = p(t) + tλp(t). Wir formulieren die obige Gleichung um zu p(t + t) p(t) t = λp(t). Lassen wir nun t 0 gehen, so erhalten wir die gewöhnliche Differentialgleichung: p (t) = λp(t) für t (0, T ).

Mathematische Modellierung II Die Größe der Population ist zum Zeitpunkt t = 0 bekannt. Die Lösung p erfüllt also das Anfangswertproblem p (t) = λp(t) für t (0, T ), p(0) = p 0. Das obige Problem hat eine eindeutige Lösung, die wir sogar angeben können: p(t) = p 0 e λt Im allgemeinen sind in Anwendungen keine Lösungen in geschlossener analytischer Form gegeben. Dann ist man auf numerische Verfahren angewiesen.

Numerisches Verfahren Sei t eine gewählte Zeitschrittweite, dann setzen wir t k = k t. Gesucht sind Näherungen p k p(t k ), wobei der Anfangswert p 0 bekannt ist. Aus der Näherung p(t + t) p(t) + tλp(t) erhalten wir die folgende Vorschrift: p k+1 = p k + tλp k. Dieses sog. explizite Verfahren lässt sich sehr einfach implementieren.

Komplettes Programmbeispiel Quelltext (Unbeschränktes Wachstum) #include <stdio.h> int main(void) { double initial =.5; double rate = 1.; double time, endtime = 4.; double deltat = 0.05; double population; for(time = 0., population = initial; time < endtime; time += deltat) { printf("%f %f\n", time, population); population += deltat*rate*population; } printf("%f %f\n", time, population); return 0; }

Visualisierung von Daten I Das obige Programm liefert je nach gewählter Zeitschrittweite t eine große Menge an Daten. Daten werden in der Regel zur späteren Verarbeitung (Postprocessing) in Dateien gespeichert. Für den Moment nutzen wir dazu die Unix-Shell. Ausgabe in Datei population.out umleiten: $./population > population.out Aufruf von gnuplot und Plotten der Daten: $ gnuplot gnuplot> plot "population.out"

Visualisierung von Daten II 30 numerical solution exact solution 25 20 Population p(t) 15 10 5 0 0 0.5 1 1.5 2 2.5 3 3.5 4 Time t Abbildung : Ergebnis für λ = 1, p 0 = 0.5, t = 0.05

Logistisches Wachstum I Beim sog. logistischen Wachstum wird die Populationsgröße durch eine Kapazitätsgrenze C beschränkt. Das modifizierte mathematische Modell lautet: p (t) = λ(c p(t))p(t) für t (0, T ), p(0) = p 0 mit p 0 C. Aus der Herleitung oben erhalten wir die folgende Vorschrift: p k+1 = p k + tλ(c p k )p k.

Logistisches Wachstum II 1.4 1.2 numerical solution exact solution 1 Population p(t) 0.8 0.6 0.4 0.2 0 0 0.5 1 1.5 2 2.5 3 3.5 4 Time t Abbildung : Ergebnis für λ = 1, C = 1, p 0 = 0.5, t = 0.05

Autoren Autoren die an diesem Skript mitgewirkt haben: 2011 2014 : Christoph Gersbacher 2014 : Patrick Schreier This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) License. http://creativecommons.org/ licenses/by-sa/4.0/legalcode