261
C-Programmierung 2003/2004 1 Friedrich-Schiller-Universität Jena Universitätsrechenzentrum Multimediazentrum Grundlagen der Programmierung

Grundlagen der - Universitätsrechenzentrumaog/C-Lehrgang-NEU-1-261.pdf · Delphi Ada 1970 1980 1990 2000 Prozedurale Sprachen Objektorientierte Sprachen Klassifikation nach Sprachtypen

  • Upload
    donga

  • View
    216

  • Download
    1

Embed Size (px)

Citation preview

1

C-Programmierung 2003/2004 1

Friedrich-Schiller-Universität Jena

Universitätsrechenzentrum

Multimediazentrum

Grundlagen der Programmierung

2

C-Programmierung 2003/2004 2

Einleitung

Friedrich-Schiller-Universität Jena

Universitätsrechenzentrum

Multimediazentrum

Was sind Programme? Warum programmieren?

Einfache und schnelle Lösung mathematischen Problemen

Erarbeitung eines Algorithmus

Übersetzen des Algorithmus in die Maschinensprache

Erstellung einer Abarbeitungsvorschrift (Programm) für den Computer in einer speziellen Sprache

Abarbeitung des Programms im Computer

Ergebnis

3

C-Programmierung 2003/2004 3

Friedrich-Schiller-Universität Jena

Universitätsrechenzentrum

Multimediazentrum

Fortran

Cobol Algol 60

Basic

Visual Basic

Pascal

1950

1960

Algol 68

C

C++

Java

C#

Delphi

Ada

1970

1980

1990

2000

Prozedurale Sprachen Objektorientierte Sprachen

Klassifikation nach Sprachtypen

4

C-Programmierung 2003/2004 4

Friedrich-Schiller-Universität Jena

Universitätsrechenzentrum

Multimediazentrum

Funktionale Sprachen: - Lisp (1960)

- das Programm besteht aus Funktionen, die sich

gegenseitig aufrufen

- Programme werden wie mathematische

Funktionen geschrieben

- Funktion hat einen Definitions- und Wertebereich

- Funktion erhält Eingebewert und berechnet den

Wert der Funktion

- Einsatz im Forschungsbereich für künstliche

Intelligenz und im Bereich der Mathematik

Logische Sprachen: - Prolog (1970)

- Sprachen sind auf die Lösung von bestimmten

Problemen abgestimmt (Datenbankabfragen)

- das Programm bestimmt eine logische Beziehung

zwischen den einzelnen Daten

5

C-Programmierung 2003/2004 5

Friedrich-Schiller-Universität Jena

Universitätsrechenzentrum

Multimediazentrum

Klassifikation nach Sprachgenerationen

Erste Generation: Maschinensprache

- Programmierung auf Maschinenniveau (0110101010)

Zweite Generation: Assembler-Sprache

- Programmierung auf Prozessorniveau; Anwendung

von speziellen Befehlen (LD 3,4 ; ADD ww1,dd4)

Dritte Generation: Problemorientierte Sprachen

- PL/1; Pascal, Cobol, Ada, C/C++, Basic usw.

Vierte Generation: Deklarative Sprachen

- SQL, Open Access

Fünfte Generation: Künstliche Intelligenz

- Lisp, Prolog, Smalltalk

6

C-Programmierung 2003/2004 6

Friedrich-Schiller-Universität Jena

Universitätsrechenzentrum

Multimediazentrum

Entwicklung und Ausführung eines Programms

Problem Lösung mittels eines Algorithmus

mehrere Module

Modul 1

Modul 2

Modul 3

Compiler

Compiliertes Modul 1

Compiliertes Modul 2

Compiliertes Modul 3

Linker

(Verbinder)

Fertiges Programm mit

relativen Adressen

(Lademodul)

LaderAusführbares

Programm mit absoluten

Adressen

InterpreterProgramm

7

C-Programmierung 2003/2004 7

Friedrich-Schiller-Universität Jena

Universitätsrechenzentrum

Multimediazentrum

Entwicklungsumgebung

Compiler und Linker sind für unterschiedliche Betriebssystemplattformen verfügbar

Für viele Betriebssysteme gibt es mächtige Entwicklungswerkzeuge, sogenannte Entwicklungsumgebungen. In diesen Tools sind die:

• Projektverwaltung,

• Editoren,

•Grafiktools,

•Compiler,

•Debugger und

•Linker

unter einer gemeinsamen Oberfläche vereinigt. Der Entwickler kann damit von der Quellcoderfassung bis zum fertigen Tool alles mit einem Werkzeug realisieren. Damit ist eine sehr effektive Arbeit möglich

Weiterhin gehören zu jeder Programmiersprache noch entsprechende Standard-bibliotheken.

8

C-Programmierung 2003/2004 8

Friedrich-Schiller-Universität Jena

Universitätsrechenzentrum

Multimediazentrum

Microsoft Visual C++ 6.0

9

C-Programmierung 2003/2004 9

Programmieren in C

10

C-Programmierung 2003/2004 10

Inhaltsverzeichnis

1. Grundlagen2. Funktionen3. Variablentyp int4. Eingabe mit scanf5. Grundrechenarten6. Entscheidung if7. Gültigkeitsbereich von Variablen8. Funktionen mir Parameterübergabe8.1. Parameterübergabe8.2. Wertrückgabe8.3. Übergabe mehrerer Parameter8.4. Prototypen parametrisierter Funktionen8.5. spezielle Hinweise zu Funktionen mit Parameterübergabe9. Die for-Schleife10. Schleifen mit Ein- und Austrittsbedingungen10.1. Schleifen mit Eintrittsbedingung10.2. Schleifen mit Austrittsbedingung10.3. Continue-Anweisung

11

C-Programmierung 2003/2004 11

11. Logische Operatoren12. Variablen vom Typ float13. Fallunterscheidungen14. Der Variablentyp char15. Zeiger und Vektoren15.1. Adressen als Funktionsparameter15.2. Zeiger auf Funktionen15.3. Zeiger auf Zeiger16. Variablenfelder17. Zeichenketten - String18. Strukturen19. Arbeit mit Dateien20. Präprozessor-Befehle21. Programmier-Technologien21.1. Eigene Header Dateien21.2. Rekursion21.3. Listen21.4 Sortierverfahren21.5 Suchalgorithmen21.6 Datenkomprimierung22. Zusammenfassung

12

C-Programmierung 2003/2004 12

1. GrundlagenDas erste C-Programm:

void main(void) /*Ein C-Programm*/

{

}

- dieses Programm realisiert nichts

- jedes C-Programm beginnt immer mit main (Haupt; Hauptfunktion)

- vor dem Funktionsaufruf steht void, das bedeutet, dass die Funktion keinen Rückgabewert

liefert

- das void nach dem Funktionsaufruf bedeutet, dass dem Funktionsaufruf keine Werte

übergeben werden

- hinter dem Funktionsaufruf stehen geschweifte Klammern, welche die Anweisungen der

Funktion umschließen (dürfen nie fehlen !)

void=leer

13

C-Programmierung 2003/2004 13

- geschweifte Klammern fassen Anweisungen zu einem Block zusammen

- Zusammengehörige geschweifte Klammern sollten immer untereinander stehen

- Kommentare werden immer in /* Kommentar */ eingeschlossen

und dürfen nicht verschachtelt werden

Ausgabe mit printf

- eine Grundfunktion mit der Ausgaben aller Art unterstützt werden heißt printf( )

#include <stdio.h>

void main(void)

{

printf("Das ist eine Bildschirmausgabe");

}

- der Funktion printf wird eine Stringkonstante übergeben, die während der

Ausführungszeit nicht verändert wird

14

C-Programmierung 2003/2004 14

- Stringkonstanten stehen immer innerhalb von doppelten Anführungszeichen

-Anweisungen, denen kein Anweisungsblock folgt, werden mit einem Semikolon

abgeschlossen

- #include <stdio.h> Standardbibliothek stdio.h an das C-Progamm binden

- der #include-Befehl ist kein Bestandteil der Sprache C, sondern der Befehl eines Präprozesses

- Präprozesse werden nur vom Compiler benötigt und nehmen bestimmte Änderungen während

der Compilierung im Programm vor

- ohne #include kommt es zu Fehlermeldungen während der Compilierung, da der Compiler

die Funktion printf nicht kennt

- Präprozessorbefehle erkennt man am # in der ersten Spalte

- diese Befehle dürfen nicht nach rechts eingerückt werden !!!

15

C-Programmierung 2003/2004 15

Steuerzeichen für die Ausgabe

#include <stdio.h>

void main(void)

{

printf ("Ausgabetext-1");

printf ("Ausgabe-2");

}

Ausgabe am Bildschirm: Ausgabetext-1Ausgabe-2

Durch den Einsatz von Steuerzeichen kann die Bildschirmausgabe den Erfordernissen des Nutzers angepasst werden.

16

C-Programmierung 2003/2004 16

Esc-Sequenz Aktion

\t HAT (horizontal tab), der Cursor geht zur nächsten horizontalen Tabulatorposition

\v VT (vertical tab), der Cursor geht zur nächsten vertikalen Tabulatorposition

\" " wird ausgegeben

\' ' wird ausgegebeb

\? ? wird ausgegeben

\\ \ wird ausgegeben

Wenn C keine Steuerinformation erhält, dann wird auch bei der Aus- und Eingabe keine Aktivität ausgelöst!!!

#include <stdio.h>

void main(void)

{

printf ("Ausgabe-1\n");

printf ("Ausgabe-2");

}

Ausgabe am Bildschirm:

Ausgabe-1

Ausgabe-2

Programm01

17

C-Programmierung 2003/2004 17

#include <stdio.h>

vioid main(void)

{

printf ("Ausgabe-1\nAusgabe-2");

}

Alternativ (Ausgabe in einer printf-Anweisung)

Esc-Sequenz Aktion

\a BEL (bell) gibt akustisches Signal

\b BS (backspace), Curser geht eine Position nach links

\f FF (formfeed), Seitenvorschub wird ausgelöst

\n NL (new line), Curser geht zum Anfang der nächsten Zeile

\r CR (carriage return), der Cursor geht zum Anfang der aktuellen Zeile

18

C-Programmierung 2003/2004 18

2. Funktionen

Die Zerlegung eines Programms in verschiedene Funktionen dient der Verbesserung der Übersichtlichkeit und der effektiveren Realisierung des Programmablaufs.

Programme sollten immer in sinnvolle Blöcke gegliedert werden!!!

Diese Planung sollte bereits vor der Programmierung erfolgen, denn später lässt sich eine Gliederung in mehrere Blöcke (Funktionen) meist nicht mehr realisieren.

#include <stdio.h>void funktion1(void){printf ("Ausgabe-1\n");}void funktion2(void){printf ("Ausgabe-2\n");}

19

C-Programmierung 2003/2004 19

void main(void){funktion1( );funktion2( );}

Startmain

funktion1

funktion2

EndemainFunktionsaufruf

funktion1

funktion2

{printf ("Ausgabe-1\n");}

{printf ("Ausgabe-2\n");}

20

C-Programmierung 2003/2004 20

Funktionsnamen müssen mit Buchstaben oder Unterstrich beginnen und dürfen nur Buchstaben, Ziffern oder Unter- striche enthalten.

Bei Namen wird auf Groß- und Kleinbuchstaben geachtet.

Nur die ersten 31 Zeichen werden bei der Namensunterscheidung benutzt.

Diese Regeln gelten für alle Namen (Variablen, Funktionsnamen, Strukturnamen usw).

21

C-Programmierung 2003/2004 21

Funktionsdeklarationen und Prototypen

Prototyp

Funktionsdeklaration

#include <stdio.h>

void funktion1(void);void funktion2(void);

void main(void){funktion1();funktion2();

}void funktion1(void){

printf("Ausgabe-Text-Funktion1\n");}void funktion2(void){

printf("Ausgabe-Text-Funktion2\n");}

22

C-Programmierung 2003/2004 22

3. Variablentyp int

Variablen bestehen aus Buchstaben oder einem Wort (evtl. in Verbindung mit Ziffern) und repräsentieren einen Wert.

Variablentyp int (integer) = ganzzahlig

z.B. 2, 99, -23, 387 usw.

Typ Größe Zahlenbereich FZint 2 Byte -32768 bis +32767 i

unsignetd int 2 Byte 0 bis 65535 u

long 4 Byte - 2147483648 bis + 2147483647 li

unsigned long 4 Byte 0 bis 4294967295 lu

short 1 Byte - 128 bis + 127 hi

unsigned short 1 Byte 0 bis 255 hu

FZ = Formatzeichen

Varianten von Integer-Variablen

23

C-Programmierung 2003/2004 23

Die angegebenen Längen von Integer Variablen sind Mindestgrößen, die ein Compiler benutzen muss, es können aber auch mehr sein.

24

C-Programmierung 2003/2004 24

Formatzeichen für die Ausgabe

Um printf innerhalb eines Strings mitzuteilen welcher Variablentyp zu benutzen ist, muss das entsprechende Formatzeichen angegeben werden.

printf ("Ausgabe einer Int Zahl mit 2 Byte: %i", zahl1);

an %i kann man erkennen, daß Zahl1 eine Variable vom Typ int sein muss !!!

printf ("Ausgabe von Zahlen %i, %hu, %li", x1, x2, x3);

int unsigned int long int

25

C-Programmierung 2003/2004 25

#include <stdio.h>void main(void){

int zahl1;int zahl2;int zahl3;

zahl1=19;zahl2=-23;zahl3=299;

printf("Die Zahlen lauten %i, %i und %i\n",zahl1,zahl2, zahl3);}

Bildschirmausgabe:

Die Zahlen lauten 19, -23 und 299

26

C-Programmierung 2003/2004 26

1. Variablen werden definiert

2. Variablen wird ein Wert zugewiesen = initialisieren

Dies erfolgt in C durch den Zuweisungsoperator "="

3. Steht rechts vom Gleichheitszeichen ein Ausdruck, z.B.

a=b+c, wird zuerst berechnet und dann der Wert zugewiesen.

verkürzte Schreibweise

int zahl1; int zahl2; int zahlxyz; int a;

kann auch wie folgt realisiert werden:

int zahl1, zahl2, zahlxyz, a;

oder sofort mit Wertzuweisung:

int zahl1=222, zahl2=333, zahlxyz=-234, a=-99;

Vor dem Gleichheitszeichen dürfen keine konstanten Ausdrücke stehen

27

C-Programmierung 2003/2004 27

Variablen, welche nicht initialisiert sind, haben immer einen undefinierten Wert.

Variablen prinzipiell initialisieren

Erweiterte Formatierung bei der Ausgabe

printf ("Ausgabe des Wertes %+i", 99);

Der Wert bekommt immer ein Vorzeichen +99

printf ("Ausgabe des Wertes %5i und %5i\n", 99, 33333);

Beide Zahlen haben die gleiche Länge (hier 5). Fehlende Stellen werden mit Leerzeichen aufgefüllt. Ist die Zahl länger als der reservierte Platz, wird sie trotzdem komplett ausgegeben

28

C-Programmierung 2003/2004 28

printf ("Ausgabe des Wertes %-5i und %-5i\n", 99, 33333);

Werte linksbündig ausgeben

printf ("Ausgabe des Wertes %05i und %05i\n", 99, 33333);

Mit führenden Nullen auffüllen

29

C-Programmierung 2003/2004 29

4. Eingabe mit scanf

Eingabe erfolgt mit der Funktion scanf. Diese Funktion steht genau wie printf in der Headerdatei stdio.h.

#include <stdio.h>

void main(void){unsigned int zahl;

printf("Geben Sie bitte eine Zahl größer gleich Null und kle\iner 65536 ein:");

scanf("%u",&zahl);printf("Sie haben %u eingegeben.\n",zahl);

}

Trennsymbol "\"

Folgezeile nicht einrücken

30

C-Programmierung 2003/2004 30

scanf("%u",&zahl);

Adresse von Zahl (&=Addreßoperator

Formatzeichen

scanf("Bitte eine Zahl eingeben %u", &zahl);

Text wird ignoriert !!!!!

printf ("Bitte eine Zahl eingeben:");

scanf ("%i",&zahl);

Richtig !!!!!

31

C-Programmierung 2003/2004 31

Achtung:

Die Programmiersprache C prüft bei scanf nicht die Überschreitung des Wertebereiches der definierten Variablen !!!!!

Programmierer muss selbst die Richtigkeit der Eingaben prüfen. Einfügen von entsprechenden Prüfprogrammen (Funktionen).

32

C-Programmierung 2003/2004 32

5. Grundrechenarten

+ Addiert zwei Werte

- Subtrahiert den rechten Wert vom linken

* Multipliziert zwei Werte miteinander

/ Dividiert den linken Wert durch den rechten

Punktrechnungen (* und /) binden stärker als Strichrechnungen ( + und -).

Wird eine andere Reihenfolge der Berechnung benötigt, so müssen Klammern verwendet werden.

aa=5*3+zahl1;

aa=5*(3+zahl1);

int-Variablen nehmen nur ganzzahlige Werte auf. Bei "/" werden die entstehenden Nachkommastellen weggelassen (es erfolgt keine Rundung).

33

C-Programmierung 2003/2004 33

Der Modulo-Operator %

Der Modulo-Operator bestimmt den Rest einer Division von Ganzzahlen.

13%4 = 1 denn 13/4=3 und 3*4=12

13-12=1

23%5 = 3 denn 23/5=4 und 5*4=20

23-20=3

Anwendungsfall:

Schubladenprinzip: - es existieren 8 Schubladen 0 bis 7

- es werden Zahlen in die Schubladen einsortiert

- 0 in Schublade 0

- 7 in Schublade 7

- 8 in Schublade 0 usw.

schublade=zahl%8;

33 / 8 = 4

4 * 8 = 32 Rest 1

Schublade 1

34

C-Programmierung 2003/2004 34

Weitere Operatoren (Zuweisungsoperatoren)

+= zahl+=5; zahl=zahl+5;

-= zahl-=5; zahl=zahl-5;

*= zahl*=5; zahl=zahl*5;

/= zahl/=wert; zahl=zahl/wert;

%= zahl%=6; zahl=zahl%6;

Frage ?

zahl=wert1/wert2 + zahl;

zahl+=wert1/wert2;

Die beiden Ausdrücke sind nur deshalb äquivalent, da "/" eine stärkere Bindung hat als "+".

35

C-Programmierung 2003/2004 35

zahl=zahl*wert1+wert2 ;

zahl*=wert1+wert2;

Achtung: Es erfolgt immer erst die Berechnung rechts und dann die Zuweisung !!!!!

falsch

36

C-Programmierung 2003/2004 36

Ausgabe von Ausdrücken

An jeder Stelle im Programm, an der eine Variable stehen kann, ist auch ein berechenbarer Ausdruck möglich. Außer auf der linken Seite eines Ausdruckes.

z3=z1+z2;

printf ("%i plus %i gleich %i\n", z1,z2,z3);

oder

printf ("%i plus %i gleich %i\n", z1, z2, z1+z2);

oder

printf ("%i plus %i gleich %i\n", z1, z2, z3=z1+z2);

Steht an einer Stelle im Programm ein berechenbarer Ausdruck, kann er auch dort zugewiesen werden.

37

C-Programmierung 2003/2004 37

An jeder Stelle im Programm, an der eine Variable steht, kann auch eine Konstante stehen.

printf ("Die Zahl heißt %i\n" , 123);

oder

printf ("Die Zahl heißt 123");

38

C-Programmierung 2003/2004 38

Die Operatoren ++ und --

Eine Variable wird inkrementiert (++), wenn ich ihren Wert um eins erhöhe.

Eine Variable wird dekrementiert (--), wenn ich ihren Wert um eins erniedrige.

Verwendung: Bei der Benutzung von Zählern !!!

wert=3;

printf ("Die Zahl lautet %i", wert);

wert++;

printf ("Die Zahl lautet %i"; wert);

wert--;

printf ("Die Zahl lautet %i", wert);

Als Ausgabe erfolgt in diesem Beispiel: 3 4 3

Die Operatoren stehen hinter der Variablen, d.h. das de- bzw. inkrementieren wird nach der Benutzung der Variablen ausgeführt.

Dieser Vorgang wird als Postinkrement bzw. Postdekrement bezeichnet.

39

C-Programmierung 2003/2004 39

wert=3;

printf ("Die Zahl lautet %i", wert);

++wert;

printf ("Die Zahl lautet %i"; wert);

--wert;

printf ("Die Zahl lautet %i", wert);

Als Ausgabe erfolgt in diesem Fall 3 4 3

In diesem vorliegendem Beispiel erfolgt die Inkrementierung bzw. Dekrementierung vor der Benutzung der Variablen. Dieser Vorgang wird als Präinkrement bzw. Prädekrement bezeichnet.

Warum erfolgt die gleiche Ausgabe, obwohl im ersten Beispiel die Operatoren als Postinkrement/-dekrement und im zweiten Beispiel als Präinkrement/-dekrement angewendet werden ?????

40

C-Programmierung 2003/2004 40

Weil in beiden Programmen die Variablen während dem Inkrementieren / Dekrementieren nicht benutzt wurden. Der Vorgang wurde separat ausgeführt

41

C-Programmierung 2003/2004 41

wert=3;

printf ("Das ist Zahl %i",wert++);

printf ("Das ist Zahl %i",wert--);

printf ("Das ist Zahl %i", wert);

Das Ergebnis lautet: 3 4 3

wert=3;

printf ("Das ist Zahl %i",++wert);

printf ("Das ist Zahl %i",--wert);

printf ("Das ist Zahl %i", wert);

Das Ergebnis lautet: 4 3 3

42

C-Programmierung 2003/2004 42

Fragen:1.) Ist x+=2 gleich x++2 ???

2.) Worin liegt der Vorteil von ++ gegenüber von +=1 ???

Programm 02

Programm 02_2

43

C-Programmierung 2003/2004 43

6. Entscheidungen

Entscheidungen werden benutzt, um den sequentiellen Programmablauf zu verändern.

if (bedingung)

{

}

if zahl==0

{

printf (Achtung Wert nicht gueltig !!!!" \n);

}

erg=zahl01*zahl02;

Abfrage auf Gleichheit erfolgt mit: ==

44

C-Programmierung 2003/2004 44

Der Operator !

In C hat man die Möglichkeit die Aussage einer Bedingung zu negieren, wenn "!" vor die Aussage gesetzt wird.

if (! (wert==100))

{

printf ("Der Wert ist ungleich 100 !!!!!");

}

Besteht der Anweisungsblock hinter einer if Kontrollstruktur nur aus einer Anweisung, so können die geschweiften Klammern weggelassen werden.

45

C-Programmierung 2003/2004 45

Die else-Anweisung

Die else Anweisung ist ein Zusatz zu if und kann auch nur im Zusammenhang damit verwendet werden.

if (a>b)

{

printf ("Die Zahl a ist grösser als die Zahl b");

a=a-b;

}

else

{

print ("Die Zahl a ist nicht grösser als b");

a=b-a;

}

Der else Zweig wird immer dann ausgeführt, wenn die Bedingung nicht erfüllt ist. Ist die Bedingung erfüllt, so wird der gesamte else Zweig ignoriert und es werden nur die Anweisungen (Anweisungsblock) hinter der Bedingung abgearbeitet.

46

C-Programmierung 2003/2004 46

Vergleichsoperatoren

a<b Wahr, wenn a kleiner b

a<=b Wahr, wenn a kleiner gleich b

a>b Wahr, wenn a größer b

a>=b Wahr, wenn a größer gleich b

a==b Wahr, wenn a gleich b

a!=b Wahr, wenn a ungleich b

Achtung:

Unzulässig sind die Operatoren => und =<

47

C-Programmierung 2003/2004 47

Testfragen:

1.) Der if-Anweisungsblock wird nur dann ausgeführt, wenn die Bedingung erfüllt ist? Ja/Nein????

2.) Worin liegt der Unterschied von = und == ?

3.) Worin liegt der Unterschied in den beiden Vergleichen?

(a>b)

(!(a<=b))

48

C-Programmierung 2003/2004 48

#include <stdio.h>

void main(void){int zahl;

printf("Bitte geben Sie eine Zahl ein :");scanf("%i",&zahl);

if(zahl<100){printf("Die Zahl ist kleiner als Hundert.\n");

}if(zahl==100){printf("Hundert war die gesuchte Zahl.\n");}if(zahl>100)printf("Die Zahl ist größer als Hundert.\n");

}

Programm 3.cpp

49

C-Programmierung 2003/2004 49

Behandlung der Bedingung

C behandelt Bedingungen wie einen Wert. Eine Entscheidung kann nur zwei Zustände annehmen, wahr oder falsch. Um die Werte für eine Entscheidung zu erhalten, kann man das folgende Programm nutzen.

#include <stdio.h>

void main(void){int wahr,falsch;

wahr=(3==3);falsch=(2==4);

printf("Der Wert für wahr ist %i\n",wahr);printf("Der Wert für falsch ist %i\n",falsch);

}

Eine Bedingung ist falsch, wenn sie den Wert 0 hat und wahr, wenn sie einen Wert ungleich 0 hat.

Programm 04

50

C-Programmierung 2003/2004 50

Eine Bedingung darf auch in einem berechenbaren Ausdruck stehen. Dabei nimmt sie die Werte 0 und 1 an, 0 bei falsch und 1 bei wahr.

Eine Bedingung ist falsch, wenn sie den Wert 0 hat.

Abfrage auf ungleich Null kann wie folgt realisiert werden:

if (x)

{

}

Der Anweisungsblock hinter if wird dann ausgeführt, wenn x ungleich null ist. Das ergibt sich daraus, dass alle Werte ungleich Null für C "wahr" sind.

51

C-Programmierung 2003/2004 51

Die Abfrage auf gleich Null kann damit durch folgende

Anweisung realisiert werden.

Das man mit Bedingungen rechnen kann, das wurde im

Beispielprogramm bereits bewiesen.

if (!x)

{

}

Programm 6.cpp

52

C-Programmierung 2003/2004 52

7. Gültigkeitsbereiche von Variablen

Lokale Variablen

Eine Variable, die innerhalb eines Anweisungsblocks definiert ist, hat nur lokal in diesem Block ihre Gültigkeit.

#include <stdio.h>

void aendern(void){

x=10;}

void main(void){int x=4;

printf("x = %i\n",x);

aendern();

printf("x = %i\n",x);}

Fehler beim compilieren, Variable x ist nicht definiert

53

C-Programmierung 2003/2004 53

Wird ein Anweisungsblock verlassen, werden alle Variablen, die in ihm definiert wurden, gelöscht.

Gibt es mehrere Variablen mit gleichem Namen, so spricht man immer die lokalste Variable an.

Kann man Variablen auch noch lokaler als im Beispiel auf der

vorherigen Seite definieren? ?

54

C-Programmierung 2003/2004 54

#include <stdio.h>

void main(void){int wert;

printf("Bitte Zahl eingeben :");scanf("%i",&wert);if(wert<=20){int quadrat;

quadrat=wert*wert;printf("Das Qudrat von %i ist %i\n",wert,quadrat);}printf("Quadrat hat den Wert %i",quadrat);

}

Variable quadrat ist innerhalb des if-Blocks definiert und nur dort gültig

Fehler beim compilieren, da Variable quadrat nicht definiert ist !!!!

Lokale Variablendefinitionen müssen immer die ersten Anweisungen des Blockes sein, in dem sie stehen !!!

55

C-Programmierung 2003/2004 55

Globale Variablen

#include <stdio.h>

int x=4;

void aendern(void){

x=10;}

void main(void){

printf("x = %i\n",x);

aendern();

printf("x = %i\n",x);}

Die Variable x ist als globale Variable definiert

Variablen, die außerhalb einer Funktion definiert werden, sind global und können somit in jeder Funktion benutzt werden.

56

C-Programmierung 2003/2004 56

#include <stdio.h>

int a,b;

void aendern(void){int a;

a=0;if(a==0)

{ int a=20;printf("a=%i\n",a);

}printf("a=%i\n",a);

}void main(void){a=b=10;

printf("a=%i und b=%i\n",a,b);aendern();printf("a=%i und b=%i\n",a,b);

}

Globale und lokale Variablen können in einem Programm zusammen genutzt werden. Dabei sind gleiche Namen durchaus erlaubt.

Variable a und b global definiert

Variable a lokal definiert

57

C-Programmierung 2003/2004 57

Wenn eine lokale Variable definiert wurde, dann ist es nicht möglich auf globale Variablen gleichen Namens zuzugreifen. Dies ist erst in C++ möglich.

void main(void)

{

int a;

int a;

a=10;

}

Es dürfen nicht zwei Variablen mit gleichem Namen und dem gleichen Gültigkeitsbereich definiert werden

Achtung

Bei der Definition von Variablen gilt folgender Grundsatz

So lokal wie möglich, so global wie nötig.

Globale Variablen erleichtern das Programmieren ungemein, da man in jeder Funktion auf alle Variablen ungehindert zugreifen kann. Für eine modulare Programmierung sollten globale Variablen jedoch vermieden werden. Sie sollten nur dann verwendet werden, wenn es keine andere Möglichkeit in der Programm-realisierung gibt.

58

C-Programmierung 2003/2004 58

Statische Variablen

Statische Variablen sind eine Mischung aus globalen und lokalen Variablen. Sie werden beim Verlassen ihres Gültigkeitsbereiches nicht gelöscht, sondern behalten ihren Wert.

#include <stdio.h>void test(void){int a=1;

printf("a=%i\n",a); a++;}void main(void){

test();test();test();

}

Was wird in diesem Programm ausgegeben ? ?1 1 1

59

C-Programmierung 2003/2004 59

#include <stdio.h>void test(void){static int a=1;

printf("a=%i\n",a);a++;

}void main(void){

test();test();test();

}

Definition von a als statische Variable

Was wird im Testprogramm ausgegeben? ?1 2 3

Statische Variablen müssen bei ihrer Definition immer initialisiert werden.

Wenn eine Variable als statisch definiert wurde, ist sie immer noch lokal, d.h. im Testprogramm kann in der main-Funktion nicht auf a zugegriffen werden. Nach Verlassen des Gültigkeitsbereiches bleibt jedoch der Wert der Variablen a erhalten.

60

C-Programmierung 2003/2004 60

#include <stdio.h>void test(void){static int a;

a=1;printf("a=%i\n",a);

a++;}void main(void){

test();test();test();

}

Was wird im Programm ausgegeben? ?1 1 1

Im Programmbeispiel wurde die statische Variable bei ihrer Definition nicht initialisiert. Aus diesem Grund wird bei jedem Aufruf von test immer a=1 zugewiesen. Die Variable hat damit in jedem printf den Wert 1.

Programm 05

61

C-Programmierung 2003/2004 61

8. Funktionen mit Parameterübergabe

Funktionen können Werte übergeben werden. Das void vor der Klammer des Funktionsnamens bedeutet, dass die Funktion keinen Wert zurückliefert. Das void in der Klammer nach dem Funktionsaufruf bedeutet, das der Funktion kein Wert übergeben wird.

Funktionsparameter sind lokale Variablen der Funktion, die mit der Übergabe initialisiert werden.

8.1 Parameterübergabe

62

C-Programmierung 2003/2004 62

Parameterübergabe an quadrat

#include <stdio.h> /*Programm 07 */

void quadrat (int x){int ergebnis;

ergebnis=x*x;printf("Das Quadrat von %i",x);printf (" ist %i\n",ergebnis);

}

void main(void){int wert;

printf("bitte geben Sie eine Zahl ein: ");scanf("%i",&wert);

quadrat(wert);}

Wert wird an die Funktion übergeben

63

C-Programmierung 2003/2004 63

Im Beispiel hat int x den Platz von void eingenommen, d.h. die Funktion quadrat bekommt einen int Wert übergeben. Die Variable x bekommt diesen Wert zugewiesen und kann wie jeden andere Variable in der Funktion genutzt werden.

Achtung! Mit der Übergabe des Wertes an die Funktion ist die Variable x initialisiert.

In der Hauptfunktion main wird die Funktion quadrat aufgerufen. Im Funktionsaufruf wird wert an die Funktion übergeben und damit die Variable x in der Funktion quadratinitialisiert.

Funktionsparameter verhalten sich wie lokale Variablen, d.h. Innerhalb der Funktion kann diese Variable geändert werden, ohne das sich die Variable in der übergeordneten Funktion ändert (Gültigkeitsbereich lokaler Variablen).

64

C-Programmierung 2003/2004 64

8.2 Wertrückgabe

#include <stdio.h> /* Programm 8 */

int quadrat (int x){int ergebnis;

ergebnis=x*x;return(ergebnis);

}void main(void){int wert,qwert;

printf("bitte geben Sie eine Zahl ein: ");scanf("%i",&wert);printf ("\n\n\n");qwert=quadrat(wert);

printf("Das Quadrat von %i ist %i\n\n\n",wert,qwert);}

Funktion quadrat

Das int vor dem Funktionsname bedeutet, daßein int Wert zurückgegeben wird

Rückgabewert

Funktionsaufruf

Funktionen, die einen Wert zurückliefern, repräsentieren diesen Wert mit dem Aufruf.

65

C-Programmierung 2003/2004 65

Soll eine Funktion einen Wert zurückgeben, dann erfolgt dies mit "return".

Funktionen werden mit "return beendet, wenn ein Wert in die übergeordnete Funktion übergeben werden soll. Die Klammern hinter return sind nicht zwingend, erhöhen aber die Übersichtlichkeit in Programm.

An den Stellen, wo im C-Programm eine Variable steht, kann auch ein berechenbarer Ausdruck stehen.

#include <stdio.h>int quadrat (int x){

return(x*x);}void main(void){int wert,qwert;printf("bitte geben Sie eine Zahl ein:");scanf("%i",&wert);qwert=quadrat(wert);printf("Das Quadrat von %i ist %i\n",wert,qwert);}

Die Berechnung erfolgt direkt in return, die Variable quadratwird nicht benötigt

66

C-Programmierung 2003/2004 66

Der Funktionsaufruf repräsentiert direkt den Wert, den die Funktion liefert. Damit kann man das Testprogramm weiter vereinfachen.

#include <stdio.h>int quadrat (int x){

return(x*x);}void main(void){int wert,qwert;printf("bitte geben Sie eine Zahl ein:");scanf("%i",&wert);qwert=quadrat(wert);printf("Das Quadrat von %i ist %i\n",wert,quadrat(wert));}

Funktionsaufruf ist direkt in die printf-Anweisung integriert

Wird der Rückgabewert einer Funktion nicht angegeben, geht der Compiler davon aus, dass ein int-Wert zurückgegeben wird.

Kann entfallen

67

C-Programmierung 2003/2004 67

Wie würde das Programm aussehen, wenn die eben besprochene Tatsache zur Anwendung kommt???

Test#include <stdio.h> /*Programm 9 */quadrat (int x){

return(x*x);}void main(void){int wert;printf("bitte geben Sie eine Zahl ein:");scanf("%i",&wert);printf("Das Quadrat von %i ist %i\n",wert,quadrat(wert));}

Das int vor der Funktion kann weggelassen werden

68

C-Programmierung 2003/2004 68

8.3 Übergabe mehrerer Parameter

Eine Funktion kann nur einen Wert zurückgeben (auf diese Art und Weise). Es können aber beliebig viele Werte an die Funktion übergeben werden.

#include <stdio.h>int max(int a, int b){int maxwert;

if(a>b){maxwert=a;}

else{maxwert=b;}

return(maxwert);}void main(void){int zahl1,zahl2;

printf("Bitte geben Sie Zahl 1 ein:");scanf("%i",&zahl1);printf("Bitte geben Sie Zahl 2 ein:");scanf("%i",&zahl2);printf("Die größere Zahl ist %i\n", max(zahl1,zahl2));

}

Was realisiert dieses Programm?????

69

C-Programmierung 2003/2004 69

8.4 Prototypen parametrisierter Funktionen

Wann ist ein Prototyp für eine Funktion erforderlich? ?Ein Prototyp für eine Funktion ist dann erforderlich, wenn die Funktion hinter die main-Funktion platziert wird!

Wird ein Prototyp einer Funktion benutzt, so müssen nur die Variablentypen der Funktionsparameter angegeben werden, nicht die Variablennamen.

int funktion(int x, int y)

{

x=((x+9)*12)/y

}

int funktion (int, int); Funktion als Prototyp

!

70

C-Programmierung 2003/2004 70

8.5 sonstiges bei Funktionen mit Parameterübergabe

Funktionen, die einen Wert zurückgeben, müssen immer mit return beendet werden. !

Ist das folgendem Programmausschnitt richtig?

int testfkt (int x)

{ if (x==20)

return (x+12);

}

Der Compiler wird einen Fehler melden, da die Funktion einen Rückgabewert hat und return aber nur ausgeführt ´wird, wenn x=20 ist. Ist x ungleich 20, so wird die Funktion beendet und es wird kein Rückgabewert geliefert.

Wie muss die Funktion richtig lauten ????

71

C-Programmierung 2003/2004 71

int testfkt (int x)

{ if (x==20)

return (x+12); else { return (x*x) };

}

72

C-Programmierung 2003/2004 72

9. Die for-Schleife

Aufgabenstellung:

Ausgabe der Zahlen von 1 bis 100 am Bildschirm.

1. Möglichkeit 100 printf-Anweisungen

2. Möglichkeit mit einer Schleife und einer printf-Anweisung

Syntax der for-Schleife

for (anweisung1 ; bedingung ; anweisung2)

{ anweisungsblock

}

73

C-Programmierung 2003/2004 73

for (anweisung1 ; bedingung ; anweisung2)

{ anweisungsblock}

Anweisung1

Bedingung wahr? Anweisungs-block

Anweisung2nein

ja

74

C-Programmierung 2003/2004 74

Reihenfolge der Abarbeitung der for-Scheife

1. Anweisung1 ausführen

2. Bedingung prüfen, wenn wahr, dann weiter mit Pkt.3,

sonst bei Pkt.6

3. Anweisungsblock hinter for ausführen

4. Anweisung2 ausführen

5. Weiter bei Pkt.2

6. Zur ersten Anweisung hinter den Anweisungsblock der

for-Anweisung springen

75

C-Programmierung 2003/2004 75

#include <stdio.h>

void main(void){int x;

for(x=1; x<=3; x++){printf("Aktueller Wert :%i\n",x);}

}

Anweisung1 bedingung anweisung2

anweisungsblock

Programm 10

76

C-Programmierung 2003/2004 76

An jeder Stelle der for Anweisung, an der eine Variable steht, kann auch ein berechenbarer Ausdruck stehen.

Innerhalb einer for Anweisung können auch mehrere Anweisungen stehen. Diese sind dann durch Komma zu trennen.

#include <stdio.h>

void main(void){int x,y,zahl1,zahl2;

printf("Bitte Zahl x eingeben :");scanf("%i",&zahl1);printf("Bitte Zahl y eingeben :");scanf("%i",&zahl2);

for(x=1,y=zahl2; x<=zahl1; x++,y--)printf("Aktuelle Werte :%i und %i\n",x,y);

}

Was realisiert das Programm ??? ?

Programm 11

77

C-Programmierung 2003/2004 77

Initialisierungen weglassen

In for Schleifen kann man auf Initialisierung von Variablen teilweise verzichten. Es ist jedoch aus Gründen der Übersichtlichkeit und Lesbarkeit des Programms nicht immer zu empfehlen.

#include <stdio.h> Programm 11_04

void main(void){int x;

printf("Bitte Zahl eingeben :");scanf("%i",&x);

for(; x ; x--)printf("Aktueller Wert :%i\n",x);

}

An der Stelle der Bedingung steht x, das heißt, solange der wert von x ungleich Null ist, gilt die Bedingung als wahr.

78

C-Programmierung 2003/2004 78

10. Schleifen mit Ein-/Austrittsbedingungen

10.1Schleifen mit Eintrittsbedingung

Die Schleife in C mit Eintrittsbedingung ist die while-Schleife. Syntax:

while (bedingung)

{anweisungsblock

}

Bedingung wahr? anweisungsblockja

nein

79

C-Programmierung 2003/2004 79

Ist die Bedingung wahr, dann wird der Anweisungsblock hinter while ausgeführt. Anschließend wird die Bedingung erneut geprüft. Der Anweisungsblock wird solange ausgeführt, bis die Bedingung falsch ist. Dann wird die while Schleife verlassen und das Programm fortgesetzt.

#include <stdio.h> Programm 11-01

void main(void){int zahl;

zahl=0;

while(zahl!=200){printf("Bitte geben Sie 200 ein:");scanf("%i",&zahl);}

}

Was realisiert dieses Programm??

80

C-Programmierung 2003/2004 80

Auch bei der while Anweisung gilt, daß die Klammern entfallen, wenn es sich nur um eine Anweisung im Anweisungsblock handelt

Eine while-Schleife ist als eine vereinfachte Form von for zu betrachten. Aus diesen Gründen kann auch eine for-Schleife mit while simulieren.

for (x=5;x<=25;x++)

printf ("Der Wert betraegt %i\n",x);

x=5;

while (x<=25)

{ printf ("Der Wert betraegt %i\n",x);

x++;

}

81

C-Programmierung 2003/2004 81

Wenn man das obige Beispiel betrachtet, so kann man feststellen, dass die Lösung mit for viel einfacher erscheint. Warum also while benutzen?

Die while Schleife wird für spezielle Probleme genutzt, z.B. wenn auf ein bestimmtes Ereignis gewartet wird (Syntaxprüfung bei der Eingabe von Daten/Wertebereich).

In diesem Fall eignet sich die while Schleife auf Grund ihrer einfachen Konstruktion sehr gut.

In einigen Anwendungsfällen kann man sogar auf den Anweisungsblock verzichten.

#include <stdio.h> // Programm 11-02int getzahl(void){ int zahl;

printf("Bitte geben Sie eine Zahl ein:");scanf("%i",&zahl);return(zahl);

}void main(void){

while(getzahl()!=200);}

82

C-Programmierung 2003/2004 82

10.2 Schleifen mit Austrittsbedingung: do while

Bei while wird erst der Vergleich durchgeführt, d.h. der Anweisungsblock wird nach dem Vergleich abgearbeitet oder bei falscher Bedingung nicht abgearbeitet.

Bei Benutzung von do while wird erst der Anweisungs-block abgearbeitet und danach die Bedingung geprüft.

Problem wird bei der Eingabe mit Syntaxprüfung benutzt. Um zu prüfen, ob eine eingegebene Zahl eine gewisse Bedingung erfüllt, muß ich sie zuerst einlesen und danach prüfen. Das bedeutet, der Anweisungsblock muß erst abgearbeitet werden und danach wird erst die Bedingung geprüft.

Syntax:

do

{ anweisungsblock

}

while (Bedingung);

83

C-Programmierung 2003/2004 83

Die do while Sckleife wird wie folgt abgearbeitet:

(1) Abarbeitung des Anweisungsblockes zuwischen do und while

(2) prüfen der Bedingung

(3) bei wahr wird zu do gesprungen und der Anweisungsblock

erneut abgearbeitet (1)

(4) ist die Bedingung nicht erfüllt (falsch), so fährt das Pro-

gramm hinter while fort

nein

jaBedingung wahr?

Anweisungs-Block

84

C-Programmierung 2003/2004 84

Die while Abfrage in der do while Konstruktion wird immer mit einem Semikolon abgeschlossen.

Das Programm von Seite 79 könnte mit einer do while Konstruktion wie folgt aussehen:

#include <stdio.h>void main(void){int zahl;

do{printf("Bitte geben Sie 200 ein:");scanf("%i",&zahl);}

while(zahl!=200);}

In C gibt es eine spezielle Anweisung, welche nur innerhalb von Schleifen benutzt werden kann. Das heißt nur innerhalb von for, while oder do while. Das ist die continue Anweisung.

Keine Anfangsinitialisierung

von „zahl“ notwendig

Programm 11_03

„Eingabeprüfung“

85

C-Programmierung 2003/2004 85

10.3 Continue-Anweisung

x=0;

while (x<20)

{

x++

if (x==10)

continue;

printf ("x=%i\n",x);

}

Continue springt immer an den Anfang der innersten Schleife!!

Programm 991

86

C-Programmierung 2003/2004 86

Beginn

x=0

solangeX<20

x=x+1

x==10

nein

ja

In diesem Fall tritt die continue

Anweisung in Aktion

1

1

Ausgabe von x

Schleifenende

Ende

87

C-Programmierung 2003/2004 87

Welche Auswirkung hat while (1) auf den Programmablauf? ?Die Bedingung while ist immer wahr, d.h. es ist eine Endlosschleife

88

C-Programmierung 2003/2004 88

11. Logische Operatoren

Der logische Operator &&

Der logische Operator && wir als UND oder AND-Operator bezeichnet. Er verknüpft zwei Bedingungen auf folgende Weise.

Bedingung1 Bedingung2 Bedingung1 && Bedingung2

falsch falsch falsch

falsch wahr falsch

wahr falsch falsch

wahr wahr wahr

89

C-Programmierung 2003/2004 89

if ((x>=20) && (x<=40))

{ anweisungsblock

}

Der Anweisungsblock hinter if wird nur abgearbeitet, wenn

X größer gleich 20 und kleiner gleich 40 ist ?Achtung!!Der && Operator ist kommutativ, das heißt

x && y ist gleichbedeutend mit y && x

90

C-Programmierung 2003/2004 90

Bedingung1 Bedingung2 Bedingung1 || Bedingung2

falsch falsch falsch

falsch wahr wahr

wahr falsch wahr

wahr wahr wahr

Der logische Operator ||

Der logische Operator || wird auch als ODER bzw. OR Operator bezeichnet. Er realisiert folgende Verknüpfungen.

Achtung!!!Der || Operator entspricht nicht dem gebräuchlichem ODER, er bedeutet,

dies oder jenes oder beides !Der || Operator ist ebenfalls kummutativ. Daraus folgt, dass

a || b gleichbedeutend mit b|| a ist

91

C-Programmierung 2003/2004 91

Der && Operator und der || Operator können auch gemeinsam innerhalb eines Ausdruckes auftreten.

do

{

printf ("Bitte eine Zahl im Bereich von 20 bis\ 40 eingeben oder eine 0 für\Ende der Eingabe");

scanf ("%i", &wert);

}

while (((wert<20) || (wert>40)) && (wert !=0));

Die Schleife wird beendet, wenn der Wert zwischen 20 und 40 liegt oder wenn eine 0 eingegeben wird.

Das heißt, wenn der Wert kleiner als 20 oder größer als 40 ist und ungleich Null ist, dann wird wieder zu do gesprungen.Alle Werte zwischen 20 und 40 du die Null sind gültig!!!!

Programm 12

92

C-Programmierung 2003/2004 92

10 wahr || falsch = wahr wahr && wahr = wahr

in Schleife verbleiben!!!

30 falsch || falsch= falsch falsch && wahr = falsch

Schleife verlassen

0 wahr || falsch = wahr wahr && falsch = falsch

Schleife wird verlassen

93

C-Programmierung 2003/2004 93

12. Variablen vom Typ float

Float-Point Variablen stehen in 3 verschiedenen Varianten zur Verfügung.

Typ Größe Mindestgenauigkeit Formatzeichen

float 4 6 f

double 8 10 f

long double 10 10 lf

Die Größe gibt die Byte an, die von einer Variablen belegt werden. Die Mindestgenauigkeit ist die Anzahl der Stellen hinter dem Komma. Alle Variablen decken einen Wertebereich von mindestens 1038 bis 10-38 ab. Es gibt in C keine vorzeichenlosen Gleitkommazahlen.

Diese Genauigkeit der Gleitkommazahlen ist ausreichend für die meisten Operationen, auch im mathematischen Bereich. Man sollte sich jedoch immer genau den Einsatz von Gleitkommazahlen überlegen, da diese Operationen rechenintensiver und speicher-intensiver als int Variablen sind

94

C-Programmierung 2003/2004 94

#include <stdio.h>void main(void){unsigned long n=3,max;//unsigned long 4 Byte 0 bis 4.294.967.295

float pi=1.0;printf("Bis zu welchem n soll gerechnet werden:");scanf("%li",&max);while(n<max)

{pi=pi-(1.0/n)+(1.0/(n+2));n+=4;printf("n=%lu :%f\n",n,pi*4.0);

}}Dieses Programm realisiert die Berechnung der Zahl pi nach dem Verfahren von Leibnitz.

pi=(1-1/3+1/5-1/7+1/9-1/11+1/13-1/15+1/17-1/19+1/21-.......)*4

Gleitkommazahlen verhalten sich in Operationen genau wie Ganze Zahlen. Es muss nur eine andere Deklaration und ein anderes Formatzeichen benutzt werden.

Programm 13

95

C-Programmierung 2003/2004 95

Werden zwei Variablen unterschiedlichen Typs durch einen Operator verknüpft, so bekommt das Ergebnis den genaueren Typ der beiden Variablen.

1/n ist immer 0, wenn n>1 und eine int Variable.

1.0/n bekommt als Ergebnis den Wert einer Gleitkommzahl, da 1.0 als Gleitkommazahl interpretiert wird.

Typumwandlung mit dem cast-Operator

Mit dem cast Operator kann der Programmierer den Typ des Ergebnisses selbst bestimmen. Mit cast wird eine Typumwandlung realisiert.

Syntax des cast Operators:

(typ) (variable)

96

C-Programmierung 2003/2004 96

int a=3, b=2; /* Beispiel-1

float c;

c=a/b;

Als Ergebnis hat c den Wert 1, da erst die Division mit int-Variablen durchgeführt wird. Erst danach erfolgt die Anpassung an das float Format.

int a=3, b=2; / /Beispiel-2

float c;

c=(float) (a) / (float) (b);

Im zweiten Beispiel wird der cast Operator verwendet. Damit erfolgt erst die Anpassung an das float Format und danach die Division. Damit lautet das Ergebnis 1,5.

int a=3, b=2; /* Beispiel-3

float c;

c=(float) a / (float) b;

97

C-Programmierung 2003/2004 97

Auch wenn die Klammern nicht geschrieben sind, erfolgt erst die Typumwandlung und danach die Division. Die Ursache liegt darin, dass der cast Operator eine stärkere Bindung hat als die Division. Deshalb erfolgt erst die Umwandlung und dann die Division

98

C-Programmierung 2003/2004 98

Die Funktionen von math.h

In der Bibliothek math.h sind die wesentlichsten mathematischen Funktionen enthalten. Werden diese be-nötigt, so ist diese Bibliothek am anfang des Programms anzuhänhen.

#include <math.h>

acos Umkehrfunktion des Kosinus

asin Umkehrfunktion des Sinus

atan Umkehrfunktion des Tangens

ceil grundsätzliches aufrunden

cos Kosinus

cosh Kosinus Hyperolicus

exp Exponentialfunktion (e hoch a)

fabs Absolutwert von |a|

floor grundsätzliches abrunden

99

C-Programmierung 2003/2004 99

fmod Modulowert (a%b)

frexp Aufspalten von a in a=f*2i

ldexp Umkehrung zu frexp

log nathürlicher Logarithmus (Basis e)

log10 dekadischer Logarithmus (Basis 10)

modf Aufspaltung von a in a=f+i

pow Potenz a hoch b

sin Sinus

sinh Sinus Hyperbolicus

sqrt Quadratwurzel

tan Tangens

tanh Tangens Hyperbolicus

100

C-Programmierung 2003/2004 100

Beschreibung ausgewählter Funktionen

sqrt

double sqrt (double a);

Berechnet die Quadratwurzel von a

#include "stdio.h"#include "math.h"void main (void){double zahl=4.3456, ergebnis;printf ("Eingabe einer Zahl: ");//scanf ("%lf",&zahl); Probleme bei %f und double zahlergebnis=sqrt(zahl);

printf ("Ergebnis von Quadratwurzel aus %f ist: %f \n",zahl,ergebnis);}

101

C-Programmierung 2003/2004 101

tandouble tan (double a);Berechnet den Tangens von a im Bogenmaß.

sindouble sin (double a);Berechnet den Sinus von a im Bogenmaß.

ceil

double ceil (double a)

Liefert die nächst höhere Ganzzahl von a.

z.B aus 6.4 wird 7, aus -3.1 wird -3

102

C-Programmierung 2003/2004 102

acos

double acos (double a);

Berechnung Arcus Kosinus (Umkehrfunktion von Kosinus) im Wertebereich -1 bis 1

fabs

double fabs (double a)

Liefert den Betrag oder Absolutwert von a ( |a| )

floor

double floor (double a)

Liefert die nächstniedrige Ganzzahl

103

C-Programmierung 2003/2004 103

FZ Typ Zahlensystem Besonderheit

f double Dezimal *.*****

Lf long double Dezimal *.*****

e double Dezimal *.***E**

Le long double Dezimal *.***E**

E double Dezimal *.***E**

LE long double Dezimal *.***E*

g double Dezimal mit oder ohne Exponent

Lg long double Dezimal mit oder ohne Exponent

G double Dezimal mit oder ohne Exponent

LG long double Dezimal mit oder ohne Exponent

Formatzeichen Gleitkommazahlen

104

C-Programmierung 2003/2004 104

Erweiterte Formatierung der Ausgabe

printf ("%.2f\n",1234.3456) .2

Legt fest, daß zwei Stellen nach dem Komma ausgegeben werden.

printf ("%15.2f\n",1223.34345); 15.2

Diese Anweisung setzt 8 Leerzeichen vor die Zahl. Die Zahl selbst ist 17 Stellen lang (geplanter Wert) die auszugebende Zahl ist im Original 9 Stellen. 17 - 9 =8 ---> 8 Leerstellen.

105

C-Programmierung 2003/2004 105

printf ("%-15.2f\n",1223.34345); -15.2

Zahl wird linksbündig ausgegeben.

printf ("%+15.2f\n",1223.34345); +15.2

Zahl wird immer als positive Zahl ausgegeben.

Programm 14

Programm 14_01

106

C-Programmierung 2003/2004 106

13. Fallunterscheidungen

Gibt es zu einem Entscheidung mehrere Möhlichkeiten der Entscheidung, so müssen verschachtelte if Anweisungen oder die case-Anweisung genutzt werden.

Syntax:

switch (variable)

{

case 1:

case 12:

case -9:

}

Die Variable dient in dieser Anweisung als Schalter. Hat die Variable den entsprechenden Wert, so wird die zugehörige case Anweisung angesprungen. Hinter der Sprungmarke case muß immer eine ganzzahlige Konstante stehen.Wird eine case Marke angesprungen, so werden alle danach folgenden case Anweisungen mit abgearbeitet. Wird keine Übereinstimmung mit den Konstanten erzielt, so passiert nicht. Das Programm wird fortgesetzt.

107

C-Programmierung 2003/2004 107

Sollen nach dem Ansprung einer case Marke die anderen nachfolgenden CaseAnweisungen nicht abgearbeitet werden, so muß break verwendet werden.

Break springt immer hinter die innerste for, switch oder while Anweisung.

Beginn

case 1 ?

case 2 ?

case 3 ?

ja

ja

ja

Ausgabe 1

Ausgabe 2

Ausgabe 3

nein

nein

nein

Ende

Switch/case ohne break

108

C-Programmierung 2003/2004 108

Beginn

case 1 ?

case 2 ?

case 3 ?

ja

ja

ja

Ausgabe 1

Ausgabe 2

Ausgabe 3

nein

nein

nein

Ende

Switch/case mit break

109

C-Programmierung 2003/2004 109

#include <stdio.h> /*Programm 15 */

void main(void){int x;

printf("Geben Sie bitte 1,2 oder 3 an:");scanf("%i",&x);switch(x)

{case 1: printf("Das war Zahl-1-\n");

break;

case 2: printf("Das war Zahl -2-\n");break;

case 3: printf("Das war Zahl -3-\n");break;

}}

110

C-Programmierung 2003/2004 110

Beginn

case 1 ?

case 2 ?

case 3 ?

ja

ja

ja

Ausgabe 2

Ausgabe 3

nein

nein

nein

Ende

Mehrere case Anweisungen mit gleichem Sprungziel

Es können beliebig viele case-Anweisungen das gleiche Sprungziel haben.

111

C-Programmierung 2003/2004 111

switch(x){case 1:case 2: printf("Das war Zahl 2 oder 1 \n");

break;case 3: printf("Das war Zahl 3 \n");

break;}

Die default-Anweisung

Wenn für einen Wert keine Sprungmarke existiert, dann kann default verwendet werden. Wird also keine Übereinstimmung erzielt, dann wird immer defaultangesprungen. Damit kann der Sachverhalt, dass eine begrenzte Anzahl case-Anweisungen für bestimmte Bedingungen und ein Standard für "sonstiges", abgedeckt werden.

Keine Sprungmarke für einen Wert default (wenn vorhanden)

112

C-Programmierung 2003/2004 112

#include <stdio.h> /*Programm 15-01 */

void main(void){int x;

printf("Geben Sie bitte 1,2 oder 3 an:");scanf("%i",&x);switch(x)

{case 1: printf("Das war Zahl 1 \n");

break;

case 2: printf("Das war Zahl 2 \n");break;

case 3: printf("Das war Zahl 3 \n");break;

default: printf("ungültige Eingabe \n");break;

}}

113

C-Programmierung 2003/2004 113

14. Der Variablentyp charDer Variablentyp char gestattet es, mit einzelnen Zeichen zu arbeiten.

char x;

printf ("Bitte ein Zeichen eingeben");

scanf ("%c",&x);

printf ("Das eingegebene Zeichen lautet >%c< \n",x);

Das Formatzeichen ist %c

Wertebereich von 0-255 (ASCII)

Eine Wertzuweisung (Initialisierung) einer char-Variablen erfolgt mit:

char x ; x='F'; Achtung: Wertzuweisung immer in einfachen Anführungszeichen!!!!!

114

C-Programmierung 2003/2004 114

Der Variablentyp char ist fast identisch mit unsigned short.

Man kann char somit auch wie ganzzahlige Variablen behandeln.

x='F';

printf ("Der Wert von %c ist %i",x,x);

int x;

for (x=0;x<256;x++)

printf ("Das Zeichen ist \"%c\", der Wert ist %i \n",x,x); ?int x; x=24+'B';

switch (x)

{

case 'a': printf (" Ein kleines a\n");

break;

case 'b': printf ("Ein kleines b\n");

break;

}

Programm 15_02

ASCII Tabelle Teil-1

ASCII Tabelle Teil-2

115

C-Programmierung 2003/2004 115

Die Funktionen von ctype.h

isalnum wahr für einen Buchstaben oder eine Zahl

isalpha wahr für einen Buchstaben

iscntrl wahr für ein bestimmtes Steuerzeichen

isdigit wahr für eine dezimale Ziffer

isgraph wahr für darstellbare Zeichen außer Leerzeichen

islower wahr für Kleinbuchstaben

isprint wahr für darstellbare Zeichen incl. Leerzeichen

isupper wahr für Großbuchstaben

isxdigit wahr für eine Hexadezimalzahl

116

C-Programmierung 2003/2004 116

#include <stdio.h> /*Programm 15-03 */#include <ctype.h>void main(void){char x; printf("Bitte Zeichen eingeben:");

scanf("%c",&x);if(isdigit(x)){printf("Es war eine dezimale Ziffer!\n");}else{printf("Das Zeichen war keine Ziffer\n");}

}

117

C-Programmierung 2003/2004 117

Die Headerdatei ctype.h stellt außerdem noch zwei Umwandlungsfunktionen zur Verfügung.

tolower Umwandlung in Kleinbuchstaben

toupper Umwandlung in Großbuchstaben

Bei Eingaben sind diese Funktionen sehr gut zu benutzen. Soll z.B. der Buchstabe c eingegeben werden, dann sollte es egal sein, ob der Nutzer ein kleines c oder ein großes C eingibt.

Die Funktionen wandeln nur, wenn es etwas zum um-wandeln gibt, sonst wird das gleiche Zeichen zurückgegeben.

x=tolower(x);

Die Variable x wird nur verändert, wenn der Wert von x ein Großbuchstabe ist. Dann wandelt tolower ihn in den entsprechenden Kleinbuchstaben um. Ist es bereits ein Kleinbuchstabe, dann hat tolower keine Bedeutung.

118

C-Programmierung 2003/2004 118

isalnum

int isalnum (int a);

Liefert einen wahren Wert, wenn a ein Zeichen aus folgendem Wertevorrat ist: a-z, A-Z, 0-9

Erläuterungen der einzelnen Funktionen

isalpha

int isalpha (int a);

Liefert einen wahren Wert, wenn a ein Zeichen aus den folgenden wertevorrat ist: a-z, A-Z oder landesspezifische Zeichen (in Deutschland äöüÄÖÜß)

iscntrl

int iscntrl (int a);

Liefert einen wahren Wert, wenn a eins der folgenden Steuerzeichen ist: FF, NL, CR, HAT, VT, BEL oder BS

119

C-Programmierung 2003/2004 119

isdigit

int isdigit (int a);

Liefert einen wahren Wert, wenn a eine Ziffer von 0-9 ist.

isgraph

int isgraph (int a);

Liefert einen wahren Wert, wenn a ein darstellbares Zeichen ist, aber kein Leerzeichen.

islower

int islower (int a);

Liefert einen wahren Wert, wenn a ein Zeichen von a-z oder ein umgebungsspezifisches Zeichen ist (Kleinbuchstabe).

isprint

int isprint (int a);

Liefert einen wahren Wert, wenn a ein darstellbares Zeichen ist oder ein Leerzeichen.

120

C-Programmierung 2003/2004 120

ispunct

int ispunct (int a);

Liefert einen wahren Wert, wenn isgraph (a) wahr und isalnum (a) falsch ist.

isspace

int isspace (int a);

Liefert einen wahren Wert, wenn a ein Leerzeichen oder FF, NL, CR, HAT oder VT ist.

isupper

int isupper (int a);

Liefert einen weahren Wert, wenn a ein Zeichen von A-Z ist oder ein umgebungsspezifischer Großbuchstabe.

isxdigit

int isxdigit (int a);

Liefert einen wahren Wert, wenn a ein Zeichen von 0-9, a-f oder A-F ist (hexadezimaler Wertebereich).

121

C-Programmierung 2003/2004 121

tolower

int tolower (int a);

Liefert den Kleinbuchstaben von a, falls a bereits ein Kleinbuchstabe ist, wird dieser unverändert zurückgegeben.

toupper

int toupper (int a);

Liefert den Großbuchstaben von a, falls a bereits ein Großbuchstabe ist, wird dieser unverändert zurückgegeben.

122

C-Programmierung 2003/2004 122

15. Vektoren und Zeiger

Vektoren und Zeiger verhalten sich wie Konstanten und Variable zueinander.

Bei Vektoren handelt es sich um konstante Adressen und bei Zeigern um variable Adressen.

000000002323432A X

412

Wert VariablennameSpeicher-adresse

Eine Variable ist durch folgende 4 Angaben eindeutig identifiziert:

• Adresse (Position)

• Name (Variablenname)

• Inhalt (Wert)

• Größe (belegter Speicherplatz)

123

C-Programmierung 2003/2004 123

Der Adreßoperator &&x liefert nicht den Inhalt der Variablen x, sondern die Adresse der Variablen x.

#include <stdio.h> /* Programm 16 */

void main(void){int x;

x=100;printf("Adresse von x mit dem Wert %i ist %p\n", x, &x);

x=800;printf("Adresse von x mit dem Wert %i ist %p\n", x, &x);

}

Adreßoperator &Formatzeichen für Adressen

Was liefert das Programm für Ausgaben ? ?

124

C-Programmierung 2003/2004 124

Die Adresse einer Variablen bleibt während der Programmabarbeitung immer gleich, auch wenn sich der Inhalt ändert.

Bei jedem Neustart verändert sich die Adresse, da das Programm an einer anderen Stelle im Hauptspeicher steht.

Der Wert, den der Adreßoperator & liefert ist ein Vektor.

Vektoren sind konstante Adressen!

Der Dereferenzierungsoperator *

Eine Variable, welche eine Adresse als Wert beinhaltet, nennt man einen Zeiger.

Syntax für Zeigerdefinitionen:

typ *variablenname

125

C-Programmierung 2003/2004 125

int x, *b;

x=99;

b=&x;

Zeiger auf einen int-Wert

Dem Zeiger wird ein Vektor zugewiesen.

126

C-Programmierung 2003/2004 126

Zeiger speichern Adresse, Variable speichern Werte. !

000BAC32D2FF2A b

000000002323432A

000000002323432A X

412

int x, *b;

x=99;

b=&x;

b ist der Zeiger auf die Variable x

Zeiger auf eine Variable

Dies macht aber Zeiger noch nicht interessant, wesentlich ist, wenn man die Adresse von x in b gespeichert hat, kann man darüber auf x zugreifen.

127

C-Programmierung 2003/2004 127

#include <stdio.h> /* Programm 18 und 18-1 */void main(void){int x,*z;

x=10;printf("x = %i\n", x);z=&x;*z+=10;printf("x = %i\n", x);x+=10;printf("x = %i, dereferenziertes z = %i\n", x, *z);

}

int x, *b; /* Programm 17*/

x=99;

b=&x;

printf ("Adresse von x ist %p, der Wert von b ist %p", &x,b);

Was wird in diesem Beispiel ausgegeben??? ?

128

C-Programmierung 2003/2004 128

Definition der int Variablen x und eines Zeigers z.

Der Variablen x wird der Wert 10 zugewiesen und dieser wird in der folgenden printf-Anweisung ausgegeben.

Danach wird die Adresse von x dem Zeiger z zugwiesen.

Jetzt wird durch eine Dereferenzierung von z (*z) nicht die in z gespeicherte Adresse von x angesprochen, sondern der Wert der an dieser Adresse steht (das ist der Wert von x). Das bedeutet, daß der Wert von x um 10 erhöht wird. In der folgenden printf-Anweisung wird der Wert von x ausgegeben. Dieser ist in diesem Fall 20.

Dann wird x erneut um den Wert von 10erhöht und in der folgenden printf-Anweisung wird x ausgegeben (30) und der dereferenzierte Wert von z, also nochmals 30.

Zeiger können auch direkt bei ihrer Deklaration initialisiert werden.

int x=24;

int *z=&x;

oder

int x=24 , *z=&x;

129

C-Programmierung 2003/2004 129

000000002323432A X

412

000000002323432A X

412

000BAC32D2FF2A b

000000002323432A

000BAC32D2FF2A b

000000002323432A

b

000000002323432A

*b

412

130

C-Programmierung 2003/2004 130

000000002323432A X

412

000BAC32D2FF2A b

000000002323432A

&b

000BAC32D2FF2A

131

C-Programmierung 2003/2004 131

Warum wird bei scanf immer der Adressoperator benutzt? ?scanf ("%i",&a);

Beim Aufruf von scanf wird die Adresse übergeben, wo der einzulesende Wert abgespeichert wird. Innerhalb der Funktion scanf wird dann über eine Dereferenzierungauf die Position (Adresse) zugegriffen wo der einzulesende Wert abgespeichert wird. Würde nicht die Adresse übergeben, dann könnte man nicht auf diese variable Adresse zugreifen, da die Variable innerhalb der Funktion nicht bekannt ist.

132

C-Programmierung 2003/2004 132

15.1 Adressen als Funktionsparameter

In der dargestellten Form werden Zeiger nur selten verwendet, denn es ist einfacher direkt auf die Variablen zuzugreifen als über Zeiger.

Im Zusammenhang mit Funktionen sind aber Zeiger sehr bedeutsam. Hauptsächlich werden Zeiger benutzt, um Adressen an Funktionen zu übergeben. Über diesen Umweg können dann direkt Variablen verändert werden.

#include <stdio.h> /* Programm 19 */void quadrat(int *wert){

*wert=(*wert)*(*wert);}void main(void){int x;

printf("Bitte eine Zahl eingeben:");scanf("%i",&x);quadrat(&x);printf("Das Quadrat ist %i\n",x);

}

Zeiger auf eine Variable wird übergeben

Adresse von x wird übergeben

Programm 19_01

133

C-Programmierung 2003/2004 133

15.2 Zeiger auf Funktionen

Zeiger beinhalten Adressen von Variablen. Es können aber in Zeigern auch Adressen von Funktionen gespeichert sein.

Anwendung: - bei Parameterabhängiger Auswahl von Funktionen

- in der objektorientierten Programmierung

rtype (*fkt) (para1,para2,….)

Syntax: Der Zeiger mit dem Namen fkt zeigt auf die Startadresse einer Funktion, die einen wert vom Typ rtyp zurückgibt und die Parameter para1, para2,… besitzt

Der Funktionszeiger kann nur Adressen von Funktionen aufnehmen, die die gleichen Eingabe-und Ausgabeparameter haben

134

C-Programmierung 2003/2004 134

#include <stdio.h> /* Programm 990 */void ausgabe(void) //Funktion ausgabe{

printf("Bitte geben Sie eine Zahl ein:");}int summe(int a, int b) // Funktion summe{

return(a+b);}

void main(void){int x,y;void (*fkt1)(void);int (*fkt2)(int, int);

fkt1=ausgabe;fkt2=summe;

fkt1();scanf("%i",&x);

(fkt1)();scanf("%i",&y);

printf("Die Summe ist %i\n",fkt2(x,y));}

Der Name einer Funktion ohne Klammern repräsentiert ihre Adresse

Programm 990_1

(Ohne Funktionsadressen)

135

C-Programmierung 2003/2004 135

15.3 Zeiger auf Zeiger

typ **name

Syntax

#include <stdio.h> /* Programm 992 */void main(void){int x,y,*xptr,**ptrptr;

x=10;y=10;printf("x = %i\n",x);

xptr=&x;*xptr=20;printf("x = %i, *xptr = %i\n",x,*xptr);

ptrptr=&xptr;**ptrptr=30;printf("x = %i, *xptr = %i, *ptrptr = %i\n",x,*xptr,**ptrptr);*ptrptr=&y;**ptrptr=40;

printf(„y = %i, x= %i *xptr = %i, *ptrptr = %i\n",y,x,*xptr,**ptrptr);}

136

C-Programmierung 2003/2004 136

Übung !!!Arbeiten mit Adressen;

Übergabe von Adressen an Funktionen;

Übergabe mehrerer Adressen an Funktionen

137

C-Programmierung 2003/2004 137

16. Variablenfelder

Anstelle n Variablen zu definieren (z.B. für eventuelle Sortierungen) kann man ein Feld (array) anlegen, in welchem dann alle Werte gespeichert sind.

Syntax eines Feldes:

typ name[anzahl]

int testfeld[20];

testfeld[3]=12;

testfeld[17]=99;

Felddefinition mit 20 int Werten

Wert 3 des Feldes wird mit 12 initialisiert und Wert 17 mit 99

Der Feldindex beginnt immer mit 0 und reicht bis n-1, bei einem Feld mit n Elementen. !

138

C-Programmierung 2003/2004 138

Ein Feld kann auch gleich bei seiner Definition initialisiert werden.

int testfeld[5]={12,4,5,33,-88};

#include <stdio.h> /*Programm 20 */

void main(void){

int x[10],y;

for(y=0;y<10;y++){printf("Bitte Zahl %i eingeben:",y+1);scanf("%i",&x[y]);}

for(y=0;y<10;y++)printf("%i multipliziert mit 2 ist %i\n",x[y],x[y]*2);

}

139

C-Programmierung 2003/2004 139

Felder als Funktionsparameter

Der Name eines Feldes ohne [...] ist identisch mit der Startadresse des Feldes. Der Feldname ist ein Vektor.

Der Zeiger auf eine Variable ist identisch mit dem Zeiger auf ein Feld.

Bei Zeigern auf Felder darf bei der Benutzung des Index kein Dereferenzierungsoperatorangewendet werden.

140

C-Programmierung 2003/2004 140

#include <stdio.h> /*Programm 21 */void input(int *a){int y;

for(y=0;y<10;y++){printf("bitte Zahl %i angeben:",y+1);scanf("%i",&a[y]);}

}void calc(int *a){int y; for(y=0;y<10;y++)

a[y]*=2;}void output(int *a){int y;

for(y=0;y<10;y++)printf("Das Ergebnis der %i. Multiplikation ist%i\n", y+1,a[y]);

}void main(void){ int x[10];

input(x);calc(x);output(x);

}

141

C-Programmierung 2003/2004 141

Mehrdimensionale Felder

Die bisherigen Felder waren eindimensional. In C ist es aber auch möglich, daßmehrdimensionale Felder aufgebaut werden.

int tabelle[4][10];

Mit dieser Definition wird ein zweidimensionales Feld angelegt, welches 4 Spalten und 10 Zeilen hat. Es kann dann ebenfalls jedes einzelnen Element in der Tabelle initialisiert werden. Soll z.B. in der 2. Spalte und der 8. Zeile eine 5 stehen, dann wird folgende Zuweisung notwendig:

int tabelle[1][7]=5 ?Achtung!!!

Das erste Feldelement beginnt immer mit der Position 0, das heißt, die Feldposition ist immer die reale Position -1.

142

C-Programmierung 2003/2004 142

In C können auch noch mehr Dimensionen benutzt werden.

int dreidimfeld[80][80][80];

Dieses Feld beinhaltet 80x80x80 int-Werte zu je 2 Byte. Es gilt unbedingt zu beachten, dass dieses Feld dann fast 1 MByte Speicher belegt.

Auch mehrdimensionale Felder können sofort bei ihrer Deklaration initialisiert werden. Dabei erfolgt die Initialisierung immer von der letzten Dimension aus.

int tabelle[2][4]={{4,5,6,7},{5,4,3,2}};

2 Spalten 4 Zeilen

1 2

1 4 5

2 5 4

3 6 3

4 7 2

SpalteZeile

143

C-Programmierung 2003/2004 143

Initialisierung eines dreidimensionalen Feldes:

int drei[2][3][4]={{{1,2,3,4},{5,6,7,8},{-2,4,-6,2}},{{12,4,5,33},

{22,33,44,55},{1,2,3,4}}};

Übung !!!Arbeiten mit Feldern;

Übergabe von Feldern an Funktionen;

Felder als Rückgabewert von Funktionen

Verbesserung von Praktikum 1 durch Nutzung von Feldern

144

C-Programmierung 2003/2004 144

Mit beliebigen Variablentypen kann man Felder erzeugen. Das geht auch mit char.

char[51] definiert ein Feld mit 50 Charakter-Werten.

Ein String besteht aus einer Folge von Zeichen und hat eine Endekennung. In C hat die Endekennung immer den Wert 0.

"erg"

Stringkonstante der Länge 4 (3 Zeichen und Endekennung 0)

17. Zeichenketten - String

Ein- und Ausgabe von Strings

Da Strings den Status eines Feldes haben, können sie auch so behandelt werden. Sie werden besonders für E/A-Operationen genutzt.

Das Formatzeichen für Strings ist %s.

145

C-Programmierung 2003/2004 145

#include <stdio.h> /* Programm 22 */void main(void){char a[7];

a[0]='S'; a[1]='t';a[2]='r'; a[3]='i';a[4]='n'; a[5]='g';a[6]=0;printf("Der erzeugte String ist :%s\n",a);

}

#include <stdio.h> /* Programm 23 */

void main(void){int x;char a[7];

a[0]='S'; a[1]='t'; a[2]='r'; a[3]='i';a[4]='n'; a[5]='g'; a[6]=0;

for (x=0;a[x]!=0;x++)printf("%c \n",a[x]);

}

146

C-Programmierung 2003/2004 146

Das Formatzeichen %s für Strings kann auch bei scanf genutzt werden, um ganze Zeichenketten einzulesen.

#include <stdio.h> //Programm 24void main(void){char a[81];printf("Bitte einen max. 80 Zeichen langen text eingeben:");scanf("%s",a);printf("Sie gaben \"%s\" ein.\n",a);}

?

Ein Character-Feld hat eine besondere Stellung. Scanf betrachtet das gesamte Feld als einen Variablentyp, als String.

Vor dem a in scanf fehlt der Adreßoperator &. Das ist richtig, denn ein Feld ohne eckige Klammern repräsentiert bereits die Adresse. Damit muss in der scanf-Anweisung nicht explizit der Adreßoperator angegeben sein, denn a ist bereits die Adresse. Alternativ könnte man auch folgendes schreiben:

scanf ("%s", &a[0]);

Debugger

147

C-Programmierung 2003/2004 147

Die Funktion scanf hat die Eigenschaft, dass mehrere Worte eingelesen werden können, die durch Leerzeichen getrennt sind. Die durch Leerzeichen getrennten Worte werden als mehrere Strings aufgefasst. Um einen String einzulesen, welcher Leerzeichen enthält, kann scanf nicht verwendet werden.

Die Eingabefunktion gets ist speziell für die Arbeit mit strings gedacht.

#include <stdio.h> //Programm25void main(void){char a[81];printf("Bitte einen max. 80 Zeichen langen text eingeben:");

gets(a);

printf("Sie gaben \"%s\" ein.\n",a);}

Die Funktion gets ist als Prototyp ebenfalls in der Headerdatei stdio.h enthalten. Für deren Benutzung ist also ebenfalls ein #include stdio.h notwendig.

Der Funktion gets wird die Adresse des Strings übergeben, damit diese den String überschreiben kann.

148

C-Programmierung 2003/2004 148

Analog zur Funktion gets gibt es auch eine Ausgabefunktion puts, welche einen String ausgibt. Auch diese Funktion steht als Prototyp in der Headerdatei stdio.h.

puts ("Das ist ein Text mit puts ausgegeben.\n");

Ein String darf mit Endekennung nur gleich oder kleiner als das definierte Feld sein, niemals größer!

149

C-Programmierung 2003/2004 149

Die Funktionen von string.h

memchr Zeichen im Speicherblock suchen

memcmp Speicherblöcke vergleichen

memcpy Speicherblöcke kopieren

memmove Sicheres kopieren von Speicherblöcken

memset Speicherblöcke initialisieren

strcat String an einen anderen hängen

strchr Zeichen im String suchen

strcmp Zwei Strings vergleichen

strcoll Zwei Strings umgebungsunabhängig ver-

gleichen

strcpy String kopieren

strerror Umwandlung eines Feldes in verbale Form

strlen Länge eines String ermitteln

150

C-Programmierung 2003/2004 150

strncat Teil eines String an einen anderen hängen

strncmp Teile von zwei Strings vergleichen

strncpy Teile eines String kopieren

strrchr Zeichen von Stringende aus suchen

strstr prüfen, ob String Teil eines anderen ist

Erläuterungen zu den Funktionen aus string.h

strcpy

char *strcpy (char ziel, const char *quelle);

Die Funktion strcpy kopiert den String Quelle komplett mit Endekennung in den String Ziel. Es wird der String Ziel zurückgegeben

151

C-Programmierung 2003/2004 151

Arbeiten mit Strings

Einem String kann bei der Initialisierung sofort ein Name zugewiesen werden.

char test[10]="Beispiel";

Der String Test wird mit "Beispiel" initialisiert und hat die Länge 9 (8 Zeichen und Endekennung).

Um dem String einen neuen Inhalt zu geben, muss eine Funktion aus der Headerdateigenutzt werden. Folgende Anweisung ist nicht zulässig:

test="Kunde";

Eine Stringkonstante steht immer für ihre Adresse. !strcpy (ziel,quelle);

strcpy (test,"Kunde")

Nutzung der Funktion strcpy (kopieren von Strings)

152

C-Programmierung 2003/2004 152

Der Name eines String steht immer für seine Adresse und eine Stringkonstante steht ebenfalls für ihre Adresse. Damit ist dieser Aufruf korrekt.

Stringzuweisungen außerhalb der Deklaration bedürfen immer der Nutzung von strcpy.

#include <stdio.h> //Programm26#include <string.h>void fkt(char *a){ printf("Inhalt in der Funktion :%s\n",a);

strcpy(a,"Anton");printf("Nach strcpy in der Funktion :%s\n",a);

}

void main(void){char x[15]="Willibald";

printf("Inhalt vor der Funktion :%s\n",x);fkt(x);printf("Inhalt nach der Funktion :%s\n",x);

}

153

C-Programmierung 2003/2004 153

Der String wird in der Funktion verändert. Das hat auch Auswirkungen auf den String außerhalb der Funktion, da die Adresse des Strings übergeben wurde.

Soll der String außerhalb der Funktion nicht verändert werden, so muss innerhalb der Funktion eine Kopie angefertigt werden.

154

C-Programmierung 2003/2004 154

#include <stdio.h> //Programm27#include <string.h>

void fkt(char *a){ printf("In der Funktion :%s\n",a);

strcpy(a,"Anton");printf("Nach strcpy :%s\n",a);

}void main(void){char x[15]="Willibald";

printf("Vor der Funktion :%s\n",x);fkt(x);printf("Nach der Funktion :%s\n",x);

}

ersetzen

void fkt (char *a){char b[15];strcpy(b,a);printf ("In der Funktion: %s\n",b);strcpy (b,"Anton");printf ("Nach strcpy : %s\n",b); }

Das Original von a bleibt erhalten!!!!!

155

C-Programmierung 2003/2004 155

Ein String kann auch zeichenweise ausgegeben werden.

a=0;

while (x[a])

printf ("%c", x[a++]);

Ein String wird immer mit 0 als Endekennung abgeschlossen, damit bricht die while-Schleife bei erreichen der Endekennung ab.

Steht jedoch nicht der wirkliche String zur Verfügung, sondern nur der Zeiger auf den String (ist bei Funktionsparametern üblich), muss die Zeichenweise Ausgabe wie folgt realisiert werden.char *z;z=x;while (*z);

printf ("%c",*(z++));

Zeiger auf char wird definiert. Dieser Zeiger bekommt die Adresse von x (Variablennameeines String verkörpert die Adresse). Durch Dereferenzierung wird auf das Zeichen an der Adresse zugegriffen, die der Zeiger gespeichert hat.

Programm27_1

156

C-Programmierung 2003/2004 156

String-Felder

Mehrere Strings können zu einem Stringfeld zusammengefasst werden.

char test[5][10]; 5 String zu je 10 Zeichen

char test[5][10]={"Otto1","Otto2","Kurt1","Kurt2","Willi"};

Auf diese einzelnen String kann problemlos zugegriffen werden:

for (a=0;a<5;a++)

printf ("%s\n",test[a]);

Achtung!!Der Name eines Stringfeldes mit einem Index weniger als in der Definition, repräsentiert die Adresse eines speziellen String.

Programm 28

ein Index

157

C-Programmierung 2003/2004 157

18. StrukturenVariablen unterschiedlichen Typs können zu einer Gruppe zusammengefasst werden. Diese Gruppe von unterschiedlichen Variablen werden als Strukturen bezeichnet.

char name[40]; char vorname[40];

int gehalt; int alter;

Soll das Programm eine definierte Menge dieser Personen verarbeiten, z.B. 500, so müßte für jede Variable ein Feld definiert werden.

char name[500][40];

char vorname[500][40];

int gehalt[500];

int alter[500];

Dies ist eine Realisierungsmöglichkeit, jedoch lässt sich das Problem mit Strukturenbedeutend eleganter lösen.

158

C-Programmierung 2003/2004 158

struct personaldaten

{char name[40];

char vorname[40];

int gehalt;

int alter;};

Struktur Personaldaten

Abschluß immer mit Semikolon

Die einzelnen Elemente der Struktur werden auch als Member (Mitglieder der Struktur) bezeichnet.

Eine Variable dieses Strukturtypes wird wie folgt definiert:

struct personaldaten arbeiter1;

Es wurde eine Variable arbeiter1 erzeugt, die vom Typ struct personaldaten ist.

Auf die einzelnen Elemente dieser Struktur kann jetzt zugegriffen werden. Die einzelnen Variablen innerhalb der Struktur können wie normale Variablen behandelt und verarbeitet werden. Es muss nur der Variablenname der Struktur vorangestellt werden.

159

C-Programmierung 2003/2004 159

arbeiter1.alter=34;

arbeiter1.gehalt=6700;

strcpy(arbeiter1.vorname="Otto");

strcpy(arbeiter1.name="Mueller");

Wird in der gleichen Funktion auch eine Variable mit dem Namen alter deklariert, so führt das zu keinen Konflikten, da diese Variable außerhalb der Struktur steht und damit unabhängig von der Variablen arbeiter1.alter ist.

int alter=99; unabhängig von arbeiter1.alter

Variablen innerhalb einer Struktur besitzen lokalen Charakter

Strukturen können mit Hilfe des Zuweisungsoperators kopiert werden wie elementare Datentypen.

Strukturen können in ihrer Komplexität trotzdem fast wie normale elementare Datentypen behandelt werden.

160

C-Programmierung 2003/2004 160

#include <stdio.h> //Programm 29#include <string.h>struct Personendaten

{char Vorname[40];char Nachname[40];int Bruttogehalt;int Alter; };

void main(void){ struct Personendaten person, person2;

person.Alter=34;person.Bruttogehalt=6700;strcpy(person.Vorname,"Joseph");strcpy(person.Nachname,"Müller");

printf("%s,%s. Alter:%i Bruttogehalt:%i\n",person.Nachname, person.Vorname, person.Alter,person.Bruttogehalt);

person2=person;printf("%s,%s. Alter:%i Bruttogehalt:%i\n", person2.Nachname, person2.Vorname,person2.Alter,person2.Bruttogehalt);

}

161

C-Programmierung 2003/2004 161

Strukturen können auch direkt bei ihrer Definition initialisiert werden.

struct personaldaten arbeiter1={"Otto","Mueller",6700,34};

162

C-Programmierung 2003/2004 162

#include "stdafx.h"struct feld{int wert[10];};

int main(int argc, char* argv[]){

struct feld vfeld_1={1,2,3,4,5,6,7,8,9,0};struct feld vfeld_2;

vfeld_2=vfeld_1;

printf ("%i %i %i \n",vfeld_2.wert[0],vfeld_2.wert[1],vfeld_2.wert[3]);

return 0;}

Direktes Kopieren von Feldern mittels Strukturen, da feld_1=feld_2 nicht zulässeig ist

// int feld_1[10]={1,2,3,4,5,6,7,8,9,0};// int feld_2[10];

// feld_2=feld_1;

Programm Test_1

163

C-Programmierung 2003/2004 163

Zeiger auf Strukturen

Auch auf Strukturen können Zeiger definiert werden.

struct personaldaten arbeiter1;

struct personaldaten *arbeiter1zgr;

Zeiger auf struct arbeiter1

Die Zuweisung erfolgt dann analog wie bei anderen Variablentypen.

arbeiter1zgr=&arbeiter1;

164

C-Programmierung 2003/2004 164

Normaler Zugriff auf Elemente von Strukturvariablen

arbeiter1.alter=99;

Zugriff über Zeiger auf ein Element einer Strukturvariablen

arbeiter1zgr->alter=99;

Es wird nur die Variable alter aus der Struktur arbeiter1 geändert, da arbeiter1zgr auf die Struktur arbeiter1 zeigt.

struct personaldaten maurer,*x;

x=&maurer; maurer.alter=44;

x->gehalt=3000;

aus der Strukturvariablen Maurer wird das Element alter direkt geändert und die Variable Gehalt durch einen Zugriff über Zeiger.

Programm 30

"zeigt auf"

165

C-Programmierung 2003/2004 165

Felder von Strukturen

Felder bieten in der Massendatenverarbeitung oft die Möglichkeit bestehende Probleme auf elegante Art zu lösen.

int x; Definition einer int Variablen

int x[100]; Definition eines int Feldes mit 100

Einträgen

Diese Möglichkeit bietet sich auch bei Strukturen, wenn man ein Feld von Strukturen bildet.

struct personaldaten arbeiter1;

struct ersonaldaten arbeiter1[500];

Auf die Elemente dieses Strukturfeldes kann jetzt ebenfalls einzeln durch Indizierung zugegriffen werden.

arbeiter1[12].alter=99;

arbeiter1[455].gehalt=3900;

166

C-Programmierung 2003/2004 166

Es soll das Alter der 320. Person auf 32 gesetzt werden:

arbeiter1[319].alter=32;

Achtung !!! Felder beginnen immer mit dem Index 0

Das Gehalt der 10. Person soll auf 4000 gesetzt werden. Der Zugriff ist mit Zeiger zu realisieren.

struct personaldaten *arbeiter1zgr[500];

arbeiter1zgr=&arbeiter1;

arbeiter1zgr[9]->gehalt=4000;

167

C-Programmierung 2003/2004 167

Weiterhin könnte man ein Feld von Zeigern auf die Strktur personaldaten definieren.

struct personaldaten arbeiter1zgr[100];

Änderung des Gehaltes der 30.Person:

arbeiter1zgr[29] ->gehalt=7600;

168

C-Programmierung 2003/2004 168

Verschachtelte Strukturen

Strukturen können ineinander verschachtelt werden

Deklaration der inneren Struktur:

struct p-adressen

{ char strasse[100];

unsigned long plz;

char ort[80] };

Einsetzen dieser Struktur in eine andere:

struct personaldaten

{ struct p-adressen adresse;

char vorname[40];

char nachname[40];

int bruttogehalt;

int alter; };

169

C-Programmierung 2003/2004 169

Variable vom Typ personaldaten deklarieren:

struct personaldaten person1, person2,person3;

Zugriffe auf die Elemente

person1.adresse.plz=07551;

Beim kopieren von verschachtelten Strukturen wird sowohl die innere als auch die äußere Struktur zusammen kopiert. Damit kann ein Kopiervorgang von verschachtelten Strukturen wie folgt realisiert werden:

person2=person1;

person3=person1;

personaldaten

personaldaten

personaldaten

p-adressen

p-adressen

p-adressen

Kopie

170

C-Programmierung 2003/2004 170

Änderungen einer Variablen in der Struktur person1 vom Typ Personaldatenhat damit keine Auswirkungen auf andere Strukturen des gleichen Typs.

Man kann die Daten der inneren Struktur aus dem vorherigem Beispiel auch außerhalb verwalten.

struct personaldaten

{

struct p-adressen *adressen;

char vorname[50];

char nachname[50];

int bruttogehalt;

int alter; };

personaldaten adressenZeiger

171

C-Programmierung 2003/2004 171

struct p-adressen homedaten;

struct personaldaten daten;

daten.adressen=&homedaten;

Zugriff auf die Werte:

daten.adressen->plz=07551;

Kopieren von verschachtelten Strukturen (flache Kopie)

personaldaten adressen

ZeigerPersonaldaten_1

Zeiger

Kopie

Zeiger

172

C-Programmierung 2003/2004 172

Kopieren von verschachtelten Strukturen (tiefe Kopie)

personaldaten adressen

personaldaten_1

Zeiger

Kopie

Zeiger

adressen_1

Kopie

173

C-Programmierung 2003/2004 173

UnionsWenn in einer Struktur mehrere Variable unterschiedlichen Typs gespeichert werden sollen, aber auf Grund eines Auswahlverfahrens nur ein Typ real gespeichert wird, dann ist der Speicherplatz für die anderen Variablen verschenkt.

struct werte

{int intzahl;

float floatzahl;

char charwerte[20];

}

Speicherplatzverschwendung,wenn nur ein Typ abgelegt wird

union werte

{int intzahl;

float floatzahl;

charwerte[20];

}

Es kann nur ein Typ gespeichert werden,

entweder intzahl oder floatzahl oder charwerte

174

C-Programmierung 2003/2004 174

#include <stdio.h> //Programm 31#include <string.h>union block {

char string[20];double dbl;int intzahl;

};void main(void){ union block sammlung;

sammlung.intzahl=20;printf("int = %i\n",sammlung.intzahl);strcpy(sammlung.string, "Johann");printf("string = %s\n", sammlung.string);printf("int = %i\n",sammlung.integer);sammlung.dbl=3.1415926535;printf("double = %f\n",sammlung.dbl);printf("string = %s\n", sammlung.string);printf("int = %i\n",sammlung.integer);

}

Bei einer union benutzen alle

Elemente den gleichen Speicherplatz.

175

C-Programmierung 2003/2004 175

Aufzählungstyp enum

Der Aufzählungstyp enum ist ein Ganzzahltyp, dessen Zahlenmenge eingeschränkt ist.

enum woche {MO,DI,MI,DO,FR,SA,SO};

C weist den 7 Konstanten jetzt Werte zu:

MO=0 DI=1 ....SO=6

Variable definieren:

Enum woche tag;

tag=MI; oder tag=(woche)(2); Typumwandlung mit cast-Operator

tag=XO Fehler nicht im Wertebereich

tag=(woche)(20) Fehler, wird aber nicht bemerkt

Schleifenbildung:

int z=0;

for (tag=MO;tag<=SO; tag=(woche)(++x))

176

C-Programmierung 2003/2004 176

Zuweisungen an andere Ganzzahlvariablen sind möglich:

int x,y;

x=DO;

printf („%i“,x);

Welchen Wert hat x ???????

Es muss bei bestimmten Ausdrücken auch eine Typumwandlung erzwungen werden (siehe Beispiele), dann ist aber der Programmierer dafür verantwortlich, dass der Wertebereich nicht überschritten wird.

tag=(woche) (x);

Ist der Wert einer Konstanten nicht explizit angegeben, ist er um 1 höher als der der Vorgängerin. Ist der Wert der ersten Konstanten nicht angegeben, dann ist er immer 0. !

177

C-Programmierung 2003/2004 177

#include "stdafx.h"enum wochentage{MO,DI,MI,DO,FR,SA,SO};

int main(int argc, char* argv[]){enum wochentage tag,*tagzgr;

tagzgr=&tag;tag=MO; printf ("%i\n\n",tag);tag=SO; printf ("%i\n\n",tag);

int x;x=2;

tag=(wochentage)(x); printf ("%i\n\n",tag);if (tag==MO)

{printf ("Montag \n\n");}else {printf ("Nicht Montag -- anderer

Wochentag\n\n");}tag=(wochentage)(0);

x=0;while (tag<=SO)

{printf ("%i\n", tag);x++;tag=(wochentage)(x);}printf ("\n\n");

for (tag=(wochentage)(0),x=0;tag<=SO; tag=(wochentage)(++x))printf ("%i\n", tag);

return 0;}

Programm 31_1Programm 31_1 .NET

178

C-Programmierung 2003/2004 178

Eigene Typen mit typedef

Es gibt die Möglichkeit, eigene Variablentypen zu deklarieren, so dass der eigentliche Variablentyp im Programm nicht vorkommt.

typdef int INTzahl;

typdef unsigned int uint;

typdef char Name[40];

Eine Definition einer Variablen vom Typ Name als char mit 40 Zeichen könnte dann so erfolgen:

Name vorname;

Eine Variable vom Typ INTzahl könnte wie folgt angelegt werden:

INTzahl zahl1, zahl2, zahl3, zahl4;

179

C-Programmierung 2003/2004 179

Für Strukturen gilt dies analog:

typdef struct Adresse

{

int privatnr;

int dienstnr;

char ort[20];

}SAdressen;

SAdressen adr;

180

C-Programmierung 2003/2004 180

19. Arbeiten mit Dateien

Um eine Datei zu öffnen wird die Funktion fopen benutzt. Eine Datei wird mit fclosegeschlossen. Beide Funktionen stehen in der Headerdatei stdio.h.

Fopen und fclose haben folgenden Aufbau:

fileptr=fopen(dateiname, modus);

.......

.......

fclose(fileptr);

fileptr ist ein Zeiger auf eine FILE-Struktur und wird wie folgt definiert:

FILE *fileptr

Datei

Text-Datei Binär-Datei

181

C-Programmierung 2003/2004 181

fileptr=fopen(dateiname, modus);

Dateiname verkörpert den Namen der zu öffnenden Datei und wird in einer Stringkonstanten gespeichert. Der Aufbau des Dateinamens ist abhängig vom Computersystem.

Modus ist ebenfalls eine Stringkonstante und gibt den Modus der zu öffnenden Datei an. Der Modus entscheidet über das Format der zu öffnenden Datei (Textdatei, Binärdatei) und darüber, ob in der Datei nur gelesen oder auch geschrieben werden soll.

Die File-Struktur enthält nach dem öffnen der Datei deren charakteristische Merkmale. Da dort ein eindeutiger Bezug zur Datei besteht, können auch mehrere Dateien geöffnet werden. Wenn filrptr nach dem Aufruf von fopen 0 ist, dann konnte die Datei nicht geöffnet werden.

Die Deklaration von FILE steht ebenfalls in stdio.h.

182

C-Programmierung 2003/2004 182

Text-Dateien

Modus Beschreibung

"r" öffnet eine Textdatei zum lesen

"w" erstellt eine Textdatei zum Schreiben. Der Inhalt einerunter diesem Namen bereits existierenden Datei wirdgelöscht.

"a" Erstellt oder öffnet eine bereits existierenden Datei zum Schreiben. Der Dateipositionszeiger steht am der Datei, dadurch werden neue Daten hinten angehängt.

"w+" Erstellt eine Textdatei zum Lesen oder Schreiben. Der Inhalt einer bereits unter diesem Namen existierenden Datei wird gelöscht.

"a+" Erstellt oder öffnet eine bereits existierenden Datei zum Schreiben oder Lesen. Der Dateipositionszeigersteht am der Datei, dadurch werden neue Datenhinten angehängt.

183

C-Programmierung 2003/2004 183

Öffnen einer Datei "test.txt" zum Schreiben:

fileptr=fopen(test.txt,"w");

Die Datei wird in das aktuelle Verzeichnis geschrieben. Dieses hängt vom Computersystem und vom eingestellten Pfad auf dem Rechner ab.

184

C-Programmierung 2003/2004 184

Die Funktionen fputs, fgets und feof

Die Funktionen sind mit den normalem puts und gets identisch, nur dass noch zusätzlich ein Zeiger auf die zu bearbeitende Filestruktur existiert und bei fgets noch die Anzahl der maximal einzulesenden Zeichen angegeben wird.

Weiterhin wird die Funktion feof benutzt. Diese Funktion wird benötigt, um zu prüfen, ob das Dateiende erreicht ist.

Dateiende erreicht: Wert von feof ist wahr

Dateiende noch nicht erreicht: Wert von feof ist falsch

Die Funktion feof wird folgendermaßen aufgerufen:

wert=feof(fileptr);

fgets (name,länge,fileptr);

fputs (name,fileptr);

185

C-Programmierung 2003/2004 185

#include <stdio.h> //Programm 32#include <string.h>#define DATNAME "test.txt"

void schreiben(void){FILE *fhd;char s[160];

fhd=fopen(DATNAME,"w");if(!fhd) {

printf("Datei konnte nicht erzeugt werden!\n\n");}

else {printf("Bitte maximal 160 Zeichen pro Zeile eingeben.\n");printf("Eingabe wird mit . beendet.\n\n");getchar();do { printf(">>>");

gets(s);if(strcmp(s,".")) //Vergleichen von Strings{fputs(s,fhd);

fputs("\n",fhd);}

} while(strcmp(s,"."));fclose(fhd);printf("\nEingabe beendet!\n");

}}

Problem Tastaturpuffer

186

C-Programmierung 2003/2004 186

void lesen(void){FILE *fhd;char s[160];int x=1;

fhd=fopen(DATNAME,"r");if(!fhd)

{printf("Datei konnte nicht geoeffnet werden!\n\n");}

else{printf("Die Datei hat folgenden Inhalt:\n");

fgets(s,160,fhd);do

{printf("%i:%s",x++,s);fgets(s,160,fhd);

} while(!feof(fhd));

fclose(fhd);printf("\nEnde der Datei!\n");

}}

187

C-Programmierung 2003/2004 187

void main(void){int input;

printf("Soll die Datei 1=gelesen oder 2=beschrieben werden?");scanf("%i",&input);if(input==1)

{lesen();

}else

{if(input==2)

{schreiben();

}else

{printf("\nFalsche Eingabe!\n\n");

}}

}

188

C-Programmierung 2003/2004 188

Feof liefert erst dann einen wahren Wert, wenn versucht wird, Daten zu lesen, obwohl das Dateiende erreicht ist.

Es muss bemerkt werden, dass die do-Schleife im folgenden Beispiel nur dann fehlerfrei funktioniert, wenn die Datei mindestens einen Datensatz enthält. Soll auch der Fall einge-schlossen sein, dass die Datei vollständig leer sein kann, dann muß die do-Schleife noch in eine if-Schleife eigebettet werden.

fgets (s,MAXZEILENLAENGE,fhd);

if (!feof(fhd)

{ do {

printf("%i: %s",x++,s);

fgets(s,MAXZEILENLAENGE,fhd);

} while (!feof(fhd));

} fclose(fhd);

Eine Funktion, die in einer Datei liest, positioniert den Dateipositionszeiger immer hinter das zuletzt gelesene Zeichen. Eine Funktion, die in eine Datei schreibt, positioniert den Datei-positionszeiger immer hinter das zuletzt geschriebene Zeichen.

Zuerst lesen, wenn EOF, dann wird Schleife nicht abgearbeitet.

189

C-Programmierung 2003/2004 189

Die Funktionen fprintf und fscan

Weitere Funktionen zur Bearbeitung von Textdateien sind fprintf und fscan. Die Funktionen sind identisch mit printf und scanf.

printf ("Das Wort heißt %s und hat %i Buchstaben", wort,strlen(wort));

fprintf (fhd, "Das Wort heißt %s und hat %i Buchstaben", wort,strlen(wort));

Den Text, welchen printf auf den Bildschirm schreibt, bringt fprintf in eine Datei,die der File-Struktur fhd zugeordnet ist.

Analog dazu holt sich fscan eine Eingabe von einer Datei, während scanf vom Bildschirm liest.

fscan (fhd, "%i %s", x, s); Programm32_1

190

C-Programmierung 2003/2004 190

Die Funktionen fgetc und fputc

Die Funktionen fgets und fputs lesen und schreiben Strings. Es gibt aber auch Funktionen, die ein einzelnes Zeichen aus einer Datei lesen oder schreiben, das sind fgetc und fputc.

fputc (zeichen, fhd);

speichert das in der Variablen zeichen gespeicherte Zeichen in die Datei, die der File-Struktur fhd zugeordnet ist.

fputc liefert den wert von zeichen zurück, wenn die Übertragung erfolgreich war, bei Fehlern wird der Wert EOF zurückgegeben.

wert=fputc(zeichen,fhd);

if (wert==EOF)

printf("Fehler beim Schreiben!!!\n");

zeichen=fgetc(fhd);

Die Funktion fgetc liest ein Zeichen aus der Datei, welche der File-Struktur fhdzugeordnet ist. Danach enthält die Variable zeichen das eingelesene Zeichen.

191

C-Programmierung 2003/2004 191

Binärdateien

In den bisherigen Varianten wurden die Daten als Textdateien gespeichert. Damit sind sie mit jedem beliebigen Editor lesbar. Oft ist es aber günstigen (z.B. aus Speicherplatzgründen) die Daten direkt als Binär-Daten zu speichern.

Ein Umwandeln von Textdaten in Zahlenvariablen kann bei der Speicherung als Binärdaten ebenfalls entfallen.

192

C-Programmierung 2003/2004 192

Modus Beschreibung

"rb" öffnet eine Binärdatei zum Lesen

"wb" erstellt eine Binärdatei zum Schreiben. Der Inhalt einer bereitsbestehenden Datei wird gelöscht.

"ab" erstellt oder öffnet eine bereits bestehende Binärdatei zum Schreiben. Der Dateipositionsanzeiger steht am Ende der Datei,d.h. Die Daten werden angehängt.

"rb+" öffnet eine Binärdatei zum Lesen oder Schreiben

"wb+" erstellt oder öffnet eine Binärdatei zum Lesen oder Schreiben. DerInhalt einer bereits bestehenden Datei wird gelöscht.

"ab+" erstellt oder öffnet eine Binärdatei zum Lesen oder Schreiben. Der Dateipositionsanzeiger steht am Ende der Datei,d.h. Die Daten werden angehängt.

193

C-Programmierung 2003/2004 193

Die Funktionen fwrite und fread

Syntax von fwrite:

anz=fwrite (adresse, groesse, anzahl, fhd);

adresse ist die Adresse, an der die zu speichernde Variable oder das zu speichernde Feld steht.

groesse ist die Größe der Variablen oder die eines Feldelements in Byte.

anzahl ist bei einer Variablen 1, bei einem Feld die Anzahl der Elemente.

fhd ist der Zeiger auf die FILE-Struktur, mit der die zu beschreibende Datei verknüpft ist.

fwrite gibt die Anzahl der komplett geschriebenen Elemente zurück.

194

C-Programmierung 2003/2004 194

Syntax von fread:

anz=fread (adresse, groesse, anzahl, fhd);

adresse ist die Adresse an der die aus der Datei gelesenen Daten gespeichert werden.Alle anderen Parameter sind analog fwrite.

195

C-Programmierung 2003/2004 195

Die Funktion sizeof

Die besprochenen Funktionen bergen zur Zeit noch einige Probleme in sich, denn die Größe der Variablen ist in den meisten Fällen unbekannt. Selbst bei int-Werten ist es von System zu System verschieden, wie viel Byte zur Speicherung benutzt werden. Um das Problem zu beseitigen, wurde die Funktion sizeof geschaffen. Sie bestimmt die Größe einer jeden Variablen und liefert damit den benötigten Wert für die Lese- und Schreibfunktionen für Binärdateien.

char s[80]; //Programm 37

strcpy (s,"Otto");

printf ("Die Größe von s ist %i \n",sizeof (s));

printf ("Der Variablentyp int ist %i Bytes gross. \n",sizeof (int));

Im ersten Fall wird 80 ausgegeben, da sich sizeof mit der Definition von s befasst und nicht mit der Zuweisung des Inhaltes. Im zweiten Fall wird die Größe des int Variablentypesermittelt und mit printf ausgegeben.

196

C-Programmierung 2003/2004 196

#include <stdio.h> //Programm 33#include <string.h>#define DATNAME "test.txt"#define MAXVORNAME 25#define MAXNACHNAME 20void schreiben(void){FILE *fhd;char vname[MAXVORNAME],nname[MAXNACHNAME];unsigned int alter,groesse;

fhd=fopen(DATNAME,"wb");if(!fhd) { printf("Datei konnte nicht erzeugt werden!\n\n"); }else {

printf("Vorname (Max. %i Zeichen) :",MAXVORNAME-1);scanf("%s",vname);

printf("Nachname (Max. %i Zeichen) :",MAXNACHNAME-1);scanf("%s",nname);

printf("Alter in Jahren :"); scanf("%u",&alter);printf("Groesse in Zentimetern :"); scanf("%u",&groesse);fwrite(vname,sizeof(vname),1,fhd);

fwrite(nname,sizeof(char),MAXNACHNAME,fhd);fwrite(&alter,sizeof(alter),1,fhd);fwrite(&groesse,sizeof(unsigned int),1,fhd);fclose(fhd); printf("\nEingabe beendet!\n");

}}

197

C-Programmierung 2003/2004 197

void lesen(void){FILE *fhd;char vname[MAXVORNAME],nname[MAXNACHNAME];unsigned int alter,groesse;

fhd=fopen(DATNAME,"rb");if(!fhd)

{ printf("Datei konnte nicht erzeugt werden!\n\n"); }else

{fread(vname,sizeof(vname),1,fhd);fread(nname,sizeof(nname),1,fhd);fread(&alter,sizeof(alter),1,fhd);fread(&groesse,sizeof(groesse),1,fhd);

fclose(fhd);

printf("Vorname : %s\n",vname);printf("Nachname : %s\n",nname);printf("Alter in Jahren : %u\n",alter);printf("Groesse in cm : %u\n",groesse);}

}

198

C-Programmierung 2003/2004 198

void main(void){int input;

printf("Soll die Datei 1=gelesen oder 2=beschrieben werden?");scanf("%i",&input);

if(input==1){

lesen();}

else{

if(input==2){

schreiben();}

else{

printf("\nFalsche Eingabe!\n\n");}

}}

199

C-Programmierung 2003/2004 199

Dateipositionsanzeiger

Für Binärdateien gibt es die Möglichkeit ein spezielles Element aus der Datei zu be-arbeiten. Das setzt natürlich die Veränderung des Dateipositionszeigers voraus. Nur dadurch kann eine spezielle Stelle innerhalb einer Datei erreicht werden.

Der Dateipositionszeiger wird mit der Funktion fsetpos verändert.

Syntax von fsetpos:

fpos_t position;

a=fsetpos(fhd,&position);

Die Variable a enthält den Wert 0, wenn das Setzen des Dateipositionszeigers erfolgreich war.

Die Adresse der Variablen Position vom Typ fpos_t wird an die Funktion fsetposübergeben (fpos_t ist ein selbst deklarierter Variablentyp).

Fsetpos löscht auch das Dateiendeflag.

200

C-Programmierung 2003/2004 200

void lesen2(void){FILE *fhd;char vname[MAXVORNAME],nname[MAXNACHNAME];unsigned int alter,groesse;fpos_t position;

fhd=fopen(DATNAME,"rb");if(!fhd)

{printf("Datei konnte nicht erzeugt werden!\n\n");

}else

{position=sizeof(vname)+sizeof(nname)+sizeof(alter);fsetpos(fhd,&position);

fread(&groesse,sizeof(groesse),1,fhd);fclose(fhd);

printf("Groesse in cm : %u\n",groesse);}

}

Programm 33_1

201

C-Programmierung 2003/2004 201

Es wird eine Variable mit dem Namen position definiert. In ihr wird die Summe der Längen der zu überspringenden Daten gespeichert. Nach dem Öffnen der Datei wird mit fsetpos der Dateipositionszeiger an die Stelle vor den gespeicherten Daten der Größe gesetzt. Alle anderen Anweisungen sind dann analog dem Beispiel 33.

Die Variablen vname, nname, alter wurden definiert, aber nur zur Überspringung der Daten benutzt. Der Compiler kann hier eine Warnung ausgeben, da die Variablen nicht benutzt wurden. Diese Warnung kann ignoriert werden.

202

C-Programmierung 2003/2004 202

Das Gegenstück zu fsetpos ist fgetpos. Diese Funktion speichert den aktuellen Wert des Dateipositionszeigers in einer Variablen.

Syntax:

fpos_t position;

a=fgetpos(fhd, &position);

Jetzt wird der aktuelle Inhalt des Dateipositionszeigers in die Variable positiongeschrieben. Ist die Funktion erfolgreich ausgeführt, dann gib die Funktion den Wert 0 zurück, welcher dann in der Variablen a gespeichert ist

203

C-Programmierung 2003/2004 203

Eine weitere Funktion zur Veränderung des Dateipositionszeigers ist fseek. Diese Funktion kann in verschiedenen Modi aufgerufen werden.

Syntax von fseek:

a=fseek(fhd, distanz, modus);

SEEK_SET Der Dateipositionszeiger wird auf Dateianfang gesetzt und

bekommt den Wert von distanz hinzuaddiert. Damit

sind nur positive Werte sinnvoll. Der Aufruf ist analog fsetpos(fhd,

&position), wenn position und distanz gleich sind.

SEEK_END Der Dateipositionszeiger wird auf Dateiende gesetzt und bekommt

den Wert von distanz hinzuaddiert. Es sind nur negative

Werte für distanz sinnvoll.

SEEK_CUR Zum Dateipositionszeiger wird der Wert von distanz addiert. Damit

sind positive und negative Werte sinnvoll.

204

C-Programmierung 2003/2004 204

fgetpos (fhd, &position);

position+=distanz;

fsetpos (fhd, &position);

Dateipositionsteiger um 2 Byte nach vorn bewegen:

fseek (fhd,2,SEEL_CUR);

Die Modi für fseek sind Makros, die in der Datei stdio.h definiert sind. Die Funktion fseek liefert den Wert 0 zurück, wenn der Dateipositionszeider fehlerfrei verändert wurde.

Fseek löscht ebenfalls das Dateiendeflag.

Die Funktion rewind setzt den Dateipositionszeiger auf den Anfang der Datei und löscht das Fehlerflag.

Der Aufruf erfolgt mit: rewind (fhd);

Die Funktionen fsetpos, fgetpos und fseek spezifizieren einen eventuell aufgetretenen Fehler im Makro errno.

205

C-Programmierung 2003/2004 205

Weitere Funktionen zur Arbeit mit Dateien

rename

#include <stdio.h> /* Programm 38 */

void main(void){

printf("Datei wird umbenannt");rename("test.txt","mueller.txt"); /* Datei wird von */

/* test.txt *//* nach mueller.txt umbenannt */

}

206

C-Programmierung 2003/2004 206

remove

remove löscht eine Datei namens name und gibt bei Erfolg den Wert 0 zurück.

Name ist die Adresse eines String.

a=remove (name);remove ("test.txt")

löscht die Datei test.txt

207

C-Programmierung 2003/2004 207

Oft werden im Programmen Dateien zur Zwischenspeicherung benötigt, die nach Programmende gelöscht werden können. Dabei ist besonders wichtig, dass ein Dateiname gewählt wird, der einzigartig ist, um das Überschreiben bzw. Zerstören anderer Dateien zu vermeiden.

Dies kann mit der Funktion tmpname erfolgen, diese Funktion erzeugt einen Filenamen, der einzigartig ist.

Syntax:char a[80];

tmpnam (a);

Die Datei kann dann mit fopen geöffnet werden.

char a[80];

tmpnam (a);

fhd=fopen(a,"wb+");

208

C-Programmierung 2003/2004 208

Für die Aufgabe der Erzeugung einer temporären Datei kann auch die Funktion tmpfilegenutzt werden. Diese Funktion öffnet eine binäre Datei zur Ein- und Ausgabe und liefert die Adresse der File-Struktur zurück, über die die Datei verwaltet wird.

fhd=tmpfile();

Wenn Fehler innerhalb der Dateiarbeit auftreten, dann kann die Funktion ferror genutzt werden.

a=ferror(fhd);

Bei aufgetretenen Fehlern ist a dann ungleich Null. Diese Funktion kann genutzt werden, um Fehler auszutesten und entsprechende Meldungen zu erzeugen.

209

C-Programmierung 2003/2004 209

#include <stdio.h> /* Programm 39 */#include <conio.h>#include <stdlib.h>void main(void){int zahl; zahl=0;

while(zahl!=200){

printf("Bitte geben Sie 200 ein:");scanf("%i",&zahl);//clrscr ();

system("cls");printf("Bitte geben Sie 900 ein:");scanf("%i",&zahl);//clrscr();

}}

Anwendung der Funktion system zum löschen des Konsolenfensters.

210

C-Programmierung 2003/2004 210

20. Präprozessor-Befehle

Ein Präprozessor-Befehl, #include, wurde bereits in vielen Programmen genutzt. Der Präprozessor kann jedoch noch bedeutend mehr Unterstützung für den Programmierer bieten.

#define ohne ParameterDie define Anweisung erlaubt es, dass einem bestimmten Wert ein Name zugewiesen wird.

#define MAXWERT 80

Dem symbolischen Name MAXWERT wird der Wert 80 zugeordnet. An jeder Stelle im Programm, an der MAXWERT auftaucht wird dies durch den Präprozessor mit 80 ersetzt.

void main (void)

{char feld[MAXWERT]; ....... ; }

Der String wird in diesem speziellen Fall 80 Zeichen groß. Die define Anweisung arbeitet auf Textebene, aus diesem Grund ist auch folgendes Programm richtig:

#define START main

void START (void)

211

C-Programmierung 2003/2004 211

Bevor der Compiler den Quelltext bearbeitet, ersetzt er START durch main. Damit ist das C-Programm in Ordnung und es wird zu keinen Fehlern während der Compilierung kommen.

Weitere Anwendungen von #define sind:

#define STRING "Tabelle"

void main (void)

{char Feld[80]=STRING;}

#define WERTE 80+80void main (void){int x;x=WERTE*2; ...........;}

#define WERTE (80+80)void main (void){int x;x=WERTE*2;...........;}

212

C-Programmierung 2003/2004 212

#define mit ParameterEs können auch Makros mit Parameter definiert werden.

#define QUADRAT(x) (x*x)

Wenn der Präprozessorjetzt auf QUADRAT(ausdruck) stoßt, dann ersetzt er dies durch (ausdruck)*(ausdruck).

#define QUADRAT(x) (x*x) //Programm 36

void main (void)

{int zahl;

printf ("Bitte einen Wert eingeben:");

scanf ("%i", &zahl);

printf ("Das Quadrat von %i ist %i \n",zahl, QUADRAT(zahl));}

printf ("Das Quadrat von %i ist %i \n",zahl, QUADRAT(zahl++)); ?Was berechnet das Programm, wenn die Zahl 4 eingegeben wird und wie groß ist der Wert von zahl am Programmende?

Der Präprozessor ersetzt zahl++ * zahl++. Damit lautet das Ergebnis 16 (4*4) und zahl ist am Programmende 6.

213

C-Programmierung 2003/2004 213

#undefMit der Anweisung #undef kann eine bestehende #define-Anweisung aufgehoben werden. Das kann z.B. notwendig sein, wenn ein definiertes Makro nur in einem bestimmten Bereich gültig sein soll, oder wenn Makros aus bestehenden Header-Files nicht genutzt werden sollen, oder durch eigene Definitionen ersetzt werden müssen.

#define STRING "Tabelle"

............

#undef STRING

#define STRING "MUSTER"

#includeDie #include-Anweisung wird schon seit längeren in Programmen genutzt.

#include <stdio.h>

Die spitzen Klammern bedeuten, dass die Header-Datei im include Pfad des Compilers zu suchen ist. Der Nutzer kann aber auch eigene Header-Dateien schreiben, in welchen die ganzen Deklarationen stehen. Die eigenen Header-Dateien speichert man im gleichen Verzeichnis wie das Programm.

Möchte man eine Header-Datei einbinden, die im gleichen Verzeichnis wie das Programm steht, benutzt man doppelte Anführungszeichen (#include "header1").

214

C-Programmierung 2003/2004 214

#define STD <stdio.h>

#define EIG "eigen.h"

#include STD

#include EIG

Die #include-Anweisung kann natürlich auch in Verbindung mit #define benutzt werden.

215

C-Programmierung 2003/2004 215

#if und #endifDie #if Anweisung entspricht der C-if-Anweisung, nur dass es sich auf eine Definition des Präprozessors bezieht. Diese Anweisung ist hauptsächlich zum bedingten Compilieren notwendig.

Es werden bestimmte Anweisungen nur dann kompiliert, wenn die entsprechenden Randbedingungen erfüllt sind.

#if TEST == 1

print ("Das ist ein Test - Makro Test ist 1");

x++;

#endif

Die Anweisungen im Beispiel zuwischen #if unf #endif werden nur dann kompiliert, wenn das Makro den Wert 1 hat.

Die #endif Direktive ist unbedingt notwendig und schließt jede #if Direktive ab.

Mit diesen Anweisungen ist es z.B. möglich, dass ein Programm geschrieben wird und vor dem kompilieren wird entschieden in welcher Sprache das Programm übersetzt wird.

216

C-Programmierung 2003/2004 216

#include <stdio.h> // Programm 34

#define DEUTSCH 1#define ENGLISCH 2

#define WERT DEUTSCH

void main(void){int zahl;

#if WERT == DEUTSCHprintf("Bitte Wert eingeben:");

#endif

#if WERT == ENGLISCHprintf("Please enter a value:");

#endif

scanf("%i",&zahl);}

217

C-Programmierung 2003/2004 217

__DATE__

Makro steht für eine Stringkonstante mmm tt jjjj

Startdatum der Kompilierung

__TIME__

Makto steht für das Datum hh:mm:ss

Startzeit der Kompilierung

__FILE__

Stringkonstante mit dem aktuellen Namen der Quellcodedatei

__LINE__

Aktuelle Zeilennummer Ganzzahl

__STDC__

Liefert Ganzzahl 1, wenn Compiler ein ANSI C Compiler ist

(geht nicht bei allen Compilern)

Vordefinierte Makros

Programm 43

218

C-Programmierung 2003/2004 218

21. Programmier-Technologien

219

C-Programmierung 2003/2004 219

Headerdatei-1.h Headerdatei-2.h Headerdatei-3.h Headerdatei-4.h

xx-1.cpp xx-2.cpp xx-3.cpp xx-4.cpp

Compiler

xx-1. obj xx-2. obj xx-3. obj xx-4. obj

Linker

Programm xx.exe

220

C-Programmierung 2003/2004 220

21.1 Eigene Header-Dateien

- Programme modular aufbauen

- Möglichkeit der eigenen Header-Dateien nutzen

- Auslagerung in Header-Dateien:

- alle #define Anweisungen

- Struktur- und Uniondeklarationen

- Prototypen

Bei doppelten Anführungszeichen stehen die Headerdateien im aktuellen Verzeichnis

#include <stdio.h>

#include <string.h>

#include "eigene-header-datei.h"

Programm 40

221

C-Programmierung 2003/2004 221

Bei Headerdateien sollte unbedingt verhindert werden, dass sie mehrfach kompiliert werden. Dies kann in komplexen Projekten zu Fehlern führen.

Um das zu vermeiden, wird die Präprozessoranweisung #ifndef benutzt.

#ifndef __HEADERDATEI001_H

#define __HEADERDATEI001_H

#include …….

.

.

#endif

Namenskonventionen von C

siehe auch Programm 40

222

C-Programmierung 2003/2004 222

Programm 41

Statische Variablen und Funktionen

static int rekfakul (int x, int y)

{if (x==1) return (y);

return (rekfakul (x-1,y*(x-1)));

}

int fakul (int x)

{if x<0) return (0);

if (x==0) return(1);

return (rekfakul (x,x));

Programm 42

Statische Variablen

223

C-Programmierung 2003/2004 223

Hinweise zur modularen Programmierung:

- Funktionen zu sinnvollen Modulen zusammenstellen

- Themenbezogene Strukturierung

- Schnittstellen zu den Funktionen transparent darstellen und dokumentieren

- wenn möglich auf globale Variablen verzichten

- Informationen zu den Funktionen hinzufügen (Kommentarzeilen), in denen die Funktion

erklärt wird

- Module genau beschreiben, Zusammenhänge eindeutig erläutern

- Aufbau von eigenen Header-Dateien für Definitionen

- Angabe von Änderungsständen und Versionsnummern

- Nutzung der Readme-Files der Entwicklungsumgebung

224

C-Programmierung 2003/2004 224

21.2. Rekursion

Von Rekursionen spricht man, wenn sich Funktionen selbst aufrufen.

// Rekursion01.cpp//#include <stdio.h>

void rekfunk (void){int x=99;static int z=1;printf ("Ausgabe innerhalb der Funktion rekfunk beim %i. Aufruf mit Wert %i\n",z,x);z++;rekfunk();}void main(void){

rekfunk();}

Absturz des Programms durch Stack-Übrlauf

• immer neue Rücksprungadresse von rekfunk

• immer neue Lokale Variable x

225

C-Programmierung 2003/2004 225

Sinnvolle Anwendung von rekursiven Funktionsaufrufen.

Beispiel: Berechnung der Fakultät einer Zahl

3!= 1*2*3=6 4!=1*2*3*4=24 4!=1*2*3*4*5=120

#include <stdio.h> // Programm: Fakultaet01.cppvoid main(void){int x;

do{ int i,erg=1,z;

printf ("Bitte die Zahl eingeben, von der die Fakultät berechnet werden soll: ");scanf ("%i",&i);

if (!(i==0)){ for (z=1;z<i+1;z++)

erg=erg*z;}printf ("Die Fakultaet von %i ist %i\n\n",i,erg);printf ("Soll eine weitere Berechnung durchgefuehrt werden? j=1/n=2: ");scanf ("%i",&x);

} while (x==1);}

Berechnung ohne rekursiven Funktionsaufruf

226

C-Programmierung 2003/2004 226

Berechnung auch wie folgt möglich: x!=x*(x-1)! ; mit 0!=1

#include <stdio.h> // Programm: Fakultaet02.cpp

int fakultaet (int x){ if (x<0) return (0);

if (x==0) return (1);return (x*fakultaet (x-1));

}

void main(void){int wert,x,erg;do{ printf ("Bitte die Zahl eingeben, von der die Fakultät berechnet werden soll: ");

scanf ("%i",&wert);

erg=fakultaet (wert);printf ("Die Fakultaet von %i ist %i\n\n",wert,erg);printf ("Soll eine weitere Berechnung durchgefuehrt werden? j=1/n=2: ");scanf ("%i",&x);

} while (!(x==2));

}

227

C-Programmierung 2003/2004 227

Programm am Beispiel von Fakultät 4:

Aufruf von fakultaet (4): x>0 Rückgabe von 4*fakultaet (3);

Aufruf von fakultaet (3): x>0 Rückgabe von 3*fakultaet (2);

Aufruf von fakultaet (2): x>0 Rückgabe von 2*fakultaet (1);

Aufruf von fakultaet (1): x>0 Rückgabe von 1*fakultaet (0);

Aufruf von fakultaet (0): x==0 Rückgabe von 1;

Rücksprung in fakultaet (1): Rückgabewert von 1*1=1

Rücksprung in fakultaet (2): Rückgabewert von 2*1=2

Rücksprung in fakultaet (3): Rückgabewert von 3*2=6

Rücksprung in fakultaet (4): Rückgabewert von 4*6=24

Ausgabe Ergebnis: 24

228

C-Programmierung 2003/2004 228

0 1

2 3

4 5

6 7

A B C A B C

A B C A B C

A B C A B C

A B C A B C

Türme von Hanoi

229

C-Programmierung 2003/2004 229

21.3. Listen

Abstrakter Datentyp: Ein abstrakter Datentyp ist ein Datentyp, dem zusätzlich Funktionen zur Verfügung gestellt werden, die auf ihm operieren.

Sortierung von Warteschlangen: jedes Mitglied der Warteschlange merkt sich seinen Vorgänger Länge der Schlange ist nicht relevant

• ideal für dynamische Speicherverwaltung, denn der für die Speicherung notwendigefreie zusammenhängende Platz ist nicht größer als die Größe eines einzelnen Elementes

230

C-Programmierung 2003/2004 230

Einfach verkettete Listen

struct Telefon

{ char name[80];

char vorname[80];

char telefon[25];

char mail[50];

}

Es ist effektiv, die Daten immer in einer Struktur zu kapseln

Trennung zwischen Nutzdaten und Kontrolldaten

Ein Listenelement benötigt zuerst die Nutzdaten, d.h. die Struktur telefon und

die Information auf das vorherige Element, d.h. einen Zeiger auf den Nachfolger

struct Knot

{struct Telefon *telefon; //Zeiger auf ein Element vom gleichen Typ

struct Knot *next; // Zeiger auf nächstes Element

};

231

C-Programmierung 2003/2004 231

232

C-Programmierung 2003/2004 232

233

C-Programmierung 2003/2004 233

234

C-Programmierung 2003/2004 234

Listenkopf: struct Knot *listenkopf=0;

Wird mit 0 initialisiert, da am Anfang noch kein Element existiert

1. Funktion der Liste –anhängen eines Knotens an die Liste

-Parameterübergabe - Nutzdaten und Listenkopf

-Funktion erzeugt einen Knoten und hängt ihn an die Liste an

- gibt Wert zurück (Funktion ausgeführt oder Error)

Funktionen malloc und free

Anfordern von Speicher: void *malloc (size_t groesse);

- der Typ der Speicherplatzanforderung ist size_t

- sizeof liefert einen Wert vom Typ size_t zurück Nutzung bei malloc

Freigeben von Speicher: void free (void *ptr);

235

C-Programmierung 2003/2004 235

Nutzung von malloc und free

#include <stdio.h> //Speicher01.cpp#include <stdlib.h>

void main(void){

void *nullptr;int *ptr;

nullptr=malloc( sizeof(int) );ptr=(int*)(nullptr);if(ptr)

{*ptr=30;printf("Der dynamische Speicherblock hat den Wert %i

gespeichert\n",*ptr);free(ptr);

}}

236

C-Programmierung 2003/2004 236

- Funktion malloc gibt einen Zeiger auf void zurück, d.h. auf einen typenlosen Zeiger

- ein typenloser Zeiger kann auf alles zeigen

- für die weitere Nutzung muss aber dieser void Zeiger durch Typumwandlung mit

dem cast Operator in einen typisierten Zeiger gewandelt werden

- der von malloc gelieferte Zeiger ist die Adresse des reservierten Speicherblocks oder der

Nullzeiger

Nullzeiger: - beinhaltet die Adresse 0; ist per Definition ein leerer Zeiger, d.h. er

zeigt auf kein Element

- wird bei Funktionen dazu benutzt, um zu zeigen, dass kein Element

vorhanden ist oder erzeugt wurde (nullptr)

237

C-Programmierung 2003/2004 237

int ListAppend (struct Knot *hd, struct Telefon *tel)

{void *ptr;

ptr=malloc(sizeeof(struct Knot));

struct Knot *cur,*ap;

ap=(struct Knot *)(ptr)

if (ap)

{ ap->telefon=tel; ap->next=0;

if (!hd)

{hd=ap; return (1);}

else

{cur=hd;

while (cur->next) cur=cur->next;

cur->next=ap; return (1);}

}

return (0);

}

238

C-Programmierung 2003/2004 238

1. Definition von 2 Zeigern, *ap bekommt dann einen Speicherbereich in der Größe vonstruct Knot zugewiesen

2. prüfen, ob hd wirklich Speicherplatz zugewiesen wurde, wenn ja Verweis auf Nutzdaten hergestellt und Verweis auf das nächste Element wird 0 (letztes Element-> hat keinen Nachfolger

3. prüfen, ob hd 0 ist, wenn ja es existiert noch kein Knoten, dieser wird der erste

4. ist hd nicht 0 es existiert mindestens ein Knoten letzten Knoten finden, um neues Element anhängen zu können

5. cur bekommt die in hd gespeicherte Adresse und zeigt damit auch auf den ersten Knoten

6. Über while Schleife wird geprüft, ob der next-Zeiger des Knotens, auf den cur zeigt gleich 0 ist bei ja ist dies der letzte Knoten, bei nein gibt es weitere Knoten

7. Ist cur 0 wird while abgebrochen, bei ungleich 0 wird weiter gesucht

8. Ist die while Schleife abgebrochen cur zeigt auf das letzte Listenelement

9. Dann wird dessen next auf den neuen Knoten gesetzt Liste ist um ein Element länger

Nachteil: Um das letzte Element zu finden, muss die gesamte Liste durchsucht werden.

239

C-Programmierung 2003/2004 239

Effektiver: direkter Zugriff auf Anfang und Ende der Liste Einführung einer Listenkopfstruktur

struct ListHead {struct Knot *head;

struct Knot tail;}

Zeiger auf den Listenkopf: struct ListHead *liste;

struct ListHead *ListCreate(void) // Funktion zum Anlegen und initialisieren des {void *ptr3; // Listenkopfes

ptr3=malloc(sizeof(struct ListHead));struct ListHead *head;head=(struct ListHead *)(ptr3);

if(head){

head->head=head->tail=0;return(head);

}return(0);

}

240

C-Programmierung 2003/2004 240

Anpassen der ListAppend Funktion unter Nutzung des Listenkopfes:

int ListAppend(struct ListHead *hd, struct Telefon *tel) // ListAppend *********{void *ptr1;ptr1=malloc(sizeof(struct Knot));struct Knot *ap;ap=(struct Knot *)(ptr1);

if(ap) {ap->telefon=tel;ap->next=0;

if(!(hd->head)){

hd->head=hd->tail=ap;return(1);

}else {

hd->tail->next=ap;hd->tail=ap;return(1);

}}

return(0);}

241

C-Programmierung 2003/2004 241

Funktion zum Löschen der Liste und freigeben des Speichers

void ListDelAll(struct ListHead *hd) //ListDelAll ***************{struct Knot *cur=hd->head, *nex;

while(cur){

nex=cur->next;free(cur->telefon);free(cur);cur=nex;

}free(hd);

}

Die Funktion geht die gesamte Liste durch.

Bevor ein Knoten gelöscht wird prüft die Funktion, ob dieser einen Nachfolger hat; wenn

ja, dann wird dessen Adresse in einer Variablen gespeichert. Beim Löschen wird ja der

Verweis auf den Nachfolger ebenfalls gelöscht.

Zuerst wird die Nutzdatenstruktur, dann die Knoten und zuletzt der Listenkopf gelöscht.

242

C-Programmierung 2003/2004 242

Die Funktion zu Dateneingabe:

int ListInput(struct ListHead *hd) //ListInput *****************{void *ptr2;ptr2=malloc(sizeof(struct Telefon));struct Telefon *dat;dat=(struct Telefon *)(ptr2);

if(dat) { printf("Vorname :");gets(dat->vorname);printf("Nachname :");gets(dat->nachname);printf("Telefon :");gets(dat->telefon);if(ListAppend(hd,dat)){return(1); }else {free(dat); return(0);}

}else

{return(0);

}}

243

C-Programmierung 2003/2004 243

Die Funktion zum Anzeigen der Liste:

void ListShow(struct ListHead *hd) //ListShow ******************{struct Knot *cur=hd->head;

if(!cur){

printf("Die Liste ist leer!\n");return;

}

while(cur){

printf("Name: %s, %s. Tel.:%s\n",cur->telefon->nachname,cur->telefon->vorname,cur->telefon->telefon);

cur=cur->next;}

}

244

C-Programmierung 2003/2004 244

void main(void){struct ListHead *liste;int eingabe;

liste=ListCreate();if(liste)

{ do { printf("\n1 = Liste zeigen\n");printf("2 = Knoten anfuegen\n");printf("\n0 = Ende\n\n");printf("Eingabe:");scanf("%i",&eingabe);getchar();printf("\n\n");

switch(eingabe){case 1: ListShow(liste); break;case 2: ListInput(liste);break;} } while(eingabe);

ListDelAll(liste);}}

Die main-Funktion

245

C-Programmierung 2003/2004 245

21.4. Sortierverfahren

Elementare Sortierverfahren: - Selection Sort

- Insertion Sort

- Bubble Sort

- Shell Sort

- Distribution Counting

- Quick Sort

Digitales Sortieren: - Radix Exchange Sort

- Straight Radix Sort

Proiritätswarteschlangen: - Heapsort

Mergesort : - Mergesort von Listen

- Bottom-Up Mergesort

246

C-Programmierung 2003/2004 246

Bubble Sort

- Einfaches Sortierverfahren

- Sortieren durch direktes Austauschen

99 84 23 11 Austauschen, wenn a>b

84 99 23 11 Austauschen, wenn a>b

84 23 99 11 Austauschen, wenn a>b

84 23 11 99 Ergebnis des 1. Durchlaufes – größte Zahl ist ermittelt

84 23 11 99 Austauschen, wenn a>b

23 84 11 99 Austauschen, wenn a>b

23 11 84 99 Austauschen, wenn a>b

23 11 84 99 Ergebnis des 2. Durchlaufes – zweitgrößte Zahl ermittelt

23 11 84 99 Austauschen, wenn a>b

11 23 84 99 Austauschen, wenn a>b

11 23 84 99 Austauschen, wenn a>b

11 23 84 99 Sortierung fertig

247

C-Programmierung 2003/2004 247

99 84 23 11 Austauschen, wenn a>b

84 99 23 11 Austauschen, wenn a>b

84 23 99 11 Austauschen, wenn a>b

84 23 11 99 Ergebnis des 1. Durchlaufes – größte Zahl ist ermittelt

84 23 11 99 Austauschen, wenn a>b

23 84 11 99 Austauschen, wenn a>b

23 11 84 99 Austauschen, wenn a>b kann enffallen !!!

23 11 84 99 Ergebnis des 2. Durchlaufes – zweitgrößte Zahl ermittelt

23 11 84 99 Austauschen, wenn a>b

11 23 84 99 Austauschen, wenn a>b kann entfallen !!!

11 23 84 99 Austauschen, wenn a>b kann entfallen !!!

11 23 84 99 Sortierung fertig

- Bei N Elementen braucht man für die Sortierung N-1 Durchläufe in der äußeren

Schleife und in jeder inneren Schleife immer einen Durchlauf weniger

248

C-Programmierung 2003/2004 248

// Bubble_Sort.cpp : Definiert den Einsprungpunkt für die Konsolenanwendung.#include "stdafx.h"/*void bubble(int *a,int n){int i,j,hv, z1=n,z=n;

for (i=1;i<=n;i++,z1--){ for (j=0,z=z1;z>=1;j++,z--)

{ if(a[j] > a[j+1]) {hv=a[j]; a[j]=a[j+1];a[j+1]=hv;};

}}}*/void bubble(int *a,int n){int i,j,hv;

for (i=n;i>=1;i--)for (j=1;j<i;j++)

if(a[j-1] > a[j]) {hv=a[j-1]; a[j-1]=a[j];a[j]=hv;};

}int main(int argc, char* argv[]){ int feld[4]={99,23,84,11};int n=4;

printf("%i %i %i %i \n", feld[0],feld[1],feld[2],feld[3]);bubble (feld,n);printf("%i %i %i %i \n", feld[0],feld[1],feld[2],feld[3]);return 0;

}

249

C-Programmierung 2003/2004 249

21.5. Suchalgorithmen

Elementare Suchmethoden: - Sequentielle Suche

- Binäre Suche

Ausgeglichene Bäume: - Top-Down 2-3-4 Bäume

- Rot-Schwarz Bäume

Hashing - Hash-Funktionen

- getrennte Verkettung

- lineares Austesten

- doppeltes Hashing

Digitale Suche

Externe Suche - indexsequentieller Zugriff

- B-Bäume

250

C-Programmierung 2003/2004 250

21.6. Datenkomprimierung

- Lauflängencodierung

- Kodierung mit variabler Länge

- Huffmann Codierung

-

251

C-Programmierung 2003/2004 251

22. Zusammenfassung

252

C-Programmierung 2003/2004 252

Steuerzeichen

\a BEL (bell), gibt ein akustisches Signal

\b BS (backspace), der Cursor geht eine Position nach links

\f FF (formfeed), Seitenvorschub wird ausgelöst

\n NL (new line), der Cursor geht zum Anfang der nächsten Zeile

\r CR (carriage return), der Cursor geht zum Anfang der aktuellen Zeile

\t HAT (horizontal tab), der Cursor geht zur nächsten horizontalen

Tabulator position

\v VT (vertical tab), der Cursor geht zur nächsten vertikalen

Tabulatorposition

\" " es wird " ausgegeben

\' ' es wird ' ausgegeben

\? ? Es wird ein ? ausgegeben

\\ \ Es wird ein \ ausgegeben

253

C-Programmierung 2003/2004 253

Bindungsstärke der Operatoren

Operator Bedeutung Priorität

a++ Postinkrement 1

a-- Postdekrement 1

a[b] Index 1

a(b) Funktionsaufruf 1

a.b Zugriff auf Element 1

b->b zeigt auf Element 1

254

C-Programmierung 2003/2004 254

Operator Bedeutung Priorität

sizeeof a Größe 2

++a Präinkrement 2

--a Prädekrement 2

&a Adresse 2

*a Dereferenzierung 2

+a Plus 2

-a Minus 2

~a NOT Bitweise 2

!a NOT Logisch 2

(Deklaration)(a) Cast-Operator 2

255

C-Programmierung 2003/2004 255

Operator Bedeutung Priorität

a*b Multiplikation 3

a/b Division 3

a%b Modulo (Rest) 3

a+b Addition 4

a-b Subtraktion 4

a<<b Linksverschiebung 5

a>>b Rechtsverschiebung 5

a<b kleiner 6

a>b größer 6

a<=b kleiner gleich 6

a<=b größer gleich 6

256

C-Programmierung 2003/2004 256

Operator Bedeutung Priorität

a==b gleich 7

a!=b ungleich 7

a&b UND Bitweise 8

a^b exclusiv ODER Bitweise 9

a|b ODER Bitweise 10

a&&b UND Logisch 11

a||b ODER Logisch 12

257

C-Programmierung 2003/2004 257

Operator Bedeutung Priorität

a?b:c Bedingung 13

a=b Zuweisung 14

a*=b Multiplikation Zuweisung 14

a/=b Division Zuweisung 14

a%=b Modulo Zuweisung 14

a+=b Addition Zuweisung 14

a-=b Subtraktion Zuweisung 14

a<<=b Linksverschiebung Zuweisung 14

a>>=b Rechtsverschiebung Zuweisung14

a&=b UND Bitweise Zuweisung 14

a^b exclusiv ODER Bitzuweisung 14

a|=b ODER Bitzuweisung 14

a,b Komma 15

258

C-Programmierung 2003/2004 258

Formatzeichen Gleitkommazahlen

FZ Typ Zahlensystem Besonderheit

f double Dezimal *.*****

Lf long double Dezimal *.*****

e double Dezimal *.***E**

Le long double Dezimal *.***E**

E double Dezimal *.***E**

LE long double Dezimal *.***E*

g double Dezimal mit oder ohne E.

Lg long double Dezimal mit oder ohne E.

G double Dezimal mit oder ohne E.

LG long double Dezimal mit oder ohne E.

259

C-Programmierung 2003/2004 259

Formatzeichen Strings

FZ Typ Besonderheit

c char einzelnes Zeichen

s char[ ] String mit abschließender 0

% gibt % selbst aus

Formatzeichen Zeiger

FZ Typ Besonderheit

n int *

hn short *

ln long *

P void *

260

C-Programmierung 2003/2004 260

FZ Typ Zahlensystem

i int Dezimal

d int Dezimal

hi short Dezimal

hd short Dezimal

li long Dezimal

ld long Dezimal

u unsigned int Dezimal

hu unsigned short Dezimal

lu unsigned long Dezimal

Formatzeichen Ganzzahlen

261

C-Programmierung 2003/2004 261

Ende