(eBook German) C Von a-Z - Galileocomputing Galileo Computing Programmierung

Embed Size (px)

Citation preview

Xoops2 RC3

C von A bis Z ( Online-Version des Buches )Wer kennt das nicht! Wieder mal haben Sie ein teures Computerfachbuch gekauft, mit Sie dem so gut wie berhaupt nichts anfangen knnen. Also muss ein weiteres Buch her, dass Ihren Vorstellungen entspricht. Wenn Sie Glck haben, ist das nchste Buch Ihre ultimative Bibel. Ansonsten sucht man weiter, nach seinem "heiligen Gral". Damit will ich nicht sagen, dass es schlechte Bcher sind. Nein, ganz im Gegenteil, eigentlich gibt es keine schlechten Bcher (mit einigen Ausnahmen vielleicht), sondern eher das falsche Buch fr die falsche Lesergruppe. Mit der Online-Version des Buchs C von A bis Z knnen Sie sich selbst ein Bild machen, ob, dass Buch Ihren Vorstellungen entspricht oder nicht. Wenn Ihnen dieses Buch zusagt, wrde ich mich natrlich sehr freuen, wenn Sie es kaufen wrden. Und wenn nicht, bin ich ber eine Mitteilung sehr dankbar, was Ihnen an diesem Buch nicht gefllt und was man besser machen knnte. Auf diesem Wege besttigen Sie mir und dem Verlag www.galileocomputing.de das dieser Weg, Bcher zu verkaufen, der Richtige ist. Somit ebnen Sie den Weg einer neuen OpenBook-Generation. Weitere solcher OpenBooks finden Sie auf der Webseite des Verlags.

920 S., geb., mit Referenzkarte 39,90 Euro

Bestellen

q q r r r r r

Vorwort 1. Einstieg in C 1.1. 1.2. 1.3. 1.4. 1.5. 2.1. 2.2. 2.3. 2.4. Historische Entwicklung Der ANSI C Standard Der Vorteil des ANSI C Standards Vorteile und Nachteile der Programmiersprache C C in diesem Buch Texteditor Compiler All-in-one - Die Entwicklungsumgebung Welcher Compiler und welches Betriebssystem

q r r r r

2. Was bentige ich zu C

q r r r

3. Das erste Programm 3.1. Der beste Lernerfolg 3.2. Hallo Welt in C 3.3. Analyse des Programms 4. Zeichenstze 4.1 Basic-Zeichensatz 4.2 Ausfhrungszeichensatz (Steuerzeichen) 5. Kommentare in C 5.1. Wann sind Kommentare sinnvoll? 5.2. Welche Kommentar-Schreibweise: // oder /* */ 6. Formatiertes Eingabe mit scanf 6.1. 6.2. 6.3. 6.4. Der Adressoperator "&" Probleme und deren Behandlung mit scanf() berprfen auf das richtige Format Zusammenfassung scanf()

q r r

q r r

q r r r r

q r

7. Formatierte Ausgabe mit printf 7.1. Formatierte Ausgabe mit printf 8. Elementare Datentypen 8.1. Der Datentyp int (Integer) 8.2. Variablen deklarieren 8.3. C versus C++ bei der Deklaration von Variablen 8.4. Der Datentyp long 8.5. Der Datentyp short 8.6. Die Gleitpunkttypen float und double 8.7. Nummerische Gleitpunktprobleme 8.8. Der Datentyp char 8.9. Nationale contra internationale Zeichenstze 8.10. Vorzeichenlos und vorzeichenbehaftet 8.11. Limits fr Ganzzahl- und Gleitpunktdatentypen 8.12. Konstanten 8.13. Umwandlungsvorgaben fr formatierte Ein-/Ausgabe 9. Operatoren 9.1. 9.2. 9.3. 9.4. 9.5. 9.6. Exkurs zu Operatoren Arithmetische Operatoren Erweiterte Darstellung arithmetischer Operatoren Inkrement- und Dekrement-Operatoren Bit-Operatoren sizeof Operator

q r r r r r r r r r r r r r

q r r r r r r

q r

10. Typenumwandlung 10.1. Typenumwandlung 11. Kontrollstrukturen 11.1. Verzweigungen mit if-Bedingung 11.2. Die Verzweigung mit else if 11.3. Die Verzweigung mit else 11.4. Der !-Operator (logischer Operator) 11.5. Logisches UND (&&) - Logisches ODER (||) 11.6. Bedingungsoperator ? : 11.7. Fallunterscheidung: Die switch-Verzweigung 11.8. Die while-Schleife 11.9. Die do-while Schleife 11.10. Die for - Schleife 11.11. Kontrollierte Sprnge 11.12. Direkte Sprnge mit goto 11.13. Notationsstil 12. Funktionen 12.1. Was sind Funktionen 12.2. Wozu Funktionen? 12.3. Definition von Funktionen 12.4. Funktionsaufruf 12.5. Funktionsdeklaration 12.6. Lokale Variablen 12.7. Globale Variablen 12.8. Statische Variablen 12.9. Schlsselworte fr Variablen - Speicherklassen 12.10. Typ-Qualifizierer 12.11. Geltungsbereich von Variablen 12.12. Speicherklassen-Spezifizierer fr Funktionen 12.13. Datenaustausch zwischen Funktionen 12.14. Funktion mit Wertbergabe (call-by-value) 12.15. Rckgabewert von Funktionen 12.16. Die Hauptfunktion main() 12.17. Funktionen der Laufzeitbibliothek 12.18. Getrenntes Compilieren von Quelldateien 12.19. Rekursive Funktionen 13. Prprozessor-Direktiven 13.1. 13.2. 13.3. 13.4. 13.5. 13.6. 13.7. 13.8. Einkopieren von Dateien mittels #include Makros und Konstanten - #define Bedingte Compilierung Vordefinierte Prprozessor-Direktiven (ANSI C) Ersetzung von Makroparametern durch einen String #undef - Makronamen wieder aufheben Ausgeben von Fehlermeldungen #error #pragma

q r r r r r r r r r r r r r

q r r r r r r r r r r r r r r r r r r r

q r r r r r r r r

q r r r r r r r r r r r r r r

14. Arrays 14.1. Arrays deklarieren 14.2. Initialisierung und Zugriff auf Arrays 14.3. Arrays vergleichen 14.4. Anzahl der Elemente eines Arrays (ermitteln) 14.5. bergabe von Arrays an Funktionen 14.6. Arrays aus Funktionen zurckgeben 14.7. Programmbeispiel zu den Arrays 14.8. Einlesen von Array-Werten 14.9. Mehrdimensionale Arrays 14.10. Mehrdimensionale Arrays initialisieren 14.11. Arrays in Tabellenkalkulation einlesen (*.CSV-Dateien) 14.12. Strings/Zeichenketten (char Array) 14.13. Einlesen von Strings 14.14. Standard-Bibliothek - string.h 15. Zeiger (Pointer) 15.1. Zeiger deklarieren 15.2. Zeiger initialisieren 15.3. Zeigerarithmetik 15.4. Zeiger, die auf andere Zeiger verweisen 15.5. Typensicherung bei der Dereferenzierung 15.6. Zeiger als Funktionsparameter (call-by-reference) 15.7. Array und Zeiger 15.8. Zeiger auf Strings 15.9. Zeiger auf Zeiger und Stringtabellen 15.10. Zeiger auf Funktionen 15.11. void-Zeiger 15.12. quivalenz zwischen Zeigern und Array 16. Kommandozeilenargumente 16.1. Argumente an die Hauptfunktion 16.2. Optionen (Schalter )- aus der Kommandozeile auswerten 17. Dynamische Speicherverwaltung 17.1. 17.2. 17.3. 17.4. 17.5. 17.6. 17.7. 17.8. 17.9. Das Speicherkonzept Speicherallokation mit malloc Die Freispeicherverwaltung Dynamisches Array Speicher dynamisch reservieren mit realloc und calloc Speicher vom Stack anfordern mit alloca (nicht ANSI C) free - Speicher wieder freigeben Zweidimensionale dynamische Arrays Wenn die Speicheralloktion fehlschlgt

q r r r r r r r r r r r r

q r r

q r r r r r r r r r

q r r r r r r r r r r r r r r r

18. Stukturen 18.1. Struktur deklarieren 18.2. Initialisierung und Zugriff von Strukturen 18.3. Strukturen als Wertbergabe an eine Funktion 18.4. Strukturen als Rckgabewert einer Funktion 18.5. Strukturen vergleichen 18.6. Arrays von Strukturen 18.7. Strukturen in Strukturen (Nested Structurs) 18.8. Kurze Zusammenfassung zu den Strukturen 18.9. Union 18.10 Aufzhlungstyp enum 18.11 Typendefinition mit typedef 18.12 Attribute von Strukturen verndern (nicht ANSI-C) 18.13 Bitfelder 18.14 Differenzen zwischen C und C++ (Strukturen) 18.15 Das offsetof - Makro 19. Ein-/Ausgabe-Funktionen 19.1. Was ist eine Datei? 19.2. Formatierte und Unformatierte Ein-/Ausgabe 19.3. Stream 19.4. Hhere Ein-/Augabe-Funktionen 19.5. Datei (Stream) ffnen - fopen 19.6. Zeichenweise Lesen und Schreiben - getchar und putchar 19.7. Zeichenweise Lesen und Schreiben - putc/fputc und getc/ fgetc 19.8. Datei (Stream) schlieen - fclose 19.9. Formatiertes Einlesen/Ausgeben von Streams mit fprintf und fscanf 19.10. Standardstreams in C 19.11. Fehlerbehandlung von Streams - feof, ferror, clearerr 19.12 Gelesenes Zeichen in die Eingabe zurckschieben ungetc 19.13. (Tastatur)Puffer leeren - fflush 19.14. Stream positionieren - fseek, rewind und ftell 19.15 Stream positionieren - fsetpos, fgetpos 19.16 Zeilenweise Ein-/Ausgabe 19.17. Blockweise Lesen und Schreiben - fread und fwrite 19.18. Datei (Stream) erneut ffnen - freopen 19.19. Datei lschen oder umbenennen - remove und rename 19.20. Pufferung einstellen - setbuf und setvbuf 19.21. Temporre Dateien erzeugen - tmpfile und tmpnam 19.22. Fehlerausgabe mit strerror und perror 19.23. Formatiert in einem String schreiben und foramtiert aus einem String lesen 19.24. Fortgeschrittenes Thema 19.25. Low-Level-Datei-I/O Funktionen (nicht ANSI-C) 19.26. Datei ffnen - open 19.27. Datei schlieen - close 19.28. Datei erzeugen - creat 19.29. Schreiben und Lesen - write und read 19.30. File-Deskriptor positionieren - lseek 19.31. File-Deskriptor von einem Stream - fileno 19.32. Stream von File-Deskriptor - fdopen 20. Attribute von Dateien und Arbeiten mit Verzeichnissen (nicht ANSI C) 20.1. Attribute einer Datei ermitteln-stat() 20.2. Prfen des Zugriffrechtes - access 20.3. Verzeichnis-Funktionen 21. Arbeiten mit variablen langen Argumentlisten stdarg.h 21.1. Makros in stdarg.h - va_list, va_arg, va_start und va_end 21.2. Argumentliste am Anfang oder Ende kennzeichnen 21.3. vprintf, vsprintf, vfsprintf 22. Zeitroutinen 22.1. Die Headerdatei time.h 22.2. Laufzeitmessungen (Profiling) C) 23. Weitere Headerdateien und deren Funktionen (ANSI 23.1. 23.2. 23.3. 23.4. 23.5. 23.6. 23.7. 23.8. 24.1. 24.2. 24.3. 24.4. assert.h - Testmglichkeiten und Fehlersuche ctype.h - Zeichenklassifizierung und Umwandlung math.h - Mathematische Funktionen stdlib.h setjmp.h signal.h string.h - Die mem-Funktionen zur Speichermanipulation Erweiterter ANSI C-Standard (ANSI C99) Lineare Listen (einfach verkettete Listen) Doppelt verkettete Listen Stacks nach dem LIFO (Last-in-First-out)-Prinzip Queues nach dem FIFO (First-in-First-out) Prinzip

q r r r r r r r

r r

r r r

r r r r r r r r r r r

r r r r r r r r r

q

r r r

q r r r

q r r

q

r r r r r r r r

q r r r r

24. Dynamische Datenstrukturen)

q r r r r r r r r

25. Algorithmen 25.1. Was sind Algorithmen? 25.2. Wie setze ich Algorithmen ein? 25.3. Sortieralgorithmen 25.4 Code Optimieren 25.5 Suchalgorithmen - Grundlage zur Suche 25.6 Hashing (Zerhacken) 25.7 Stringmatching 25.8 Pattern Matching (regulre Ausdrcke) 26. Sicheres Programmieren 26.1. Buffer Overflow (Speicherberlauf) 26.2. Memory Leaks (Speicherlecks) 26.3. Ausblick Sicherheitsprobleme 27. CGI mit C 27.1. Was ist CGI? 27.2. Vorteile von CGI in C 27.3. Andere Techniken der Webprogrammierung 27.4. Das dreistufige Webanwendungsdesign 27.5. Cientseitige Programmierung 27.6. Serverseitige Programmierung 27.7. Der Webserver 27.8. Das HTTP-Protokoll 27.9. Das Common Gateway Interface (CGI) 27.10. HTML-Formulare 27.11. CGI-Eingabe 27.12. Ein Gstebuch 27.13. Ausblick 28. MySQL und C 28.1. 28.2. 28.3. 28.4. 28.5. 28.6. 28.7. Aufbau eines Datenbanksystems MySQL installieren Crashkurs (My)SQL Die MySQL C - API MySQL und C mit CGI Funktionsbersicht Datentypenbersicht der C API

q r r r

q r r r r r r r r r r r r r

q r r r r r r r

q r

29. Wie geht's jetzt weiter? 29.1. Wie geht's jetzt weiter? Anhang A. Rangfolge der Operatoren B. ASCII-Code-Tabelle C. Reservierte Schlsselwrter in C D. Standardheader-Dateien der ANSI C Bibliothek

q r r r r

Xoops2 RC3

Kapitel 1: Einstieg in CUm zu verstehen, warum in C ein Standard eingefhrt wurde, bedarf es ein wenig der Geschichte zu dieser Sprache.

1.1. Historische EntwicklungC wurde 1972 von Dennis Ritchie erfunden, wobei "erfunden" nicht ganz der richtige Ausdruck ist. C wurde aufgrund einiger Einschrnkungen der Vorgngersprache B implementiert und hauptschlich fr das Betriebssystem UNIX entwickelt. Denn vorher war UNIX vollstndig in Assembler programmiert. Als die ersten frei erhltlichen Compiler fr C erschienen, war der Siegeszug nicht mehr aufzuhalten. C wurde im Zusammenhang mit UNIX zur erfolgreichsten Sprache berhaupt. C wurde aber nicht entwickelt, um Software zu schreiben, sondern fr Programmierer, die Compiler entwickelten. Und genau da lag das Problem. Jeder Compiler-Hersteller kochte sein eigenes Sppchen und erweiterte die Programmiersprache um einige Funktionen oder lie die eine oder andere bestehende wegfallen. Mit der Zeit entstanden immer mehr unterschiedliche C-Dialekte, und eine Portierung von einem zum anderen System kam dem Neuschreiben eines Programms gleich.

1.2. Der ANSI C StandardSchlielich hatte sich eine Gruppe von Compiler-, Hardware- und SoftwareEntwicklern zusammengefunden, mit der Absicht, das Problem der Vielfalt der Sprachendialekte zu beheben. Die so entstandene Vereinigung nannte sich "A-merican National Standard Institute" (kurz ANSI). Es wurde ein Entwurf fr einen gemeinsamen Standard und dessen Einhaltung entwickelt. 1989 war es dann endlich soweit: Der Entwurf wurde vorgelegt und auch von der "International Standards Organization" (ISO) bernommen. In der Kurzform hie er C89-Standard. Mittlerweile ist der C99-Standard aktuell, der 1999 festgelegt wurde. Wobei ich hier anmerken muss, dass der echte ANSI C99-Standard bei noch keinem Compiler vollstndig implementiert ist. Die meisten Compiler basieren noch auf der im Jahre 1995 aktualisierten ISO/IEC-Norm 9899. In diesem Buch werden einige neue Datentypen, Funktionen und Makros, die mit dem ANSI C99-Standard eingefhrt wurden, in einem eigenen Kapitel kurz erwhnt.

1.3. Der Vorteil des ANSI C Standards

Der Hauptvorteil des ANSI C-Standards ist die Portabilitt von CProgrammen. Das bedeutet, wenn Sie ein Programm auf Plattform A geschrieben haben und bersetzen, lsst sich dieses Programm auch auf Plattform B bersetzen. Natrlich ist damit eine Neubersetzung des Quellcodes gemeint und nicht das ausfhrbare Programm. ANSI C-Compiler gibt es fr ber 40 Systeme, vom kleinsten 8-Bit-Computer bis hin zum Superrechner. Nicht portabel hingegen sind hardwarenahe bzw. betriebssystemspezifische Operationen. Wenn Sie zum Beispiel ein Programm fr UNIX/Linux schreiben, das die Grafikkarte anspricht, wird das Programm seine Ausfhrung auf anderen Systemen verweigern. Es gibt natrlich noch eine Reihe von weiteren Standards, die aber in diesem Buch nicht behandelt werden.

1.4. Vorteile und Nachteile der Programmiersprache CAuch wenn alles nur noch von C++ redet, gibt es noch eine Menge guter Grnde C zu lernen. Hier einige davon: Wer unter Linux/UNIX programmieren will oder muss, kommt ohnehin nicht um C herum. Das Betriebssystem ist zum grten Teil in C implementiert. C bietet die Konstrukte hherer Programmiersprachen. Beherrschen Sie C, dann ist es nicht mehr schwer, andere Programmiersprachen wie z.B. C++ oder Java zu erlernen. Hardwarenahe Programmierung wird zumeist in C ausgefhrt. Einfache Portierbarkeit der Programme auf andere Systeme. C++ ist die Erweiterung zu C. Somit kann fast alles hier Gelernte spter in C++ wiederverwendet werden. In C lassen sich Programme schreiben, die schnell in der Ausfhrung sind und wenig Ressourcen bentigen.

q

q

q

q

q

q

Natrlich gibt es auch einige Nachteile der Programmiersprache C: Eine allzu groe Freiheit beim Kodieren kann dazu fhren, dass schwer lesbarer Code geschrieben wird. Als Anfnger haben Sie bereits direkten Zugriff auf die Hardware und knnen somit vieles durcheinander bringen, wenn Sie nicht wissen, was Sie genau tun. Fehler, die bei anderen Sprachen bei Compilerlauf abgeschaltet werden, bergen die Gefahr, nicht gefunden zu werden. Meist treten solche Fehler erst dann auf, wenn das Programm bereits freigegeben wurde.

q

q

q

Es soll jedoch nicht unerwhnt bleiben, dass immer noch die meisten Programme in C geschrieben sind. Wenn solche Programme den Bedrfnissen einer Anwendergruppe angepasst oder allgemein verbessert werden mssen, sind gute C-Kenntnisse von Vorteil. Es stellt sich doch immer wieder heraus, dass viele (C-) Programmierer hauptschlich damit beschftigt sind, Fehler (Speicherlecks, Pufferberlufe usw.) auszubgeln.

1.5. C in diesem BuchIm Rahmen dieses Buchs werde ich mich nicht ausschlielich mit ANSI C befassen. In manchen Kapiteln ist das einfach nicht mglich. Aber ich werde die Programme - sofern mglich - so schreiben, dass diese auf den gngigen Betriebssystemen wie Windows, MS-DOS unter einer Win32-Konsole (besser bekannt als MS-DOS-Eingabeaufforderung) oder Linuxartigen Systemen ausfhrbar sind. In solchen Fllen weise ich am Anfang eines nicht ANSI CStandard entsprechenden Kapitels gesondert darauf hin.

Weiter mit Kapitel 2: Was bentige ich zu C

Xoops2 RC3

Kapitel 2: Was bentige ich zu CLeider ist aller Anfang schwer und erfordert Geduld. Bis Sie anfangen knnen C zu lernen, werden noch ein paar Dinge bentigt. Im Normalfall kostet sie aber kein Geld.

2.1. TexteditorZuerst bentigen Sie einen beliebigen ASCII-Texteditor. Und davon gibt es ungefhr so viele wie Sand am Meer, egal fr welches System. Ob jetzt Emacs fr Unix oder unter MS-DOS der Dinosaurier Edit verwendet wird, bleibt einem selbst berlassen. Ich empfehle einen Editor zu verwenden, der in der Lage ist, die Syntax von C farbig hervorzuheben. Dies erhht die bersichtlichkeit des Programms enorm.

2.2. CompilerWenn der Quellcode mit dem Editor geschrieben und abgespeichert wurde, bentigen Sie als Nchstes einen Compiler. Dieser macht aus einer Quelldatei eine Objektdatei (Maschinencodedatei). Auf die genauen Arbeitsschritte eines Compilers wird noch im Verlauf des Buchs eingegangen. Mittlerweile sind eine Menge Compiler kostenlos verfgbar. Viele davon lassen sich aus dem Internet herunterladen - und das fr alle gngigen Betriebssysteme. Im Unterschied zu Microsoft-Betriebssystemen wird bei der Installation von Linux der GNU-GCC Compiler normalerweise standardmig mitinstalliert.

HinweisDamit Sie sich nicht mit der Installation und Ausfhrung eines Compilers herumrgern mssen, habe ich speziell fr Sie, als Leser dieses Buchs, einige Dokumentationen geschrieben. Darin finden Sie Informationen zu vielen gngigen Compilern und Entwicklungsumgebungen auf den verschiedensten Systemen, die Sie bentigen, um mit dem Programmieren anzufangen. Sie finden Sie unter der Webadresse http://www.pronix.de/.

2.3. All-in-one - Die Entwicklungsumgebung

Immer beliebter werden so genannte Entwicklungsumgebungen. Wie der Name schon sagt, befindet sich alles, was Sie zum Programmieren bentigen, in einem Fenster. Es muss nicht mehr mhevoll von einem zum anderem Fenster geklickt werden, und Sie verlieren bei umfangreicheren Projekten nicht die bersicht. Natrlich befindet sich in einer Entwicklungsumgebung mehr als nur der Compiler und ein ASCII-Texteditor. Weitere Hilfsprogramme, die Sie in einer solchen Umgebung typischerweise finden, sind: ASCII-Texteditor Compiler Projektverwaltung Debugger Profiler Versionskontrolle

q q q q q q

Solche Programm-Pakete haben aber meistens auch ihren Preis. Produkte von Borland und Microsoft kosten ab 100 Euro in der Standardversion bis zu ein paar tausend Euro. Als Anfnger reicht es vllig aus, sich zunchst einen berblick mithilfe der kostenlos erhltlichen Compiler zu verschaffen. Natrlich ist hier anzumerken, dass es mittlerweile auch einige kostenlose Varianten von Entwicklungsumgebungen gibt. Besonders zu erwhnen ist dabei die Bloodshed Dev-C++-Entwicklungsumgebung, die fr MicrosoftSysteme erhltlich ist. Fr Linux existieren noch viel mehr gute Mglichkeiten, die keinen Eurocent kosten. Mehr zu den Bezugsquellen aller hier genannten und nicht genannten Compiler oder Entwicklungsumgebungen finden Sie, wie schon erwhnt, auf der Webseite http://www.pronix.de/Einstieg/.

2.4. Welcher Compiler und welches BetriebssystemWie bereits erwhnt, behandelt dieses Buch vorwiegend den ANSI CStandard und ist somit nicht abhngig von einem Compiler bzw. von dem Betriebssystem. Alle Listings in diesem Buch wurden auf mehreren gngigen Systemen und Compilern getestet. Natrlich ist es dennoch nicht auszuschlieen, dass es in Einzelfllen zu Fehlermeldungen kommen kann. In solch einem Fall wrde ich mich ber eine Mail von Ihnen freuen, damit dieses Problem bei der nchsten Auflage des Buchs beseitigt werden kann.

HinweisOb bereits Fehler bemerkt oder einige zustzliche Anmerkungen zu dem einem oder anderen Kapitel gemacht wurden, knnen Sie ebenfalls unter http://www.pronix/ nachlesen.

Weiter mit Kapitel 3: Das erste Programm

Xoops2 RC3

Kapitel 3: Das erste Programm

Ziel von Kapitel 3 ist es, sich einen ersten berblick ber dem Aufbau eines Programms zu verschaffen. Auerdem soll das Programm ausfhrbar gemacht, also bersetzt werden. Voraussetzung fr dieses Kapitel ist, dass bereits ein Compiler installiert wurde.

3.1. Der beste LernerfolgVielleicht haben Sie in diesem Buch schon ein wenig geblttert und sich die hinteren Kapitel angesehen. Wenn Sie gerade dabei sind, C zu lernen oder auch C Ihre erste Programmiersprache ist, drfte vieles auf den hinteren Seiten ein wenig kryptisch auf Sie wirken. Als Vergleich knnte ich jetzt eine beliebige Fremdsprache nehmen, die Sie gerade lernen wollen. Wenn Sie dabei die hinteren Kapitel ansehen, wird es Ihnen genauso gehen wie mit diesem Buch, Sie werden mit den Fremdwrtern auch noch nichts anfangen knnen. Den besten Lernerfolg erzielen Sie also, indem Sie das Buch von vorn nach hinten durcharbeiten. Wer C wirklich lernen will, sollte die Programme auch in der Praxis ausfhren. Ideal wre es natrlich, wenn Sie die Beispiele abtippen und ein wenig damit experimentieren, eventuell sogar mit Absicht Fehler einbauen und sich die Meldungen des Compilers ansehen, mit dem Ziel, mglichst viel daraus zu lernen. Erhoffen Sie sich, dieses Buch in wenigen Tagen durchgearbeitet zu haben und dann ein Profi zu sein, werden Sie schnell enttuscht sein. Programmieren zu lernen, dauert ein wenig lnger. Wenn Sie aber Geduld haben und immer am Ball bleiben, ist der Grundstein einer Programmiererkarriere gelegt. Das "Programmieren lernen" beruht wie vieles im Leben auf dem Prinzip "Versuch und Irrtum".

3.2. Hallo Welt in CObligatorisch ist es, mit dem berhmten "Hallo Welt"-Programm in C zu beginnen. Ziel dieses Programms ist es, die Textfolge "Hallo Welt" auf dem Bildschirm auszugeben. Tippen Sie im Texteditor (bzw. der Entwicklungsumgebung) folgendes Programm ein: #include int main() { printf("Hallo Welt\n"); return 0; } Zunchst wird das Programm in einem Verzeichnis, wo immer das Programm zur Ausfhrung gebracht werden soll, mit der Endung - auch Extension genannt - "*.c" abgespeichert (wobei "*" fr den beliebigen Namen des Programms steht). Jetzt mssen Sie das Programm bersetzen (kompilieren). Dieser Vorgang kann von Compiler zu Compiler verschieden ablaufen. Bei einer Entwicklungsumgebung muss dabei hufig nur der Button "Compile" oder "Kompilieren" angeklickt werden. In einer Konsole wird das Programm mit der Kommandozeile bersetzt.

TippWird das Programm in einer Entwicklungsumgebung unter Windows bersetzt, sollten Sie vor der Zeile return 0; immer die Funktion getchar(); schreiben, damit das Programm kurz anhlt und sich nicht gleich wieder beendet. Damit wartet das Programm, bis die ENTER-Taste bettigt wurde, bevor es sich beendet.

HinweisAnleitungen, wie Sie ein Listing mit einem bestimmten Compiler bersetzen knnen, habe ich Ihnen unter der Webadresse http://www.pronix.de/ bereitgestellt. Als Ergebnis findet sich im Verzeichnis ein ausfhrbares Programm namens "hallo" bzw. "hallo.exe" (sollten Sie das Programm "hallo.c" genannt haben). Diese Datei kann jetzt wie jede andere ausfhrbare Datei in der Kommandozeile gestartet werden. Bei Entwicklungsumgebungen drfte meistens ein Klick auf "Ausfhren" bzw. "Run" reichen. Wenn die Textfolge "Hallo Welt" auf dem Bildschirm ausgegeben wird, ist es geschafft. Sie haben das erste Programm geschrieben und erfolgreich bersetzt!

Abbildung 3.1: "Hallo Welt" in einem Konsolenfenster unter MS-DOS

Abbildung 3.2: Programm "Hallo Welt" in einer Konsole unter Linux

HinweisSollten Sie das Programm unter Linux nicht mit dem Programmnamen starten knnen, schreiben Sie einfach ein ./ vor den Programmaufruf. Beispielsweise: ./programmname

3.3. Analyse des ProgrammsJetzt soll das erste Programm in seine einzelnen Bestandteile zerlegt und Schritt fr Schritt durchgegangen werden. #include include ist kein direkter Bestandteil der Sprache C, sondern ein Befehl des Prprozessors. Der Prprozessor ist ein Teil des Compilers, der nicht das Programm bersetzt, sondern kontrollierend nicht bleibende nderungen im Programmtext vornimmt. Diese nderungen sind jedoch nur temporr. Prprozessorbefehle erkennen Sie am vorangestellten #-Zeichen. Kompilieren Sie das Programm noch einmal ohne #include , dann sollte eine Fehlermeldung folgen, wie z.B. die folgende: Error. function 'printf' should have a prototype. printf() kommt doch im Programm vor? Richtig. printf() ist eine (Standard-) Funktion, die in #include deklariert ist. include-Dateien nennt man auch Headerdateien. Suchen Sie das Verzeichnis INCLUDE auf Ihrem System (unter Linux ist das typischerweise /USR/INCLUDE oder /USR/BIN/INCLUDE und bei MS Windows z.B. C:\Name_des_Compilers\INCLUDE), und Sie werden noch viele andere Headerdateien darin entdecken, die spter noch Verwendung finden. Die Abkrzung stdio steht fr Standard-I/O, also Standard-Ein- und Ausgabe. Es wird noch fters auf die Headerdateien eingegangen, die ohnehin in jedem Programm bentigt werden. Spter werden Sie auch eigene Headerdateien entwerfen und im Programm einbinden. Weiter zur Programmausfhrung: int main() Hier beginnt das Hauptprogramm. Eine main-Funktion wird immer bentigt damit der Compiler wei, wo er beginnen muss, dass Programm zu bersetzen. Auch wenn spter mehrere Module (Funktionen), also mehrere QuellcodeDateien, kompiliert werden (zu einer ausfhrbaren Datei binden), bentigen Sie immer eine main-Funktion. main heit auf Deutsch so viel wie Hauptfunktion. int steht fr eine Dezimalzahl. Im Fall einer Funktion bedeutet dies, dass diese einen Rckgabewert hat, vom Typ int. In diesem Programm bekommt die mainFunktion den Rckgabewert 0 durch den Aufruf: return 0; Was bedeutet: Das Programm wurde ordnungsgem beendet. Es wird also mit return hier der Funktion main der Wert 0 zurckgegeben. Genaueres dazu in einem spteren Kapitel. Weiter mit: { printf("....."); } Zwischen den geschweiften Klammern steht der Anweisungsblock. Das heit, in diesem Block befinden sich alle Anweisungen, die die Funktion int main() auszufhren hat. Natrlich knnen innerhalb eines Anweisungsblocks weitere Anweisungsblcke verwendet werden. Das hrt sich komplizierter an als es ist. Darauf wird spter noch eingegangen.

MerkeGeschweifte Klammern fassen Anweisungen zu einem Block zusammen. Und was geschieht in diesem Anweisungsblock: printf("Hallo Welt\n"); printf() ist eine Funktion, die in #include deklariert ist, wie bereits erwhnt wurde. Deswegen kann der Compiler, wenn Sie die Headerdatei #include nicht im Programm angegeben haben, nichts mit printf() anfangen. Mit printf() kann eine beliebige Stringkonstante formatiert auf dem Bildschirm ausgegeben werden. Die Stringkonstante, in diesem Fall "Hallo Welt", die ausgegeben wird, steht immer zwischen zwei Hochkommata ("Stringkonstante"). Nicht erlaubt ist es, eine Stringkonstante ber das Zeilenende fortzusetzen, wie etwa im folgenden Beispiel: printf("Dies ist in C nicht erlaubt"); Es gibt aber eine Ausnahme dieser Regel: indem Sie ein \ (Backslash) setzen. Hierzu ein Beispiel: printf("Hier ist die Ausnahme der Regel \ dies hier ist erlaubt, dank Backslash"); Sie sollten aber dabei beachten, dass alle Leerzeichen nach dem Backslash in der nchsten Zeile ebenfalls bei der Ausgabe bercksichtigt werden. Das Zeichen '\n' in der Funktion von printf() bedeutet newline und erzeugt auf dem Bildschirm einen Zeilenvorschub, wie er mit der Tastatur durch die Taste ENTER ausgelst wird. Es gibt noch mehr so genannte Escape-Sequenzen, die mit einem Backslash beginnen. Jetzt zum Semikolon (;): Es wird hauptschlich dazu verwendet, das Ende einer Anweisung anzuzeigen. Der Compiler wei dann, hier ist das Ende der Anweisung von printf() und fhrt nach der Abarbeitung der Anweisung mit der nchsten Zeile bzw. Anweisung fort.

MerkeAnweisungen, denen kein Anweisungsblock folgt, werden mit einem Semikolon abgeschlossen.

Weiter mit Kapitel 4: Steuerzeichen

Xoops2 RC3

Kapitel 4: SteuerzeichenIn (ANSI) C werden zwei Zeichenstze unterschieden. Zum einen der Zeichensatz, der bei Quelldateien verwendet werden darf, und zum anderen ein Ausfhrungszeichensatz, der beim Ausfhren des Programms interpretiert wird.

4.1. Basic-ZeichensatzFolgende Zeichen stehen Ihnen zum Programmieren in der Sprache C zur Verfgung (dies gilt auch fr den Ausfhrungszeichensatz) Die zehn Dezimalziffern: 1234567890 Die Buchstaben des englischen Alphabets: ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz Die folgenden Grafiksymbole: !"%&/()[]{}\?= '#+*~-_.:;,|^ Die Whitespace-Zeichen: Leerzeichen, Tabulatorzeichen, neue Zeile, neue Seite

q

q

q

q

Auf manchen PCs (nicht ANSI C) kann auch das Dollarzeichen ($) verwendet werden.

4.2. Ausfhrungszeichensatz (Steuerzeichen)

Beim Ausfhrungszeichensatz kommen zu den oben aufgefhrten Zeichen noch weitere hinzu, die in diesem Abschnitt beschrieben werden. Zuvor soll ein weiteres Programm analysiert werden. Dazu wird genauso vorgegangen, wie schon in Kapitel 3: das Listing in einem Texteditor abtippen, abspeichern und anschlieend mit dem Compiler bersetzen. Hier das Programmbeispiel zur Demonstration: #include int main() { printf("Ein akkustisches Signal mit : (\\a)\a"); printf("\nEin Backspace mit : (\\b) | \bx\n"); printf("Ein Zeilenvorschub mit : (\\t) |\tx"); printf("\n\tC\n\ti\n\ts\n\tt\n\ttoll\n"); printf("\t u\n\t n\n\t d\n"); printf("\t macht Spass\n"); return 0; } Nach dem bersetzen und Starten des Programms sieht die Ausgabe folgendermaen aus:

Abbildung 4.1: Ausgabe des Programms unter einer MS-DOS-Konsole Hier knnen Sie die Auswirkungen von Steuerzeichen, auch EscapeSequenzen genannt, sehen. Diese Zeichen sind nicht druckbare Zeichen in so genannten char-Konstanten. Und wie der Name (Steuerzeichen) besagt und das Programm soeben gezeigt hat, knnen Sie damit die Ausgabe auf dem Bildschirm beeinflussen. Steuerzeichen beginnen immer mit einem Backslash (\) und einer folgenden Konstante. Der Compiler behandelt diese Steuerzeichen wie ein einziges Zeichen. Mgliche Steuerzeichen und ihre Bedeutung knnen aus der folgenden Tabelle entnommen werden:

Steuerzeichen \a \b

Bedeutung BEL (bell) - akkustisches Warnsignal BS (backspace) - setzt Cursor um eine Position nach links FF(formfeed) - ein Seitenvorschub wird ausgelst. Wird hauptschlich bei Programmen verwendet, mit denen Sie etwas ausdrucken knnen. NL (newline) - Cursor geht zum Anfang der nchsten Zeile CR (carriage return) Cursor springt zum Anfang der aktuellen Zeile HT (horizontal tab) Zeilenvorschub zur nchsten horizontalen Tabulatorposition (meistens acht Leerzeichen weiter) VT (vertical tab) - Cursor springt zur nchsten vertikalen Tabulatorposition " wird ausgegeben ' wird ausgegeben ? wird ausgegeben \ wird ausgegeben NULL (ist die Endmarkierung eines Strings) Ausgabe eines Oktalwerts (z.B. = ESCAPE-Zeichen) Ausgabe eines Hexdezimalwerts

\f

\n

\r

\t

\v

\" \' \? \ \0

\nnn \xhh

Tabelle 4.1: Steuerzeichen (Escape-Sequenzen) in Zeichenkonstanten Hierzu noch ein Listing, wie Sie auer mit dem Newline-Zeichen ( ) noch einen Zeilenvorschub auslsen knnten: #include int main() { printf("Darstellung von Newline \n \n"); printf("Mgliche Ausfhrung von Newline\n"); printf("Mit hexadezimaler Angabe : \xa \xa"); printf("Mit oktaler Wertangabe : \012 \012"); printf("Mit dezimaler Angabe : 10 %c",10); printf("Hallo Ich bin nicht mehr lesbar\n"); return 0; } Dass auch ein Zeilenvorschub bei \xa , \012 und 10 vorgenommen wurde, liegt daran, dass alle diese Zeichen intern den Wert 10 darstellen. Und wenn Sie sich die ASCII-Code-Tabelle (im Anhang) ansehen, knnen Sie erkennen, dass alle diese Werte in derselben Zeile stehen und das newline-Zeichen darstellen. Dass bei der letzten printf()-Anweisung der Text nur bis "Hallo" ausgegeben wird, liegt am Steuerzeichen '\0', womit eine Stringkonstante terminiert (abgeschlossen) wird. Dazu spter mehr.

Weiter mit Kapitel 5: Kommentare in C

Xoops2 RC3

Kapitel 5: Kommentare in CIn den weiteren Programmen, die jetzt folgen, wird es hufiger vorkommen, dass der Quellcode dokumentiert ist, genauer gesagt, Kommentare eingefgt sind. Diese Kommentare werden vom Compiler ignoriert. Wie Sie Ihren Quellcode dokumentieren, bleibt letztlich Ihnen selbst berlassen. Sie knnen beliebig viel, alles oder auch gar nichts dokumentieren.

5.1. Wann sind Kommentare sinnvoll?

Eigentlich immer. Wenn Sie vorhaben sollten, ein greres Projekt zu verwirklichen, kann sich dies ber mehrere Monate hinausziehen. Um nicht immer wieder das Stckchen Quellcode von neuem verstehen zu mssen, das Sie vor einem Monat geschrieben haben, knnen Sie sich dies mit ein paar Kommentaren erleichtern. In einer Gruppe ist es ohnehin unerlsslich, mit Kommentaren zu arbeiten, damit jeder den Code des anderen besser versteht und nachvollziehen kann. Hierzu ein Beispiel: #include int main () //Beginn des Hauptprogramms { int i = 10; //Variable int mit dem Namen i und Wert 10 printf("%d",i);//gibt die Zahl 10 aus printf("\n"); //springt eine Zeile weiter printf("10"); //gibt den String "10" aus return 0; /* Hier sehen Sie noch eine 2. Mglichkeit, Kommentare einzufgen. Dieser Kommentar wird mit einem Slash-Sternchen erffnet und mit einem Sternchen-Slash wieder beendet. Alles dazwischen wird vom Compiler ignoriert */

} Kommentare sind nicht schwer zu verstehen. Sie werden einfach beginnend mit zwei // oder zwischen /* Hier steht der Kommentar */ geschrieben. Hufig werden Kommentare vor Funktionen geschrieben. Ein guter Stil knnte so aussehen: /****************************** * * * Beschreibung der Funktion * * * ******************************/ In den Kommentaren knnen Sie beliebige Zeichen verwenden, also auch deutsche Umlaute oder das Dollarzeichen.

5.2. Welche Kommentar-Schreibweise: // oder /* */

Da Sie zwei Mglichkeiten haben, Kommentare zum Programm hinzuzufgen, stellt sich die Frage, welche Methode von den beiden die bessere ist. Die Schreibweise //Kommentar wurde erst im Oktober 1999 zum C99 Standard hinzugefgt. Dieser Stil war zuvor nur fr C++ erlaubt und im C89 Standard nicht zugelassen. Problematisch knnte dies werden, wenn Sie einen etwas lteren Compiler verwenden. Er wrde einen solchen Kommentar als Fehler bemngeln und sich weigern, das Programm zu bersetzen. Etwas muss auerdem noch beachtet werden, wenn die Schreibweise // verwendet wird, etwa am folgenden Listing: #include int main() { //das Programm befindet sich im Pfad C:\programme\ printf("Hallo Welt\n"); return 0; } "Hallo Welt" wird niemals ausgegeben. Der Grund dafr ist, dass die Zeile mit dem Kommentar mit einem Backslash endet. Also achten Sie darauf, denn die Suche nach diesem Fehler knnte unntig Zeit kosten.

Weiter mit Kapitel 6: Formatiertes einlesen mit scanf

Xoops2 RC3

Kapitel 6: Formatiertes einlesen mit scanfJetzt knnen Sie zwar schon Stringkonstanten auf dem Bildschirm ausgeben, aber irgendwie fehlt doch noch etwas zur Eingabe (Input) um mehr aus den Programmen zu machen. Also auf zum Input-Befehl Namens scanf(), das Gegenstck zu printf().

6.1. Der Adressoperator &

HinweisZuerst noch einen Hinweis fr die absoluten Anfnger in der Programmiersprache C. Einiges wird Ihnen in diesem Kapitel ein wenig unklar sein. Aber wenn Sie das Buch komplett durchgelesen haben, wird sich so einiges von selber klren. Aber Sie werden Erleuchtung finden, versprochen! Hierzu zunchst die Syntax der Funktion: #include //bentigter include fr diesen Befehl

int scanf(const char *format, ...); Mit der Funktion scanf() knnen Werte unterschiedlicher Datentypen formatiert eingelesen werden. Eingelesen wird dabei von der Standardeingabe (stdin). Mit Standardeingabe ist normalerweise die Tastatur gemeint. Hierzu ein Beispiel mit scanf (): #include int main () { int i; /* Ein ganzzahliger Datentyp */ printf("Bitte geben Sie eine Zahl ein : "); scanf("%d",&i); /* Wartet auf die Eingabe */ printf("Die Zahl die Sie eingegeben haben war %d\n",i); return 0; } Wenn das Programm korrekt abluft, wird nach einer Zahl gefragt. Jetzt gibt der Anwender eine Zahl ein und drckt ENTER. Anschlieend gibt das Programm die Zahl, die eingegeben wurde, auf dem Bildschirm aus und wird beendet.

Abbildung 6.1: Programm mit der Funktion scanf() bei der Ausfhrung Bildlich knnen Sie sich diesen Vorgang folgendermaen vorstellen:

Abbildung 6.2: Programm Ein- Ausgabe mit scanf() und printf() scanf() ist hnlich aufgebaut wie printf(). Wie bei printf() werden hier zwei Klammern und zwei Hochkommata verwendet. Es wird also formatiert eingelesen. Das Formatzeichen %d steht fr die formatierte Eingabe einer dezimalen Zahl. Was aber bedeutet hier das Zeichen "&"?

6.2. Probleme und deren Behandlung mit scanf()

Den Adressoperator "&" jetzt schon besser zu verstehen kann nicht schaden. Spter wenn das Thema der Pointer (Zeiger) besprochen wird, kann dieses Vorverstndnis von Nutzen sein. Sollte Ihnen dieser Abschnitt ein wenig fremd anmuten, ist das kein Grund zur Sorge. Das Thema Pointer wird spter noch ausfhrlich behandelt. Eine Variable kann in die vier folgenden Einzelteile zerlegt werden: Datentyp Name der Variable Speicheradresse der Variable Der Wert der Variable

q q q q

Im Programmbeispiel oben heit das konkret, der Datentyp ist int, der Name ist i, die Adresse wird whrend der Laufzeit zugewiesen, darauf haben Sie keinen Einfluss. Die Speicheradresse sei hier z.B. 0000:123A. Der Wert ist der, den Sie mit scanf() noch eingeben mussten. Wurde jetzt z.B. 5 eingegeben, ist dieser Speicherplatz wie folgt belegt:

Abbildung 6.3: Stellt eine Variable im Speicher da. Das &-Zeichen ist nichts anderes als der Adressoperator. Dies bedeutet hier, der Variablen i vom Typ int mit der Speicheradresse 0000:123A wird der Wert 5 zugewiesen. Oder einfacher: Verschicken Sie eine E-Mail an jemanden, ohne die EMail-Adresse anzugeben?!

AchtungEin hufiger Fehler, den Anfnger machen, ist das Weglassen des Adressoperators &. Was im Falle zum Einlesen eines Strings (Zeichenkette) richtig wre, ist bei anderen Datentypen wie Dezimal- oder Gleitpunktzahlen wieder falsch: /* FALSCH, da Adressoperator & fehlt */ scanf("%d",zahl); /* Richtig, eine Zeichenkette bentigt keinen Adressoperator */ scanf("%s",string); Auch wenn scanf() das Gegenstck zu printf() ist und sich beide in ihrer Schreibweise hneln, sollten Sie nicht auf die Idee kommen, Folgendes zu schreiben: /* FALSCH */ scanf("Bitte geben sie eine Zahl ein: %d\n",&zahl); Das funktioniert deshalb nicht, weil scanf() fr die Standardeingabe programmiert ist und printf() fr die Standardausgabe. Wobei die Standardausgabe auf der Kommandozeile auch umgeleitet werden kann. Aber dazu spter mehr. Ein hufiges Problem, das auftritt, wenn Sie scanf() fr die Eingabe verwenden, ist die Pufferung. Diese ist je nach System und Anwendung, Zeilen- oder Vollgepuffert. Dies gilt wiederum nicht fr die Standardfehlerausgabe (stderr), die laut ANSI C, niemals vollgepuffert sein darf. Bevor ich weiter erklre, folgendes Programm zum testen: #include int main() { char a,b,c; printf("1. Buchstabe : "); scanf("%c",&a); printf("2. Buchstabe : "); scanf("%c",&b); printf("3. Buchstabe : "); scanf("%c",&c); printf("Sie gaben ein : %c %c %c ",a,b,c); return 0; } Folgendes knnte nun vom Programm auf den Bildschirm ausgegeben werden:

Abbildung 6.4: Das Problem mit der Funktion scanf()-Hier unter Linux Was ist hier passiert? Warum wird der zweite Buchstabe immer bersprungen? Wie gesagt das Problem liegt hier an der Pufferung. Und in C gibt es keinen Befehl (wie etwa chomp bei Perl), um das letzte Zeichen zu entfernen. In diesem Beispiel wurde als erster Buchstabe "a" eingegeben und ENTER gedrckt. Und dieses ENTER (ASCIICode = 10 = \n = newline) befindet sich immer noch im Puffer der Standardeingabe und wird automatisch fr das zweite Zeichen verwendet. Was knnen Sie dagegen tun? Hierzu ein paar Mglichkeiten, die allerdings auch systemabhngig sind: 6.2.1 Mglichkeit 1 Sie benutzen die Funktion fflush() zum entleeren des Tastaturpuffers. Was aber mglicherweise nicht auf jedem Betriebssystem (speziell nicht unter Linux) so funktioniert: #include int main() { char a,b,c; printf("1. Buchstabe : "); scanf("%c",&a); fflush(stdin); printf("2. Buchstabe : "); scanf("%c",&b); fflush(stdin); printf("3. Buchstabe : "); scanf("%c",&c); printf("Sie gaben ein : %c %c %c ",a,b,c); return 0; } 6.2.2 Mglichkeit 2 Sie benutzten eine do while-Schleife und ziehen das newline-Zeichen aus dem Puffer heraus: #include int main() { char a,b,c; printf("1. Buchstabe : "); do {scanf("%c",&a);} while ( getchar() != '\n' ); printf("2. Buchstabe : "); do {scanf("%c",&b);} while ( getchar() != '\n' ); printf("3. Buchstabe : "); do {scanf("%c",&c);} while ( getchar() != '\n' ); printf("%c %c %c\n",a,b,c); return 0; } Mehr zur do while Schleife finden Sie im entsprechenden Kapitel. Dieses Beispiel lsst sich natrlich auch mir einer while()-Schleife als Makro verpackt realisieren: #define Fflush(int_keyboard_buffer)\ while(( (int_keyboard_buffer) = getchar()) != '\n') Mehr zu diesem Beispiel erfahren Sie im Kapitel der Prprozessor-Direktiven. 6.2.3 Mglichkeit 3 Sie verwenden scanf() erst gar nicht und greifen auf eine der vielen anderen Standardeingaben-Funktionen zurck. Ideal wre es beispielsweise die Funktion fgets() zum Einlesen zu verwenden und diese Eingabe mit der Funktion sscanf() in ein entsprechendes Format zu konvertieren.

HinweisIm Laufe dieses Buches wird noch des fteren die Funktion scanf() verwendet. Sollte etwas nicht so funktionieren, wie es sollte, beziehen Sie sich auf dieses Kapitel.

AchtungDie Funktion scanf() ist nicht gegen einen Pufferberlauf (Buffer Overflow) geschtzt und somit unsicher, d.h. sie knnte fr einen Hack des Programms durch eine andere Person missbraucht werden. Damit ist gemeint, dass die Funktion nicht die Anzahl der eingegebenen Zeichen berprft und es damit zu Fehlern kommen kann, bzw. ein Fehlverhalten von auen provoziert werden kann.

6.3. berprfen auf das richtige Format

Um sicher zu gehen, dass der Benutzer das Richtige eingegeben hat, knnen Sie den Rckgabewert von scanf() berprfen: #include int main() { char a; int b,check; printf("Bitte Eingabe machen (Zeichen/Zahl): "); check=scanf("%c %d",&a,&b); printf("Check = %d \n",check); return 0; } Der Rckgabewert von scanf() ist immer die Anzahl der erfolgreich gelesenen Werte. In diesem Beispiel erwartet scanf() die Eingabe eines Zeichens (%c) und einer Dezimalzahl (%d). Wenn die Eingabe richtig gemacht wurde, sollte die folgende printf () Anweisung den Wert "2" ausgeben. Mit einer kleinen berprfung knnen Sie das Programm verbessern, um ein undefiniertes Verhalten fr die Weiterarbeit zu verhindern: #include int main() { int a,b,check; printf("Bitte zwei Zahlen eingeben: "); check=scanf("%d %d",&a,&b); fflush(stdin); /* Unter Linux entfernen */ //getchar() /* fr Linux */ /* Bei check istgleich 2 wahr die Eingabe richtig */ if(check==2) printf("Beide Zahlen richtig %d und %d\n",a,b); /* nicht richtig, also wahr die 2. Zahl falsch */ else if(check==1) { printf("Die 2.Zahl hat das falsche Format!!\n"); printf("Bitte Eingabe wiederholen: "); /* noch ein Versuch */ check=scanf("%d",&b); fflush(stdin); if(check) printf("Eingabe Ok. Ihre Zahlen %d %d\n",a,b); else printf("Leider nochmals falsch\n"); } else printf("Die Erste oder beide Eingaben waren falsch!\n"); return 0; } Bei fehlerfreier Ausfhrung liefert die scanf()-Funktion die Anzahl der Zeichen zurck, die erfolgreich gelesen, konvertiert und gespeichert wurden. Wenn die erste Eingabe von scanf() schon fehlerhaft ist, wird die zweite Eingabe gar nicht mehr beachtet. Daher gibt scanf() dann 0 zurck, da gar keine Zeichen gespeichert werden konnten.

Abbildung 6.5: Programm mit berprfung des Rckgabewertes von scanf()

6.4. Zusammenfassung scanf()Die Funktion scanf() liest zeichenweise eine folge von Eingabefelder ein. Fr jedes Eingabefeld muss eine Adresse vorhanden sein. Wobei das Eingabefeld, mit dem Datentyp der Adresse bereinstimmen muss. Bei Erfolg liefert scanf() die Anzahl der erfolgreich eingelesenen Felder zurck. Konnten keine Felder korrekt eingelesen werden, gibt scanf() als Rckgabewert 0 zurck. Folgende Zeichen werden bei scanf() als Eingabefelder akzeptiert: alle Zeichen bis zum nchsten Whitespace bis zu einer bestimmten Feldbreite von n-Zeichen alle Zeichen, bis zum ersten Zeichen, welches nicht mehr in entsprechendes Format konvertiert werden konnte.

q q q

HinweisEin Whitespace ist ein Leerzeichen, Tabulator oder eine Zeilenschaltungen.

Anmerkung fr den AnfngerNochmals eine Anmerkung fr die absoluten Neulinge in C. Sie wurden in diesem Kapitel teilweise mit Begriffen wie Variablen, Datentypen, Format, Formatanweisungen, Feldbreite usw. bombardiert, mit denen Sie zum grten Teil wohl noch nichts anfangen knnen. Denn Groteil dieser Begriffe werden Sie aber auf den nchsten Seiten noch genauer kennen lernen. Die Aufteilung der einzelnen Themen wurde bewusst in dieser Form verfasst. Wenn Sie dieses Buch durchgearbeitet haben, werden Sie kein Anfnger mehr sein und hin und wieder das eine oder andere Thema nachschlage wollen. Dann wird es Ihnen leichter fallen, Informationen zur Funktion scanf(), kompakt in einen oder zwei Kapiteln zu finden, anstatt im ganzen Buch verstreut danach suchen zu mssen.

Weiter mit Kapitel 7: Formatierte Ausgabe mit printf

Xoops2 RC3

Kapitel 7: Formatierte Ausgabe mit printfJetzt wurde schon des fteren die Funktion printf() zur formatierten Ausgabe verwendet, ohne bisher genauer darauf einzugehen. Zunchst die Syntax von printf(): #include int printf(const char *format,...); Der Rckgabewert von printf() ist die Anzahl der Zeichen, die ausgegeben werden (ohne das Terminierungszeichen ' '), oder im Fehlerfall EOF. folgendes Beispiel demonstriert dies: #include int main() { int zeichen; zeichen=printf("Hallo Welt"); printf(" enthaelt %d Zeichen\n",zeichen); return 0; }

//10 Zeichen

printf() bekommt mindestens einen Parameter, nmlich den Formatstring. Dieser Formatstring besteht wiederum aus einem Ausgabetext (Stringkonstante), der Nullterminiert ist ( ) und/oder einer Formatanweisung.

Abbildung 7.1: printf() in seine einzelnen Bestandteile zergliedert Bei dem Formatstring handelt es sich um einer Zeichenkette beliebiger Lnge. Zum Beispiel: printf("Ich bin der Formatstring in der printf-Anweisung");

AchtungWobei das mit der beliebigen Lnge nicht ganz stimmt. Auch mit printf() kann es einen Pufferberlauf geben, sollte der Text lnger sein als erlaubt. Ein Pufferberlauf (Buffer Overflow) wird in Hackerkreisen gerne verwendet, um an root-Rechte (Rechte des System Administrators) zu kommen. Bei mehr als 65535 Zeichen wrde printf(), laut C99 Standard, Probleme bekommen (bei dem C89 Standard sind es 32767 Zeichen). Die Funktion printf() wird bei der Ausfhrung von rechts nach links abgearbeitet. Dabei sucht die Funktion nach einem Ausgabetext (Stringkonstante) und Formatanweisungen. Diese Formatanweisung wird von printf() dann mit entsprechenden Parameter der variablen Liste ausgegeben. Formatanweisungen beginnen alle mit einem %Zeichen. Dahinter folgt ein Buchstabe, der den Datentyp des Formates angibt. %d steht z.B. fr eine Dezimalzahl. Die Formatanweisung lsst sich natrlich noch erweitert formatieren. Bevor die einzelnen und erweiterten Formatanweisungen besprochen werden, folgt erst einmal ein Kapitel, welches zeigt, was fr Datentypen Sie berhaupt zur Verfgung haben. Die Ausgabe von printf() muss brigens nicht ausschlielich auf dem Bildschirm erfolgen. Sie knnen die Standardausgabe (stdout) auch in eine Datei umleiten. #include int main() { printf("Diese Ausgabe soll in einer Textdatei stehen\n"); return 0; } bersetzten Sie dieses Programm wie gewohnt und starten es, indem Sie in einer Konsole Folgendes eingeben (als Programmname sei hier "out" gegeben): out > test.txt Jetzt befindet sich im aktuellen Verzeichnis eine Datei Namens "test.txt" mit dem Inhalt, den printf() normalerweise auf dem Bildschirm ausgegeben htte.

Weiter mit Kapitel 8: Datentypen und Variablen

Xoops2 RC3

Kapitel 8: Datentypen und Variablen

In diesem Kapitel erfahren Sie alles zu den einzelnen Datentypen in C, ohne die sich wohl kaum ein Programm realisieren lassen wrde. Zu den Grundlagen der C-Programmierung gehrt auch die Kenntnis der einzelnen Datentypen. Datentypen sind, wie der Name schon vermuten lsst, Arten von Variablen, in denen Sie Daten speichern knnen, um zu einem spteren Zeitpunkt wieder darauf zurckzugreifen. Diese Variablen bestehen aus zwei Teilen: dem Datentyp, der eine bestimmte Menge Arbeitsspeicher zugewiesen bekommt, und dem Namen der Variable, mit dem dieser Datentyp im Programm angesprochen werden kann.

8.1. Der Datentyp int (Integer)Der Datentyp int muss, gem ANSI C, mindestens eine Gre von zwei Byte aufweisen. Mit diesen zwei Bytes lsst sich ein Zahlenraum von -32768 bis +32767 beschreiben. Mit dem Datentyp int lassen sich nur Ganzzahlen darstellen. Die Abkrzung int steht fr Integer. Hier kommen Sie auch gleich in Berhrung mit betriebssystemspezifischen Eigenheiten. Auf 16-Bit-Systemen mag das eben Gesagte zutreffen. Dort ist ein Integer (int) auch wirklich zwei Bytes gro. Manch einer wird aber sagen: 16-BitSysteme sind doch schon bald Schnee von gestern und sind eigentlich nur noch fr MS-DOS und Windows 3.1 Compiler relevant. Es sollte aber bedacht werden, dass es noch andere Programmierplattformen neben Linux und MS-Windows gibt! Linux, Windows (ab Windows 95) und Macintosh sind alles schon Betriebssysteme auf 32-Bit-Basis. 32 Bit entsprechen vier Byte. Somit erstreckt sich der Zahlenraum auf 32-Bit-Systemen von -2147483648 bis +2147483647. Diese 32 Bit beziehen sich auf die WORD-Gre der CPU. Und die normale WORD-Gre von Pentium- und Athlon-Prozessoren betrgt zurzeit 32 Bit. In nicht mehr ferner Zukunft werden wohl aber 64 Bit-Prozessoren auf dem Massenmarkt erscheinen. Damit gibt es auf solchen Systemen (32 Bit) auch keinen Unterschied mehr zwischen der Gre des Datentyps int und des Datentyps long (Erklrung folgt gleich). Hierzu ein kurzer berblick ber den Datentyp int und seinen Wertebereich auf den verschiedenen Systemen: System ANSI C IBM PC MSDOS und Win3.1 Macintosh Metrowerks CW Win98/2000/ NT/XP Linux Name int int Gre 2 Byte 2 Byte Wertebereich Formatzeichen -32768 %d oder %i +32767 -32768 %d oder %i +32767 -2147483648 %d oder %i +2147483647 -2147483648 %d oder %i +2147483647 -2147483648 %d oder %i +2147483647

int

4 Byte

int int

4 Byte 4 Byte

Tabelle 8.1: Datentyp int auf verschiedenen Plattformen Wenn Sie sichergehen wollen, welchen Wertebereich der Datentyp int auf einem System hat, so kann dies mit folgendem Listing herausgefunden werden: #include #include

/* INT_MIN und INT_MAX */

int main() { printf("int Gre : %d Byte\n",sizeof(int)); printf("Wertebereich von %d bis %d\n",INT_MIN,INT_MAX); return 0; } Die Konstanten INT_MIN und INT_MAX sind in der Headerdatei mit den Werten deklariert, die der Datentyp int auf Ihrem System besitzt.

8.2. Variablen deklarierenBevor Sie Variablen verwenden knnen, mssen diese deklariert sein. Die Syntax einer solchen Deklaration sieht wie folgt aus: typ name; Der typ der Variablen gibt vor, wie viel Speicherplatz diese Variable auf dem System belegt. Der name ist der Bezeichner, mit dem Sie auf diese Variable im Programm zugreifen knnen. Dieser name muss innerhalb eines Anweisungsblocks eindeutig sein. Auerdem sollte dieser Name selbsterklrend gewhlt werden. Wie Sie Datentypen in der Praxis deklarieren und mit Werten initialisieren knnen, soll jetzt grundstzlich anhand des Datentyps int erlutert werden. Fr andere Datentypen, die noch behandelt werden, gilt dies entsprechend. Ein Listing dazu: #include int main() { int a; /*Deklaration*/ int b; int c; a=5; /*Initialisieren*/ b=100; c=12345; printf("Wert von int a=%d ,b=%d, c=%d\n",a,b,c); return 0; } Hier werden drei int-Variablen mit den Namen a, b und c deklariert. Die Auswahl der Namen bleibt dabei Ihnen berlassen. In kleinen Programmbeispielen ist die Verwendung so genannter sprechender Namen fr Variablen nicht unbedingt erforderlich, dennoch empfehle ich Ihnen aussagekrftige Namen (z.B. ZuFallsZahl, statt einfach nur z) zu verwenden. Damit behalten Sie bei greren Programmen den berblick. Hier bekommt a den Wert 5, b den Wert 100 und c den Wert 12345 zugewiesen. Die Zuweisung eines Werts wird das Initialisieren einer Variable genannt. Den Wert einer Variablen bergibt man mit dem =-Operator (wird auch Zuweisungsoperator genannt). Achtung: Um Irritationen zu vermeiden, soll der Unterschied der Begriffe "Deklaration" und "Definition" erwhnt werden. Hufig hat es den Anschein, als bedeuteten beide dasselbe. Dies trifft jedoch nicht zu. Erst wenn bei einer VariablenDeklaration eine Initialisierung vorgenommen wird, handelt es sich um eine Definition. Folgende Schreibweisen sind dabei erlaubt: int wert = 5; int wert1 = 10, wert2 = 20; /* wert=5 */ /* wert1=10 ,wert2=20 */

/* wert1=nicht initialisiert, wert2=33 */ int wert1, wert2=33; int wert1; int wert2=wert1=10;

/* wert1=10, wert2=10 */

Jetzt folgt die Beschreibung der Ausgabe mit printf(). printf("Der Wert von int a= "bis hierhin nichts Neues" %d "das Prozentzeichen ist ein Formatzeichen". Der Compiler sieht jetzt nach, um welches Format es sich dabei handelt. Im Beispiel ist es das d (fr dezimal). Sie knnen auch das Formatzeichen %i anstatt %d benutzen. Fr einige ist das leichter zu verstehen, da das i fr Integer steht. Hiermit wird also eine Ganzzahl (int) ausgegeben. Hinter dem Ende des Hochkommatas befindet sich jetzt der Variablen-Name a. Damit wird der Wert von int a an der Position ausgegeben, an der sich das Formatzeichen %d befindet. Gleiches geschieht mit den anderen beiden int-Werten fr b und c.

Abbildung 8.1: Der Ablauf der Funktion printf() Die Initialisierung dieser Werte kann aber auch noch anders bewerkstelligt werden: #include int main() { int a=5; int b=100, c=12345; printf("Wert von int a=%d ,b=%d, c=%d\n",a,b,c); return 0; } Wie Sie hier sehen, kann die Wertzuweisung schon whrend der Deklaration vorgenommen werden. Es knnen auch alle Werte auf einmal zugewiesen werden, wie bei int b und int c geschehen. Die Werte mssen mit einem Komma getrennt werden. Wenn eine Variable nicht mit einem Wert initialisiert wurde und Sie diese dennoch ausgeben, ist die Ausgabe des Werts undefiniert. Das heit, es ist nicht vorhersehbar, welcher Wert ausgegeben wird. 8.2.1 Erlaubte Bezeichner Mit dem Begriff "Bezeichner" werden Namen fr Variablen, Funktionen, Datentypen und Makros zusammengefasst. Damit Sie bei der Namensvergabe von Variablen oder (spter) Funktionen keine Probleme bekommen, mssen Sie bei deren Angabe folgende Regeln beachten: Ein Bezeichner darf aus einer Folge von Buchstaben, Dezimalziffern und Unterstrichen bestehen. Einige Beispiele: var8, _var, _666, var_fuer_100tmp, VAR, Var C unterscheidet zwischen Gro- und Kleinbuchstaben. Var, VAr, VAR, vAR, vaR, var Hierbei handelt es sich jeweils um verschiedene Bezeichner. Das erste Zeichen darf keine Dezimalzahl sein. Die Lnge des Bezeichners ist beliebig lang. Nach ANSI CStandard sind aber nur die ersten 31 Zeichen bedeutend. Obgleich viele Compiler auch zwischen mehr Zeichen unterscheiden knnen.

q

q

q q

Die reservierten Schlsselworte in C drfen logischerweise auch nicht als Bezeichner verwendet werden. Hier ein berblick der reservierten Schlsselwrter in C: auto break case char complex const continue default do double else enum extern float for goto if imaginary inline int long register restrict return short signed sizeof static struct switch typedef union unsigned void volatile while Die Schlsselworte, die hier fett dargestellt wurden, sind erst bei den neueren Compilern (C99) vorhanden. Aber es empfiehlt sich, diese dennoch nicht zu verwenden, falls sie bei Ihrem Compiler noch nicht implementiert sind.

8.3. C versus C++ bei der Deklaration von Variablen

C++ lsst sich grob als Erweiterung von C ansehen. Daher ist so manches, was in C ++ erlaubt ist, in C nicht erlaubt. In C muss die Deklaration der Variablen zu Beginn eines Anweisungsblocks geschrieben werden, bei C++ hingegen nicht. Hierzu ein kommentierter Quellcode: #include int main() { printf("Hallo Welt\n"); int i; /*Fehler in C, ok in C++*/ scanf("%d",&i); for(int x=0; x < i; x++) /*Fehler in C, ok in C++*/ { /*Ok in C und C++, da am Anfang von Anweisungsblock*/ int x=2; printf("%d*%d=%d\n",x,i,x*i); } return 0; } Heutzutage gibt es kaum noch reine C-Compiler. Ich erwhne dies jedoch fr den Fall, dass Sie es irgendwann dennoch mit einem reinen C-Compiler zu tun haben und dieser dann Variablen-Deklarationen im C++-Stil nicht versteht.

HinweisIm C99-Standard muss die Deklaration einer Variablen nicht mehr am Anfang eines Anweisungsblocks erfolgen.

8.4. Der Datentyp longDer Datentyp long entspricht wie der Datentyp int auch einer Ganzzahlvariable. Bei 16-Bit-Systemen hat dieser Typ einen greren Zahlenbereich und verbraucht somit auch mehr Speicherplatz als der Datentyp int. Hier ein Vergleich mit dem Datentyp int auf einem 16-Bit-System: Name int long Gre 2 Byte 4 Byte Wertebereich -32768 +32767 -2147483648 +2147483647 Formatzeichen %d oder %i %ld oder %li

Tabelle 8.2: Der Datentyp long im Vergleich mit int (16-Bit-Systemen) Den Datentyp long knnen Sie benutzen, wenn Berechnung mit greren Zahlen durchfhrt werden. Das Formatzeichen ist hier %ld oder %li, von "long dezimal" bzw. "long integer". long ist also nichts anderes als ein greres int, und genauso kann es auch benutzt werden. Mit dem Datentyp long kann der Datentyp int auf 16Bit-Systemen modifiziert werden, sodass der Wertebereich von int vergrert wird: long int a; Jetzt stellt sich die Frage, welche Daseinsberechtigung hat der Datentyp long dann eigentlich noch auf 32-Bit-Systemen? long hat ja auf diesen Systemen dieselbe Gre und denselben Wertebereich wie der Datentyp int. Die Antwort knnte lauten: aus Kompatibilittsgrnden. Damit alte Programme, die fr 16-Bit-Rechner geschrieben wurden, auch noch auf einem 32-Bit-Rechner laufen bzw. bersetzt werden knnen. Das gilt auch fr den umgekehrten Fall. Dies sollten Sie beachten, wenn Sie ein Programm fr ein 32-Bit-System geschrieben haben und es dann auf ein 16-Bit-System portierten wollen. In diesem Fall ist es empfehlenswert, den Datentypen long zu verwenden. Sollte bei einem Programm auf dem 16-Bit-Rechner eine Zahl, z.B. "1000000", vorkommen, und es wurde der Datentyp int verwendet, wird das Programm mit falschen Werten rechnen und mglicherweise vllig unvorhergesehene Reaktionen zeigen.

HinweisNeu (C99-Standard) ist der erweiterte long-Datentyp. long long ist ein 64 Bit (8 Byte) breiter Datentyp, der einen Wertebereich von -9.223.372.036.854.755.807 bis +9.223.372.036.854.755.807 darstellen kann.

8.5. Der Datentyp shortNach der Betrachtung der Typen int und long stellt sich die Frage: Was ist, wenn ich gar keine so groe Ganzzahl bentige? Beziehungsweise, was ist, wenn das Programm nicht so viel Speicherplatz verbrauchen darf? Dafr gibt es den Datentyp short, der genauso verwendet wird wie schon int und long. Hier die Angaben zu short: Name short Gre 2 Byte Wertebereich -32768 +32767 Formatzeichen %d oder %i

Tabelle 8.3: Der Datentyp short

AchtungWollen Sie Programme schreiben, die auf 16-Bit- und 32-BitSystemen richtig laufen sollen, verwenden Sie fr Ganzzahltypen die Typen long und short und verzichten dabei ganz auf den Datentyp int, da dieser wie gezeigt unterschiedliche Zahlenrume auf verschiedenen Systemen abdeckt.

8.6. Die Gleitpunkttypen float und double

Jetzt zu den Gleitpunkttypen (Floatingpoint). Mit ihnen wird es mglich, genauere Berechnungen mit Nachkommastellen auszufhren. Hier wieder zuerst eine kleine bersicht: Name float double long double Gre 4 Byte 8 Byte 10 Byte Wertebereich Genauigkeit Formatzeichen 6-stellig %f 1.2E-38 3.4E+38 15-stellig %lf 2.3E-308 1.7E+308 19-stellig %lf 3.4E-4932 +4932 1.1E

Tabelle 8.4: Datentypen zur Darstellung von Gleitpunktzahlen Angewendet wird dieser Datentyp genauso wie int und alle andere Datentypen, die Sie bereits kennen. Hierzu eine kurze Erklrung, warum es Gleitpunkttyp und nicht Gleitkommatyp heit. Dies liegt daran, dass die Programmiersprache C in den USA entwickelt wurde. Und dort wird anstatt eines Kommas zwischen den Zahlen ein Punkt verwendet (man spricht von floating point variables): float a=1,5; float b=1.5; /* FALSCH */ /* RICHTIG */

Das Komma verwenden die US-Amerikaner wiederum genauso wie Europer den Punkt bei greren Zahlen. Folgendes Beispiel schreiben wir (Europer) so: 1.234.567 Und die US-Amerikaner schreiben dies wiederum so: 1,234,567 Dazu ein Beispiel. Es wird ein Programm geschrieben, welches die Flche eines Rechtecks berechnet. #include int main() { /* Deklaration */ float flaeche, l, b; printf("Berechnung der Flaeche eines Rechtecks\n"); /* Werte einlesen */ printf("Laenge des Rechtecks: "); scanf("%f",&l); printf("Breite des Rechtecks: "); scanf("%f",&b); /* Flche berechnen */ flaeche = l * b; printf("Flaeche des Rechtecks betraegt : %f\n",flaeche); return 0; } Bei diesem Listing wird der Anwender nach der Lnge und der Breite einer rechteckigen Flche gefragt. Diese Gleitpunktzahl wird mit Hilfe von scanf() eingelesen und an die Adressen der Variablen l und b bergeben. Anschlieend wird dieser Wert zur Berechnung verwendet. Das Ergebnis wird am Schluss des Programms auf dem Bildschirm ausgegeben. Beachten Sie im Zusammenhang mit Gleitpunktzahlen auch Folgendes: Wenn Sie zwei Verschiedene Variablen z.B. int und float miteinander durch Operatoren verknpfen, erhalten Sie das Ergebnis vom genaueren Datentyp dieser beiden Variablen zurck. Ein Beispiel: #include int main() { float f; int i; f=5.0; i=2; printf("%f\n",f/i); /*Ergebnis = 2.500000*/ return 0; } Die Ausgabe des Programms ist "2.500000", weil der genauere der beiden Datentypen hier vom Typ float ist. 8.6.1 Gleitpunkttypen im Detail Bei Gleitpunkttypen wird auch von Zahlen mit gebrochenem Anteil (reelle Zahlen) gesprochen. Der C-Standard schreibt hierbei nicht vor, wie die interne Darstellung von reellen Gleitpunktzahlen erfolgen muss. Dies ist abhngig von den Entwicklern der Compiler. Meistens wird aber der IEEE-Standard 754 verwendet (IEEE = Institute of Electrical and Electronics Engineers). In der Regel kann es dem Programmierer egal sein, wie Gleitpunktzahlen auf seinem System dargestellt werden. Trotzdem, fr den interessierten Programmierer hier eine kurze Erklrung der internen Darstellung von Gleitpunktzahlen, ohne sich zu sehr in die Details zu verfangen. Gleitpunktzahlen werden halb logarithmisch dargestellt, das heit, die Darstellung einer reellen Gleitpunktzahl basiert auf einer Zerteilung in ein Vorzeichen, eine Mantisse und einen Exponenten zur Basis 2. Fr echte Mathematiker sei gesagt, dass der Begriff "Mantisse" hier nichts mit einer Mantisse eines Logarithmus gemeinsam hat. Die Genauigkeit nach dem Komma der Gleitpunktzahl hngt von der Anzahl der Bits ab, die der entsprechende reelle Datentyp in seiner Mantisse speichern kann. Der Wertebereich hingegen wird durch die Anzahl der Bits fr den Exponenten festgelegt. Hierzu folgen die Speicherbelegungen der einzelnen reellen Gleitpunktzahlen im IEEE-Format. 8.6.2 float im Detail float ist eine 32-Bit-Zahl. Diese 32 Bit teilen sich folgendermaen auf:

Abbildung 8.2: float im Detail Vorzeichen (Vz)-Bit (1 Bit): In Bit 31 wird das Vorzeichen der Zahl gespeichert. Ist dieses 0, dann ist die Zahl positiv, bei 1 ist sie negativ. Exponent (8 Bits): In Bit 23 bis 30 wird der Exponent mit einer Verschiebung (Bias) der Zahl gespeichert (Bias bei float 127). Mantisse (23 Bits): In Bit 0 bis 22 wird der Bruchteil der Mantisse gespeichert. Das erste Bit der Mantisse ist immer 1 und wird nicht gespeichert.

q

q

q

8.6.3 double im Detail Beim Datentyp double ist es hnlich wie bei float. double ist eine 64 Bit Zahl mit doppelter Genauigkeit. double ist folgendermaen aufgeteilt:

Abbildung 8.3: double im Detail Vorzeichen-Bit (1 Bit): In Bit 63 wird das Vorzeichen der Zahl gespeichert. Ist dieses 0, dann ist die Zahl positiv, bei 1 ist sie negativ. Exponent (11 Bit): In Bit 52 bis 62 wird der Exponent mit einer Verschiebung (Bias) der Zahl gespeichert (Bias bei double 1023). Mantisse (52 Bit): In Bit 0 bis 51 wird der Bruchteil der Mantisse gespeichert. Das erste Bit der Mantisse ist immer 1 und wird nicht gespeichert.

q

q

q

8.6.4 long double Wird dem Datentyp double das Schlsselwort long vorangestellt, erhalten Sie eine 80 Bit Zahl mit einer noch hheren Genauigkeit. Wenn Sie long double mit dem sizeof-Operator auf seine Speichergre in Bytes berprft haben, drften Sie sicherlich verwundert sein, dass der Datentyp auf 32Bit-Systemen 12 Bytes beansprucht. Auf einem 32-Bit-System werden dazu einfach zwei Fllbytes angefgt. Auf 16-Bit-Systemen beansprucht long double weiterhin 10 Bytes Speicher. Auf einer HP-UX Maschine hingegen bentigt long double gar 16 Bytes an Speicher. Dabei werden aber alle 128 Bits genutzt, und somit lsst sich eine Genauigkeit von 33 Stellen anzeigen. 8.6.5 Einiges zu n-stelliger Genauigkeit Eine Fliekommazahl mit 6-stelliger Genauigkeit wie float kann sechs Dezimalstellen nicht immer korrekt unterscheiden. Wenn beispielsweise die Zahl vor dem Komma (z.B. "1234,1234") bereits vier Stellen besitzt, so kann sie nach dem Komma nur noch zwei Stellen unterscheiden. Somit wren die Gleitpunktzahlen 1234,12345 und 1234,123999 als float-Zahlen fr den Computer nicht voneinander unterscheidbar. Mit 6-stelliger Genauigkeit sind die signifikanten Stellen von links nach rechts gemeint. Der Typ float ist also ungeeignet fr kaufmnnische und genaue wissenschaftliche Berechnungen. Dazu folgendes Beispiel: #include int main() { float x=1.1234; float dollar=100000.12; float end_float; double y=1.1234; double DOLLAR=100000.12; double end_double; printf("%f Euro mit float\n",end_float=dollar*x); printf("%f Euro mit double\n",end_double=DOLLAR*y); return 0; } Hier werden zwei verschiedene Ergebnisse zurckgegeben. Die Differenz mag minimal sein, doch bei Brsenberechnungen knnte eine solche Ungenauigkeit durchaus Millionen von Euro kosten, und in der Astronomie wre der Mond wohl heute noch nicht erreicht.

Abbildung 8.4: Darstellung von Fliekommazahlen mit double und float float ist nach sechs Dezimalstellen am Ende. Mit double haben Sie dagegen die Mglichkeit, eine auf 15 Stellen genaue Zahl zu erhalten und mit long double eine 19-stellige. Was ist zu tun, wenn diese Genauigkeit nicht ausreichen sollte? In diesem Fall mssen Sie sich nach so genannten Festkomma-Algorithmen umsehen. Denn Festkomma-Darstellungen wie die BCD-Arithmetik gibt es in C nicht.

HinweisBCD steht fr Binary Coded Dezimals und bedeutet, dass die Zahlen nicht binr, sondern als Zeichen gespeichert werden. Bspw. wird der Wert 56 nicht wie gewhnlich als Bitfolge 00111000 gespeichert, sondern als die Werte der Ziffern im jeweiligen Zeichensatz. In unserem Fall dem ASCII-CodeZeichensatz. Und dabei hat das Zeichen "5" den Wert 53 und das Zeichen "6" den Wert 54. Somit ergibt dadurch folgende Bitstellung: 00110101 (53) 00110110 (54). Damit bentigt der Wert 53 allerdings 16 anstatt der mglichen 8 Bit. Fr die Zahl 12345 hingegen bentigen Sie schon 40 Bits. Es wird zwar erheblich mehr Speicherplatz verwendet, doch wenn Sie nur die Grundrechenarten fr eine Ziffer implementieren, knnen Sie mit dieser Methode im Prinzip unendlich lange Zahlen bearbeiten. Es gibt keinen Genauigkeitsverlust.

HinweisBei dem Listing oben wurde bei der formatierten Ausgabe fr den Datentyp double %f verwendet, was brigens bei der Ausgabe mit printf() nicht falsch ist. Verwenden Sie hingegen scanf(), kommt es zu Problemen. scanf() bentigt fr double nmlich %lf. Dies liegt daran, dass Argumente in variablen Argumentlisten in C den Default Promotion unterliegen.

8.7. Nummerische GleitpunktproblemeVorsicht ist geboten vor Ungenauigkeiten durch die binre Darstellung von Gleitkommazahlen. Reelle Zahlen knnen im Gleitkommaformat nicht immer exakt dargestellt werden. Das liegt daran, dass die Gleitkommasemantik so implementiert ist, wie es der Prozessor berechnet. Wrde man dafr eine extra Funktion fr den Compiler schreiben, wre die Berechnungsdauer systemabhngig. Wrde die Berechnung beispielsweise bei einem Pentiumprozessor optimal ablaufen, knnte diese bei einem Athlon wiederum katastrophale Laufzeiten haben. Dadurch kann es bei der Berechnung von arithmetischen Ausdrcken zu Ungenauigkeiten kommen (wie weiter oben schon gezeigt wurde).

AchtungZahlen im Gleitkommaformat sollten nie auf Gleichheit berprft werden! Folgendes Programm wird in eine Endlosschleife laufen, da die Zahl 0.1 nie exakt dargestellt werden kann: #include int main() { float i=0.0; for (i=0.0; i != 1.0; i += 0.1) printf("%f",i); return(0); } Sicherer ist es, wenn Sie dieses Beispiel so berprfen: #include int main() { float i=0.0; for (i=0.0; i1.0001; i += 0.1) printf("%f",i); return(0); }

HinweisFr den Fall, dass sich jemand nher mit der Gleitpunktdarstellung auf verschiedenen Systemen auseinander setzen will (muss) ein Link dazu: http://cch.loria.fr/ documentation/IEEE754/numerical_comp_guide/index.html

Weiter mit: 8.8. Der Datentyp char

Xoops2 RC3

Kapitel 8: Datentypen und Variablen

8.8. Der Datentyp charDer Datentyp char kann auf zwei logisch vllig unterschiedliche Arten verwendet werden. Zum einen dient er der Darstellung von einzelnen Zeichen wie 'a', 'A', 'b', 'B', '5', '7', '' usw. fr Tastatureingabe und Bildschirmausgabe. Zum anderen kann char genutzt werden, um kleine Ganzzahlen zu verarbeiten. Wobei gesagt werden muss, dass dafr der Wertebereich relativ klein ist. Hier die bersicht dazu: Name char Gre 1 Byte Wertebereich -128 +127 Formatzeichen %c

Tabelle 8.3: Der Datentyp char char ist auch der kleinste darstellbare elementare Datentyp in der Programmiersprache C. An dieser Stelle will ich zum besseren Verstndnis etwas weiter ausholen. Der Computer ist eigentlich dumm. Er kennt nichts anderes als die Zustnde 0 fr "aus" und 1 fr "ein". Dies entspricht etwa einem Lichtschalter, den Sie ein- oder ausschalten knnen. Im Fall von char wren dies acht Lichtschalter. Zuerst ein kleiner berblick ber die Gre der Datentypen: Gre Gre Gre Gre Gre Gre Gre von von von von von von von char 1 short 2 int 2 oder 4 long 4 float 4 double 8 long double 10 Byte Byte Byte Byte Byte Byte Byte = = = = = = = 8 16 16 32 32 64 80 Bit Bit Bit oder 32 Bit Bit Bit Bit Bit

Abbildung 8.5: Einzelne Bits der Datentypen im berblick Betrachten Sie den Datentyp char, der ja aus acht einzelnen Bits besteht. Acht Bits sind in der Informatik ein Byte:

Abbildung 8.6: Ein Byte in der Informatik (Datentyp char) Jedes dieser acht Bits, die aus der Speichergre von einem Byte entstehen, kann einen bestimmten Wert darstellen:

Abbildung 8.7: Diese Zahlen ergeben sich durch die Potenzen von 2 Der PC kann doch nur zwei Zahlen darstellen. Woher kommen dann diese Werte? Sie werden aus der Potenz von 2 berechnet (27+26+25+24+23+22+21+20). Wrden Sie jetzt hier Bit 0 und Bit 1 auf 1 setzen, also Licht an, wrde der Wert 3 dargestellt. Dieser errechnet sich ebenfalls wieder aus den Potenzen: 0*27+0*26+0*25+0*24+0*23+0*22+1*21+1*20 = 3 Ein Beispiel:

Abbildung 8.8: Dualdarstellung des dezimalen Werts 66 Der Dezimalwert dieser Zusammensetzung der einzelnen Bits betrgt 66 (0*27+1*26 +0*25+0*24+0*23+0*22+1*21+0*20 = 66). Es mssen nur die einzelnen Bits zusammengezhlt werden, die gesetzt (also 1) sind. Wenn Sie jetzt die ASCII-CodeTabelle am Ende des Buchs betrachten und unter dem dezimalen Wert 66 nachsehen, stellen Sie fest, dass 66 fr das groe 'B' steht. Es geht nmlich hier bei char nicht um den int-Wert, sondern um das Zeichen, das diesem dezimalen Wert in der ASCIITabelle entspricht. Die ASCII-Code-Tabelle ist eine Tabelle, an die sich alle Programmierer der Welt halten mssen. Sie enthlt alle Zeichen, die der Computer darstellen kann. Nach diesem kleinen Ausflug ins Dualsystem zurck zum Thema dieses Kapitels, dem Datentyp char. Hier ein kleines Listing: #include int main() { char a = 'A'; char b = 65; int c = 65; int d; printf("a = %c\n",a); printf("b = %c\n",b); printf("c = %c\n",c); d = a + b + c; printf("d = %d\n",d); d = 'a' + 'A'; printf("d = %d\n",d); printf("char a = %c und %d\n",a,a); printf("char b = %c und %d\n",b,b); printf("int c = %c und %d\n",c,c); return 0; } Der Programmablauf sieht etwa folgendermaen aus:

/*berrascht?*/ /*Nochmals :) */ /*Rechenbeispiel*/

Abbildung 8.9: Programm bei der Ausfhrung unter Linux Jetzt zur Zeile: char a = 'A'; Wenn Sie char ein Zeichen zuweisen wollen, muss es zwischen zwei einzelnen Hochkommata stehen ('A'). Folgende Varianten sind nicht mglich bzw. falsch: /*falsch, in doppelte Hochkommata == String*/ char a = "A"; /*falsch, Variablenzuweisung*/ char a = A; /* Schlechter Stil, da nicht gleich durchschaubar, ob der * Programmierer hier den ASCII-Buchstaben oder den dezimalen * Wert verwenden will */ char b = 65; Hier auch gleich die andere Mglichkeit, char einen Wert zuzuweisen. Fr den PC ist der Wert 65 und das Zeichen 'A' identisch. Beide haben dieselbe Bitdarstellung:

Abbildung 8.10: Bitdarstellung des Dezimalwerts 65 und des Zeichens 'A' Dies besttigt auch die Ausgabe im Programm: printf("a = %c\n",a); printf("b = %c\n",b); Auch wenn es hier so aussieht, in C gibt es keinen Datentyp, mit dem Sie echte Zeichen wie 'A' 'B' oder 'C' speichern knnen. Daher stehen diese Zeichen auch zwischen einzelnen Anfhrungszeichen. Sie geben zwar Folgendes an: char a = 'A'; aber nach der bersetzung des Compilers sieht dies so aus: char a = 65; Verwenden Sie jetzt im Programm das Formatierungszeichen %c, wird der Wert 65 anhand der ASCII-Code-Tabelle kodiert. Wird hierbei das Formatierungszeichen %d verwendet, wrde dieser Wert nicht kodiert und in seiner tatschlichen Form ausgegeben, wobei "tatschliche Form" natrlich die rein optische meint. In Wirklichkeit wre die tatschliche Form eine Zahlenkolonne von Einsen und Nullen. Fr den PC gelten weiterhin nur Bits und Bytes. Und wie Sie gesehen haben, funktioniert das analog auch mit dem Datentyp int.

AchtungAuch wenn Sie char oder unsigned char fr kleine Ganzzahlwerte verwenden knnten, ist von dieser Mglichkeit abzuraten. Dies vor allem, weil in C nicht festgelegt ist, ob dieser Datentyp mit oder ohne Vorzeichen interpretiert wird. Es knnte hnlich wie bei int auf verschiedenen Systemen zu unterschiedlichem Verhalten oder gar Fehlern fhren (siehe Abschnitt 8.1 zu int).

8.9. Nationale contra internationale Zeichenstze

Der ASCII-Zeichensatz (American Standard Code for Information Interchange) wurde von US-amerikanischen Ingenieuren entwickelt. Zur damaligen Zeit wurde als achtes Bit das Parittsbit benutzt, womit nur noch sieben Bits zur Verfgung standen; also gab es Platz fr 128 Zeichen und Sonderzeichen. Nun fehlte der Platz fr westeuropische und slawische Zeichen (von der japanischen mit ber 40.000 Zeichen und der kyrillischen Schrift ganz zu schweigen). Man beschrnkte sich also auf die Zeichen, die im Englischen bentigt wurden. Als die Europer mit ihren landestypischen Zeichen ebenfalls in die ASCII-Tabelle aufgenommen werden wollten, war es schon zu spt. Wie Sie an der ASCII-CodeTabelle sehen knnen, befinden sich unter den 128 Zeichen, die in 7 Bits Platz haben, keine Umlaute wie zum Beispiel "" oder landestypische Zeichen anderer europischer Lnder wie etwa franzsische. Jetzt war die ISO (International Organisation for Standards) gefragt. Der ASCIIZeichensatz wurde auf 8 Bits erweitert und unter der Bezeichnung "ISO-8859-1, ISO8859-2 usw." etabliert. Der westeuropische Standard ist in der "ISO-8859-1" erfasst. Damit lassen sich folgende Zeichen darstellen: #include int main() { int i; for(i=0; i < 254; i++) { if(i==26) /* ESC ignorieren */ continue; printf(" |%d : %c| ",i,i); } return 0; } Die deutschen Sonderzeichen in oktaler Form knnen auch folgendermaen ausgegeben werden: #include int main() { int i; printf("Rtsel, l, berfall\n"); printf("Umlaute oktal : \n"); return 0; } Das Problem mit den deutschen Sonderzeichen unter der Windows-Konsole ist, dass diese nicht den gewhnlichen Windows-Zeichensatz verwendet, sondern einen OEMZeichensatz. Deshalb muss in diesem Fall ein Umweg gegangen werden. Mit Linux haben Sie dieses Problem nicht. Mit char knnen Sie somit Zeichenstze mit einem Speicherbedarf von 8 Bits darstellen. Fr Unicode-Zeichenstze sollte der Datentyp wchar_t eingesetzt werden. Er hat einen Speicherbedarf von 16 Bits.

8.10. Vorzeichenlos und vorzeichenbehaftet

Mit dem Schlsselwort unsigned weisen Sie den Compiler an, dass er einen Datentyp vorzeichenlos behandeln soll. Dadurch erhht sich auch der Wertebereich der positiven Zahlen. Mit dem Schlsselwort signed bewirken Sie genau das Gegenteil. signed ist bei allen Datentypen voreingestellt. Das bedeutet, dass folgende Schreibweisen die gleiche Bedeutung haben: int a; signed int a; Am besten sehen Sie sich dazu die Tabelle an, auf der sich alle Datentypen befinden, die Sie bisher kennen gelernt haben. Name char, signed char unsigned char short, signed short unsigned short int, signed int unsigned int long, signed long unsigned long float double long double Gre 1 Byte = 8 Bit 1 Byte = 8 Bit 2 Byte = 16 Bit 2 Byte = 16 Bit 4 Byte = 32 Bit 4 Byte = 32 Bit 4 Byte = 32 Bit 4 Byte = 32 Bit 4 Byte = 32 Bit 8 Byte = 64 Bit 10 Byte = 80 Bit Wertebereich -128+127 0255 -32768+32767 065535 -2147483648 +2147483648 04294967295 -2147483648 +2147483648 04294967295 3.4*10-383.4*1038 1.7*10-3081.7*10308 3.4*10-49323.4*104932

Tabelle 8.6: bersicht aller Standard-Datentypen in C Dazu nochmals char als Beispiel. Manch einer wird sich vorhin gedacht haben: "Warum kann ich mit char nur Werte zwischen -128 und 127 darstellen?" Denn, wenn alle Bits gesetzt sind, und Sie nachrechnen, ist das Ergebnis der Summe 255. Doch es mssen ja auch negative Werte dargestellt werden, etwa -100. Wenn das Schlsselwort unsigned vor einen Datentyp gestellt wird, sind keine negativen Zahlen mehr mglich. Somit verdoppelt sich aber der positive Wert der Zahl. Sollten Sie z.B. zwei Zahlen subtrahieren und es kommt ein negatives Ergebnis heraus, und es wurde vor dem Datentyp des Ergebnisses das Schlsselwort unsigned gesetzt, so wird das Minus der negativen Zahl ignoriert und es wird eine positive Zahl daraus.

8.11. Limits fr Ganzzahl- und Gleitpunktdatentypen

Jetzt haben Sie eine Menge ber Datentypen und ihre Eigenschaften erfahren. Hufig hie es jedoch, auf bestimmten Systemen hat Datentyp x die Gre y. Wenn Sie jetzt erfahren wollen, welchen maximalen oder minimalen Wert der Datentyp int z.B. auf Ihrem System besitzt, knnen Sie die Konstanten in den Standard-Headerdateien und abfragen bzw. ausgeben. Mit folgendem Listing ist es mglich, alle Limits des Datentyps int auf Ihrem System abzufragen: #include #include int main() { printf("int-Wert mindestens: %d\n",INT_MIN); printf("int-Wert maximal : %d\n",INT_MAX); printf("unsigned int max. : %u\n",UINT_MAX); printf("int bentigt %d Byte (%d Bit) Speicher\n", sizeof(int),sizeof(int)*CHAR_BIT); return 0; } Genauso wie in diesem Beispiel knnen Sie auch die anderen Limiteigenschaften der Datentypen abfragen. Vorausgesetzt, Sie binden die Headerdatei mit ein. Hierzu die Tabelle der Limits fr ganzzahlige Datentypen in der Headerdatei : Konstante CHAR_BIT SCHAR_MIN SCHAR_MAX UCHAR_MAX CHAR_MIN CHAR_MAX MB_LEN_MAX SHRT_MIN SHRT_MAX USHRT_MAX INT_MIN INT_MAX UINT_MAX LONG_MIN LONG_MAX ULONG_MAX Mindestwert 8 -127 +127 255 SCHAR_MIN oder 0 SCHAR_MAX oder UCHAR_MAX 1 -32767 +32767 65535 -32767(32Bit: 2147483647) +32767(32Bit: +2147483647) 65535(32Bit: 4294967295) -2147483647 +2147483647 4294967295 Erklrung Bitzahl fr ein Byte min. signed char max. signed char max. unsigned char min. char max. char max. Byte fr ein Viel-Bytezeichen min. short int max short int max. unsigned short min. int max. int max. unsigned int min. long int max. long int max. unsigned long int

Tabelle 8.7: Limit-Konstanten fr ganzzahlige Datentypen in Bentigen Sie hingegen Limitwerte fr Gleitpunktzahlen, gibt die Headerdatei Auskunft. Darin finden Sie u.a. Konstanten mit allen Limits und Eigenschaften, die fr Gleitpunktdatentypen entscheidend sind. Das folgende Listing gibt alle Limits und Eigenschaften fr den Datentyp float auf Ihrem System aus: #include #include #include //fr CHAR_BIT int main() { printf("Limits und Eigenschaften des float-Wertes\n\n"); printf("float bentigt %d Bytes (%d Bit) an Speicherplatz\n", sizeof(float),sizeof(float)*CHAR_BIT); printf("Basis fr Exponentendarstellung: %d\n",FLT_RADIX); printf("Anzahl der Mantissenstellen : %d\n",FLT_MANT_DIG); printf("Anzahl sign. Dezimalziffern : %d\n",FLT_DIG); printf("Kleinst. neg. FLT_RADIX-Exponent: %d\n",FLT_MIN_EXP); printf("Kleinst. neg. Zehnerexponent : %d\n",FLT_MIN_10_EXP); printf("Grter FLT_RADIX-Exponent : %d\n",FLT_MAX_EXP); printf("Grter Zehnerexponent : %d\n",FLT_MAX_10_EXP); printf("Grter endlicher float-Wert : %f\n",FLT_MAX); printf("Kleinster endlicher float-Wert : %f\n",FLT_MIN); return 0; } Auch hierzu eine Tabelle mit den Limits und Eigenschaften von Gleitpunktdatentypen, welche in der Headerdatei deklariert sind: Konstante FLT_RADIX FLT_MANT_DIG DBL_MANT_DIG LDBL_MANT_DIG FLT_DIG DBL_DIG LDBL_DIG FLT_MIN_EXP DBL_MIN_EXP LDBL_MIN_EXP FLT_MIN_10_EXP DBL_MIN_10_EXP LDBL_MIN_10_EXP FLT_MAX_EXP DBL_MAX_EXP LDBL_MAX_EXP FLT_MAX_10_EXP DBL_MAX_10_EXP LDBL_MAX_10_EXP FLT_MAX DBL_MAX LDBL_MAX FLT_EPSILON DBL_EPSILON LDBL_EPSILON FLT_MIN DBL_MIN LDBL_MIN Bedeutung Basis fr Exponentendarstellung Anzahl Mantissenstellen (float) Anzahl Mantissenstellen (double) Anzahl Mantissenstellen (long double) Genauigkeit in Dezimalziffern (float) Genauigkeit in Dezimalziffern (double) Genauigkeit in Dezimalziffern (long double) Minimalster negativer FLT_RADIX-Exponent (float) Minimalster negativer FLT_RADIX-Exponent (double) Minimalster negativer FLT_RADIX-Exponent (long double) Minimalster negativer Zehnerexponent (float) Minimalster negativer Zehnerexponent (double) Minimalster negativer Zehnerexponent (long double) Maximaler FLT_RADIX-Exponent (float) Maximaler FLT_RADIX-Exponent (double) Maximaler FLT_RADIX-Exponent (long double) Maximaler Zehnerexponent (float) Maximaler Zehnerexponent (double) Maximaler Zehnerexponent (long double) Maximaler Gleitpunktwert (float) Maximaler Gleitpunktwert (double) Maximaler Gleitpunktwert (long double) Kleinster float-Wert x fr den 1.0 + x ungleich 1.0 gilt Kleinster double-Wert x fr den 1.0 + x ungleich 1.0 gilt Kleinster long double-Wert x fr den 1.0 + x ungleich 1.0 gilt Minimalster normalisierter Gleitpunktwert (float) Minimalster normalisierter Gleitpunktwert (double) Minimalster normalisierter Gleitpunktwert (long double)

Tabelle 8.8: Limit-Konstanten fr Gleitpunkt-Datentypen in Natrlich gilt auch bei der Verwendung der Konstanten, welche sich in der Headerdatei befinden, dass die entsprechende Headerdatei mit eingebunden wird.

8.12. KonstantenEine Konstante ist entweder eine ganzzahlige Konstante, eine Gleitpunktkonstante, Zeichenkonstante oder ein String-Literal. Jede Konstante besteht aus einem Typ, der sich aus dem Wert und seiner Schreibweise ergibt. 8.12.1 Ganzzahlkonstanten Ganzzahlige Konstanten knnen als Dezimalzahl, als Oktalzahl oder als Hexadezimalzahl dargestellt werden. Die dezimale Konstante kann durch folgende Datentypen dargestellt werden: int, unsigned long, long Oktale und hexadezimale Konstanten lassen sich mit folgenden Datentypen darstellen: int, unsigned int, long, unsigned long Der Typ der Konstante lsst sich brigens auch mit dem Suffix L oder l fr long und u oder U fr unsigned beeinflussen. Einige Beispiele ganzzahliger Konstanten: dezimal 30 30U 30L 30ul hexadezimal 0x1e 0x1eu 0x1eL 0x1EUL oktal 036 036U 036l 036UL Typ int unsigned int long unsigned long

Tabelle 8.9: Beispiele ganzzahliger Konstanten 8.12.2 Gleitpunktkonstanten Eine Gleitpunktkonstante ist eine Folge von Dezimalziffern mit einem Gleitpunkt. Gleitpunktkonstanten mssen stets mit einem Gleitpunkt oder der Angabe von e oder E gekennzeichnet werden. Wird kein Suffix angegeben, ist die Konstante vom Typ double. Mit dem Suffix f oder F ist der Typ der Konstante float, und mit dem Suffix l oder L wird daraus ein long double. Auch hierzu einige Beispiele: 11. 0.007 .11e2 0.7e-2 11e0 .7E-2 11.0 7E-3

Tabelle 8.10: Beispiele von Gleitpunktkonstanten 8.12.3 Zeichenkonstanten Zeichenkonstanten bestehen aus einem Zeichen, welches zwischen zwei einfachen Hochkommata eingeschlossen wird. Zeichenkonstanten sind intern vom Typ int und werden durch entsprechenden Zeichencode (ASCII-Code) dargestellt. Einige Beispiele von Zeichenkonstanten: 'a', 'b', ' ', '\n', 'x'

Wollen Sie eine Zeichenkonstante vom Typ wchar_t verwenden, mssen Sie das Prfix L voranstellen: L'a', L'b', L' ', L'\n', L'x'

In der Praxis werden Sie hchstwahrscheinlich nie mit wchar_t zu tun haben, aber es sollte hier dennoch erwhnt werden. 8.12.4 String-Literale (Stringkonstante) Ein String-Literal ist ein char-Array, welches mit dem schlieenden StringendeZeichen gespeichert wird. Auerdem werden String-Literale zwischen zwei doppelte Hochkommata gestellt. Beispiele: "Hallo Welt", "Hallo\nWelt\n" Sofern Sie auch hierbei so genannte Wide-String-Literale definieren wollen, muss auch hier das Prfix L vorangestellt werden. L"Hallo Welt", L"Hallo\nWelt\n" Mehr zu den Strings im Allgemeinen erfahren Sie in Kapitel 14, Arrays.

8.13. Umwandlungsvorgaben fr formatierte Ein-/ AusgabeSie haben oben fr Datentypen auch die Umwandlungsvorgaben, also Formatzeichen, kennen gelernt. Es lsst sich damit aber noch eine Menge mehr anstellen. Die Formatierungszeichen (oder auch Formatierungsanweisung genannt) beginnen immer - wie schon bei scanf() und printf() - mit dem Zeichen % und beziehen sich dann auch auf das oder die nachfolgenden Argumente. Mit scanf("%d",&a); wird beispielsweise auf die Eingabe eines Integerwerts gewartet. Dies erkennen Sie am Formatierungszeichen %d. Folglich wird durch %c ein char-Zeichen anhand der ASCII-Code-Tabelle in einen Buchstaben umgewandelt (genauer kodiert). Aber auer den bereits erwhnten Umwandlungszeichen knnen noch weitere Umwandlungsvorgaben festgelegt werden. Bei der formatierten Ausgabe mit Funktionen, wie z.B. printf(), fprintf(), vprintf()und sprintf(), haben Sie noch folgende Mglichkeiten: % F W G L U Die Bedeutung der einzelnen Buchstaben ist: F = [Formatierungszeichen] W = [Weite] G = [Genauigkeit] L = [Lngenangabe] U = [Umwandlungszeichen]

q q q q q

Die Formatierungszeichen sind die Zeichen eines bestimmten Typs, die Sie ausgeben knnen. Hier ist die Liste. Einige wurden bereits verwendet: Formatierungszeichen Es wird ausgegeben (eine) %d, %i ... vorzeichenbehaftete ganze Dezimalzahl. %o ... vorzeichenlose ganze Oktalzahl. %u ... vorzeichenlose ganze Dezimalzahl. %x, %X ... vorzeichenlose ganze Hexzahl (a,b,c,d,e, f) bei x; (A,B,C,D,E,F) bei X %f ... Gleitpunktzahl in Form von ddd.dddddd %e, %E ... Gleitpunktzahl in Form von d.ddde+-dd bzw. d.dddE+-dd. Der Exponent enthlt mindestens 2 Ziffern. %g, %G ... float ohne Ausgabe der nachfolgenden Nullen %c ... Form von einem Zeichen (unsigned char) %s ... Form einer Zeichenkette %p Ausgabe eines Zeigerwertes %n Keine Ausgabe. Dieses Argument ist ein Zeiger auf eine Ganzzahl. %% ... das Zeichen % Tabelle 8.11: Typenbezeichner von Formatanweisungen Beim Einlesen eines Zeichens, eines numerischen Werts oder einer Zeichenkette gelten bei der formatierten Eingabe mit Funktionen wie etwa scanf(), sscanf(), fscanf () dieselben Umwandlungszeichen wie bei printf(). Hierbei knnen Sie aber auch noch eine Suchmengenkonvertierung verwenden: Umwandlungszeichen %[bezeichner] Es wird eingelesen ... bis ein Zeichen eingegeben wurde, welches nicht in der Liste bezeichner vorkommt. bis ein Zeichen eingegeben wurde, das in der Liste bezeichner vorkommt.

%[^bezeichner]

Tabelle 8.12: Suchmengenkonvertierung mit scanf() Diese Suchmengenkonvertierung kann durch Zeichen des Formatierungstyps s (s = String, Zeichenkette) ersetzt werden. Dabei wird die Menge von Zeichen eingeschlossen, welche sich zwischen den Klammern befindet. Beispiel: #include int main() { char str[20]; printf("Bitte geben Sie nur Zahlen ein: "); scanf("%[0-9]", str); printf("%s\n",str); return 0; }

Abbildung 8.11: Suchmengenkonvertierung mit scanf() In diesem Beispiel werden Sie aufgefordert nur Zahlen einzugeben. scanf() liet so lange Zahlen ein, bis das erste Zeichen nicht zwischen 0 bis 9 ist. Beachten Sie bitte, dass es sich hierbei um keine reellen Zahlen handelt, sondern um einen String. Wnschen Sie eine reelle Zahl, mssen Sie den String mit einer entsprechenden Funktion konvertieren. Mehr dazu spter beim Thema Strings. Ist das erste Zeichen der Suchmenge ein Caret (^), wird die Suchmenge invertiert, sodass alle ASCII-Zeichen zulssig sind, auer denen, welche in den Klammern angegeben sind. Auch hierzu ein Beispiel: #include int main() { char str[20]; printf("Eingabe machen (keine Buchstaben wie x,y und z): "); scanf("%19[^xyz]", str); printf("%s\n",str); return 0; } Hierbei liet scanf() so lange ein, bis es auf das