C - Kurs Hadersbeck Literaturhinweise: Kernighan, Ritchie : The C Programming Language, Prentice Hall, 1988 Darnell, Margolis : Software Engineering in C, Springer Verlag, 1988. 1 1. Einleitung 1.1. Historische Bemerkungen Entwickelt von Kernighan, Ritchie (AT&T Bell Laboratoriers) Relativ geringer Sprachumfang : Kontrollstrukturen, wenig Variablentypen, Funktionen, Modulares Programmieren, Kein Input Output. Erste Version 1983 von C veröffentlicht in "The C Programming Language" (Kernighan, Ritchie) (1983) UNIX geschrieben in C. Neuere ANSI Version (1988) wird zum Standard (Besseres Funktionen Konzept, definierte Library), veröffentlicht in "The C Programming Language" , second Edition (Kernighan, Ritchie) (1988) 2. Grundlagen 2.1. Allgemeine Programmstruktur Ein C-Programm kann aus beliebigen Funktionen, die über verschiedene Module verteilt sind bestehen. Eine Funktion innerhalb des Programms entspricht der Hauptfunktion und heißt main(). Sie stellt den Programmeinsprungspunkt dar. Jedes C-Programmodul hat folgende Struktur : [ Praeprozessor Direktiven ] [ Typ - Deklarationen ] [ Definition und Deklaration von Variablen (globale Variablen) ] [ Deklaration von Funktionen ] Definition von Funktionen (nur eine Funktion wird main genannt ) Jede Funktion hat folgende Struktur : [ Funktionstyp ] Funktionsname ( [ Parameter 1 ,..., Parameter n ] ) Funktionsrumpf Ein Funktionsrumpf hat folgende Struktur : { [ Deklarationen von Variablen ] Statements } 2 Beispiel : Funktion mit Hauptprogramm Praeprozessor - Direktiven funktion { /* Anweisungen der Funktion_1 */ } main () { /* Hauptprogramm */ } dazu Programmbeispiele : 1. Programm : #include <stdio.h> hallo () { puts("Hallo"); } main () { hallo(); } 2. Programm : #include <stdio.h> #define readint(Z) scanf("%d",&Z) /* Minimum, Produkt berechnet die kleinere und das Produkt zweier Zahlen, die der Benutzer eingegeben hat. */ int mult (int a, int b) { return (a*b); } main() { int kleiner,prod; int zahl1, zahl2; /* das Ergebnis */ /* Eingabe Werte */ /* prompt fuer die Benutzereingabe */ puts(" Bitte geben Sie die erste Zahl ein "); readint(zahl1); puts(" Bitte geben Sie die zweite Zahl ein "); readint(zahl2); /* suche die kleinere Zahl */ if (zahl1 < zahl2) kleiner = zahl1; else kleiner = zahl2; printf("Die kleinere der Zahlen %d und %d ist :%d\n",zahl1,zahl2,kleiner); 3 /* berechne das Produkt */ prod = mult(zahl1,zahl2); printf("Das Produkt der Zahlen %d und %d ist : %d \n",zahl1,zahl2,prod); } 2.1.1. Aufgaben 1. Kreieren Sie in Ihrem Homeverzeichnis einen Ordner Uebung1 2. Implementieren Sie in diesem Ordner das Programm 1 und Programm 2 aus diesem Kapitel. Der Source-Filename für Programm 1 ist : prog-1.c Der Source-Filename für Programm 2 ist : prog-2.c 2. Schreiben Sie ein Programm addiere, das drei ganze Zahlen einliest, die größte und die Summe der drei Zahlen ausgibt. Dazu verwenden Sie die Funktion add : int add(int a, int b, int c) { return (a+b+c) } 2.2. Kommentare in Programmen Kommentare können an beliebiger Programmstelle stehen und werden von den Zeichen /* und */ eingerahmt. Die Länge der Kommentare ist unbeschränkt, wobei die Kommentare jedoch nicht verschachtelt sein dürfen. 2.3. Konstanten 2.3.1. ganze Zahlen integer Konstanten : 1234 long integer : suffix l oder L 234L, oktal Zahl : '\013' oder prefix 0 (Hochkomma auf der Appletastatur : alt ´ (links von der DELETE Taste) ) hexadezimal Zahl : '\xhh' oder prefix 0x unsigned integer : postfix u oder U 2.3.2. floating Zahlen float Konstanten : 2.3, 1e-2 2.3.3. Zeichen und Zeichenketten string Konstanten : "abc" character Konstanten : 'c' 4 2.4. Variablen 2.4.1. Was sind Variablen Eine Variable besteht aus zwei Teilen : Einem Namen und einem Objekt. Jede Variable zeigt genau auf ein Objekt und kann zu einem Zeitpunkt nur einen Wert annehmen. x = Variablenname 10 Wert der Variable int x; Adresse Adresse Adresse Beispiel : Häuser werden mit Hausnummern verwaltet. Der Variablenname entspricht der Hausnummer. Jede Hausnummer zeigt auf ein Haus (Objekt) und kann zu einem Zeitpunkt nur einen Wert (Nummer) annehmen. Das Objekt steht an einer bestimmten Stelle (Speicheradresse), die sich nicht ändern kann. 5 2.4.2. Regeln für Variablen in C – – – - Jede Variable muß vor dem Gebrauch deklariert werden Variablennamen beginnen mit Buchstaben Groß/Kleinschreibung ist signifikant Namen sollten nicht mit Underscore beginnen (reserviert für Systemvariablen) 31 Buchstaben sind signifikant bei lokalen Variablen 2.4.3. Grundtypen von Variablen 2.4.3.1. Ganze Zahlen int ... Integer, implementationsabhängig 16, 32 oder 64 Bit short ... Integer, 16 Bit long ... Integer, 32 oder 64 Bit unsigned int, unsigned short, unsigned long ... kein Vorzeichen 2.4.3.2. Zeichen char unsigned char 2.4.3.3. ... Character 7 Bits ... Character 8 Bits enum enum ... Aufzählung einer Menge durch ihre Symbole enum boolean { YES, NO}; 2.4.3.4. float 2.4.3.5. double floating ... Reelle Zahl, 32 Bit double ... Reelle Zahl, 64 Bit 6 2.4.4. Deklaration von Variablen Jede Variable muß mit ihrem Namen und ihrem Typ vor dem Gebrauch definiert werden: Daraufhin reserviert der Kompiler Speicherplatz für sie. Die Definition einer Variablen nennt man Deklaration. Bei einer Deklaration wird der Typ und die mit Komma getrennten Namen der Variablen angegeben. Variablen können außerhalb oder innerhalb von Funktionen, oder am Anfang eines Blocks deklariert werden. Beispiel : int lower; float x,y; char esc; 2.4.5. Lebensdauer von Variablen Die Lebensdauer einer Variable ist abhängig von der Deklarationsstelle. Liegt die Deklarationsstelle : 1. Fall : außerhalb einer Funktion (globale Variable) Lebensdauer innerhalb aller Funktionen des gesamten Programms. 2. Fall : innerhalb einer Funktion (lokale Variable) Lebensdauer innerhalb der Funktion 3. Fall : innerhalb eines Blocks Lebensdauer innerhalb des Blocks 2.4.6. Gültigkeit von Variablen Die Gültigkeit einer Variable entspricht solange der Lebensdauer der Variablen, bis nicht innerhalb einer Funktion oder eines Blocks eine Variable mit dem gleichen Namen definiert wird. Beispiel : #include <stdio.h> #define readint(Z) scanf("%d",&Z) int a,b,c,d; int add(int a,b) { int c; c = a + b; return c; } main() { int c; puts( " Bitte geben Sie zwei Zahlen ein"); readint(a); readint(b); c = add(a,b); printf(" Die Addition lautet = %d\n",c); } 7 2.4.7. Schlüsselwörter Folgende Schlüsselwörter sind reserviert und dürfen nicht als Variablennamen verwendet werden : auto break else case char const float continue default do double long enum extern short for goto if int switch register return unsigned signed sizeof static struct typedef union void volatile while 2.4.8. Initialisierung von Variablen Variablen können bei der Deklaration auch Initialisierungswerte zugewiesen werden. Beispiel : char esc = ’\\’; int grenze = MAXLINE + 1; int upper=100, abc[100]; float x,y,z=1.0e-5; 2.4.9. Zuweisen von Werten an eine Variable lvalue = rvalue oder lvalue <op> = rvalue ist äquivalent zu lvalue = value(lvalue) <op> rvalue Achtung : lvalue hat : Typ, Adressenklasse, Namen, Adresse rvalue hat : Typ, Namen, Wert Beispiel : x = 2 + 3; x += 1; entspricht x = x + 1; 8 2.4.10. Konditionale Zuweisung expr1 ? expr2 : expr3 entspricht : if expr1 then expr2 else expr3; Beispiel : z = (a>b) ? a : b entspricht : z = max(a,b) oder if (a>b) z=a; else z=b; 2.4.11. Funktionen zum Einlesen und Ausgeben von Variablenwerten Zum Einlesen von Variablenwerten gibt es die Funktion scanf(" Kontrollstring ",Adresse_Variable1,Adresse_Variable2 .... ) Beim Einlesen muß die Adresse der Variable in scanf eingetragen werden (& Operator vor dem Variablennamen). Zum Ausgeben der Werte von Variablen gibt es die Funktion printf(" Kontrollstring ",Variable1,Variable2 .... ) Im Kontrollstring wird der Text der Zeile und die Formatierungsanweisung (% Operator für Formatierungsbuchstaben) für jede Variable angegeben. Soll am Ende der Zeile ein Zeilenvorschub eingefügt werden, muß dafür ein explizites Zeilenvorschub Zeichen eingefügt werden. Die wichtigsten Formatierungsbuchstaben sind : d für dezimal Zahlen f für reelle Zahlen c für Buchstaben 9 Beispiel : int m; float x; char ant; printf("Bitte geben Sie eine ganze Zahl ein >>>"); scanf("%d",&m); printf("Die Eingabe war %d\n",m); printf("Bitte geben Sie eine reelle Zahl ein >>>"); scanf("%f",&x); printf("Es wurde die ganze Zahl %d und die reelle Zahl %f eingegeben\n",m,x); printf("Es wurde die ganze Zahl >>>%d<<< und die reelle Zahl >>>%f<<< eingegeben\n",m,x); printf("Weitermachen y/n >>>"); fflush(stdin); scanf("%c",&ant); 2.4.12. Aufgaben 1. Schreiben Sie ein Programm das eine ganze und eine reelle Zahl einliest. Geben Sie das Quadrat und die Summe der Zahlen aus. 2. Schreiben Sie ein Programm, das einen Buchstaben einliest und den Buchstaben mit seinem ASCII -Wert ausgibt. Ändern Sie den Buchstaben jenachdem in seinen äquivalenten Groß/Kleinbuchstaben. 10 2.5. Operatoren 2.5.1. Arithmetische Operatoren Binäre arithmetische Operatoren sind : + * / / % plus minus Multiplikation Division, reellwertig Division, ganzzahlig Modulo Operator 2.5.2. Typenkonvertierung bei arithmetischen Ausdrücken In einem arithmetischen Ausdruck mit Variablen verschiedener Datentypen wird eine Variable mit schwächerem Typ automatisch in einen stärkeren konvertiert : schwach char -> int -> -> stark float -> double. Explizite Konvertierung muß mit dem cast Operator erzwungen werden. Der cast Operator besteht aus den Zeichen ( und ), den gewünschten Type eingeschlossen. Beispiel : x = (int) y; cast operator mit dem Typen int int a,b; (a/b)*b + (a%b) == a; float kreisfläche(float radius) { float pi = 3.14; return 2 * radius * radius *pi; } 11 2.5.3. Aufgabe Welches Ergebnis und welcher Typ wird erzwungen: short a = 10; long b = 1L; float x = 9.0; double y = 2.3d-2; a b b x x y = = = = = = (short) b; ______ a; ______ a + x; ______ sqrt ((double) x); ______ y + x; ______ a + b + x + y ______ __________ __________ __________ __________ __________ __________ 2.5.4. Relationale und Logische Operatoren Es gibt die logischen Werte : wahr (jede Zahl ungleich Null) und falsch (nur die ganze Zahl Null). logische Operatoren sind : < <= > >= == != && || ! kleiner kleiner gleich größer größer gleich gleich ungleich und oder nicht Achtung : Die Priorität von && ist größer als die von ||, sowohl && als auch || haben aber eine niedrige Priorität als > <, >= und <= (z.B. x < y && y < x ) Die Negation ( ! ) ist einstellig und konvertiert TRUE (nicht Null) in FALSE (Null) und FALSE (Null) in TRUE (nicht Null). Komplexe logische Ausdrücke werden von links nach rechts abgearbeitet, die Abarbeitung ist beendet, wenn das Ergebnis bestimmt ist. Beispiel : if (j < MAX && ((c=getchar()) != ’\n’)) if ((1<lim-1) || (!valid) && (x!=4)) x=0 12 2.5.5. Die Wahrheitstabelle bei logischen Ausdrücken int p,q; p q p && q p || q ! p ——————————————————————————————————————— 0 0 0 0 1 0 1 0 1 1 1 0 0 1 0 1 1 1 1 0 2.5.6. Aufgabe Was ist der Wert : 2 == 7 _____ 1 >= 0 _____ 4 > 4 _____ 1 = 2 _____ Beispiel : float reziprokwert(float x) { if (x != 0) return 1/x; else puts(" Achtung Eingabewert ist gleich Null") } 13 2.5.7. Increment und Decrement Operatoren ++ -- addiert eins auf eine Variable, subtrahiert eins von einer Variable. ++ und -- können bei Variablen als postfix und als prefix verwendet werden, haben aber dann bei der Auswertung des Ausdrucks unterschiedliche Bedeutungen. als prefix : verändere den Wert der Variable und verwende den neuen Wert im Ausdruck als postfix: verwende zuerst den Wert der Variable innerhalb des Ausdrucks und verändere ihn dann. Beispiel : int a = 1; b = ++a; Der Wert von a ist 2 Der Wert von b ist 2 int a = 1; b = a++; Der Wert von a ist 2 Der Wert von b ist 1 2.5.8. Aufgabe Was ist der Wert des Ausdrucks : int j = 0,m=1,n=1; x = m++ - --j; ___________ m += ++j +2; ___________ j = m++ * m++; ___________ 14 2.5.9. Arithmetische Zuweisungsoperatoren Operator Zuweisung Additionszuweisung Subtrakt. Zuweisng. Multipliz. Zuweis. Divisions Zuweisung Modulo Zuweisung Symbol = += -= *= /= %= Form a=b a += b a -= b a *= b a /= b a %= b Operation Speichere den Wert von b in a Speichere den Wert von a+b in a Speichere den Wert von a-b in a Speichere den Wert von a*b in a Speichere den Wert von a/b in a Speichere den Wert von a%b in a Achtung bei Zuweisungen, wenn die Priorität von Operatoren ins Spiel kommt. Beispiel : a = a * 3 + 4; ist ungleich zu a *= 3 + 4; 2.5.10. Aufgaben Welche Werte werden bei folgenden Ausdrücken berechnet : int m = 3,n= 4; float x = 2.5,y=1.0; a) m +=n+x-y; ____________ b) m /= x+n+y; ____________ c) m %= y+m; ____________ d) x+= y -=m; ____________ 2.5.11. Bitweise Operatoren & (bitwise AND), | (bitwise inclusive OR), ^ (bitwise exclusive OR), << left shift, >> right shift, ~ (one komplement), z.B. : ausblenden von Bits : n = n & 0177; z.B. : setzen von Bits : n = n | 0101; z.B. : shift von Bits : 007 << 3 ist 070; 07 >> 1 ist 03 15 2.5.12. Prioritäten der Operatoren Innerhalb von Ausdrücken gelten folgende Prioritäten bei der Auswertung des Ausdrucks. Je höher der Wert, desto früher wird der Operator ausgewertet. Level Operatoren Assoziativität 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 () [] -> . ! ~ ++ -- + - * & (type) sizeof + * / % >> << < <= > >= == != & ^ | && || ?: = += -= *= /= %= &= ^= |= <<= , links nach rechts rechts nach links links nach rechts links nach rechts links nach rechts links nach rechts links nach rechts links nach rechts links nach rechts links nach rechts links nach rechts links nach rechts rechts nach links rechts nach links links nach rechts Beispiel : a == b && x || !y (a == b) && (x || !y) ( x=putchar() != EOF) ( (x=putchar()) != EOF) 16 >>= 2.5.13. Aufgaben 1. Welche Werte werden von folgenden Programmen ausgedruckt ? #include <stdio.h> #define readint(Z) scanf("%d",&Z) #define readfloat(Z) scanf("%f",&Z) int arith (void) /* 1. Programm : Arithmetik */ { int a,b,c,d; int erg; puts(" Geben Sie vier ganze Zahlen ein \a: "); readint(a); readint(b); readint(c); readint(d); erg = a + b; printf(" a + b = %d\n",erg); erg = a / b; printf(" a / b = %d\n",erg); erg = a % b; printf(" a mod b = %d\n",erg); erg = c++; printf("Nach erg = c++ ist der Wert von erg = %d, von c = %d \n",erg,c); erg = --a; printf("Nach erg = --a ist der Wert von erg = %d, von a = %d \n",erg,a); a += 2; printf(" Nach a += 2 ist der Wert von a = %d\n",a); } int logik (void) /* 2. Programm Logische Ausdruecke */ { int a,b,c,d; float x; puts(" Geben Sie vier ganze Zahlen ein : "); readint(a); readint(b); readint(c); readint(d); if ( b != 0 ) { x = a/b; printf(" Der Reziprokwert = %f\n",x); }; if ( a==b ) puts( " a ist gleich b "); else puts(" a ist ungleich b"); if ( a != b && ( a != c || a != d) ) printf( "jawohl \n"); if ( a != b + c ) printf(" a != b + c \n"); } main (void) { arith(); logik(); } 17 2. Schreiben Sie ein Programm, das eine ganze Zahl einliest und ausdruckt ob die Zahl gerade oder ungerade ist. 3. Schreiben Sie ein Programm das eine ganze Zahl einliest, die Quersumme berechnet und ausgibt. Das Programm soll auch die Oktal und Hexadezimaldarstellung der Zahl ausgeben Hinweis : (Formatierungsanweisung) 4. Schreiben Sie ein Wechselkursprogramm für französische Francs. Das Programm liest den DM Betrag bzw. Francs Betrag ein und berechnet den Wert in der jeweils anderen Währung. Der aktuelle Kurs : 100 Francs kosten 29.129 DM 18 Strukturierung von Programmen 2.6. Kontrollstrukturen 2.6.1. Statements und Blöcke Jeder Ausdruck, abgeschlossen von einem Semikolon ist ein Statement. Somit ist das Semikolon kein Trennsymbol sondern das Abschlußzeichen eines Statements. Mehrere Statements können mit geschweiften Klammern zu einem Block zusammengefaßt werden. Der Block (=Block-statement) gilt nach außen wie ein Statement und wird nicht mit einem Semikolon abgeschlossen. Es gibt folgende Statements : expression-statement compound-statement selection-statement iteration-statement jump-statement labeled-statement 2.6.2. expression statement Dem expression statement entsprechen Wertzuweisungen, Wertvergleiche oder Funktionsaufrufe. Expressions werden sequentiell der Reihe nach ausgewertet und von einem Semikolon abgeschlossen. Die leere expression heißt Nullstatement. Beispiel : x = 1; i <= a; a = b + x; ; 2.6.3. compound statement Die geschweiften Klammern gruppieren statements zu einem compound statement (=Block). Innerhalb eines compound statements können Variablen deklariert werden. Die Lebensdauer der Variablen ist nur auf diesen Block geschränkt. Beispiel : { } int a; a=x; /* Hier kein Semikolon notwendig, da Block-statement */ oder : if (a==0) { b=1; c=1; d=1; printf(“%d”,i); oder : if (a==0) { int i; } i= a + 1; printf(“%d”,i); } 19 2.7. selection-statements 2.7.1. selection statment : if , if - else if (expression) statement if (expression) statement1 else statement2 Das if statement testet den numerischen Wert der Bedingung (expression). Falls der Wert ungleich Null ist (TRUE Fall), wird statement1 ausgeführt. Es wird nur ein einziges statement nach der Bedingung ausgeführt. Sollen mehrere statements zusammengefaßt werden, so müssen sie mit geschweiften Klammern geklammert werden. Bei geschachtelten if .. else gehört das else immer zum näheren if. Achtung : expression muß immer in runden Klammern eingschlossen werden. Beispiel : if (i==2) puts("i ist gleich zwei"); else puts(" i ist ungleich zwei") ; oder if ((i==2) || (j!=0)) { puts(" Der Fall ist eingetreten"); i = 3; } else puts(" Ja du Glückspilz "); Achtung, folgendes ist zulässig : Ausdruck if (i=2) if (++i) if (i=j<n) if (i) if (2) Bedeutung Zuweisung an i, dann Test : immer true Erhöhen des Wertes von i, dann Test Zuerst errechnen und zuweisen des Wertes an i, dann test ob i TRUE (!= 0) oder FALSE (=0) Test ob i TRUE (!= 0) oder FALSE (=0) immer TRUE (!= 0) 20 2.7.2. selection-statement : switch switch (expression) { case constant-expr: statements1 case constant-expr: statements2 default : statementsn } Jeder Label hat eine oder mehrere ganzzahlige Konstanten oder Konstanten Ausdrücke. Entsprechend dem Wert von expression werden sequentiell alle case constant-expr. ausgewertet und verglichen, ob sie mit dem Wert übereinstimmen. Bei Übereinstimmung werden die nachfolgenden statements ausgeführt und beim nächsten case Statement weiter getestet. Soll die Abarbeitung der sequentiellen Tests nach der Ausführung eines statements abgebrochen werden, so muß dieses statement mit break abgeschlossen werden. Die Abarbeitung wird dann hinter dem gesamten switch statement fortgesetzt. Wird keine Übereinstimmung zwischen dem Wert von expression und constant-expr. gefunden, so wird auf einen eventuell vorhandenen default Fall verzweigt. Beispiel : switch (c) { case ´0´ case ´2´ case ´2´ default } 2.8. : case ´1´ : : : case ´3´: : puts("0,1"); break; puts("2"); puts("2,3"); puts(" Nichts davon"); Iteration statements 2.8.1. iteration statement : while while (expression) statement Solange expression TRUE (ungleich Null) ist , wird statement ausgeführt. Es wird genau ein statement ausgeführt. Sollen mehrere statements ausgeführt werden, müssen sie zu einem compound-statement zusammengefaßt werden. Statement wird solange wiederholt, bis der Wert von expression FALSE (gleich Null) ist. 21 Beispiel : int while_1(void) { int num; puts("Gib den Countdown Wert ein >>>"); readint(num); /* Achtung bei Endlosschleifen */ while ( num > 0 ) { num --; printf(" Countdown laeuft >>%d<<\n",num); }; printf(" Start \n"); } Achtung vor Unendlichschleifen : i = 5; while (i) ; i --; while (i > 0) printf(" Countdownwert ist = %d\n",i); i--; 2.8.2. iteration statement : for for (expr1; expr2; expr3) statement expr1 : Wird vor dem Durchlauf der Schleife ausgeführt (Initialisierung) expr2 : Testbedingung der Scheife : Wiederholung falls expr2 ungleich Null expr3 : Wird nach einem Durchlauf von statement ausgeführt (Increment) entspricht : expr1; while (expr2) { statement; expr3; } Achtung : Im Gegensatz zu anderen Programmiersprachen ist die for Schleife bei C viel flexibler, da die Komponenten expr1, expr2, expr3 einer for loop beliebige Ausdrücke sein können, deren Werte auch innerhalb der Komponenten verändert werden können. 22 Beispiele : Es dürfen auch expr's der for Schleife fehlen : Die endlos Schleife : for (;;) ; Der Index einer for Schleife muß nicht unbedingt ein ganzzahliger Wert sein : int for_2(void) { char a; puts(" Die Buchstaben von a bis g lauten : "); for (a=’a’; a < ’g’; a ++) printf(" %c ",a); printf("\n"); int for_3(void) { float x; puts(" Die Reihe von x - 1/x lautet : "); for (x=3; x > 0.00005; x = x - 1/x) printf(" %6.3f\n ",x); printf("\n"); } for (i=0; i<n; i++) { printf(" Der Schleifendurchlauf Nummer %d\n",i); m= n+i; } komplexe Ausdrücke in expr1, expr2 und expr3, als Rumpf der for Schleife wird die leere Ausweisung verwendet. Sämtliche Berechnungen werden innerhalb der for Schleife ausgeführt. Dies ist jedoch ein sehr komplizierter Programmstil und eigentlich abzulehnen. for (i=0,j=1,x=10; i=j*2*x; i = i*j,x--) ; 2.8.3. Aufgabe : Welche Werte werden bei folgendem Programmausschnitt ausgedruckt : int i,j; int n,m; n=m=4; for (i=0;j<n;i++) for (j=0;j<m;j++) printf("Der Matrixindex lautet : i = %d 23 j = %d \n",i,j); 2.8.4. iteration statement : do - while do statement while (expression); Das statement wird ausgeführt und die expression ausgewertet. Falls die expression TRUE ist (ungleich Null) wird das statement erneut ausgeführt. Wird expression gleich Null (FALSE) terminiert die Schleife und es wird hinter das Programm wird hinter dem do statement fortgesetzt. 2.9. jump statements 2.9.1. jump statement : break Das break statement stellt ein vorzeitiges exit aus einem for, while, do oder switch statement dar. Das break statement veranlaßt, die innerste Schleife sofort zu verlassen. Das continue statement beendet eine Iteration innerhalb einer Schleife und springt direkt zum nächsten Schleifendurchlauf. 2.9.2. jump statement : goto, label label : und goto label; Es wird empfohlen, auf die Programmierung mit Lables zu verzichten (Spagetticode). Es gibt genügend Kontrollanweisungen um Sprünge innerhalb des Programms zu vermeiden. 2.10. Die Vor- und Nachteile von for, do und while Die for Loop wird dann verwendet : - wenn der Schleifenindex im Vordergrund steht. (z.B. Durchlaufen von Arrays). - Bei einfachen Interationsschritten - Falls die Iteration und das Abbruchkriterium eng zusammenhängen Die while ( ) Loop wird verwendet : - wenn das Abbruchkriterium im Vordergrund steht - es soll zuerst getestet werden, bevor die Statements im while Block ausgeführt werden, da sonst Fehler auftreten könnten (z.B. Arithmetischer Ausdruck um Division durch Null zu vermeiden) Die do () Loop wird verwendet : - wenn die Statements im do Block im Vordergrund stehen. - Es sollen zuerst die Statements ausgeführt werden und dann die Bedingung getestet werden. (z.B : Einlesen von Abbruchkriterien) 24 Beispiel : #include <stdio.h> main() /* Demonstration of blocks and statements */ { char in,buffer[10]; int len,i=0; while ( ( (buffer[i++]=getchar() ) != ’\n’) && (i < 10)) ; len=i; for (i=0;i<len;i++) { char c; switch (c = buffer[i]) { case ’0’:case ’1’:case ’2’:case ’3’:case ’4’:case ’5’ : case ’6’:case ’7’: puts(" Die Zahl ist kleiner 8"); break; case ’8’:case ’9’: puts(" Die Zahl ist größer 8"); break; default : if (( c >= 'A' && c <= 'Z') || ( c >= 'a' && c <= 'z')) puts(" Wir haben einen Buchstaben"); else puts(" Wir haben ein Sonderzeichen"); } } } 2.10.1. Aufgaben 1. Schreiben sie ein Programm zur Lösung von Gleichungen höheren Grades nach den Newtonschen Näherung und nach dem Sehnenverfahren: Es sein eine Funktion f(x), und x1 ein Näherungswert für die Nullstelle f(x), so ist xt eine bessere Näherung der Nullstelle. (a) xt = x1 - f(x1) ------f’(x1) oder nach dem Sehnenverfahren : (b) xt = x1 x1 - x2 - f(x1) * -----------f(x2) - f(x1) 2. Schreiben Sie ein Programm, das bis zu 5 mal eine nur im Programm bekannte Geheimzahl abfagt. Bei jedem Durchlauf wird dem Benutzer ein neuer Tip gegeben, der einen neuen Hinweis zu dieser Geheimzahl gibt. Wird die Zahl gefunden, dann werden die Anzahl der Versuche ausgegeben. 3. Schreiben Sie ein Programm, das eine Zahl einliest und in Abhängigkeit der Zahl einen beliebigen Spruch auf das Terminal ausgibt. Nur bei einer bestimmten Zahl soll das Program terminieren. Verwenden Sie zum beenden des Programms dazu die Lösung aus Aufgabe 2 25 26