1. Einleitung. 2. Grundlagen Historische Bemerkungen Allgemeine Programmstruktur

C - Kurs Hadersbeck Literaturhinweise: Kernighan, Ritchie : The C Programming Language, Prentice Hall, 1988 Darnell, Margolis : Software Engineering ...
Author: Ingeborg Böhme
18 downloads 2 Views 111KB Size
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 hallo () { puts("Hallo"); } main () { hallo(); } 2. Programm : #include #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 #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 = rvalue ist äquivalent zu lvalue = value(lvalue) 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>%f>"); 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 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), > 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 > 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 + * / % >> = == != & ^ | && || ?: = += -= *= /= %= &= ^= |= =

2.5.13. Aufgaben 1. Welche Werte werden von folgenden Programmen ausgedruckt ? #include #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 0 ) { num --; printf(" Countdown laeuft >>%d