CPP 123 Uo 00 Es 0119
CPP 123 Uo 00 Es 0119
C/C++
new reference
Markt+Technik Verlag
Die Deutsche Bibliothek CIP-Einheitsaufnahme
Umwelthinweis:
Dieses Buch wurde auf chlorfrei gebleichtem Papier gedruckt.
Die Einschrumpffolie zum Schutz vor Verschmutzung ist aus
umweltverträglichem und recyclingfähigem PE-Material.
10 9 8 7 6 5 4 3 2 1
04 03 02 01
ISBN 3-8272-6121-X
Inhaltsverzeichnis
Übersicht . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
Grundlagen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
Die Programmiersprachen C und C++. . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
Leistungsmerkmale . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
Der ANSI-Standard . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
Schreibkonventionen in C/C++ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
Aufbau eines C/C++-Programms . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
Typische Komponenten von C/C++-Programmen . . . . . . . . . . . . . . . . . . 20
Größere Programme und Modularisierung . . . . . . . . . . . . . . . . . . . . . . . . 26
Objektorientiertes Programmieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
Verwendung der Standardbibliotheken . . . . . . . . . . . . . . . . . . . . . . . . . . 29
Ein- und Ausgabe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
Programmfluß . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
Programmerstellung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
5
Inhaltsverzeichnis
Variablendeklaration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
Gültigkeitsbereiche . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
Namensbereiche . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
Sichtbarkeit und Verdeckung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
Lebensdauer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64
Zusammengesetzte Datentypen. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
Zusammengesetzte Datentypen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
Aufzählungstypen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
Mehrdimensionale Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
Zeichenketten (Strings) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
Strukturen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74
Bitfelder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
Unions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
Zeiger und Referenzen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
Zeiger . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
Spezielle Zeiger . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
Referenzen (nur C++) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
Typdefinitonen und Typumwandlungen . . . . . . . . . . . . . . . . . . . . . . . . . . 89
Typdefinitionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89
Standardkonvertierungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90
Typumwandlung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92
Konstanten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94
Konstanten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94
Literale . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94
#define – symbolische Konstanten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96
const – konstante Variablen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98
Operatoren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99
Operatoren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99
Vorzeichen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101
Arithmetische Operatoren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102
In- und Dekrementoperator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103
Zuweisungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104
Vergleichende Operatoren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106
Logische Operatoren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106
Datenzugriff . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109
Bitweise Operatoren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113
Streamoperatoren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116
Die Operatoren new und delete . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117
Typumwandlung und -identifizierung . . . . . . . . . . . . . . . . . . . . . . . . . . . 119
Sonstige Operatoren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125
Synonyme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128
Priorität und Assoziativität . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128
Überladung von Operatoren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129
Programmsteuerung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132
Programmsteuerung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132
6
Inhaltsverzeichnis
7
Inhaltsverzeichnis
Instanzbildung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 188
Vererbung und Polymorphie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 189
Vererbung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 189
Vererbung versus Einbettung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 191
Zugriffsbeschränkung bei der Vererbung . . . . . . . . . . . . . . . . . . . . . . . . . 192
Zugriffsrechte für einzelne Elemente auflockern . . . . . . . . . . . . . . . . . . . . 194
Vererbung und Konstruktor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 194
Nicht vererbbare Methoden . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 197
Polymorphie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 197
Überschreibung und virtuelle Methoden . . . . . . . . . . . . . . . . . . . . . . . . . 199
Vererbung und Destruktor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 201
Abstrakte Methoden und Klassen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 201
Basisklassenzeiger . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 202
RTTI – Laufzeittypidentifizierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 203
Mehrfachvererbung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 204
Virtuelle Basisklassen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 205
Templates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 207
Templates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 207
Funktionentemplates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 209
Klassentemplates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 210
Methoden in Klassentemplates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 211
Instanziierung und Spezialisierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 212
Implizite Instanziierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 213
Explizite Instanziierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 215
Explizite Spezialisierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 216
Der Präprozessor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 217
Quellcode einfügen und ersetzen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 219
Makros definieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 220
Argumente in Makros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 221
Direktiven zur bedingten Kompilierung . . . . . . . . . . . . . . . . . . . . . . . . . . 222
Zeichenkettenbildung und Grundsymbolverbindung . . . . . . . . . . . . . . . . 224
Sonstige Direktiven und Symbole . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 225
Exception-Behandlung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 226
Exception-Behandlung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 226
Exceptions auslösen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 230
Exceptions abfangen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 232
Handler-Bereich festlegen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 233
Verwandte Funktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 233
Zeichenketten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 235
C-Strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 235
Die Klasse string . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 237
Wide characters und Multibyte-Zeichen . . . . . . . . . . . . . . . . . . . . . . . . . 238
Ein- und Ausgabe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 239
Formatierte und unformatierte E/A . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 239
Streams in C . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 240
Streams in C++ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 242
Pufferung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 246
8
Inhaltsverzeichnis
9
Inhaltsverzeichnis
queue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 349
set . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 350
sstream . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 351
stack . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 351
stdexcept . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 352
streambuf . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 352
string . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 353
typeinfo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 354
utility . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 354
valarray . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 354
vector . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 356
Die Container-Klassen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 357
Allgemeine Eigenschaften . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 357
bitset . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 360
deque . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 362
list . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 365
map und multimap . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 367
priority_queue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 372
queue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 373
set und multiset . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 375
stack . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 378
vector . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 379
Die Iteratoren-Klassen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 382
Allgemeines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 382
reverse_iterator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 384
Insert-Iteratoren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 385
Stream-Iteratoren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 387
Unterstützung eigener Implementierungen . . . . . . . . . . . . . . . . . . . . . . . . 390
Die Algorithmen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 392
Die Stream-Klassen. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 400
Übersicht . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 400
ios_base . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 402
basic_ios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 404
basic_streambuf . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 405
basic_istream . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 407
basic_ostream . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 409
basic_iostream . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 411
basic_stringbuf . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 411
basic_istringstream . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 413
basic_ostringstream . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 414
basic_stringstream . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 415
basic_filebuf . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 415
basic_ifstream . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 417
basic_ofstream . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 418
basic_fstream . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 419
Die String-Klassen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 420
10
Inhaltsverzeichnis
Übersicht . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 420
char_traits . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 420
basic_string . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 421
Die Klassen zur lokalen Einstellung. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 425
Übersicht . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 425
locale . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 427
Die Hilfsklassen für die einzelnen Kategorien . . . . . . . . . . . . . . . . . . . . . . 428
Die numerischen Klassen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 443
complex . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 443
valarray . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 444
Teilmengen von valarray-Objekten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 447
numeric_limits . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 452
Klassen und Funktionen zur Exception-Behandlung . . . . . . . . . . . . . . . . . 453
exception . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 453
Abgeleitete Exception-Klassen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 454
Funktionen zur Exception-Behandlung . . . . . . . . . . . . . . . . . . . . . . . . . . 456
Laufzeittypidentifizierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 458
type_info . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 458
Utilities . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 459
Die Struktur pair . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 459
Funktionsobjekte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 459
Speicherallokation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 464
allocator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 464
auto_ptr . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 465
Funktionen und Iteratoren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 466
Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 467
11
C/C++
new reference
Übersicht
Grundlagen. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
Sprachkonzepte und Syntax . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
Die C-Standardbibliothek. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 247
Die C++-Standardbibliothek . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 329
13
Grundlagen
Grundlagen
14
Leistungsmerkmale
Leistungsmerkmale
C wurde ursprünglich als High-Level-Sprache zur Systemprogrammierung, nament-
lich der Entwicklung des Betriebssystems UNIX, konzipiert. Insofern war C nur ein
untergeordnetes Hilfsmittel, und C-Programme sollten einfach zu kompilieren und
schnell sein. Das Ergebnis war eine Sprache, die sich durch
● ihren geringen Umfang an Sprachelementen,
● die schnelle Laufzeit ihrer Programme,
● die Unterstützung modularer Programmierung und
● ihrer guten Portabilität bei gleichzeitiger Systemnähe
auszeichnete.
Heutzutage sieht die Situation so aus, daß Rechenzeit immer billiger und der Pro-
grammieraufwand immer kostspieliger wird. Ziel der objektorientierten Program-
mierung mit C++ ist es daher, Quelltext zu schaffen, der sich durch
● einfache und sichere Verwendung,
● hohe Wiederverwertbarkeit,
● einfache Wartbarkeit,
● gute Verständlichkeit und Lesbarkeit
auszeichnet.
Der ANSI-Standard
Der Erfolg einer Programmiersprache hängt nicht nur von der Sprache selbst,
sondern auch von der Verfügbarkeit passender Compiler (oder Interpreter) und
unterstützender Bibliotheken ab. Letztere waren für die Verbreitung von C sogar
von besonderer Bedeutung, da es in C für viele zentralen Aufgaben (Ein- und Aus-
gabe, Stringbearbeitung, dynamische Speicherverwaltung) keine in der Sprache ver-
ankerte Elemente gibt.
Die Abhängigkeit von Standardbibliotheken bedeutet aber auch zusätzliche Abhän-
gigkeit von den Compiler-Entwicklern. Um diesem Einfluß entgegenzuwirken und zu
verhindern, daß jeder C-Compiler-Entwickler seinen eigenen C-Dialekt definiert, trat
im Jahre 1983 im American National Standard Institute (ANSI) ein Komitee aus
15
Grundlagen
Bezugsquellen
C- und C++-Standard können Sie online beim ANSI-Institut oder IHS (Information
Handling Service) anfordern:
[Link]
[Link]
Kopien der Standards können auch aus der Schweiz
ISO/IEC Copyright Office
Case Postale 56
CH-1211 Genève 20
Schweiz
16
Schreibkonventionen in C/C++
Schreibkonventionen in C/C++
Bei der Festlegung der Namen von Bezeichnern, das sind Variablen-, Funktions-,
Klassen-, Typen- und Makronamen, dürfen folgende Zeichen benutzt werden:
● alle Buchstaben des englischen Alphabets (a bis z, A bis Z)
● die Ziffern 0 bis 9
● der Unterstrich »_«
● Der Name eines Bezeichners muß mit einem Buchstaben oder dem Unterstrich
beginnen. Die Verwendung einer Ziffer als ersten Buchstaben eines Bezeich-
ners ist nicht erlaubt.
● Die deutschen Umlaute und andere Sonderzeichen dürfen also nur in Kom-
mentaren und in Zeichenketten vorkommen.
● Die maximale Länge der Bezeichner ist nicht vorgeschrieben, jedoch müssen
nach ANSI C mindestens die ersten 31 Zeichen zur Unterscheidung herange-
zogen werden.
Warnung
Die Sprache C unterscheidet zwischen Groß- und Kleinschreibung. Die Bezeichner
var1 und Var1 können also für zwei verschiedene Variablen benutzt werden.
17
Grundlagen
Beschreibung
C/C++-Programme bestehen aus einer Ansammlung von Deklarationen und Definitionen von
Datentypen, Variablen, Funktionen und Klassen (sowie einigen speziellen Direktiven an den
Präprozessor). Anweisungen, die festlegen, was ein Programm macht, findet man nur innerhalb
von Funktionsdefinitionen (in C++ auch in den Methoden (Elementfunktionen) der Klassen).
Jedes C/C++-Programm muß eine main()-Funktion definieren, mit deren Ausführung das
Programm beginnt.
Anwendung
Im einfachsten Fall besteht ein C/C++-Programm
● aus einer oder mehreren include-Direktiven, die den Zugriff auf bestimmte
Funktionen und Klassen der C/C++-Standardbibliotheken ermöglichen, sowie
● der obligatorischen Funktion main(), in der alle Anweisungen zur Ausführung
des Programms stehen,
● aus Variablen, die deklariert werden, um Werte zu repräsentieren und zwi-
schenzuspeichern,
● aus Anweisungen, in denen die Werte in den Variablen bearbeitet werden.
Beispiel
Um ein einfaches Programm aufzusetzen, das zwei Zahlen multipliziert und das
Produkt der beiden Zahlen ausgibt, könnte man folgendermaßen vorgehen:
Um zwei ganzzahlige Werte im Programm verwalten zu können, deklariert man
zwei Variablen des Datentyps int (Datentyp für ganzzahlige Werte). Für das Ergeb-
nis kann man eine dritte Variable definieren.
int main()
{
int zahl1, zahl2;
int ergebnis;
Mit Hilfe des Zuweisungsoperators kann man den Variablen Werte zuweisen:
int main()
{
...
zahl1 = 120; /* Werte zuweisen */
zahl2 = 4;
Zur Multiplikation von int-Werten verwendet man den *-Operator. Das Ergebnis
der Berechnung weist man direkt der dritten Variablen zu.
ergebnis = zahl1 * zahl2;
18
Aufbau eines C/C++-Programms
Um Werte auszugeben, kann man sich einer speziellen Funktion namens printf()
bedienen, die Teil der C-Laufzeitbibliothek ist.
printf("Das Produkt der Zahlen ist : %d\n", ergebnis);
Bevor man eine Funktion aufruft, muß die Funktion allerdings dem Compiler per
Deklaration bekanntgemacht worden sein. Die Deklarationen für die Funktionen
der Laufzeitbibliothek sind in einer Reihe von Header-Dateien zusammengefaßt.
Nachdem man sich erkundigt hat, in welcher Header-Datei die gewünschte Funk-
tion deklariert ist, bindet man die Header-Datei mittels einer #include-Anweisung
am Anfang des Programms ein.
#include <stdio.h>
Warnung
Leser, die mit C/C++ für Windows programmieren wollen, seien darauf hingewie-
sen, daß Windows-Programme statt der main()-Funktion die Funktion WinMain()
verwenden. Je nach verwendetem Compiler und Klassenbibliothek kann WinMain()
selbst wieder durch eine andere Funktion (beispielsweise OwlMain() für Borland C++
mit OWL) oder eine Klasseninstanz (beispielsweise ein globales Objekt der MFC-
Klasse CWinApp in Visual C++) ersetzt sein.
Konsolenprogramme, die unter Windows ausgeführt werden (sprich im Fenster der
MS-DOS-Eingabeaufforderung ablaufen und über keine eigene Windows-Oberflä-
che verfügen), verwenden aber wie reine DOS- oder UNIX-Programme die main()-
Funktion.
Beispiel
Das folgende Programm kann nach der Kompilation von der Konsole (unter Win-
dows die MS-DOS-Eingabeaufforderung) Ihres Betriebssystems aus aufgerufen und
ausgeführt werden.
#include <stdio.h>
int main()
{
int zahl1, zahl2; /* Faktoren */
int ergebnis; /* Produkt */
return 0;
}
19
Grundlagen
Verweise
Siehe nachfolgende Abschnitte für weitere einführende Informationen zum Aufbau
von C/C++-Programmen.
Siehe Kapitel zur Sprache für detaillierte Informationen zu Variablen, Datentypen,
Operatoren, Funktionen.
Beschreibung
Die Funktionalität eines Programmes wird bestimmt durch die Daten, die es verarbeitet, und die
Operationen, die es auf den Daten ausführt. Insofern könnte man meinen, ein Programm
bestünde nur aus Variablendefinitionen und Anweisungen. Dem ist aber nicht so. Der Compiler
unterscheidet noch ganz andere Elemente.
20
Typische Komponenten von C/C++-Programmen
21
Grundlagen
Verweise
Siehe Elemente der Sprache.
Verweise
Siehe Abschnitt, Kategorie Variablen und Datentypen.
Anweisungen ;
Der eigentliche Code des Programms. Die Anweisungen werden vom Compiler in
Maschinenbefehle umgesetzt, die vom Prozessor des Computers bei Ausführung des
Programms nacheinander abgearbeitet werden. Anweisungen enden stets mit einem
Semikolon.
● Anweisungen dürfen nur innerhalb der Anweisungsblöcke von Funktionen
stehen.
● Jede Programmanweisung muß mit einem Semikolon abgeschlossen werden.
● Mehrere Anweisungen können – durch Semikolons getrennt – in einer Zeile
stehen.
● Außer Anweisungen werden auch Deklarationen mit einem Semikolon abge-
schlossen.
22
Typische Komponenten von C/C++-Programmen
Anweisungsblöcke {}
In C/C++ werden Anweisungen in Anweisungsblöcken zusammengefaßt. Ein
Anweisungsblock beginnt mit einer öffnenden geschweiften Klammer und endet
mit einer schließenden geschweiften Klammer.
Anweisungsblöcke können ineinander verschachtelt werden. Der äußerste Block ist
dabei stets der Definitionsblock einer Funktion. Innerhalb des Anweisungsblocks
der Funktion kann man weitere Blöcke definieren, beispielsweise zur Implemen-
tierung einer Schleife oder zur Verzweigung des Programmablaufs in Abhängigkeit
von einer if-Bedingung .
void func() // Funktion
{ // Anweisungsblock zu Schleife
long loop = 1;
Funktionen
Funktionen unterstützen die Modularisierung des Quellcodes. Statt alle Anwei-
sungen in die main()-Funktion zu schreiben, kann man zusammengehörende Anwei-
sungen, die eine gemeinsame Aufgabe erfüllen, als Funktionen auslagern.
Eine Funktion verfügt über
● einen Anweisungsblock,
● eine Schnittstelle zu den anderen Teilen des Programms und
● einen Namen, über den die Funktion aufgerufen werden kann.
Die folgende Funktion vergleich() definiert zwei Parameter, denen beim Aufruf der
Funktion Werte übergeben werden können. Als Ergebnis liefert die Funktion mit-
tels des Schlüsselworts return einen ganzzahligen Wert zurück, der anzeigt, ob die
beiden übergebenen Werte gleich oder unterschiedlich sind.
Funktionsdefinition:
int vergleich (int parameter1, int parameter2)
{
23
Grundlagen
if (parameter1 == parameter2)
return 1;
else
return 0;
}
Funktionsaufruf:
int ergebnis;
int var = 25;
Verweise
Siehe Kapitel Funktionen.
Präprozessor-Direktiven #
Präprozessor-Direktiven sind spezielle Anweisungen an den Compiler (genauer
gesagt, den Präprozessor), die vor der eigentlichen Übersetzung des Programms in
Maschinencode ausgeführt werden. Präprozessor-Direktiven beginnen stets mit
einem »#« und stehen immer allein in einer Zeile.
Die wichtigste Präprozessor-Direktive lautet: #include. Sie dient dazu, den Inhalt
einer Textdatei in den Quelltext der aktuellen Datei einkopieren zu lassen. In
C/C++ werden selbst Anfänger gleich mit diesem Konzept konfrontiert, da man nur
auf diese Weise auf die Funktionen/Klassen der Standardbibliothek zugreifen kann.
Die Standardbibliotheken von C und C++ liegen als kompilierte LIB-Dateien vor
und enthalten die Definitionen einer Reihe von nützlichen Funktionen (und Klas-
sen). Um eine dieser Funktion in einem Programm aufrufen zu können, muß man
die Funktion zuvor beim Compiler bekanntmachen. Dies geschieht durch eine
Deklaration.
Um dem Programmierer die Tipparbeit für die Deklaration der Bibliothekselemente
zu ersparen, sieht der ANSI-Standard eine Reihe von Header-Dateien vor, in denen
die Deklarationen der Bibliothekselemente stehen. Jede Header-Datei ist einem spe-
ziellen Themengebiet gewidmet. Die Funktion printf() zur Textausgabe fällt bei-
spielsweise in den Bereich Ein- und Ausgabe, englisch Input/Output (IO), ihre
Deklaration ist in der Header-Datei stdio.h enthalten. Statt printf() und weitere
Funktionen zur Ein- und Ausgabe extra im Programm vorab zu deklarieren, genügt
es daher die Header-Datei stdio.h einzubinden:
#include <stdio.h>
24
Typische Komponenten von C/C++-Programmen
Kommentare /* */ und //
Kommentare sind Textpassagen, die vom Compiler ignoriert werden. Sie erlauben
dem Programmierer, Anmerkungen in den Quelltext aufzunehmen – meist zur
Erklärung des nebenstehenden oder nachfolgenden C/C++-Codes.
C
Kommentare beginnen in C mit der Zeichenkombination Schrägstrich – Stern »/*«
und enden mit der Zeichenkombination Stern – Schrägstrich »*/«. Die dazwischen-
stehenden Zeichen werden vom Compiler ignoriert. Dies gilt auch für das Zeilenen-
dezeichen, so daß sich Kommentare auch über mehrere Zeilen erstrecken dürfen.
Sie dürfen jedoch nach dem ANSI-Standard nicht verschachtelt werden. (Einige
Compiler erlauben optional die Verschachtelung von Kommentaren.)
/* Dies ist ein Kommentar, der sich über mehrere – genauer gesagt zwei -
Zeilen erstreckt */
Tip
In C++ bietet es sich an, innerhalb von Anweisungsblöcken nur //-Kommentare zu
verwenden und die Klammern /* und */ zum Auskommentieren größerer Blöcke
beim Debuggen einzusetzen.
25
Grundlagen
26
Größere Programme und Modularisierung
Alle Quelltextdateien, die zusammen in einem Schritt vom Compiler übersetzt und
zu einer Objektdatei kompiliert werden, bezeichnet man als Modul oder Überset-
zungseinheit. Eine Übersetzungseinheit besteht aus einer Implementierungsdatei
(Extension .c oder .cpp) und allen Quelltextdateien, deren Inhalt direkt oder indi-
rekt per #include-Anweisung eingebunden werden.
Beispiel
Für ein Programm, das zwei Zahlen von der Tastatur einliest und sowohl das Pro-
dukt als auch den Mittelwert der beiden Zahlen berechnet und ausgibt, könnte
man beispielsweise zwei spezielle Funktionen zur Berechnung des Produkts und des
Mittelwerts aufsetzen und diese dann in der main()-Funktion aufrufen.
(Für zwei so simple Berechnungen wie das Produkt und den Mittelwert zweier Zah-
len, würde man in der Praxis allerdings keine eigene Funktion aufsetzen. Doch geht
es hier nur darum, das Prinzip der Modularisierung zu verdeutlichen.)
#include <stdio.h>
/* Zahlenwerte einlesen */
printf("Geben Sie zwei Zahlen zwischen 0 und 100 ein: \n\n");
scanf("%d %d", &zahl1, &zahl2);
fflush(stdin);
/* Ergebnisse berechnen */
produkt = produkt_berechnen(zahl1, zahl2);
mittelwert = mittelwert_berechnen(zahl1, zahl2);
27
Grundlagen
/* Ergebnisse ausgeben */
puts("\n");
printf("Produkt = %d\n", produkt);
printf("Mittelwert = %f\n", mittelwert);
return 0;
}
Verweise
Siehe Abschnitt zur Sprache für detailliertere Informationen zu Funktionen und
Klassen.
Objektorientiertes Programmieren
Objektorientiert zu programmieren bedeutet nicht einfach, sich die Annehmlich-
keiten von C++ gegenüber C zunutze zu machen oder die Klassenbibliotheken statt
der C-Bibliotheken zu benutzen. In diesem strengeren Sinne kann man das folgende
Programmbeispiel, in dem statt der C-Funktion printf() die Klasseninstanz cout
und der überladene <<-Operator verwendet werden, nicht als objektorientiert pro-
grammiert bezeichnen.
Beispiel
/* Das erste C++-Programm. */
#include <iostream>
using namespace std;
int main() {
cout << "Hello world!" << endl;
return 0;
}
Objektorientierte Programmierung beginnt eigentlich erst da, wo Klassen definiert
und die wichtigen Konzepte der Kapselung und des Polymorphismus sinnvoll einge-
setzt werden, und sie rechtfertigt sich vor allem dort, wo Klassenbibliotheken ent-
stehen, die sich leicht und sicher verwenden lassen.
Letztendlich laufen alle wesentlichen Konzepte der objektorientierten Program-
mierung darauf hinaus, den Prozeß der Programmentwicklung zu beschleunigen,
sei es durch
● die Wiederverwertbarkeit bereits implementierter Codes,
● schnellere Entwicklung von Datentypen durch Vererbung und Polymorphis-
mus,
28
Verwendung der Standardbibliotheken
Verweise
Siehe Kapitel über Klassen.
Beschreibung
Zu C und C++ gehört eine umfangreiche Sammlung von Funktionen und Klassen, die der Bewäl-
tigung der wichtigsten Programmieraufgaben dienen etwa der Ein- und Ausgabe von Daten,
der Programmierung mit Zeichenketten (Text), der Verwendung mathematischer Funktionen
wie Sinus, Kosinus, Potenz, etc.
Anwendung
C/C++ verfügt über einen recht kleinen Satz von Schlüsselwörtern, etlichen Opera-
toren und einer äußerst umfangreichen Sammlung von Syntaxregeln, die vorschrei-
ben, wie man Schlüsselwörter, Operatoren und selbst definierte Bezeichner zu
korrekten C/C++-Programmen verknüpft.
Das Potential dieser Sprachelemente und -regeln ist enorm, doch wäre die Entwick-
lung selbst einfachster Programme allein mit diesen Sprachelementen eine mühsame
Angelegenheit, denn selbst für elementarste Programmieraufgaben bieten diese
Sprachelemente keine Unterstützung. So müßte man
● zum Kopieren von Zeichenketten (sprich Textpassagen) Schleifen program-
mieren, in denen die Zeichenfolgen Zeichen für Zeichen kopiert werden,
● zur Berechnung des Sinus einer Zahl sich zuerst in einem Lehrbuch der Mathe-
matik darüber informieren, wie man den Sinus einer Zahl durch Berechnung
einer trigonometrischen Reihe annähern kann,
● für Ein- und Ausgaben auf Betriebssystemebene programmieren.
29
Grundlagen
Warnung
Gemäß ANSI-C lauten alle Header-Dateien für die C-Laufzeitbibliothek auf .h aus.
Gemäß ANSI-C++ haben die Header-Dateien dagegen keine Extension und den
alten C-Headern wird der Buchstabe c vorangestellt (cstdio statt stdio.h). Zudem
sind alle Bibliothekselemente in dem Namensbereich std deklariert. Die korrekte
Einbindung der Header-Dateien in C++, beispielsweise der Header-Datei iostream
mit den Stream-Klassen zur Ein- und Ausgabe, sähe damit wie folgt aus:
30
Ein- und Ausgabe
#include <iostream>
using namespace std;
Einige Compiler unterstützen derzeit aber auch noch ältere Versionen von iostream
oder haben die Stream-Klassen nicht im Namensbereich std deklariert. In solchen
Fällen muß man sich notgedrungen nach der vom Compiler vorgegebenen Syntax
richten, meist:
#include <iostream.h>
oder
#include <iostream>
Beschreibung
Um mit dem Anwender interagieren zu können, muß ein Programm in der Lage sein, Informa-
tionen und Daten vom Anwender entgegenzunehmen und selbst Daten und Informationen über
den Bildschirm auszugeben.
Anwendung
Im Unterschied zu Sprachen wie Fortran oder Basic besitzt die Sprache C keine
eigenen Sprachelemente zur Ein- oder Ausgabe. Dies bedeutet nicht, daß mit C-
oder C++-Programmen keine E/A-Operationen durchgeführt werden können. Man
muß nur statt eines Schlüsselworts der Sprache eine passende Funktion der Lauf-
zeitbibliothek aufrufen.
In C sind dies vor allem die Funktionen
● printf() für die Ausgabe auf die Konsole (Bildschirm)
● scanf() für das Einlesen von Tastatur.
In C++ bedient man sich der Klassen
● cout (Ausgabe auf Konsole) und
● cin (Einlesen von Tastatur)
und der Stream-Operatoren << und >>.
31
Grundlagen
Warnung
Die oben beschriebenen Funktionen und Klassen sind gemäß ANSI Teil der Stan-
dardbibliotheken von C/C++ und daher stets verfügbar. Der Austausch von Infor-
mationen zwischen Anwender und Programm über diese Funktionen und Klassen
ist allerdings auf Konsolenprogramme beschränkt. Programme mit grafischer
Benutzeroberfläche (GUI), die unter Windows, X-Windows oder OSF Motif laufen,
verwenden andere Möglichkeiten der Ein- und Ausgabe, die durch spezielle APIs
(Sammlungen von Funktionen und Klassen für bestimmte Programmieraufgaben)
unterstützt und implementiert werden.
Beispiele
Ein- und Ausgabe unter C:
#include <stdio.h>
int main()
{
int zahl1, zahl2;
/* Daten einlesen */
printf("Geben Sie zwei Zahlen zwischen 0 und 100 ein: \n\n");
scanf("%d %d", &zahl1, &zahl2);
fflush(stdin);
/* Daten ausgeben */
puts("\n");
printf("1. Zahl = %d\n", zahl1);
printf("2. Zahl = %d\n", zahl2);
printf("Produkt = %d\n", zahl1 * zahl2);
return 0;
}
Ein- und Ausgabe unter C++:
#include <iostream>
using namespace std;
int main()
{
int zahl1, zahl2;
/* Daten einlesen */
cout << "Geben Sie zwei Zahlen zwischen 0 und 100 ein: \n\n";
cin >> zahl1 >> zahl2;
/* Daten ausgeben */
cout << endl;
cout << "1. Zahl = " << zahl1 << endl;
cout << "2. Zahl = " << zahl2 << endl;
32
Programmfluß
Programmfluß
C/C++-Programme bestehen aus einer Ansammlung von Deklarationen und Defini-
tionen. Anweisungen findet man nur in Funktionen (in C++ auch in den Methoden
(Elementfunktionen) von Klassen). Damit stellt sich die Frage, mit welcher Anwei-
sung die Ausführung eines Programmes beginnt.
● Jedes C/C++-Programm beginnt mit der Hauptfunktion main(), die im Quell-
text des Programms definiert sein muß.
● Die Anweisungen in der main()-Funktion werden nacheinander ausgeführt.
● Durch Aufruf einer Funktion aus einer anderen Funktion heraus, beispielswei-
se auch aus main(), kann der Programmfluß gesteuert und der Quellcode durch
Aufteilung auf mehrere Funktionen modularisiert werden.
● Innerhalb einer Funktion kann der Programmfluß durch Verzweigungen (if,
switch) und Schleifen (for, while) gesteuert werden.
Warnung
Leser, die mit C/C++ für Windows programmieren wollen, seien darauf hingewie-
sen, daß Windows-Programme statt der main()-Funktion die Funktion WinMain()
verwenden. Je nach verwendetem Compiler und Klassenbibliothek kann WinMain()
selbst wieder durch eine andere Funktion (beispielsweise OwlMain() für Borland C++
mit OWL) oder eine Klasseninstanz (beispielsweise ein globales Objekt der MFC-
Klasse CWinApp in Visual C++) ersetzt sein.
Konsolenprogramme, die unter Windows ausgeführt werden (sprich im Fenster der
MS-DOS-Eingabeaufforderung ablaufen und über keine eigene Windows-Oberflä-
che verfügen), verwenden aber wie reine DOS- oder UNIX-Programme die main()-
Funktion.
Verweise
Siehe die Anschnitte zu Programmsteuerung, Funktionen, Exception-Behandlung.
33
Grundlagen
Programmerstellung
Beschreibung
Um aus einem in C/C++ formulierten Programmquelltext ein ausführbares Programm zu
machen, muß man es kompilieren. Bei der Kompilation wird der Programmquelltext vom Com-
piler in Maschinencode umgewandelt. In Zusammenarbeit mit dem Linker wird aus diesem
Maschinencode eine ausführbare Datei (unter Windows mit der Extension .exe) erzeugt, die
allerdings nur auf bestimmten Plattformen (Kombination aus Prozessor und Betriebssystem,
beispielsweise Intel-kompatibler Prozessor und Windows 95-Betriebssystem) ausgeführt
werden kann.
Anwendung
Die Erstellung eines Programmes ist natürlich nicht mit der Eingabe des Quelltextes
in einen Editor abgeschlossen. Bevor ein Programm ausgeführt werden kann, muß
es in maschinenlesbaren Code umgewandelt werden. Besteht ein Programm aus
mehreren Modulen, müssen diese zusammengebunden werden. Diese Aufgaben
übernehmen der Compiler und der Linker.
1. Quelltext in Editor eingeben. Dies kann prinzipiell in jedem ASCII-Texteditor
geschehen. PC-Compiler verfügen meist über eine integrierte Entwicklungsum-
gebung (IDE) mit eigenem Editor, der mehr Unterstützung bei der Programmer-
stellung bietet.
2. Header-Dateien einkopieren. Zu Beginn der Kompilation wird der Quelltext mit-
tels der #include-Direktive aufgeführter Header-Dateien in den Quelltext der Pro-
grammdatei kopiert.
3. Quelltextdateien kompilieren. Der Compiler übersetzt dann den Quelltext in ma-
schinenlesbaren Objektcode. Der Objektcode ist meist an eine bestimmte Umge-
bung (Computerkonfiguration) angepaßt und nicht zwischen unterschiedlichen
Umgebungen portierbar. Syntaktische Fehler im Programm werden vom Compi-
ler angezeigt und müssen korrigiert werden.
4. Objektcode-Dateien (.obj) und Bibliotheken (.lib) zusammenbinden. Besteht ein
Programm aus mehreren Quelltextdateien, werden diese vom Compiler einzeln in
Objektcode übersetzt. Dem Linker obliegt dann die Aufgabe, diese Objektcode-
Dateien sowie den Objektcode der benutzten Bibliotheksfunktionen in eine Pro-
grammdatei (.exe unter Windows) zusammenzubinden.
5. Debuggen. Nach dem Kompilieren und Linken liegt ein ausführbares, aber selten
ein korrektes Programm vor. Bezüglich lauffähigen Programmen unterscheidet
man Laufzeitfehler, die sich meist durch Programmabstürze oder Endlosschleifen
äußern, und logische Fehler, wenn das Programm zwar läuft, aber nicht seinen
Zweck erfüllt. Zum Aufspüren dieser Fehler verwendet man üblicherweise einen
Debugger, mit dessen Hilfe man das Programm schrittweise ausführen und kon-
trollieren kann.
34
Programmerstellung
Der GNU-Compiler
Der GNU-Compiler ist ein frei verfügbarer Compiler, den man kostenlos aus dem
Internet beziehen kann ([Link] Den GNU-Compiler gibt es
für UNIX wie für Windows.
Etwas unbequem für Windows-Anwender ist, daß der GNU-Compiler über keine
integrierte Entwicklungsumgebung verfügt, und man daher den Compiler explizit
aus der MS-DOS-Eingabeaufforderung heraus aufrufen muß.
1. Setzen Sie Ihren Quelltext mit einem beliebigen ASCII-Editor auf, und speichern
Sie die Datei.
2. Sofern Sie das /bin-Verzeichnis des Compilers in Ihren Pfad eingetragen haben, so
daß der Compiler gcc oder g++ von überall aufrufbar ist, wechseln Sie in das
Verzeichnis, in dem die Quelltextdatei steht.
3. Rufen Sie den C++-Compiler mit dem Dateinamen der Quelltextdatei auf:
g++ [Link]
oder
gcc quelltext.c
für den Aufruf des reinen C-Compilers.
Das fertige Programm lautet [Link] ([Link] unter Unix) und kann direkt ausgeführt
werden.
35
Grundlagen
Wenn Sie möchten, können Sie auch einen expliziten Namen für die ausführbare
Datei angeben.
g++ [Link] -o progname
Programme, die aus mehreren Modulen bestehen, erstellen Sie durch Auflistung
aller beteiligten Quelldateien (#include-Dateien werden nicht aufgeführt).
gcc [Link] [Link] -o progname
Wenn Sie dem Compiler irgendwelche Optionen übergeben wollen (beispielsweise -
ansi für strikt ANSI-kompatiblen Code oder -c für Kompilieren ohne zu Linken),
setzen Sie diese hinter den Dateinamen.
gcc [Link] -ansi -c
Für die Erstellung der Windows-Programme müssen verschiedene Bibliotheken
explizit mit eingebunden werden:
gcc [Link] -lkernel32 -luser32 -lgdi32
Welche weiteren Bibliotheken unter Umständen aufgenommen werden müssen, ent-
nehmen Sie der Compiler-Dokumentation.
Warnung
Die neueste Version des GNU-Compilers heißt jetzt egcs.
36
Programmerstellung
5. Rufen Sie den Compiler auf (Befehl Projekt/Projekt neu kompilieren für Bor-
landC++ 5.0).
6. Führen Sie das Programm aus (Befehl Debug/Ausführen für BorlandC++ 5.0). Unter
Win32 läuft das Programm in einem MS-DOS-Fenster ab, das sofort wieder
verschwindet, nachdem das Programm beendet wurde. Um dies zu verhindern,
können Sie die Beispielprogramme um einen Aufruf der Funktion getchar() vor
der return-Anweisung von main() erweitern. Das Programm wartet dann auf eine
Tastatureingabe, und das DOS-Fenster bleibt sichtbar.
Die Einstellungen für den Compiler und Linker werden in entsprechenden Dialog-
feldern gesetzt (Befehl Optionen/Projekt für BorlandC++ 5.0).
Zur Erstellung von Windows-Programmen wählen Sie im Target Expert als Zieltyp
Anwendung, als Umgebung Win32 und als Zielmodell GUI (statt Konsole). Achten Sie
darauf, daß keine zusätzliche Klassenbibliothek (OWL, OCF, MFC, etc.) eingebun-
den wird, da in diesem Buch nur reine API-Programme beschrieben sind.
Der C++-Builder
Der C++Builder von Borland arbeitet ebenfalls mit einer Projektverwaltung. Wäh-
rend der C++Builder 1.0 die Projekte jedoch noch einzeln verwaltete, gibt es in der
Version 3.0 nun auch die Möglichkeit, mehrere zusammengehörende Projekte
zusammen in einer Projektgruppe zu verwalten (analog den Arbeitsbereichen in
Visual C++).
1. Legen Sie ein neues Konsolen-Projekt an (Befehl Datei/Neu für C++Builder 3.0). Es
erscheint ein mehrseitiges Dialogfenster, in dem Sie zur Seite Neu wechseln.
2. Doppelklicken Sie auf das Symbol Konsolen-Experte (Textbildschirm-Anwen-
dung für 1.0).
3. Es erscheint direkt der Quelltexteditor des C++Builders mit einer extra Seite für
Ihren Quelltext. Speichern Sie Projekt und Quelltext (Befehl Datei/Alles spei-
chern).
4. Geben Sie Ihren Quelltext ein – entweder indem Sie ihn in das vorgegebene Gerüst
einpassen oder indem Sie das vorgegebene Gerüst zuvor löschen und dann Ihren
Text eintippen.
5. Führen Sie das Programm aus (Befehl Start/Start). Unter Win32 läuft das Pro-
gramm in einem MS-DOS-Fenster ab, das sofort wieder verschwindet, nachdem
das Programm beendet wurde. Um dies zu verhindern, können Sie die Beispielpro-
gramme um einen Aufruf der Funktion getchar() vor der return-Anweisung von
main() erweitern. Das Programm wartet dann auf eine Tastatureingabe, und das
DOS-Fenster bleibt sichtbar.
37
Grundlagen
Die Einstellungen für den Compiler und Linker werden in entsprechenden Dialog-
feldern gesetzt (Befehl Optionen/Projekt für C++Builder 1.0 oder Projekt/Optionen
für 3.0).
Zur Erstellung von Windows-Programmen doppelklicken Sie im Schritt 1 auf das
Symbol Anwendung statt auf Konsolen-Experte.
Warnung
Wenn Sie mit dem C++Builder 3 arbeiten, müssen Sie in Ihre Konsolenanwendun-
gen unter Umständen auch die Header-Datei <condefs.h> aufnehmen.
Tip
Der große Vorzug des C++-Builders liegt in der RAD-Umgebung zur Entwicklung
von Windows-Programmen. RAD bedeutet Rapid Application Development und
steht für die visuelle, komponentenbasierte Erstellung von Programmen.
38
Programmerstellung
Die Einstellungen für den Compiler und Linker werden in entsprechenden Dialog-
feldern gesetzt (Befehl Projekt/Einstellungen ab VisualC++ 5.0).
Zur Erstellung von Windows-Programmen doppelklicken Sie im Schritt 1 auf das
Symbol Win32-Anwendung statt auf Win32-Konsolenanwendung.
39
Zeichensatz
Zeichensatz
Beschreibung
Man unterscheidet zwischen zwei Zeichensätzen:
Dem Basiszeichensatz, den jeder ANSI-C/C++-Compiler zur Aufsetzung des Programmcodes
bereitstellt.
Dem Ziel- oder Umgebungszeichensatz, den das Programm bei der Ausführung verwendet,
etwa für Ein- und Ausgaben.
Der Basiszeichensatz
Der Basiszeichensatz, den jeder C/C++-Compiler versteht und in dessen Zeichen der
Programmquelltext aufgesetzt wird, enthält die folgenden Zeichen:
a b c d e f g h i j k l m n o p q r s t
u v w x y z
A B C D E F G H I J K L M N O P Q R S T
U V W X Y Z
0 1 2 3 4 5 6 7 8 9
_ { } [ ] # ( ) < > % : ; . ? * + - / ^
& | ~ ! = , \ " '
sowie:
41
Sprachkonzepte und Syntax
Zeichen Escape-Sequenz
Neue Zeile NL (LF) \n
Horizontaler Tabulator HT \t
Vertikaler Tabulator VT \v
Rücktaste BS \b
Wagenrücklauf CR \r
Seitenvorschub FF \f
Signalton BEL \a
Backslash \ \\
Fragezeichen ? \?
Hochkomma ' \'
Anführungszeichen " \"
Oktaler Code \ooo
Hexadezimaler Code \xhhh
Beispiele
#include <stdio.h>
#include <string.h>
42
Trigraphsequenzen
Trigraphsequenzen
Beschreibung
Trigraphsequenzen sind Folgen von jeweils drei Zeichen, die als Ersatz für bestimmte Zeichen
des Basiszeichensatzes verwendet werden können.
Anwendung
Der Basiszeichensatz ist eng an die englische Sprache und die englische Tastaturbe-
legung geknüpft. Für Programmierer anderer Nationen kann die Eingabe bestimm-
ter Zeichen auf Grund ihrer landesspezifischen Tastaturbelegung unbequem, wenn
nicht sogar nur über ALT+ASCII-Code möglich sein. Der ANSI-Standard definiert
aus diesem Grund eine Reihe von Trigraphsequenzen, die vom Compiler zu Beginn
der Kompilation in die entsprechenden Zeichen des Basiszeichensatzes umgewan-
delt werden.
Tip
Für die deutsche Tastaturbelegung bedeuten die Trigraphsequenzen keine große
Erleichterung. Um den Programmcode lesbar zu gestalten, sollte man auf Trigraph-
sequenzen verzichten.
Beispiele
??=include <stdio.h>
43
Sprachkonzepte und Syntax
Schlüsselwörter
asm (nur C++) false (nur C++) sizeof
auto float static
bool (nur C++) for static_cast (nur C++)
break friend (nur C++) struct
case goto switch
catch (nur C++) if template (nur C++)
char inline (nur C++) this (nur C++)
class (nur C++) int throw (nur C++)
const long true (nur C++)
const_cast (nur C++) mutable (nur C++) try (nur C++)
continue namespace (nur C++) typedef
default new (nur C++) typeid (nur C++)
delete (nur C++) operator (nur C++) typename (nur C++)
do private (nur C++) union
double protected (nur C++) unsigned
dynamic_cast (nur C++) public (nur C++) using (nur C++)
else register virtual (nur C++)
enum reinterpret_cast (nur C++) void
explicit (nur C++) return volatile
export (nur C++) short wchar_t (nur C++)
extern signed while
Warnung
Schlüsselwörter dürfen nicht als Bezeichner für Variablen, Funktionen, etc. verwen-
det werden.
Symbole
C/C++ kennt eine erstaunliche Zahl an bedeutungstragenden Symbolen, wobei ein
Großteil auf die vielen Operatoren der Sprache fällt.
44
Schlüsselwörter und Symbole
Alternative Zeichen
Für Programmierer mit ungünstigen nationalen Tastaturbelegungen gibt es für
einige Symbole alternative Zeichenfolgen (ähnlich den Trigraphsequenzen).
Alternative für
<% { Anweisungsblock beginnen
%> } Anweisungsblock beenden
<: [ Array-Definition und -Indizierung
45
Sprachkonzepte und Syntax
Alternative für
:> ] Array-Definition und -Indizierung
%: # Zeichenkettenbildung
%:%: ## Grundsymbolverbindung
and && Logische UND-Verknüpfung
and_eq &= Bitweise UND-Verknüpfung und Zuweisung
bitand & Bitweise UND-Verknüpfung
bitor | Bitweises ODER
compl ~ Komplement
not ! Nicht-Operator, Verneinung
not_eq != vergleicht zwei arithmetische Operanden auf Ungleichheit
or || Logisches ODER
or_eq |= Bitweises ODER und Zuweisung des Ergebnisses
xor ^ Bitweises exklusives ODER
xor_eq ^= Bitweises exklusives ODER und
Anwendung
Die wichtigsten Elemente, die ein Programmierer in ein Programm einführen kann,
sind:
● Variablen, um Daten zwischenzuspeichern,
● eigene Datentypen, um die Verwaltung der Daten zu organisieren und zu ver-
einfachen (einschließlich der Definition von Klassen),
● Funktionen, um zusammengehörige Anweisungen zusammenzufassen und den
Quelltext zu modularisieren.
Warnung
Die beiden Begriffe Deklaration und Definition werden häufig in etwas nachlässi-
gem Sprachgebrauch synonym gebraucht, auch wenn sie eigentlich Unterschied-
liches bedeuten.
46
Eigene Bezeichner: Definition und Deklaration
Deklaration
Deklaration bedeutet, dem Compiler einen Namen (Bezeichner) einer Variablen,
Funktion, Klasse, eines Templates, Datentyps oder Sprungmarke (Label) bekannt-
zumachen. Neben dem Namen des neuen Elements enthält die Deklaration bereits
alle nötigen Informationen, die den Compiler in die Lage versetzen die ordnungs-
gemäße Verwendung des Elements im Programmquelltext zu kontrollieren, und
Anweisungen, in denen das Element verwendet wird, in Maschinencode zu über-
setzen.
● Mit der Deklaration einer Variablen wird ihr Name, ihr Typ, die Speicher-
klasse und die Sichtbarkeit des Bezeichners festgelegt.
● Bei der Deklaration einer Funktion wird ihr Name, ihr Rückgabewert, die
Liste der Parameter und die Sichtbarkeit festgelegt.
● Mit einer Deklaration geht keine Speicherreservierung einher.
● Eine Variablendeklaration ist automatisch auch eine Definition, es sei denn,
die Deklaration ist als extern gekennzeichnet und enthält keine explizite Initia-
lisierung, oder es wird ein statisches Element einer Klasse deklariert.
Definition
Erst durch die Definition stellt der Compiler Speicherplatz für ein Element zur Ver-
fügung.
● Für Variablen wird in diesem Speicher der Wert der Variablen abgelegt.
● Für Funktionen wird in diesem Speicher der Code der Funktion abgelegt.
● Die Zuordnung von Namen zu Speicherbereichen muß eindeutig sein, d. h., ein
Name kann nicht gleichzeitig auf zwei verschiedene Speicherbereiche weisen.
In C bedeutet dies, daß innerhalb eines Gültigkeitsbereiches jeder Bezeichner nur
einmal definiert verwendet werden kann.
In C++ können, dank der Möglichkeit der Überladung, Bezeichner von Funktionen
und Operatoren innerhalb eines Gültigkeitsbereiches gleichzeitig in mehreren Defi-
nitionen benutzt werden. (Der Compiler löst dies, indem er die Namen um eine
codierte Form der Parameter oder Operanden erweitert, so daß jedem erweiterten
Namen wieder genau ein Speicherbereich zukommt.)
Verweise
Siehe Gültigkeitsbereiche, Sichtbarkeit, Lebensdauer
47
Sprachkonzepte und Syntax
Variablen
Eine Variable ist ein Name für einen Speicherbereich, in den ein Datenobjekt abge-
legt werden kann (beispielsweise eine ganze Zahl, eine Gleitkommazahl, eine Zei-
chenkette, etc.). Über den Namen der Variablen kann auf den Speicherbereich
zugegriffen werden, um die sich dort befindenden Daten zu lesen oder Daten dort-
hin zu schreiben. Der Compiler legt zu diesem Zweck eine Symboltabelle an, in der
zu jedem Variablenname die Anfangsadresse des zugehörigen Speicherbereichs ver-
merkt ist. Bei der Kompilation kann er dann jedes Vorkommen eines Variablenna-
mens durch die passende Adresse ersetzen. Für das Anlegen dieser Symboltabelle ist
es aber notwendig, daß jede Variable vor ihrer Verwendung deklariert wird, bei-
spielsweise:
int erste_Zahl;
Die wichtigste Angabe bei der Deklaration ist, neben dem Namen der Variablen,
der Datentyp.
Datentypen
Je nach Art der Daten, die in einer Variablen abgelegt werden können, unterschei-
det man verschiedene Datentypen, beispielsweise:
● int für ganze Zahlen
● double für reelle Zahlen (auch Gleitkommazahlen genannt)
● char für Zeichen (Buchstaben, Ziffern, Sonderzeichen)
● bool für Boolesche Variablen, die einen Wahrheitswert annehmen können
(true, false)
Die Datentypen bestimmen
● die interne Darstellung der Werte der Variablen im Rechner. (Bedenken Sie,
daß alle Daten im Speicher als eine Folge von Nullen und Einsen dargestellt
48
Variablen und Datentypen
werden müssen. Die Codierung eines Zeichens in eine Bitfolge erfolgt dabei
nach anderen Regeln als die Codierung einer ganzen Zahl oder einer Gleit-
kommazahl),
● die Größe des Speicherbereichs. (Eine Gleitkommazahl benötigt mehr Speicher
als ein einzelnes Zeichen, und eine Strukturvariable benötigt meist mehr Spei-
cher als eine Gleitkommazahl),
● den Wertebereich. (Dieser ergibt sich letztendlich aus der Größe des Speicher-
bereichs und der Art der Codierung),
● die Operationen, die auf den Werten des Datentyps ausgeführt werden können.
(Beispielsweise kann man ganze Zahlen addieren, nicht aber Zeichenketten).
C/C++ unterscheiden zwischen elementaren Datentypen, die in der Sprache veran-
kert sind (int, float, double, char, wchar_t und bool für C++), und zusammengesetz-
ten Datentypen, die vom Programmierer definiert werden (Aufzählungen, Arrays,
Strukturen und Klassen in C++).
Nach ihren gemeinsamen Eigenschaften und Einsatzgebieten bei der Programmier-
ung kann man die Datentypen weiter klassifizieren:
● Integrale Typen. Der Datentyp bool, die Datentypen char und wchar_t, die
Datentypen int und long, Aufzählungen (enum), Bitfelder. Integrale Datentypen
sind als Datentyp für switch-Variablen erlaubt.
● Arithmetische Typen. Alle integralen Typen plus die Datentypen float, double
und long double. Sie sind als Operanden für die arithmetischen Operatoren
(+, --, *, /) erlaubt.
● Skalare Typen. Arithmetische Datentypen und Zeiger. Sie sind als Schleifen-
variablen für for erlaubt.
char
class wchar_t
struct short
union int
array long
Integer- Bitfelder
typen
Objekttypen
Aufzählungen
Arithmetische
Typen
float
Skalare Gleitkomma- double
Typen typen long double
Zeiger-
typen
49
Sprachkonzepte und Syntax
Beschreibung
Die elementaren Datentypen sind Datentypen, die fest in Form von Schlüsselworten in der
Sprache verankert sind.
Anwendung
Mit Hilfe der elementaren Datentypen kann der Programmierer Variablen für die
verschiedenen Arten von Daten deklarieren (Zahlen, Zeichen, Wahrheitswerte).
Darüber hinaus kann man auf der Grundlage der elementaren Datentypen eigene
zusammengesetzte Datentypen definieren.
Die Programmiersprache C/C++ kennt folgende elementare Datentypen:
● die Datentypen short, int und long für Ganzzahlwerte
● die Datentypen float, double und long double für Gleitkommazahlen
● die Datentypen char und wchar_t für Zeichen (Buchstaben, Ziffern, Satzzei-
chen, etc.)
● den Datentyp bool für Wahrheitswerte (nur C++)
Der Wertebereich der Datentypen – also der Bereich von Werten, die man Varia-
blen dieses Datentyps zuweisen kann – hängt von der Anzahl Bytes ab, die der
Compiler für eine Variable dieses Datentyps im Speicher bereitstellt.
Bis auf den Datentyp bool sind alle diese Datentypen vorzeichenbehaftet, d. h., man
kann den Variablen diesen Typs negative wie positive Werte zuweisen. Durch Vor-
anstellung des Schlüsselworts unsigned kann man festlegen, daß für den Datentyp
nur positive Werte erlaubt sind. Das Schlüsselwort signed gibt explizit an, daß ein
Datentyp vorzeichenbehaftet ist, und ist üblicherweise redundant, da die Daten-
typen ehedem vorzeichenbehaftet sind. Einzige Ausnahme: der Datentyp char.
Warnung
Für den Datentyp char ist gemäß ANSI nicht festgelegt, ob der Datentyp vorzei-
chenbehaftet ist oder nicht. Im Zweifelsfall empfiehlt sich bei der Variablendekla-
ration die explizite Deklaration als signed char oder unsigned char.
50
Speicherbelegung der Integer-Typen
Tip
Die minimalen und maximalen Werte für die einzelnen Datentypen sind in den
ANSI-C Headerdateien limits.h und float.h bzw. für C++ in den Spezialisierungen
der Template-Klasse numeric_limits (aus limits) festgelegt und können von dort
abgefragt werden.
Beschreibung
Vorzeichenbehaftete Integer-Werte werden üblicherweise gemäß dem 2er-Komplement binär-
codiert. Das erste Bit von links codiert dabei das Vorzeichen: 0 steht für positive Zahlen, 1 für
negative Zahlen. Multiplikationen mit -1 entsprechen der Invertierung aller Bits mit an-
schließender Addition von 1.
51
Sprachkonzepte und Syntax
R|∑ a ⋅ 2n −1
|
i
für an = 0
∂ ba , K , a g := S
i
i=0
n 0
||∑ a ⋅ 2 - 2
n −1
i n
für an = 1
T i=0
i
Speicherbelegung
int i = 3;
00000000 00000000 00000000 00000011
&i
Beschreibung
Gleitkommazahlen werden durch zwei Werte codiert, von denen der eine Mantisse, der andere
Exponent genannt wird. In dieser sogenannten Exponential-Schreibweise wird z. B. die Zahl
54.123 folgendermaßen aussehen: 0,54123*10e4. Die Zahl 0,54123 ist in dem Beispiel die (nor-
malisierte) Mantisse, die Zahl 4 der Exponent zur Basis 10 (Compiler verwenden allerdings
üblicherweise die Basis 2).
Der ANSI-Standard schreibt nicht explizit vor, wie Gleitkommazahlen zu codieren sind, die Codie-
rung muß aber dem von ANSI vorgegebenen Gleitkommamodell folgen, und die Charakteristika
der Codierung müssen in den Konstanten aus der Header-Datei float.h festgehalten werden
(numeric_limits<float> und numeric_limits<double> aus der Header-Datei limits für C++).
x = s ⋅ be ⋅
LM∑ f
p
OP
⋅ b− k , emin ≤ e ≤ emax
N
k=1
k
Q
s = Vorzeichen
b = Basis des Exponenten
e = Exponent
p = Anzahl Stellen der Mantisse (bestimmt die Genauigkeit)
fk = Ziffer der Mantisse
52
Vorzeichen integraler Datenypen
Speicherbelegung
Vorzeichenbit (1)
Vorzeichenbit (1)
Anwendung
Wertebereichsverschiebungen durch signed/unsigned:
Warnung
● Variablen von unsigned Datentypen können nicht überlaufen. Wird versucht,
Werte außerhalb ihres Gültigkeitsbereichs an sie zuzuweisen, wird automa-
tisch der Modulo-Operator auf den Wert angewandt.
● Beachten Sie, daß in C/C++ die Datentypen von Operanden intern angeglichen
werden (Arithmetische Konvertierungen). Vergleicht man beispielsweise einen
signed-Wert mit einem unsigned-Wert, wird der signed-Wert als unsigned-Wert
interpretiert. Auf diese Weise kann ein kleiner negativer Wert zu einem großen
positiven Wert werden. (Beachten Sie insbesondere, daß der Rückgabewert des
sizeof-Operators unsigned ist.)
53
Sprachkonzepte und Syntax
● Liegt eine char-Variable mit Vorzeichen im Bereich von -128 bis 127, liegt eine
entsprechende char-Variable ohne Vorzeichen im Bereich zwischen 0 und 255.
Dies kann bei der Portierung unter Umständen zu Problemen führen. Man
kann dem durch die Voranstellung eines der Qualifizierer signed oder unsigned
vorbeugen.
Variablendeklaration
datentyp variablenname;
Beschreibung
Variablen sind vom Programmierer eingeführte Bezeichner, denen Werte zugewiesen werden
können. Welche Werte einer Variablen zugewiesen werden können, hängt vom Datentyp der
Variablen ab. Der Compiler verbindet die Variable mit einem Speicherbereich, in dem der
jeweils aktuelle Wert der Variablen abgespeichert wird.
Anwendung
Variablen sind für ein Programm wie ein Zwischenspeicher, in dem Daten abgelegt
und bei Bedarf wieder hervorgeholt und weiter verarbeitet werden können. Eine
Variable wird durch eine Deklaration eingeführt und ist grundsätzlich vom Ort
ihrer Deklaration ab verfügbar.
Warnung
Die Verfügbarkeit einer Variablen hängt von mehreren Faktoren ab: dem Ort der
Deklaration, den bei der Deklaration verwendeten Spezifizierern, dem Gültigkeits-
bereich und der Lebensdauer der Variablen.
54
Variablendeklaration
Syntax
datentyp variablenname;
datentyp var1, var2, var2;
● datentyp: Bei der Deklaration wird zuerst der Datentyp durch Verwendung
des entsprechenden Typbezeichners angegeben. Erlaubt sind sowohl elemen-
tare wie auch zuvor definierte, zusammengesetzte Datentypen.
● variablenname: Durch mindestens ein Leerzeichen getrennt, folgt auf den Typ-
bezeichner der Name der Variablen. Es können mehrere Variablen gleichzeitig
deklariert werden, wobei die Bezeichner durch Kommata getrennt werden.
Initialisierung
Variablen kann man direkt im Zuge der Deklaration einen Wert zuweisen.
int monate = 12;
Spezifizierer
spezifizierer datentyp variablenname;
Die Variablendeklaration kann durch eine Reihe von speziellen Schlüsselwörtern
näher spezifiziert werden:
Schlüsselwort const Legt fest, daß der Variablen nach der Initialisierung
(Wertzuweisung im Zuge der Deklaration) kein anderer
Wert mehr zugewiesen werden kann.
const int monate = 12;
Schlüsselwort volatile Teilt dem Compiler mit, daß diese Variable nicht etwaigen
Optimierungen im Zuge der Kompilation zum Opfer fallen
darf.
volatile double var;
Speicherklassenspezifizierer Zur expliziten Vergabe einer Speicherklasse. Zusammen
mit dem Ort der Deklaration legt die Speicherklasse die
Sichtbarkeit und Lebensdauer der Variablen fest.
auto
extern
register
static
Speicherklasse auto
Das Schlüsselwort auto weist einer Variablen explizit die automatische Speicher-
klasse zu. Diese Speicherklassenangabe kann nur innerhalb von Blockbereichen
(und für Parameter) verwendet werden und ist im übrigen überflüssig, da lokale
Variablen standardmäßig auto sind.
55
Sprachkonzepte und Syntax
Der Speicherplatz für automatische Variablen wird bei Abarbeitung des Blocks, in
dem sie deklariert werden, auf dem Stack erzeugt, und beim Verlassen des Blocks
wieder freigegeben.
Speicherklasse register
Grundsätzlich entspricht der Spezifizierer register dem Schlüsselwort auto. Es teilt
dem Compiler darüber hinaus aber mit, daß auf die derart deklarierte Variable so
schnell wie möglich zugegriffen werden soll.
Für PCs bedeutet dies, daß die Variablen in die Register des Prozessors geladen
werden sollen. Der Compiler braucht dies jedoch nicht zu tun.
In C kann im Gegensatz zu C++ die Adresse eines Objekts, das mit register dekla-
riert worden ist, nicht mehr ermittelt werden, gleichgültig, ob dieses Objekt sich in
einem Prozessorregister befindet oder nicht. In C gibt es daher keine Zeiger auf
Register-Variablen.
Grundsätzlich sollte man heutzutage die Aufteilung der Register den mittlerweile
sehr leistungsfähigen Compilern überlassen und auf die Spezifikation des Schlüssel-
worts register verzichten.
Speicherklasse static
Grundsätzlich impliziert das Schlüsselwort static lokale Gültigkeit und einmalige
Allokation (letzteres bedeutet, daß statische Elemente nicht auf dem Stack angelegt
werden).
Damit ergeben sich drei wichtige Einsatzbereiche:
Bezeichner, die global deklariert sind, haben üblicherweise externe Bindung (das
heißt, in Programmen, die aus mehreren Modulen zusammengelinkt werden,
bezeichnen sie in allen Modulen das gleiche Objekt). Werden Sie als static dekla-
riert, sind sie nur innerhalb ihres Moduls gültig.
Lokale Variablen von Funktionen werden bei Aufruf der Funktion neu allokiert
und bei Verlassen der Funktion zerstört. Wird eine solche Variable als static dekla-
riert, wird nur beim ersten Aufruf der Funktion Speicherplatz für die Variable
reserviert und gegebenenfalls initialisiert. Zusätzlich endet ihre Lebensdauer erst
mit dem Programm und nicht der Funktion. Die Sichtbarkeit bleibt unverändert.
Klassen können nicht als static deklariert werden, aber Klassenelemente (siehe
Kategorie Klassen).
● Ein statisches Klassen-Datenelement erfüllt ähnliche Aufgaben wie eine globa-
le Variable. Ein solches Datenelement wird nur einmal initialisiert (und zwar
außerhalb der Klasse!) und dann von allen Instanzen der Klasse geteilt. (Übli-
cherweise hat jede Instanz der Klasse natürlich eine eigene Kopie der Klassen-
elemente.)
56
Variablendeklaration
● Eine statische Klassenmethode ist eine Methode, die nur auf statische Klassen-
elemente zugreifen kann und wie ein statisches Datenelement von allen Instan-
zen der Klasse oder über den Klassennamen aufgerufen werden kann.
Deklarationen von Funktionsparametern und Funktionsdeklarationen in einem
Blockbereich können nicht als static spezifiziert werden.
Speicherklasse, extern
Mit dem Spezifizierer extern kann einem Objekt oder einer Funktion externe Bin-
dung zugewiesen werden. Externe Bindung bedeutet dabei, daß alle Vorkommen
eines Bezeichners mit externer Bindung sich auf ein und dasselbe Objekt beziehen.
Bei der internen Bindung beziehen sich nur die Bezeichner aus einer Datei auf ein
und dasselbe Objekt. Bezeichner ohne Bindung identifizieren eindeutige Objekte.
● Objekte und Funktionen, die in einem Namensbereich oder global deklariert
sind, haben automatisch externe Bindung, es sei denn, sie wurden schon zuvor
mit einem anderen Speicherklassenspezifizierer deklariert. (In C++ haben zu-
dem auch globale Objekte, die als const deklariert sind, interne Bindung.)
● Klassenelemente und Funktionsparameter können nicht als extern deklariert
werden.
● Objektdefinitionen ohne gleichzeitige Initialisierung werden durch den Spezifi-
zierer als reine Deklaration gekennzeichnet. Auf diese Weise kann ein Objekt
mit externer Bindung in allen Modulen bekannt gemacht werden, ohne daß es
zu mehrfachen Definitionen kommt.
● C++ erlaubt die mehrfache Definition von Funktionen gleichen Namens, so-
weit sich diese durch Anzahl und Typen ihrer Parameter unterscheiden. Intern
wird diese Namensmehrdeutigkeit vom Compiler so aufgelöst, daß er den ein-
zelnen Funktionsdefinitionen neue Namen zuordnet, in die die Parameter in
codierter Form mit aufgenommen sind. Dies ist nicht immer erwünscht, bei-
spielsweise, wenn Funktionen aus kompiliertem C-Code benutzt werden. Die
Namenserweiterung kann daher durch den Bindungs-Spezifizierer extern "C"
unterdrückt werden.
Beispiele
short int woche;
char zeichen;
int tag, monat;
int jahr = 1998; // Initialisierung
const int monate = 12; // konstante Variable
Verweise
Siehe Gültigkeitsbereiche, Sichtbarkeit, Lebensdauer
57
Sprachkonzepte und Syntax
Gültigkeitsbereiche
Beschreibung
In C/C++ wird jeder Variablen in Abhängigkeit davon, an welcher Stelle des Programms die
Variable deklariert wird, ein Gültigkeitsbereich zugeordnet.
Anwendung
Der Gültigkeitsbereich einer Variablen ist der Bereich eines Programms, in dem
eine Variable gültig ist. Variablen können nur innerhalb ihres Gültigkeitsbereichs
und nach ihrer Deklaration verwendet werden.
Tip
Diese automatische Vergabe von Gültigkeitsbereichen kann vom Programmierer
durch die Aufnahme bestimmter Speicherklassenspezifizierer in die Deklaration an
seine Bedürfnisse angepaßt werden.
Gültigkeitsbereiche
● Blockbereich: Variablen, die innerhalb eines Anweisungsblocks (abgegrenzt
durch die geschweiften Klammern {..}) deklariert werden, sind von lokaler
Gültigkeit. Sie sind nur innerhalb des Blocks bekannt und existieren nur so-
lange, wie der Block abgearbeitet wird. Der Compiler erzeugt diese Variablen
dynamisch. Nach der Beendigung des Blocks wird der Speicherplatz der loka-
len Variablen freigegeben. Damit ist auch ihr Wert verloren. Lokale Variablen
werden zumeist innerhalb von Funktionen deklariert.
C erlaubt Deklarationen nur zu Beginn eines Blocks, also vor irgendwelchen
Anweisungen. C++ erlaubt Deklarationen dagegen an jeder beliebigen Stelle
im Block (sogar in Schleifenheadern).
● Dateibereich: Variablen, die außerhalb jeden Anweisungsblocks, jeder Klasse
und jeden Namensbereiches deklariert werden, sind von globaler Gültigkeit
und können ab dem Punkt ihrer Deklaration benutzt werden. Sie haben globa-
le Lebensdauer, das heißt, sie existieren vom Start des Programms bis zu des-
sen Ende.
● Funktionsbereich: Dieser Bereich gilt nur für die Vergabe von Marken für die
goto-Anweisung , denn Marken dürfen nicht aus der Funktion, in der sie de-
klariert wurden, herausweisen.
● Klassenbereich (nur C++): Elemente von Klassen sind – mit Ausnahme stati-
scher Elemente – nur innerhalb ihrer Klasse gültig. Sie werden bei der Instanz-
bildung erzeugt und bei der Auflösung der Instanz zerstört.
● Namensbereiche (nur C++): In C++ ist es möglich, den globalen Gültigkeits-
bereich durch die Deklaration von Namensbereichen aufzuteilen. Die Dekla-
58
Namensbereiche
Beispiel
#include <stdio.h>
int main()
{
...
return 0;
}
Verweise
Siehe Namensbereiche
Siehe Sichtbarkeit, Lebensdauer
Namensbereiche
namespace bereichsname { }
Beschreibung
Mit Hilfe des Schlüsselwortes namespace kann der Programmierer den globalen Gültigkeitsbe-
reich (Dateibereich) in Unterbereiche aufteilen.
59
Sprachkonzepte und Syntax
Anwendung
Die Aufteilung des globalen Gültigkeitsbereichs ist vor allem für Programmierer
interessant, die mit anderen Programmierern zusammen an umfangreicheren Soft-
wareprojekten arbeiten. Würden in so einem Fall alle Programmierer ihre globalen
Variablen in einem gemeinsamen globalen Gültigkeitsbereich deklarieren, kann es
bei der Zusammenführung der Quelltextdateien zu einem Programm schnell zu
Fehlermeldungen des Linkers wegen mehreren globalen Variablen gleichen Namens
kommen. Durch die Einrichtung individueller Namensbereiche kann man dem
abhelfen.
Zudem steht es dem Programmierer, der Elemente aus einem Namensbereich ver-
wenden will, frei, diese bei Bedarf einzeln anzusprechen oder mit Hilfe des using-
Schlüsselwortes alle Deklarationen aus dem Namensbereich mit einer Anweisung in
seinen eigenen globalen Gültigkeitsbereich oder den Blockbereich einer speziellen
Funktion einzuführen.
Namensbereiche verwenden
using namespace NameDesNamensbereichs;
Mit Hilfe des Schlüsselwortes using kann ein Namensbereich in einen anderen Gül-
tigkeitsbereich eingeführt werden. Danach sind alle in dem neu eingeführten
Namensbereich deklarierten Elemente auch in dem Gültigkeitsbereich bekannt, in
den der Namensbereich eingeführt wurde.
60
Namensbereiche
Namensbereiche erweitern
namespace bezeichner {
// Deklarationen
}
namespace bezeichner {
// weitere Deklarationen
}
Namensbereiche können mehrfach deklariert werden, wobei nachfolgende Deklara-
tionen als Erweiterungen behandelt werden.
Auf diese Weise können Namensbereiche über Dateigrenzen hinweg deklariert, aus-
getauscht und erweitert werden.
61
Sprachkonzepte und Syntax
Synonyme
namespace Deklarationen_für_speziellen_Zweck
namespace Spez1 = Dekarationen_für_speziellen_Zweck
Für die Bezeichner von Namensbereichen können Synonyme eingeführt werden.
Für Namensbereiche mit extralangen Namen können so kürzere Aliase definiert
werden.
Beispiele
Das folgende Programm demonstriert die Definition und Einführung von Namens-
bereichen:
namespace A { // Definition eines Namensbereichs
int i = 1;
}
namespace B {
int i = 2;
using namespace A; // Einführung eines Namensbereichs
}
int main() {
//cout << i; // Fehler, da i nicht global deklariert
// und kein Namensbereich angeschaltet
cout << A::i; // ok, Zugriff über vollständigen Qualifizierer
using namespace A;
cout << i; // ok, liefert A::i
using namespace B;
//cout << i; // Fehler, kann A::i oder B::i sein
return 1;
}
Das zweite Beispiel zeigt Möglichkeiten und Fallstricke bei der Erweiterung von
Namensbereichen:
namespace demo {
int i = 1; // demo::i
void func1(int);
void func2(int);
class X {
int i = 2; // demo::X::i
};
}
namespace demo { // Erweiterung
//int i = 3; // Fehler: doppelte Definition
62
Sichtbarkeit und Verdeckung
Verweise
Siehe Kapitel über Verwendung der Standardbibliotheken
Verdeckung
Wird ein und derselbe Bezeichner mehrfach benutzt, um Elemente in ineinander
verschachtelten Gültigkeitsbereichen zu deklarieren (beispielsweise für eine globale
Variable und eine gleichlautende lokale Variable in einer Funktion), verdeckt die
Variable des innersten Gültigkeitsbereichs alle Variablen der umschließenden Gül-
tigkeitsbereiche.
In C++ kann man auf verdeckte Variablen aus dem globalen Gültigkeitsbereich mit
Hilfe des Gültigkeitsbereichoperators weiterhin zugreifen:
● für globale Variablen aus dem Dateibereich stellt man dem Bezeichner einfach
den Operator voran ::var_name
● für Variablen aus Namensbereichen gibt man zusätzlich den Namensbereich
an: namensbereich::var_name
Zudem kann man in abgeleiteten Klassen auf verdeckte Elemente der Basisklassen
über den Gültigkeitsbereichoperator zugreifen: basisklasse::element.
Warnung
Die Mehrfachverwendung eines Bezeichners innerhalb eines Gültigkeitsbereichs ist
nur in Ausnahmefällen möglich:
● Klassen- und enum-Bezeichner können durch Bezeichner für Variablen, Funk-
tionen und enum-Elemente im gleichen Gültigkeitsbereich verdeckt werden.
63
Sprachkonzepte und Syntax
● Die Überladung von Funktionen in C++ beruht auf der Verwendung des glei-
chen Bezeichners für die Definition mehrerer Funktionen in einem Gültigkeits-
bereich. (Der Compiler löst die Namen intern anhand der Parameterliste auf.)
Beispiele
int wert = 1; // global deklariert
void func() {
int wert = 2; // lokal deklariert, verdeckt globales wert
cout << " wert = " << wert << endl; // Ausgabe: 2
cout << "::wert = " << ::wert << endl; // Ausgabe: 1
};
Lebensdauer
Beschreibung
Wenn Sie eine Variable definieren, erzeugt der Compiler für diese Variable ein Objekt im Spei-
cher (auf das Sie über den Namen der Variablen zugreifen können). In ähnlicher Weise werden
Objekte im Speicher erzeugt, wenn Sie dynamischen Speicher reservieren, wenn bei einem
Funktionsaufruf die Parameter eingerichtet werden, wenn Instanzen von Klassen gebildet
werden (wobei Klassenobjekte erst nach Aufruf des Konstruktors existieren).
Wie lange diese Objekte verfügbar und existent sind, hängt von verschiedenen Faktoren ab.
Anwendung
● Ort der Deklaration. Variablen (einschließlich der Instanzen von Klassen), die
in einem Blockbereich definiert werden, existieren nur bis zum Ende des
Blockbereichs und werden bei Verlassen des Blocks aufgelöst (liegt daran, daß
der Speicher für die Variablen auf dem Stack abgelegt wird). Variablen, die
global deklariert werden, existieren bis zum Programmende.
● Speicherklassenspezifizierer static. Für Variablen, die innerhalb eines Block-
bereichs als static deklariert werden, wird der Speicher nicht auf dem Stack
reserviert. Die Variablen existieren bis zum Programmende.
● Art der Speicherreservierung. Objekte, für die der Speicher dynamisch reser-
viert wird (mit malloc() oder new), wird der Speicher auf dem Heap reserviert
und wird erst freigegeben, wenn der Programmierer dies explizit fordert
(free() oder delete) oder das Programm beendet wird.
Verweise
Siehe Funktionen, Funktionen und der Stack
64
Zusammengesetzte Datentypen
Zusammengesetzte Datentypen
Zusammengesetzte Datentypen
Beschreibung
Mit den elementaren Datentypen ist bereits der Grundstock für die Datenverarbeitung in Pro-
grammen gelegt. Tatsächlich käme man sogar ohne die Möglichkeit zur Definition weiterer
Datentypen aus, doch die Programmierung würde sich dann in vielen Fällen äußerst mühsam
gestalten.
Aus diesem Grunde sieht C/C++ verschiedene Möglichkeiten zur Definition eigener Datentypen
vor. Bevor wir uns diese aber im einzelnen anschauen werden, sollte man sich noch einmal klar
machen, daß man mit der Definition eines neuen Datentyps nicht nur die eigenen Bedürfnisse,
sondern auch die Bedürfnisse des Compilers befriedigen muß.
Konkret bedeutet dies, daß der Compiler wissen muß, wie er für Variablen dieses Datentyps
Speicher belegen muß, wie die Werte der Variablen codiert und im Speicher abgelegt werden
sollen, welche Operationen auf den Variablen des Datentyps erlaubt sind und schließlich wie
Typkonvertierungen vorgenommen werden können.
Aus all diesen Anforderungen könnte man nun ablesen, daß die Möglichkeiten zur Definition
eigener Datentypen entweder sehr eingeschränkt oder mit sehr viel Arbeit verbunden sind. Nun
beides ist nicht der Fall. Der Trick dabei ist einfach, daß man die neuen selbst definierten
Datentypen aus den elementaren Datentypen ableitet.
Insgesamt stehen Ihnen folgende Möglichkeiten zur Definition eigener Datentypen zur Verfü-
gung:
Definition eines Datentyps durch Aufzählung der Wertemenge des Datentyps (enum)
Definition eines Datentyps durch Zusammenfassung mehrerer Variablen eines Datentyps
(Arrays)
Definition eines Datentyps durch Zusammenfassung mehrerer Variablen verschiedener
Datentypen (Strukturen)
Definition eines Datentyps durch Zusammenfassung mehrerer Variablen verschiedener
Datentypen, und durch Bereitstellung typspezifischer Funktionen und Operatoren (Klassen).
Dies ist die freieste und weitreichendste Form der Typdefinition.
Schließlich gibt es noch die Möglichkeit, Zeiger zu definieren, mit denen man direkt auf Spei-
cherbereiche zugreifen und Objekte im Speicher manipulieren kann.
65
Sprachkonzepte und Syntax
Aufzählungstypen
enum {element1, element2, ...};
enum typbezeichner {element1, element2, ...};
Beschreibung
Aufzählungstypen sind Datentypen, deren mögliche Werte durch explizite Aufzählung von Inte-
ger-Konstanten festgelegt werden. Die aufgeführten Werte können im wesentlichen wie im
umgebenden Gültigkeitsbereich definierte Konstanten verwendet werden.
Anwendung
Bei allen anderen Datentypen sind die Wertebereiche durch die interne Codierung
der Werte in Binärdarstellung vorgegeben. Welche Werte beispielsweise eine int-
Variable annehmen kann, hängt nicht von Ihnen, sondern von Ihrem Compiler ab.
Bestenfalls können Sie über Spezifizierer wie short, long oder unsigned auf den Wer-
tebereich einwirken.
Bei einem Aufzählungstyp können Sie durch explizite Auflistung selbst angeben,
welche Werte zum Wertebereich des neuen Aufzählungstyps gehören. Dies kann
einen Programmcode lesbarer und leichter verständlich machen. In C++ kommt
hinzu, daß der Compiler prüfen kann, daß Variablen eines Aufzählungstyps auch
wirklich nur Werte aus seinem Wertebereich zugewiesen werden.
Da intern alle Werte eines Aufzählungstyps durch Integer-Konstanten repräsentiert
werden, kann man Werte aus Aufzählungen beispielsweise auch in switch-Verzwei-
gungen verwenden.
Syntax
enum {element1, element2, ...};
enum typbezeichner {element1, element2, ...};
● elemente: Die in einem Aufzählungstyp definierten Elemente werden wie Inte-
ger-Konstanten behandelt. Damit die Konstanten nicht undefinierte Werte an-
nehmen, werden sie vom Compiler automatisch initialisiert. Nichtinitialisierte
Elemente bekommen dabei den Wert ihres Vorgängers +1 zugewiesen. Dem
ersten Element wird 0 zugewiesen. Mit Hilfe des Zuweisungsoperators kann
der Programmierer den Elementen selbst Werte zuordnen. Es sind allerdings
nur Integer-Werte erlaubt oder Werte, die als Integer-Werte interpretiert wer-
den können. Verschiedene Elemente dürfen gleiche Werte haben.
● typbezeichner: Wird ein typbezeichner spezifiziert, kommt dies einer Typdefini-
tion gleich. Später können dann Variablen dieses Typs definiert werden. In C
lautet der Typ enum typbezeichner, in C++ reicht einfach der typbezeichner.
66
Arrays
Variablendeklaration
enum {elem1 = 1, elem2 } var1, var2;
Oder
enum typbez {elem1 = 1, elem2 };
enum typbez var1, var2;
Wertzuweisung
var1 = elem2;
var1 = typbez(3);
Warnung
Der Compiler reserviert für enum-Variablen Speicher, der groß genug sein muß, um
alle Integer-Werte zwischen dem kleinsten und größten Wert des enum-Typs aufneh-
men zu können. Prinzipiell kann man enum-Variablen jeden Wert innerhalb dieses
Wertebereichs zuweisen, auch wenn der Wert nicht explizit in der Aufzählung
definiert ist (in C++ erfordert dies eine explizite Typumwandlung).
Beispiele
#include <stdio.h>
enum {ERROR_LESEN = 101,ERROR_SCHREIBEN = 102};
Arrays
typ feldname[groesse];
Beschreibung
Ein Array, auch Datenfeld oder Feld genannt, ist die Zusammenfassung von mehreren Daten
des gleichen Typs zu einer Variablen.
67
Sprachkonzepte und Syntax
Anwendung
Arrays ermöglichen Ihnen, eine (nahezu) beliebige Zahl von Variablen gleichen
Datentyps en bloc zu definieren:
int i[100];
Der Vorteil der Array-Deklaration liegt jedoch nicht nur in der eingesparten Tip-
parbeit. Die einzelnen Elemente eines Arrays werden im Speicher hintereinander, in
einem zusammenhängenden Block abgelegt. Dies bringt eine Reihe interessanter
Vorteile, beispielsweise die Möglichkeit, über einen Index auf einzelne Elemente im
Block zuzugreifen:
i[3] = i[2]+i[1];
Syntax
typ feldname[groesse];
● typ: Die Typangabe legt fest, aus welchen Elementen das Array gebildet wird,
und liefert zusammen mit der groesse Informationen über den Speicherplatzbe-
darf (groesse * sizeof(typ)).
Folgende Datentypen sind für Elemente eines Arrays nicht zulässig: Referen-
zen, Funktionen, abstrakte Klassen.
● feldname: Frei wählbarer Name für die Array-Variable. Array-Typen sind im-
mer an Variablen gebunden. Dies ist eine Besonderheit der Arrays.
● groesse: Die groesse legt die Anzahl der Elemente fest, aus denen das Array be-
steht. Als Größenangabe sind nur konstante Ausdrücke erlaubt, die größer
Null sind. Die Größenangabe kann auch weggelassen werden. In solch einem
Fall muß eine vollständige Deklaration nachfolgen, oder das Array muß bei
der Deklaration mit Hilfe einer Initialisierungsliste initialisiert werden. (Aus
der Anzahl der Initialisierungswerte wird dann die Dimension errechnet.)
Variablendeklaration
int feld[3]; // Array für drei int-Objekte
struct person leser[40]; // 40 Elemente vom
// Typ struct person
Oder
#define ANZAHL 400;
double feld[ANZAHL];
Initialisierung
Es ist möglich, bei der Definition eines Arrays Initialisierungen vorzunehmen. Dem
Namen des Arrays folgt dann das Gleichheitszeichen und in geschweifte Klammern
gefaßt die einzelnen Werte, die zugewiesen werden sollen.
68
Arrays
Warnung
Die Indizierung der Elemente im Array beginnt immer mit 0, weswegen beispiels-
weise die Indizes für ein Array, das als feld[20] deklariert ist, von 0 bis 19 laufen.
Der Zugriff über höhere Indizes ist möglich (der Compiler kontrolliert nicht die
Verwendung korrekter Indizes), führt aber fast ausnahmslos zu Laufzeitfehlern.
Wenn man sowohl die Arraygröße angibt als auch eine Initialisierungsliste defi-
niert, darf letztere nicht mehr Elemente enthalten als durch die Arraygröße festge-
legt.
Beispiele
#include <stdio.h>
#include <stdlib.h>
#include <mem.h>
#define MAX 100 // Anzahl der Elemente in Array
int main()
{
int feld[MAX]; // Array deklarieren
int i;
69
Sprachkonzepte und Syntax
return 0;
}
Verweise
Siehe Mehrdimensionale Arrays
Siehe Zeichenketten (Strings)
Mehrdimensionale Arrays
typ feldname[dim1][dim2];
Beschreibung
Zwei- oder mehrdimensionale Arrays sind Arrays, deren Elemente wiederum Arrays sind.
Auch mehrdimensionale Arrays werden nacheinander im Speicher abgelegt. Das Prinzip funk-
tioniert so, daß der letzte Index sich am schnellsten verändert. Die Elemente des Arrays
int matrix[3][2];
würden im Speicher also in folgender Reihenfolge abgelegt:
matrix[0][0]
matrix[0][1]
matrix[1][0]
matrix[1][1]
matrix[2][0]
matrix[2][1]
Anwendung
Mehrdimensionale Arrays werden am sinnvollsten dort eingesetzt, wo Daten ver-
waltet werden sollen, die von sich aus schon mehrdimensional organisiert sind, so
daß sich eine 1:1-Entsprechung zwischen der natürlichen Anordnung der Daten
und ihrer Abspeicherung im Array ergibt.
70
Mehrdimensionale Arrays
Ein Beispiel wären die Elemente einer zweidimensionalen Matrix, die sich wunder-
bar in einem zweidimensionalen Array verwalten lassen.
Syntax
typ feldname[dim1][dim2];
● typ: Die Typangabe legt fest, aus welchen Elementen das Array gebildet wird.
● feldname: Frei wählbarer Name für die Array-Variable.
● dim: Die Definition enthält so viele Paare eckiger Klammern mit Größenanga-
ben, wie das Array Dimensionen besitzt. Bei mehrdimensionalen Arrays kann
die erste eckige Klammer leer bleiben. Dies erklärt sich dadurch, daß ein
mehrdimensionales Array als ein einfaches Array angesehen wird, dessen Ele-
mente wiederum Arrays sind. Die Größe des Arrays darf später deklariert wer-
den, aber die Größe der Elemente muß bei der Deklaration feststehen.
Variablendeklaration
int feld[3][2];
Initialisierung
Mehrdimensionale Arrays können auf zwei Arten initialisiert werden. Entweder
wird für jede Komponente eine eigene Initialisierungsliste benutzt, die in
geschweifte Klammern eingeschlossen wird, oder jeder Komponenten des unterge-
ordneten Aggregattyps werden die Werte einfach der Reihe nach zugewiesen.
int matrix[][2] = { { 1, 2 },
{ 10, 20 },
{ 100, 200 } };
Oder
int matrix[3][2] = { 1, 2 , 10, 20, 100, 200 };
Beispiele
#include <stdio.h>
#define SPALTEN 10
#define ZEILEN 5
71
Sprachkonzepte und Syntax
int main() {
int x[ZEILEN][SPALTEN];
int i = 0;
int j = 0;
return 0;
}
Ausgabe
a a a a a a a a a a
b b b b b b b b b b
c c c c c c c c c c
d d d d d d d d d d
e e e e e e e e e e
Verweise
Siehe Arrays
Zeichenketten (Strings)
charTyp str[groesse];
Beschreibung
Arrays bieten sich auch als Variablen für Zeichenketten (Strings) an. In diesem Fall sind die
Elemente des Arrays die Zeichen der Zeichenkette.
Anwendung
72
Zeichenketten (Strings)
ANSI C/C++ verwendet zur Repräsentation von Text die sogenannten ASCIIZ-
Strings. Dies sind Zeichenketten, die durch das Zeichen \0 abgeschlossen werden.
Variablen, die einen solchen Strig aufnehmen können, kann man auf verschiedene
Weise deklarieren:
● als Array mit Elementen eines char-Typs.
● als Zeiger auf einen char-Typ.
● als Instanz einer string-Klasse (nur C++).
Entscheidet man sich für ein Array, genießt man den Vorteil, daß zusammen mit
der Array-Deklaration auch gleich der Speicher für den String reserviert wird. Man
muß aber aufpassen, daß man der Array-Variablen keinen String zuweist, der aus
mehr Zeichen besteht als das Array reserviert hat.
Warnung
Beachten Sie zudem, daß ein String in C/C++ immer mit dem Zeichen \0 abge-
schlossen werden muß. Dieses Terminierungszeichen ist bei der Berechnung des
Speicherbedarfs mit einzurechnen.
Syntax
charTyp feldname[groesse];
● charTyp: Als Elementtyp wählt man in diesem Fall char, signed char, unsigned
char oder wchar_t.
● feldname: Frei wählbarer Name für die Array-Variable.
● dim: Anzahl der Zeichen, für die Speicher reserviert wird und die in dem
Array abgelegt werden können.
Initialisierung
char str[ ] = {'e', 'i', 'n', 's', '\0'}; // mit Initialisierungsliste
Oder
char str2[50] = "Dies ist ein String"; // mit String-Literal
wchar_t str3[10] = L"zwei"; // Wide Character-Zeichen (UNICODE)
Bei der Initialisierung mit String-Literalen wird das abschließende Nullterminie-
rungszeichen \0 automatisch durch den Compiler angehängt.
Zuweisung
Die Zuweisung mit Hilfe des Zuweisungsoperators ist nur bei der Initialisierung
möglich. Danach bedient man sich am besten der Funktionen der Laufzeitbiblio-
thek (C-Header-Datei string.h).
strcpy(str2, "Neuer Text"); // kopieren
strcat(str1, str2); // anhängen
73
Sprachkonzepte und Syntax
Beispiele
#include <stdio.h>
#include <string.h>
int main() {
char string1[] = "C und C++";
char string2[] = "C++ und C";
if(strcmp(string1, string2) > 0)
printf("%s ist groesser als %s\n",string1,string2);
else
printf("%s ist kleiner oder gleich %s\n", string1, string2);
return 0;
}
Ausgabe
C und C++ ist kleiner oder gleich C++ und C
Verweise
Siehe Arrays
Siehe Zeichenketten, C-Strings
Strukturen
struct typbezeichner
{
typ1 element1;
typ2 element2;
};
Beschreibung
Strukturen fassen mehrere Daten, die unterschiedlichen Datentypen angehören können, zu
einer Variablen zusammen. In C++ ist eine Struktur ein Sonderfall einer Klasse, in der alle Ele-
mente standardmäßig public sind.
Anwendung
Strukturen sind Datentypen, in denen mehrere Variablen verschiedener Datentypen
zusammengefaßt werden können. Die in der Struktur zusammengefaßten »Varia-
blen« bezeichnet man als Felder oder Elemente der Struktur. Der Vorteil dabei ist, daß
mehrere, logisch zusammengehörende Daten in einem Datentyp vereinigt werden
können.
74
Strukturen
Ein typisches Beispiel wäre die Definition von Variablen zum Abspeichern von
Vektoren. Für einen zweidimensionalen Vektor benötigt man zwei int-Werte für
die x- und die y-Koordinate. Diese als einzelne int-Variablen zu definieren, ist
unbequem und äußerst unübersichtlich:
int v1_x, v1_y; // erster Vektor
int v2_x, v2_y; // zweiter Vektor
Besser ist die Einführung eines Strukturtyps für Vektoren:
struct vektor {
int x;
int y;
};
struct vektor v1, v2;
Warnung
● Eine Struktur kann keine Variable ihres eigenen Typs als Element enthalten.
Zeiger oder Referenzen auf Variablen ihres eigenen Typs sind aber erlaubt.
● In C++ sind Strukturen Klassen mit public-Zugriff auf die Strukturelemente. In
C++ dürfen Strukturen daher auch Funktionen als Elemente enthalten.
Syntax
struct typbezeichner {
typ1 element1;
typ2 element2;
/* weitere Elemente */
};
● typbezeichner: Wird ein typbezeichner spezifiziert, kommt dies einer Typdefini-
tion gleich. Später können dann Variablen dieses Typs definiert werden. In C
lautet der Typ struct typbezeichner, in C++ reicht einfach der typbezeichner.
● typ element: Innerhalb der Klammern werden die Elemente der Struktur dekla-
riert.
75
Sprachkonzepte und Syntax
int y;
float laenge;
} vektor1, vektor2;
Initialisierung
Strukturvariablen können bei ihrer Definition direkt initialisiert werden. Dazu wer-
den die Werte, mit denen die Strukturelemente initialisiert werden sollen, in
geschweiften Klammern aufgelistet und mittels des Zuweisungsoperators der Varia-
blen zugewiesen.
● Es ist nicht erforderlich, alle Elemente der Struktur zu initialisieren.
struct person {
char name[20];
int plz;
char ort[20];
char strasse[20];
};
struct person leser = {"Klaus Müller",
7652 , "Entenhausen", "Duckstr. "
};
Beispiele
struct person {
char name[20];
int plz;
char ort[20];
};
int main() {
struct person leser;
struct person *pleser;
pleser = &leser;
[Link] = 5100;
strcpy([Link], "Otte");
strcpy(pleser->ort, "Karlsbad");
printf("Leser: %s, PLZ: %d Ort: %s\",
[Link], [Link], [Link]);
printf("Leser: %s, PLZ: %d Ort: %s\",
76
Bitfelder
Bitfelder
struct typbezeichner
{
intTyp1 element1 : Zahl;
intTyp2 element2 : Zahl;
};
Beschreibung
Bitfelder sind besondere Elemente in Strukturtypen, für die man explizit angeben kann, wieviel
Bit für das Element benötigt werden.
Anwendung
Bitfelder werden benutzt, wenn Daten gespeichert werden sollen, die weniger als 1
Byte Speicherplatz benötigen. Hierzu gehören zum Beispiel 1 Bit große Flags, die
ausreichen, um Wahrheitswerte darzustellen. Nach der Typangabe und dem optio-
nalen Namen des Elements folgt ein Doppelpunkt. Daran schließt sich ein ganzzah-
liger Wert an, der bestimmt, wie viele Bits diesem Element zur Verfügung gestellt
werden sollen.
Bitfelder werden traditionell häufig zur Speichereinsparung eingesetzt. Dahinter
verbirgt sich die Idee, daß die Bits der Bitfelder hintereinander abgespeichert
werden, daß eine Struktur mit zwei Bitfeldern von 3 und 5 Bit Länge, also bei-
spielsweise ingesamt nur 8 aufeinanderfolgende Bits (1 Byte), belegen würde; ob
dem so ist, hängt allerdings vom Compiler ab. Deswegen und wegen des heute rela-
tiv billigen Arbeitsspeicher, ist von dem Einsatz von Bitfeldern zur Speichererspar-
nis eher abzuraten.
Warnung
● Ein einzelnes Bitfeld muß nach ANSI C immer den Datentyp int, signed int
oder unsigned int besitzen. C++ erlaubt dagegen jeden Typ, der als Integer
interpretierbar ist, also auch char, short, long und Aufzählungstypen.
● Für Bitfelder können keine Zeiger und Referenzen deklariert werden.
● Unbenannte Bitfelder der Größe 0 bewirken, daß das nächste Bitfeld in einer
neuen Allokationseinheit (meist int oder word) beginnt.
77
Sprachkonzepte und Syntax
Syntax
struct typbezeichner {
intTyp1 element1 : Zahl;
intTyp2 element2 : Zahl;
/* weitere Elemente */
};
● typbezeichner: Wird ein typbezeichner spezifiziert, kommt dies einer Typdefini-
tion gleich. Später können dann Variablen dieses Typs definiert werden. In C
lautet der Typ struct typbezeichner, in C++ reicht einfach der typbezeichner.
● typ element : zahl: Innerhalb der Klammern werden die Bitfelder deklariert.
Als Typ dürfen nur int-Typen verwendet werden. Auf den Elementnamen
folgt ein Doppelpunkt und die Angabe der Bits, die für das Bitfeld reserviert
werden sollen. Gibt man keinen Elementnamen an, erhält man ein sogenann-
tes unbenanntes Bitfeld, mit dessen Hilfe man die Ausrichtung der Bitfelder im
Speicher steuern kann. Ein unbenanntes Bitfeld der Größe 0 weist den Compi-
ler an, das nächste Element an den vom Compiler intern zur Speicherauftei-
lung verwendeten Bytegrenzen auszurichten (reduziert die Zugriffszeiten).
Beispiele
struct s_karten {
unsigned int wert : 3;
unsigned int farbe : 2;
unsigned int spieler : 2;
unsigned int gespielt : 1;
} karten[32];
int main() {
int farbe, wert, loop;
for(farbe=0; farbe<4; farbe++)
for(wert=0; wert<8; wert++) {
karten[8*farbe+wert].farbe = farbe;
karten[8*farbe+wert].wert = wert;
karten[8*farbe+wert].spieler = 0;
karten[8*farbe+wert].gespielt = 0;
}
for(loop=0; loop < 32; loop++)
printf("Farbe = %d, Wert = %d\n",karten[loop].farbe,
karten[loop].wert);
return 0;
}
Verweise
Siehe Strukturen
78
Unions
Unions
union typbezeichner {
Typ1 element1;
Typ2 element2;
};
Beschreibung
Eine Union ist ein Datentyp, der für verschiedene Elemente deklariert wird, dessen Variablen
aber nur eines der Elemente aufnehmen können. Die Größe einer Unionvariablen entspricht
der Größe des größten Elements.
Anwendung
Unions sparen gegenüber Strukturen Speicher, wenn nur ein Element benötigt wird,
dessen Typ aber vom Programmierer nicht vorhergesehen werden kann.
Warnung
Eine Union kann keine Variable ihres eigenen Typs als Element enthalten. Zeiger
oder Referenzen auf Variablen ihres eigenen Typs sind aber erlaubt.
Wird eine Unionvariable bei ihrer Definition initialisiert, kann nur dem ersten Uni-
onelement der Wert zugewiesen werden.
In C++ gibt es einige Besonderheiten zu beachten:
● In C++ sind Unions Klassen und dürfen auch Funktionen als Elemente enthal-
ten.
● Virtuelle Elementfunktionen sind nicht erlaubt.
● Unions können nicht Bestandteil von Klassenhierarchien sein.
● Klassen mit eigenen Definitionen für Konstruktor, Destruktor, Kopierkon-
struktor oder Zuweisungsoperator können nicht Element einer Union sein.
Syntax
union typbezeichner {
typ1 element1;
typ2 element2;
/* weitere Elemente */
};
● typbezeichner: Wird ein typbezeichner spezifiziert, kommt dies einer Typdefini-
tion gleich. Später können dann Variablen dieses Typs definiert werden. In C
lautet der Typ union typbezeichner, in C++ reicht einfach der typbezeichner.
● typ element: Innerhalb der Klammern werden die Elemente der Union dekla-
riert.
79
Sprachkonzepte und Syntax
Initialisierung
Bei der Initialisierung wie der Zuweisung kann man nur einem Element der Union
einen Wert zuweisen.
union Login user = {"Geheim"};
Beispiele
#define KENNUNG
union Login{
char passwort[10];
int kennung;
};
int main()
{
union Login user1;
#ifdef KENNUNG
printf("Geben Sie ihre Kennummer ein: \n");
scanf("%d",&[Link]);
fflush(stdin);
#else
printf("Geben Sie ihr Passwort ein: \n");
scanf("%s",[Link]);
fflush(stdin);
#endif
printf("\n");
printf("Groesse der Union: %d\n",sizeof(Login));
return 0;
}
Verweise
Siehe Strukturen
80
Zeiger
Zeiger
typ* zeigervariable;
Beschreibung
Ein Zeiger ist eine Variable, in der sich die Adresse eines Datenobjektes oder einer Funktion
befindet. Die Verwendung von Zeigern bringt verschiedene Vorteile mit sich.
Anwendung
Einsatzgebiete für Zeiger
● Speicherersparnis. Zeigervariablen speichern Adressen. Ihr Speicherbedarf ist
also auf 16 oder 32 Bit festgelegt, wohingegen die Objekte, auf die sie zeigen,
wesentlich größer sein können.
● Übergabe an Funktionen. Durch die Übergabe von Zeigern (call by reference)
an Funktionen wird die Funktion in die Lage versetzt, auf Objekte zuzugrei-
fen, die außerhalb ihres Gültigkeitsbereiches liegen. Zudem ist die Übergabe
von Zeigern wesentlich schneller als das Kopieren großer Datenobjekte. (In
C++ werden aus den gleichen Gründen oft Referenzen übergeben.)
● Dynamische Speicherverwaltung. Mittels Zeigern kann der Programmierer
selbst entscheiden, wann Speicher reserviert und wann freigegeben wird. Zei-
ger erlauben die Implementierung dynamischer Datenstrukturen wie Listen
und Bäume.
● Rekursive Datenstrukturen. Zeiger können für Datentypen definiert werden,
die deklariert, aber noch nicht definiert sind. Auf diese Weise kann eine Klasse
beispielsweise Zeiger auf ihre eigenen Instanzen haben.
● Arrays von Zeigern auf Funktionen sind erlaubt, i.G. zu Arrays von Funktio-
nen.
● Generische Implementierungen. Mit Zeigern lassen sich viele Probleme effizi-
enter und/oder allgemeiner lösen. Beispielsweise durch Verwendung von Zei-
gern auf void, Zeigern auf Funktionen, um Funktionen als Argumente an
andere Funktionen zu übergeben, Basisklassenzeiger auf abgeleitete Objekte
zur Verwaltung von Objekten verschiedener abgeleiteter Klassen in einem Ar-
ray, Nutzung virtueller Methoden statt expliziter Laufzeitidentifizierung,
81
Sprachkonzepte und Syntax
Warnung
Ein Zeiger kann auf jedes beliebige Datenobjekt zeigen, mit zwei Ausnahmen:
● Referenzen und
● Bitfelder.
Syntax
typ* zeigervariable;
● typ: Datentyp der Objekte, auf die der Zeiger weist. Diese Angabe wird für die
korrekte Dereferenzierung des Zeigers benötigt.
● *: kennzeichnet die Variable als Zeiger und kann sowohl hinter der Typanga-
be stehen als auch vor dem Zeigernamen.
● zeigervariable: Name des Zeigers.
Initialisierung
Die Initialisierung eines Zeigers erfolgt durch die Zuweisung einer Adresse und
eines mit der Adresse verbundenen Speicherbereichs. Die Initialisierung kann auf
verschiedene Weisen geschehen.
1. Zuweisung der Adresse eines existierenden Objekts.
● Die Adresse einer Variablen kann über den Adreß-Operator & ermittelt wer-
den.
● Zeiger sind selbst Adressen.
● Die Namen von Arrays und Funktionen stellen ebenfalls Adressen dar.
int i_var = 13;
int *ptr1 = &i_var;
int *ptr2 = ptr1;
int feld[10] = {11,11,11};
ptr3 = feld;
2. Zuweisung von NULL.
● Zeiger, die auf kein Objekt gerichtet sind, sollten mit der NULL-Adresse in-
itialisiert werden. Auf diese Weise kann leicht getestet werden, ob der Zeiger
auf ein Objekt weist oder nicht.
double *ptr4 = NULL;
82
Zeiger
Dereferenzierung
Zeiger sind Adressen. Dereferenzierung bedeutet, über diese Adresse auf das refe-
renzierte Objekt zuzugreifen. Dazu dienen die Dereferenzierungs-Operatoren *, -
>,.* und ->* .
● *: der eigentliche Dereferenzierungs-Operator.
● ->: eine Verbindung aus Dereferenzierungs- und Punkt-Operator, der einen
Zeiger auf einen Klassentyp dereferenziert und gleichzeitig auf ein Element des
referenzierten Objekts zugreift.
● .*: dereferenziert einen Zeiger auf ein Klassenelement für ein gegebenes Klas-
senobjekt.
● ->*: dereferenziert einen Zeiger auf ein Klassenelement für einen gegebenen
Zeiger auf ein Klassenobjekt.
Beispiel
#include <stdio.h>
int main() {
int i;
int *p_i = &i; // Deklaration und Initialisierung
struct koord {
int x,y;
} pos;
struct koord *p_pos1 = &pos; // Deklaration und Initialisierung
// Dereferenzierung
*p_i = 2;
(*p_pos1).x = 3; // Dereferenzierung einer Struktur mit *
p_pos1->y = p_pos1->x+1; // Dereferenzierung einer Struktur mit ->
return 0;
}
83
Sprachkonzepte und Syntax
Warnung
● Das Zeichen * wird also in der Deklaration dazu benutzt, eine Zeigervariable
zu spezifizieren. In Anweisungen teilt es dem Compiler mit, daß nicht die
Adresse, die in der Zeigervariablen gespeichert ist, gefragt ist, sondern das
Objekt, das an dieser Adresse abgelegt ist.
● Ein Zeigername ist eine Adresse. Diese Adresse verweist auf die Speicherzelle,
in der der Wert des Zeigers abgelegt wird. Der Wert eines Zeigers ist ebenfalls
eine Adresse. Diese Adresse wird benutzt, um auf andere Datenobjekte zu ver-
weisen.
● Dereferenzieren Sie niemals Zeiger, die ungültige Adressen beinhalten (nicht-
initialisierte Zeiger, Zeiger auf Objekte, die nicht mehr existieren, etc.).
Spezielle Zeiger
Zeiger auf Zeichenketten char*
Ein Zeiger vom Typ char* weist auf ein einzelnes Zeichen. Viele Bibliotheksfunktio-
nen, die Zeichenketten verarbeiten (strcpy(), strlen() etc.), erwarten als Argument
solch einen Zeiger auf das erste Zeichen einer zu verarbeitenden Zeichenkette. Die
so übergebene Zeichenkette beginnt mit der Adresse, die der Zeiger liefert, und
endet mit dem ersten Auftauchen des Nullzeichens '\0'.
Bei der Verwendung der entsprechenden Bibliotheksfunktionen ist daher darauf zu
achten, daß die übergebenen Zeiger auch stets auf nullterminierte Zeichenketten
verweisen, und daß Zeichenketten nur in Speicherbereiche kopiert oder geschrieben
werden, die groß genug sind, die gesamte Zeichenkette einschließlich Nullterminie-
rungszeichen aufzunehmen. Ansonsten kommt es zu unerwünschten Speicherzugrif-
fen – meist begleitet von Programmabstürzen.
char str[20] = "Hello World!";
// reserviere Speicher so groß wie der String in str plus '\0'
p_str = (char*) malloc(strlen(str)+1);
strcpy(p_str,str);
84
Spezielle Zeiger
// Initialisierung:
int person::* int_ptr = &person::plz;
85
Sprachkonzepte und Syntax
// Zugriff:
class person leser, *p_leser;
leser.*int_ptr = 66111;
p_leser->*int_ptr = 66111;
// Initialisierung:
void (person::*func_ptr) (int) = &leser::print_adresse;
// Zugriff:
class person leser, *p_leser;
(leser.*func_ptr) (64);
(p_leser->*func_ptr) (64);
Basisklassenzeiger (basis*)
In C++ kann jedes abgeleitete Objekt auch als Objekt einer seiner eindeutigen Basis-
klassen angesehen werden. Entsprechend kann ein Zeiger auf ein abgeleitetes Objekt
ohne Probleme in einen Zeiger auf eines seiner eindeutigen Basisklassen umgewandelt
werden. Dies erlaubt beispielsweise, die Verwaltung abgeleiteter Objekte unter-
schiedlicher Klassen als Basisklassenobjekte in einem gemeinsamen Array.
Basisklassenzeiger werden zumeist in Zusammenhang mit virtuellen Methoden einge-
setzt.
class Basis {...}; // Klassenhierarchie
class Abg1 : public Basis {...};
class Abg2 : public Basis {...};
86
Referenzen (nur C++)
this-Zeiger this
Jede nicht-statische Methode einer Klasse erhält vom Compiler intern einen zusätz-
lichen Parameter zugewiesen. Dies ist der this-Zeiger, der auf die Anfangsadresse
der jeweiligen Instanz verweist, für die die Methode aufgerufen wird.
#include <iostream>
using namespace std;
class demo
{
public:
void func() {cout << this;}
};
int main()
{
class demo d1,d2;
cout << "This-Zeiger der Instanz d1 = " << [Link]() << endl;
cout << "This-Zeiger der Instanz d2 = " << [Link]() << endl;
return 0;
}
Beschreibung
Referenzen verweisen wie Zeiger auf Objekte, können jedoch nur einmal mit einem Objekt
initialisiert und danach nicht mehr auf andere Objekte umgelenkt werden. Zudem entfällt für
Referenzen die typische Zeigersyntax sie werden wie ganz normale Variable, quasi als Syn-
onyme der Variablen, auf die sie verweisen, verwendet.
Technisch gesehen entspricht eine Referenz damit einem const-Zeiger, der bei jedem Zugriff
automatisch dereferenziert wird.
Anwendung
Referenzen, auch Aliase genannt, sind im Gebrauch den Zeigern verwandt und
werden in ähnlicher Weise zur Übergabe von Variablen an Funktionen eingesetzt,
wenn die Funktionen die übergebenen Variablen direkt ändern (call by reference)
oder Laufzeitverschlechterungen durch Kopieren großer Datenobjekte vermieden
werden sollen. Referenzen haben dabei aber den Vorteil,
● daß sie wie normale Variablen angesprochen werden (die zeigertypische Dere-
ferenzierungssyntax entfällt)
● daß ihr Einsatz sicherer ist als der von Zeigern (da sie immer auf ein genau de-
finiertes Objekt verweisen)
87
Sprachkonzepte und Syntax
Warnung
Eine Referenzvariable muß direkt bei ihrer Deklaration initialisiert werden, außer
● sie ist explizit als extern deklariert,
● es handelt sich um einen Funktionsparameter,
● es handelt sich um ein Klassenelement.
Eine Referenzvariable kann nur auf eine Variable gesetzt werden. Sie kann nicht
auf eine andere Variable umgesetzt werden!
Es lassen sich keine Zeiger auf Referenzen definieren.
Es lassen sich keine Arrays von Referenzen bilden.
Es gibt keine Referenzen auf Referenzen.
Referenzen können nicht vom Typ void& sein.
Syntax
typ& referenzname = var;
● typ: Datentyp des Objekts, auf das die Referenz verweist.
● &: Referenzoperator &, der in der Deklaration eine Variable als Referenz
kennzeichnet.
● referenzname: Name der deklarierten Referenzvariablen.
● = var: Referenzen müssen direkt bei der Definition initialisiert werden.
Beispiele
Das folgende Beispiel demonstriert die Übergabe von Argumenten an Referenzpara-
meter.
#include <iostream>
using namespace std;
class Leute {
int alter;
public:
Leute(int age) {alter = age;}
void altern() {alter++;}
int get_alter() {return alter;}
};
int main()
88
Typdefinitionen
{
Leute dennis(30);
cout << "Dennis ist " << dennis.get_alter()
<< " Jahre alt\n";
Warnung
Bei der Parameterübergabe müssen Datentyp des Referenzparameters und Datentyp
des Arguments genau übereinstimmen. Ansonsten gilt:
● Für const-Referenzparameter nimmt der Compiler eine Typumwandlung vor
und erzeugt eine zu dem Referenzparamter passende temporäre Variable. Der
Referenzparameter weist dann auf diese temporäre Variable. Die Zurückliefe-
rung von Werten über den Parameter an das Aufrufargument ist daher nicht
mehr möglich, für const-Parameter aber auch sicherlich nicht vorgesehen.
● Für nicht-const-Referenzparameter gibt der Compiler eine Fehlermeldung aus.
(Einige ältere Compiler geben nur eine Warnung aus und legen eine temporäre
Variable an.)
Typdefinitionen
typedef
Beschreibung
C erlaubt die Definition beliebiger Datentypen auf der Grundlage der im Sprachumfang enthal-
tenen Typen. Bei einer Typdefinition wird ein neuer Typ spezifiziert und mit einem Bezeichner
für den Typ verbunden. Eine solche Typdefinition kann durch die Schlüsselworte struct, union,
class oder typedef erfolgen.
89
Sprachkonzepte und Syntax
Anwendung
Mit typedef werden im Grunde keine neuen Typen definiert, sondern lediglich Syn-
onyme für bereits mögliche Typspezifikationen eingerichtet. Dies kann aus zwei
Gründen geboten sein:
● Eine Typdefinition soll per Präprozessorschalter anpaßbar sein (erstes Bei-
spiel).
● Eine komplexe Typdefinition soll durch ein einfaches Synonym repräsentiert
werden (zweites Beispiel)
Warnung
typedef-Typen sind nicht erweiterbar:
typedef int INT;
unsigned INT x; // nicht erlaubt
Syntax
typedef typ_spezifikation typbezeichner;
● typ_spezifikation: Hier wird der neue Typ definiert. Die Form der Typangabe
entspricht der Angabe in Variablendeklarationen.
● typbezeichner: Name für den neuen Typ.
Beispiele
Typdefinitionen in Abhängigkeit von Compiler-Schaltern:
#if defined (LONG)
typedef wchar_t long;
#else
typedef wchar_t int;
#endif
Typdefinitionen als Vereinfachungen:
typedef unsigned int UINT; // Beispiel aus windows.h
typedef void (*func_typ) (int, int); // definiert func_typ
Standardkonvertierungen
Beschreibung
In verschiedenen Situationen nimmt der Compiler automatische Typkonvertierungen vor.
Anwendung
Die wichtigsten automatischen Konvertierungen sind:
90
Standardkonvertierungen
Bezeichner
● Auf der rechten Seite von Zuweisungen werden Bezeichner als R-Werte (Wert,
nicht Speicheradresse) aufgefaßt.
● Array-Namen werden auf der rechten Seite von Anweisungen (inklusive Funk-
tionsaufrufen) als Zeiger auf ihr erstes Element aufgefaßt.
● Funktionsnamen repräsentieren auf der rechten Seite von Anweisungen den
Rückgabewert der Funktion.
Typangleichung
● Arithmetische Datentypen können ineinander konvertiert werden, wenn der
Datentyp, in den konvertiert wird, geeignet ist, den zu konvertierenden Wert
aufzunehmen (bei Konvertierung von Gleitkommazahlen in Integer-Werte geht
dabei der Nachkommaanteil verloren).
● Für binäre Operatoren, die arithmetische Operanden übernehmen, gleicht der
Compiler automatisch die Typen beider Operanden an – man bezeichnet dies
als die standardmäßige arithmetische Konvertierung.
Boolesche Wahrheitswerte
● Null-Zeiger und Null-Repräsentationen arithmetischer Datentypen können in
den Booleschen Wert false konvertiert werden, andere Werte dieser Daten-
typen werden entsprechend als true interpretiert.
● Umgekehrt kann der Boolesche Wert false in eine arithmetische Null, true in
eine Eins konvertiert werden.
91
Sprachkonzepte und Syntax
● Wenn Sie einer Klasseninstanz einen Wert zuweisen und in der Klasse ein ent-
sprechender Konstruktor definiert ist, der mit genau einem Argument des
Typs aufgerufen wird, dem auch der Wert angehört, wird der Konstruktor wo
nötig zur automatischen Konvertierung von Werten des entsprechenden Da-
tentyps in Objekte der Klasse herangezogen (kann durch explicit-Deklaration
unterbunden werden).
Beispiele
Operandenkonvertierung
float f = 3/4; // ergibt 0.0;
// Integer-Division von 3/4 ergibt 0
// 0 wird für Zuweisung in 0.0 umgewandelt
float f = 3/4.0; // ergibt 0.75;
// 4.0 ist Gleitkommazahl, der Integer-Operand 3
// wird daher in Gleitkommazahl umgewandelt
// Es wird eine Gleitkomma-Division durchgefuehrt
Konstruktoren mit einem Argument
class Feld {
public:
int anzahl;
Feld(int a) {anzahl = a;}
};
...
Feld stack(3);
stack = 13; // impliziter Aufruf: stack = Feld(13);
Typumwandlung
(typ) wert
Beschreibung
Gelegentlich ist es wünschenswert, daß eine Variable eines bestimmten Datentyps als einem
anderen Datentyp angehörig behandelt wird. Sofern eine solche Typumwandlung durchführbar
ist, kann sie durch den C-Cast-Operator () oder die C++-Operatoren const_cast, dynamic_cast,
static_cast und reinterpret_cast, die als Schlüsselworte in die Sprache aufgenommen sind,
explizit herbeigeführt werden.
92
Typumwandlung
Anwendung
Für Typkonvertierungen gibt es fünf typische Gründe:
● Sie wollen eine Gleitkommazahl in eine Integer-Zahl verwandeln oder umge-
kehrt. Letzeres ist beispielsweise geboten, wenn Sie eine Integer-Zahl durch
eine andere Integer-Zahl teilen wollen, das Ergebnis aber mit Divisionrest in
einer Gleitkommavariablen gespeichert werden soll.
● Sie haben einen void-Zeiger vorliegen, den Sie in einen Zeiger auf einen be-
stimmten Datentyp umwandeln wollen.
● Sie haben einen Basisklassenzeiger auf ein abgeleitetes Objekt, den Sie in einen
Zeiger auf die abgeleitete Klasse umwandeln wollen.
● Sie wollen durch die Typumwandlung eines Zeigers eine bestimmte Speicher-
interpretation erzwingen. Diese Möglichkeit ist selten erforderlich, dafür aber
recht fehleranfällig.
Operator Einsatzgebiet
static_cast<Typ>(var) Zur Umwandlung zwischen »nahe verwandten« Typen
– also alle Fälle, in denen der Compiler auch eine impli-
zite Konvertierung vornehmen könnte, plus einige
einfache Sonderfälle.
reinterpret_cast<Typ>(var) Für fast alle anderen erlaubten Umwandlungen.
const_cast<Typ>(var) Entfernt eine const- oder volatile-Deklaration aus
einem Typ.
dynamic_cast<Typ>(var) Zur Umwandlung zwischen Zeigern oder Referenzen
auf Klassentypen einer gemeinsamen Klassenhierarchie
93
Sprachkonzepte und Syntax
Beispiele
int i = int(3.14);
double var = (double) 13/2);
int ptr = (int *) malloc(80 * sizeof(int));
Konstanten
Konstanten
Beschreibung
Neben den Variablen stellen die Konstanten die zweite Möglichkeit zur Repräsentation von
Daten in Programmen dar. Der Unterschied zwischen Variablen und Konstanten liegt auf der
Hand: Während eine Variable im Laufe eines Programms unterschiedliche Werte annehmen
und repräsentieren kann, stellt eine Konstante immer einen festen Wert dar.
C/C++ kennt 3 verschiedene Typen von Konstanten:
Literale
Symbolische Konstanten
Konstante Variablen
Anwendung
Konstanten stellen eine Möglichkeit dar, feststehende Daten direkt im Programm-
code zu verankern: etwa um den Zahlenwert von PI in eine Formel einzubauen
oder in Form einer String-Tabelle für Fehlermeldungen des Programms.
Literale
Beschreibung
Die einfachste Form der Konstante ist ein konstanter Wert. Um sie von den konstanten Varia-
blen zu unterscheiden, bezeichnet man die konstanten Werte auch als Literale.
94
Literale
Anwendung
Konstante Werte werden bei der Übersetzung durch den Compiler hartcodiert,
d. h., die Werte sind nicht irgendwo im Speicher abgelegt, von wo sie bei Bedarf
ausgelesen werden können, sondern die Werte stehen direkt in den betreffenden
Maschinenbefehlen.
Die einzige Ausnahme: für String-Literale wird Speicher reserviert, doch hat der
Programmierer üblicherweise keinen Zugriff auf diesen Speicherbereich.
printf("Hello World\n");
Die automatische Speicherallokation erlaubt allerdings die Zuweisung von String-
Literalen an Zeiger auf char.
char *str1;
str1 = "Hello World\n";
Datentyp Literal
bool true, false
char 'c', 'Ü', '\n', '\\',
'ab' (Multibyte-Zeichen)
wchar_t L'c', L'Ü', L'\n', L'\\',
L'ab' (Multibyte-Zeichen)
Zeichenketten (char*) "Dies ist ein String"
Zeichenketten (wchar_t*) L"Dies ist ein String"
short 12, -128
int 12, -128, 128u, 1277U
012, -077 (Oktal)
0x12, 0XEE (Hexadezimal)
long 12l, 1400000L, 12lu
float 47.11f, 12.0F, 10e-2F
double 47.11, 12.0, 10e-2
long double 47.11l, 12.0L, 10e-2L
Warnung
Wichtig bei der Verwendung von Literalen ist, daß Sie sich an die vorgesehene Syn-
tax zur Angabe der Werte halten, damit der Compiler aus dem Wert auch den
zugehörigen Datentyp ablesen kann.
95
Sprachkonzepte und Syntax
Beispiele
int i = 513; // Zuweisung einer Konstanten an eine Variable
double feld[30]; // Angabe der Array-Groesse
if( (x < 100) && (x > 50)) // Zur Formulierung von
if(!strcmp(str,"Vergleichstext"); // Bedingungen
Verweise
Siehe #define
Siehe const-Variablen
Anwendung
Wird eine Konstante mehrfach verwendet, ist es sinnvoll, sie vorab zu deklarieren
und mit einem symbolischen Namen zu verbinden, der dann im weiteren Verlauf
des Programms die Konstante repräsentiert. Dies ermöglicht die Präprozessor-
Direktive #define:
#define symbolBezeichner KONSTANTE
Danach kann der symbolische Bezeichner im weiteren Quelltext stellvertretend für
die Konstante eingesetzt werden. Bei der Kompilation werden alle Vorkommen des
symbolischen Bezeichners durch die zugehörige Konstante ersetzt.
Der Vorteil besteht einmal darin,
● daß Sie eine Konstante mit einem aussagekräftigen Namen verbinden können,
und
● zum anderen nur die #define-Anweisung anpassen müssen, wenn Sie die Kon-
stante mit einem anderen Wert verbinden wollen (beispielsweise ist es sinn-
voll, Obergrenzen für Arrays, Abbruchbedingungen für Schleifen oder Schalter
für die bedingte Kompilation mit Hilfe von #define am Dateianfang festzule-
gen, damit man sie später bei Bedarf schnell findet und zentral ersetzen kann).
Vordefinierte Konstanten
Eine Reihe interessanter Konstanten sind bereits in den Header-Dateien der Stan-
dardbibliothek vordefiniert, so zum Beispiel
96
#define – symbolische Konstanten
Beispiele
#define STUNDE 60
#define dutzend 12
#define Name "C++Compiler"
Der symbolische Bezeichner ist lediglich ein Aliasname für ein Literal. Vor der
eigentlichen Übersetzung in Objektcode geht der Compiler (genauer gesagt der Prä-
prozessor) den Quelltext durch und ersetzt alle Vorkommen des symbolischen
Bezeichners durch die zugehörige Konstante. Wenn es dann an die eigentliche Über-
setzung geht, sieht der Quelltext so aus, daß es keine symbolischen Konstanten,
sondern nur noch Literale gibt:
Original-Quelltext
#define MAX 30
double feld[MAX];
...
for (int i = 0; i < MAX; i++) {...}
...
for (int i = 0; i < MAX; i++) {...}
...
if (i < MAX) {...}
Nach Bearbeitung durch Präprozessor:
double feld[30];
...
for (int i = 0; i < 30; i++) {...}
...
for (int i = 0; i < 30; i++) {...}
...
if (i < 30) {...}
Verweise
Siehe Zusammengesetzte Datentypen, Aufzählungstypen
97
Sprachkonzepte und Syntax
Anwendung
Konstante Variablen werden mit den Schlüsselwort const deklariert. Sie sind aus
Sicht des Compilers keine echten Konstanten, sondern vielmehr Variablen, die er
vorm Überschreiben schützt.
In C wie C++ kann man mit const
● beliebige Objekte (also auch Variablen selbst definierter Datentypen wie
Strukturen und Klassen) als konstant deklarieren,
● verhindern, daß als Zeiger übergebene Funktionsargumente in einer Funktion
verändert werden,
● Zuweisungsmöglichkeiten erweitern,
● stärker von der Typprüfung des Compilers profitieren.
Warnung
In C++ wird eine konstante Variable wie eine echte Konstante angesehen.
In C, das nach ANSI ebenfalls das Schlüsselwort const kennt, können konstante
Variablen jedoch nicht an Stellen verwendet werden, an denen der Compiler eine
Konstante bzw. einen konstanten Ausdruck erwartet – also
● nicht bei der Angabe der Größe eines Arrays,
● nicht als case-Marken.
Beispiele
const int monate = 12;
int func (const int par1, const char *par2);
Verweise
Siehe Literale
Siehe #define
Siehe Klassen, Konstante Datenelemente und Methoden
98
Operatoren
Operatoren
Operatoren
Beschreibung
ANSI C/C++ kennt mehr als 40 Operatoren. Mit diesem Wert übersteigt bei C/C++, und das ist
bei Programmiersprachen nicht üblich, die Anzahl der Operatoren die Anzahl der Schlüsselwör-
ter der Sprache. Der größte Teil der Operatoren stammt bereits aus der Zeit der ersten Sprach-
definition durch Kernighan & Ritchie.
Bei den hier aufgelisteten Formen der Operatoren handelt es sich um ihre ursprüng-
lichen Definitionen und nicht um überladene Versionen. Die meisten der Operato-
ren können von Programmen überladen werden (nicht jedoch für die elementaren
Datentypen, für die sie bereits standardmäßig definiert sind) und nur unter Beibe-
haltung ihrer üblichen Syntax.
Operator Kurzbeschreibung
+ addiert zwei Operanden
+= addiert zwei Operanden und weist Ergebnis zu
- subtrahiert zwei Operanden
-= subtrahiert zwei Operanden und weist Ergebnis zu
* multipliziert zwei arithmetische Operanden
*= multipliziert zwei arithmetische Operanden und weist Ergebnis zu
/ dividiert zwei arithmetische Operanden
/= dividiert zwei arithmetische Operanden und weist Ergebnis zu
% Modulo-Operator, ermittelt den Rest einer Ganzzahldivision
%= Modulo-Operator mit gleichzeitiger Zuweisung
! Nicht-Operator, Verneinung
not Nicht-Operator, Verneinung
!= vergleicht zwei arithmetische Operanden auf Ungleichheit
not_eq vergleicht zwei arithmetische Operanden auf Ungleichheit
& Bei einem Operanden liefert dieser Operator die Adresse des Operanden
& Bei zwei Operanden wird eine bitweise UND-Verknüpfung ausgeführt
bitand Bitweise UND-Verknüpfung
&= Bitweise UND-Verknüpfung und Zuweisung
and_eq Bitweise UND-Verknüpfung und Zuweisung
&& Logische UND-Verknüpfung
99
Sprachkonzepte und Syntax
Operator Kurzbeschreibung
and Logische UND-Verknüpfung
() Cast-Operator, erzwingt Typumwandlung
, Operator für sequentielle Auswertung, Kommaoperator
++ inkrementiert den Operanden
-- dekrementiert den Operanden
-> Elementverweis-Operator
. Punkt-Operator
* Indirektions-Operator
= Zuweisungsoperator
== testet auf Gleichheit
< Kleiner als
> Größer als
<= Kleiner als oder gleich
=> Größer als oder gleich
<< Bitweise Linksverschiebung
<<= Bitweise Linksverschiebung und Zuweisung des Ergebnisses
>> Bitweise Rechtsverschiebung
>>= Bitweise Rechtsverschiebung und Zuweisung des Ergebnisses
?: Bedingungsoperator
[] Array-Indizierung
^ Bitweises exklusives ODER
xor Bitweises exklusives ODER
^= Bitweises exklusives ODER und Zuweisung des Ergebnisses
xor_eq Bitweises exklusives ODER und Zuweisung des Ergebnisses
| Bitweises ODER
bitor Bitweises ODER
|= Bitweises ODER und Zuweisung des Ergebnisses
or_eq Bitweises ODER und Zuweisung des Ergebnisses
|| Logisches ODER
or Logisches ODER
~ Komplement
compl Komplement
: Klasseninitialisierer
:: Bereichsoperator
.* Dereferenzierung von Zeigern auf Klassenelemente
->* Dereferenzierung von Zeigern auf Klassenelemente
100
Vorzeichen
Operator Kurzbeschreibung
sizeof ermittelt Größe des Operanden in Bytes
new Dynamische Speicherreservierung
new[] Dynamische Speicherresevierung für Arrays
delete Speicherfreigabe
delete[] Speicherfreigabe für Arrays
# Zeichenkettenbildung
## Grundsymbolverbindung
defined testet, ob Makro definiert ist
typeid Dynamische Typinformation
Klassifizierung
Alle Operatoren lassen sich, je nachdem, mit wie vielen Operanden sie arbeiten,
einer der folgenden Gruppen zuordnen:
● unäre Operatoren (arbeiten mit einem Operanden),
● binäre Operatoren (arbeiten mit zwei Operanden) und
● ternäre Operatoren (arbeiten mit drei Operanden).
Vorzeichen
Beschreibung
Unärer Operator der festlegt, ob ein Zahlenwert positiv oder negativ ist.
Anwendung
Mit den unären Operatoren »+« und »-« können Sie arithmetischen Typen ein Vor-
zeichen zuweisen. Werte ohne Vorzeichen sind automatisch positiv.
Operator Bedeutung
+ positiver Wert
- negativer Wert
Beispiele
int var1, var2;
var1 = -3;
var2 = 3 * -var1;
101
Sprachkonzepte und Syntax
Arithmetische Operatoren
Beschreibung
Binäre Operatoren zur Durchführung der algebraischen Verknüpfungen: Addition, Subtraktion,
etc., sowie der Divisionsrestberechnung.
Anwendung
Mit den arithmetischen Operatoren können Sie, wie es der Name vermuten läßt,
einfache arithmetische Operationen durchführen, wie sie auch in anderen Program-
miersprachen üblich sind.
Operator Bedeutung
+ Addition
- Subtraktion
* Multiplikation
/ Division
% Modulo, Rest einer Ganzzahldivision
Warnung
● Werden in einem Ausdruck mehrere Operatoren verwendet, gilt: Punktrech-
nung geht vor Strichrechnung. Vorzeichen, Inkrement und Dekrement kom-
men vor Punktrechnung. Bei gleicher Priorität werden die Operatoren von
links nach rechts abgearbeitet.
● Generell gilt, daß jeder Operator einer Prioritätstufe zugeordnet ist, und Ope-
ratoren höherer Priorität vor Operatoren niedrigerer Priorität ausgewertet
werden.
● Durch Setzen von Klammern können Sie die Reihenfolge der Auswertung von
Operatoren selbst festlegen.
Beispiele
var1 = 5+3;
var2 = 20 % var1; // = 4
var2 = 3 * 4 + var1; // = 20
var2 = 3 * (4 + var1); // = 36
Verweise
Siehe Priorität und Assoziativität
102
In- und Dekrementoperator
Anwendung
Die Programmiersprache C/C++ stellt zwei Operatoren zur Verfügung, mit denen
der Wert einer Variablen inkrementiert (um eins erhöht) oder dekrementiert (um
eins vermindert) werden kann, wobei die Operatoren vor oder nach der Variablen
stehen können.
lwert++
++lwert
lwert--
--lwert
Die Position des Operators legt fest, wann die Erhöhung oder Erniedrigung der
Variablen berechnet wird. Wichtig ist dies, wenn der Operator in komplexeren
Ausdrücken verwendet wird.
int var1, var2 = 12, var3 = 12;
var1 = 3 * ++var2; // ergibt var1 = 39
var1 = 3 * var3++; // ergibt var1 = 36
Die Notation, bei der der Operator vor der Variablen steht, wird Präfix-Schreib-
weise genannt und führt dazu, daß der Wert der Variablen zuerst neu berechnet
wird, bevor er benutzt wird. In der Postfix-Schreibweise (der Operator steht nach
der Variablen) wird der Wert des Operanden benutzt, bevor er verändert wird.
Operator Bedeutung
++ Inkrementoperator, erhöht seinen Operanden um 1
-- Dekrementoperator, vermindert seinen Operanden um 1
Warnung
● Die In- und Dekrementoperatoren sind nicht für Aufzählungstypen definiert.
● Die In- und Dekrementoperatoren können auch bei Zeigern benutzt werden.
In diesem Fall wird die Adresse um die Größe des Objekts, auf das der Zeiger
zeigt, erhöht oder vermindert.
● Das Inkrement einer Variablen vom Typ bool ergibt 1, das Dekrement ist nicht
definiert.
103
Sprachkonzepte und Syntax
Beispiel
#include <stdio.h>
int main() {
int x,y;
x = 5;
y = 5;
printf("Wert von ++x ist %d\n", ++x);
printf("Wert von y++ ist %d\n", y++);
printf("x nach der Inkrementierung: %d\n", x);
printf("y nach der Inkrementierung: %d\n", y);
return 0;
}
Das Programm erzeugt folgende Ausgabe:
Wert von ++x ist 6
Wert von y++ ist 5
x nach der Inkrementierung: 6
y nach der Inkrementierung: 6
Zuweisungen
Beschreibung
Mit Zuweisungsoperatoren können Werte zugewiesen und verändert werden. Neben dem ein-
fachen Zuweisungsoperator gibt es auch die sogenannten zusammengesetzten Zuweisungs-
operatoren, mit denen in einer Anweisung sowohl eine Berechnung als auch eine Zuweisung
durchgeführt werden kann.
Anwendung
Grundsätzlich gilt, daß mit einer Zuweisung dem linken Operanden der Wert des
rechten Operanden zugewiesen wird. Damit dies möglich ist, muß der linke Ope-
rand veränderbar sein, sich also auf eine Adresse im Speicher beziehen. Diese Aus-
drücke werden als »L-Wert« bezeichnet.
Einfache Zuweisung =
Bei der einfachen Zuweisung erhält der linke Operand den Wert des rechten Ope-
randen.
int main() {
int bestand, eingang;
bestand = 10;
eingang = 20;
bestand = bestand + eingang;
return 0;
}
104
Zuweisungen
int main() {
Abgeleitet abg;
Basis bs;
105
Sprachkonzepte und Syntax
Vergleichende Operatoren
Beschreibung
Mit den vergleichenden Operatoren, die auch relationale Operatoren genannt werden, wird ein
Vergleich zwischen zwei Operanden, die auch Ausdrücke sein können, durchgeführt. Das Ergeb-
nis dieser Operation ist entweder wahr oder falsch.
Anwendung
Ausdrücke, die vergleichende Operatoren enthalten, werden häufig als Kontrollbe-
dingung in do-, while- oder for-Schleifen und if-Anweisungen eingesetzt.
Operator Bedeutung
== Gleich
!= Ungleich
< Kleiner als
> Größer als
<= Kleiner als oder gleich
>= Größer als oder gleich
Warnung
● Das Ergebnis eines Vergleichs ist ein Wahrheitswert (true, false).
● Jeder Wert, der ungleich 0 ist, wird von C/C++ als true interpretiert.
● Zwei Zeiger gleichen Typs, die auf das gleiche Objekt weisen, sind gleich.
● Zeiger auf verschiedene Elemente einer Klasse sind ungleich, wobei spätere
Deklarationen höhere Adressen haben. Dies gilt allerdings nur, wenn kein Zu-
griffsspezifizierer zwischen den Deklarationen steht. Sollte dies der Fall sein,
ist das Ergebnis undefiniert.
Beispiele
if (var1 <= var2)
funktion();
do {
ergebnis = funktion();
} while (ergebnis != 0);
Logische Operatoren
Beschreibung
Die logischen Operatoren dienen der Verknüpfung oder Negierung logischer Aussagen.
106
Logische Operatoren
Anwendung
Die Programmiersprache C kennt drei logische Operatoren: UND, ODER und
NICHT. Beim logischen UND- und ODER-Operator wird der Wahrheitswert der
Operanden verknüpft, der logische NICHT-Operator konvertiert den logischen
Wert seines Operanden in dessen Gegenteil. Die Operanden müssen als Boolesche
Werte (true, false) interpretierbar sein.
Operator Bedeutung
&& Logisches UND
|| Logisches ODER
! Logisches NICHT
logisches ODER ||
Der logische ODER-Operator verknüpft seine Operanden, so daß das Ergebnis der
Verknüpfung den Wert true hat, wenn einer oder beide Operanden den Wert true
hat.
Die Operanden werden von links nach rechts ausgewertet. Wenn der erste Operand
den Wert true (also ungleich Null) ergibt, wird der zweite Operand nicht ausgewer-
tet. Die folgende Wahrheitstabelle zeigt Ihnen die möglichen Kombinationen:
107
Sprachkonzepte und Syntax
Beispiele
Das Beispielprogramm gibt eine formatierte ASCII-Tabelle auf den Bildschirm aus.
In Zeile 7 wird der logische UND-Operator eingesetzt, um zu erreichen, daß die
Ausgabe nur dann erfolgt, wenn spalte einen Wert kleiner als 13 hat (pro Zeile sol-
len dreizehn Zeichen ausgegeben werden) und der Wert von zeichen kleiner ist als
256 (um auch nur die ASCII-Zeichen auszugeben).
In Zeile 8 wird der logische ODER-Operator eingesetzt, um zu erreichen, daß auch
die Zeichen des erweiterten IBM-Zeichensatzes ausgegeben werden, da isprint()
nur für die ASCII-Zeichen mit den Codes 32 bis 126 das Resultat true liefert.
#include <ctype.h>
int main() {
int zeile, spalte, zeichen;
printf("ASCII-Tabelle\n");
for(zeile = 0, zeichen = 0; zeile < 20; zeile++)
{
for(spalte=0; spalte<13 && zeichen<256; spalte++)
{
if (isprint(zeichen) || zeichen>127)
printf("%3c %3d
else
printf(" %3d
zeichen++;
}
printf("\n");
}
return 0;
}
logisches NICHT !
Der logische NICHT-Operator verkehrt den Wahrheitswert seines logischen Ope-
randen in dessen Gegenteil. Dabei wird der Wert 0 (false) in den Wert 1 (true)
umgewandelt und alle Werte ungleich 1 zu 0.
Beispiele
Das folgende Programm enthält eine Endlosschleife, in der der Anwender aufgefor-
dert wird, eine Zahl einzugeben. In der Schleife wird mit einer if-Abfrage über-
prüft, ob die Zahl 0 eingegeben wurde. Wenn ja, wird die Schleife mit break been-
det.
#include <stdio.h
int main() {
int zahl:
for (;;) {
printf("Geben Sie eine Zahl ein: ");
108
Datenzugriff
scanf("%d", &zahl);
if (!zahl)
break;
}
return 0;
}
Verweise
Siehe Kategorie Programmsteuerung, if-Bedingung
Siehe Kategorie Programmsteuerung, Schleifen
Datenzugriff
Beschreibung
Mehrere Operatoren von C und C++ dienen dem Zugriff auf Daten.
Anwendung
Diese Operatoren benötigt man, um auf einzelne Elemente eines Arrays, einer
Struktur, Union oder Klasse zuzugreifen. Auch der Gültigkeitsbereichoperator und
die Operatoren zur Dereferenzierung von Zeigern, die den Zugriff auf die Objekte
ermöglichen, auf die die Zeiger verweisen, gehören in diese Kategorie.
Operator Bedeutung
* Indirektions-Operator
[] Array-Indizierung
. Punkt-Operator
-> Elementverweis-Operator
.* Dereferenzierung von Zeigern auf Klassenelemente
->* Dereferenzierung von Zeigern auf Klassenelemente
:: Gültigkeitsbereichoperator
Dereferenzierungs-Operator *
Der Dereferenzierungs-Operator »*« dient dazu, einen Zeiger zu dereferenzieren
und auf dessen Objekt zuzugreifen.
Der Typ des Zeigers bestimmt den Typ des Ergebnisses. Wenn also der Operand
ein Zeiger auf int ist, hat das Ergebnis den Datentyp int.
int func(int *zeiger) {
int ergebnis;
*zeiger = ergebnis; /* Wert zuweisen */
}
109
Sprachkonzepte und Syntax
Warnung
● Der Dereferenzierungs-Operator kann nicht auf einen unvollständigen Typ,
beispielsweise einen Zeiger auf void, angewendet werden.
● Das Zeichen »*« wird ebenfalls bei der Deklaration von Variablen benutzt,
um anzugeben, daß die deklarierte Variable ein Zeiger ist. Es handelt sich
dann dabei nicht um einen Dereferenzierungs-Operator. Die Bedeutung ergibt
sich somit immer aus dem Kontext.
Array-Indizierung []
Der Operator »[ ]« kann verwendet werden, um gezielt auf einzelne Elemente eines
Arrays oder eines dynamisch reservierten Feldes zuzugreifen.
#define FELD_GROESSE 20
int array[FELD_GROESSE];
int dyn_feld = (int*) malloc(FELD_GROESSE*sizeof(int));
for (i=0; i < Feld_GROESSE; i++) {
array[i] = i;
dyn_feld[i] = i;
};
Warnung
● Das erste Element eines Arrays (Feldes) besitzt den Index 0.
● Intern wird der Indizierungsoperator vom Compiler durch eine Zeigerberech-
nung aufgelöst. Die Syntax array[i] ist daher identisch zu *(array+i).
Punkt-Operator .
Der Punkt-Operator dient dazu, auf einzelne Elemente einer Klasse, Struktur oder
einer Union zuzugreifen.
[Link]
● objekt: muß der Name einer Klasse, Struktur oder einer Union sein.
● element: muß der Name eines Elements sein.
struct person {
char name[20];
int plz;
};
int main() {
struct person leser;
strcpy([Link], "Otto");
[Link] = 5100;
return 0;
}
110
Datenzugriff
Elementverweis-Operator ->
Der Operator bietet eine vereinfachte Syntax, um über Zeiger auf Klasseninstanzen
(inklusive Strukturen und Unions) auf deren Elemente zugreifen zu können.
pObjekt->element
● pObjekt: Zeiger auf eine Variable vom Typ Klasse, Struktur oder Union.
● element: ein Element.
struct person {
char name[20];
int plz;
};
int main() {
struct person p_leser;
strcpy(p_leser->name, "Otto");
p_leser->plz = 5100;
return 0;
}
int main() {
class extreme extr; // Instanzbildung
int extremum;
int wert1, wert2;
wert1 = rand()%20;
wert2 = rand()%40;
111
Sprachkonzepte und Syntax
Bereichsoperator ::
Objekte und Funktionen gleichen Namens und gleicher Signatur (Parametertypen)
aus unterschiedlichen Gültigkeitsbereichen verdecken sich gegenseitig. Mittels des
Bereichsoperators kann aus dem aktuellen Gültigkeitsbereich auf verdeckte Varia-
blen und Funktionen anderer Gültigkeitsbereiche zugegriffen werden.
::global_name
Der unäre Operator dient dazu, auf verdeckte globale Variablen zugreifen zu kön-
nen (siehe erstes Beispiel).
space::name
In seiner binären Form wird der Operator eingesetzt, um
● auf bestimmte Namensbereiche zuzugreifen,
● auf statische Klassenelemente zuzugreifen,
● auf Basisklassenelemente zuzugreifen.
Der Zugriff funktioniert nur, wenn der Name eindeutig aufgelöst werden kann
(siehe zweites Beispiel).
Beispiele
Zugriff auf verdeckte, globale Variable:
#include <stdio.h>
int i = 1;
int main() {
int i = 2;
printf("i = %d\n",i); // lokales i verdeckt globales i
printf("i = %d\n",::i); // Zugriff auf globales i
return 0;
}
112
Bitweise Operatoren
Verweise
Siehe Kategorie Klassen, Zugriff von außerhalb der Klasse
Bitweise Operatoren
Beschreibung
Operatoren zur bitweisen Manipulation von Daten. Als Operanden sind allerdings nur Integer-
Werte erlaubt.
Anwendung
Mit Hilfe der Bit-Operatoren lassen sich bestimmte Programmieraufgaben sehr ele-
gant und effizient lösen. Voraussetzung für den sicheren Gebrauch der Operatoren
sind allerdings Kenntnisse über die Binärcodierung der manipulierten Daten.
113
Sprachkonzepte und Syntax
bitweises ODER |
Der Operator für die bitweise ODER-Verknüpfung »|« vergleicht die Bitmuster sei-
ner Operanden und setzt das entsprechende Bit im Ergebnis, wenn eines der Bits in
den Operanden gesetzt ist.
Dieser Operand kann beispielsweise dazu verwendet werden, um gezielt einzelne
Bits zu setzen, ohne die anderen Bits der ersten Operanden zu verändern.
Ein Beispiel dafür ist die Umwandlung von Groß- in Kleinbuchstaben. In der
ASCII-Tabelle unterscheiden sich die Klein- von den Großbuchstaben des engli-
schen Alphabets (also nicht die deutschen Umlaute) binär dadurch, daß bei den
Kleinbuchstaben immer Bit 5 gesetzt ist.
Um einen Großbuchstaben in den entsprechenden Kleinbuchstaben umzuwandeln,
braucht also nur Bit 5 gesetzt zu werden, was Sie im folgenden Beispiel sehen:
0100 0001 Buchstabe 'A'
| 0010 0000 Maske dezimal 32
--------------------
0110 0001 Buchstabe 'a'
114
Bitweise Operatoren
bitweises Komplement ~
Der bitweise Komplement-Operator »~« kippt alle Bits seines Operanden. Durch
Invertierung werden im Ergebnis alle Bits, die im Operanden gesetzt waren,
gelöscht, und alle Bits, die gelöscht waren, gesetzt. Die Zahl 4 besitzt folgendes Bit-
muster:
0000 0100
Durch die Operation ~4 erhalten wir folgendes Muster:
1111 1011
Rechtsverschiebung >>
Bei der bitweisen Rechtsverschiebung werden die einzelnen Bits eines Operanden
um die festgelegte Anzahl nach rechts verschoben.
Der Operator kann beispielsweise für eine schnelle Programmierung der Division
durch die Potenzen der Zahl 2 benutzt werden.
Der Ausdruck 80 >> 3 entspricht 80 / 2^3 und erzeugt folgendes Ergebnis:
dezimal binär
vor Verschiebung 80 0101 0000
nach Verschiebung 10 0000 1010
Linksverschiebung <<
Bei der bitweisen Linksverschiebung werden die einzelnen Bits eines Operanden um
die festgelegte Anzahl nach links verschoben.
Der Operator kann beispielsweise für eine schnelle Programmierung der Multipli-
kation mit den Potenzen der Zahl 2 benutzt werden.
Der Ausdruck 3 << 2 entspricht 3 * 2^2 und erzeugt folgendes Ergebnis:
dezimal binär
vor Verschiebung 3 0000 0011
nach Verschiebung 12 0000 1100
Beispiele
#include <stdio.h>
int main() {
printf(" a & 223 = %c\n", 'a' & 223);
printf(" A | 0x20 = %c\n", 'A' | 0x20);
printf(" 25 ^ 12 = %d\n", 25 ^ 12);
printf(" 3 << 2 = %d\n", 3 << 2);
115
Sprachkonzepte und Syntax
Verweise
Siehe Streamoperatoren
Streamoperatoren
Beschreibung
In C++ sind die Operatoren >> und << für das formatierte Einlesen und Schreiben von und in
Streams überladen.
Anwendung
Der Einsatz der Streamoperatoren für die Ein- und Ausgabe ist recht komfortabel
und sehr übersichtlich.
int wert = 3;
cout << "Wert = " << wert << endl; // cout ist der Standardausgabestream
Die Programmierung mit Streamoperatoren ist zudem in vorbildlicher Weise
objektorientiert:
● die Streamoperatoren sind standardmäßig für alle elementaren Datentypen
überladen (int, float, char, etc.).
● durch Überladung kann das Einsatzgebiet der Operatoren auf selbst definierte
Klassentypen ausgedehnt werden.
Durch sogenannte Manipulatoren kann die Formatierung der Ein- und Ausgabe
gesteuert werden.
Beispiele
int wert;
cout << "Geben Sie einen Wert ein:" << endl;
cin >> wert;
cout << left;
cout << "Wert = " << wert << endl;
116
Die Operatoren new und delete
Verweise
Siehe Referenz der C++-Laufzeitbibliothek, Header-Dateien iostream, iomanip, etc.
new-Operator new
Der new-Operator dient zur dynamischen Speicherallokation. Für die Implementie-
rung des Operators sind im ANSI C++-Standard allein 6 Operatorfunktionen vor-
gesehen.
Die verschiedenen Operatorfunktionen sind für die Unterscheidung von einfachen
Objekten und Arrays als Operanden, und für die einfache Steuerung der Fehlerbe-
handlung und die Zuweisung eines bestimmten Speicherbereiches gedacht.
Zudem gibt es zwei Formen des Aufrufs, je nachdem, ob die Typangabe geklam-
mert wird oder nicht. Dies ist notwendig, um in Typangaben, die Operatoren wie
&, * oder [] enthalten, unterscheiden zu können, ob die Deklarations- oder die
Zuweisungsoperatoren gemeint sind:
new [freie_arg] Typ [initialisierer]
new [freie_arg] (Typ) [initialisierer]
● freie_arg: Argumentenliste, die überladenen Formen übergeben werden kann.
● Typ: Datentyp, der für den Speicher zu reservieren ist.
● initialisierer: Wert, der benutzt wird, den reservierten Speicherplatz zu initiali-
sieren.
Beispiel
1: long double *p, *q, **pp;
2: p = new long double;
3: pp = new long double*;
4: p = new long double(1.2);
5: //q = new long double * 3;
6: q = new long double [3];
7: //q = new long double [3](1,2,3);
8: class demo {
9: int i;
10: } *p_demo;
117
Sprachkonzepte und Syntax
Erläuterung
In Zeile 2 wird ein Zeiger auf Objekte des Datentyps long double eingerichtet, in
Zeile 3 ein Zeiger auf einen Zeiger auf Objekte des Datentyps long double.
In Zeile 4 wird der Zeiger p eingerichtet und der Speicherbereich, auf den der Zei-
ger p verweist, mit dem Wert 1.2 initialisiert.
In Zeile 5 wird versucht, einen Zeiger auf ein Array von 3 long double Werten ein-
zurichten. Die verwendete Syntax ist ähnlich dem Gebrauch der Funktion malloc(),
führt hier aber zu Fehlern, da der Compiler den Aufruf als (new long double)*3 ver-
steht.
In Zeile 6 erfolgt die korrekte Allokation des Arrays.
Zeile 7: syntaktisch korrekt, aber Arrays können nicht initialisiert werden.
In Zeile 11 wird ein Array von Klassenobjekten eingerichtet.
In Zeile 12 wird ein Zeiger func_ptr auf Funktionszeiger deklariert. Danach soll für
den Zeiger func_ptr Speicher für ein Array von Funktionszeigern reserviert werden,
dessen erstes Element ihm als Adresse übergeben wird. Die Zuweisung in Zeile 13
führt wie in Zeile 5 zu einem Interpretationsfehler. In Zeile 14 wird daher die
zweite Syntaxform gewählt, bei der die Typangabe eingeklammert ist.
In Zeile 15 wird Speicher von der Größe eines demo-Objekts reserviert. In Zeile 16
wird das demo-Objekt in dem Speicherbereich, auf den ziel verweist, eingerichtet
(Plazierungsform des Operators).
Warnung
● Objekte, die mit new eingerichtet wurden, haben unbegrenzte Lebensdauer.
Der Speicherplatz muß daher mittels des delete-Operators wieder freigegeben
werden.
● Wird Speicher für ein Array reserviert, liefert der new-Operator einen Zeiger
auf das erste Array-Element zurück.
● Bei der Reservierung von Arrays müssen alle Dimensionen durch konstante,
positive Ausdrücke angegeben werden; die erste Dimension kann durch einen
allgemeinen Ausdruck spezifiziert werden.
● Arrays können nicht initialisiert werden.
118
Typumwandlung und -identifizierung
● Klassenobjekte können nur mit new eingerichtet werden, wenn die Klasse einen
Standardkonstruktor besitzt, oder die Argumente für den Konstruktor dem
Operator übergeben werden.
● Referenzen können nicht mit new eingerichtet werden, da sie keinen Speicher-
platz haben.
● Der Operator berechnet den Speicherbedarf für den einzurichtenden Datentyp
selbst, weswegen der erste Parameter einer new-Operatorfunktion immer vom
Typ size_t ist (zu beachten bei Überladung).
● Wird der new-Operator überladen, sollte auch eine entsprechende Form des
delete-Operators implementiert werden.
delete-Operator delete
Der delete-Operator dient zur dynamischen Freigabe von mittels new allokiertem
Speicher.
delete p_objekt
delete [] p_objekt
Warnung
● Zeiger auf Konstanten können nicht gelöscht werden.
● Für Klassen wird beim Löschen der Destruktor aufgerufen.
● Die zweite Version ist zur Freigabe von Arrays. Die Dimension wird dabei
nicht angegeben.
● Aufrufe mit Nullzeigern sind ohne Effekt.
Beispiele
class demo *p;
p = new demo[10];
delete[] p;
int **p;
p = new int*;
delete p;
119
Sprachkonzepte und Syntax
Anwendung
Gelegentlich ist es wünschenswert, daß eine Variable eines bestimmten Datentyps
als einem anderen Datentyp angehörig behandelt wird. Sofern eine solche Typum-
wandlung durchführbar ist, kann sie durch den C-Cast-Operator () oder die C++-
Operatoren const_cast, dynamic_cast, static_cast und reinterpret_cast, die als
Schlüsselworte in die Sprache aufgenommen sind, explizit herbeigeführt werden.
Die C++-Operatoren sind vor allem dazu gedacht, die verschiedenen Konvertierun-
gen (die auch mit dem Cast-Operator () vorgenommen werden könnten) nach
ihrem Gefahrenpotential und dem Einsatzgebiet zu kategorisieren. Bei Auftreten
eines Fehlers kann der Programmierer dann eventuell aus der Art des Fehlers auf
die betreffende Typumwandlung schließen und mit Hilfe der Suchfunktion seines
Editors schnell zu allen Vorkommen des jeweiligen Operators springen.
Operator Beschreibung
static_cast<Typ>(var) Zur Umwandlung zwischen »nahe verwandten« Typen –
also alle Fälle, in denen der Compiler auch eine implizite
Konvertierung vornehmen könnte, plus einige einfache
Sonderfälle.
reinterpret_cast<Typ>(var) Für fast alle anderen erlaubten Umwandlungen.
const_cast<Typ>(var) Entfernt eine const- oder volatile-Deklaration aus ei-
nem Typ.
dynamic_cast<Typ>(var) Zur Umwandlung zwischen Zeigern oder Referenzen auf
Klassentypen einer gemeinsamen Klassenhierarchie
Der Cast-Operator ()
Der Cast-Operator kann benutzt werden, um in einer Anweisung den Typ des Aus-
drucks der rechten Seite in den Typ des Bezeichners der linken Seite umzuwandeln:
bezeichner1 = (Typ_von_bezeichner1) AUSDRUCK;
bezeichner1 = (Typ_von_bezeichner1) bezeichner2;
Eine zweite Form der Syntax wandelt den Typ einer Variablen direkt um
bezeichner = Datentyp();
Beispiele
intptr = (int *) malloc(80 * sizeof(int));
printf("%f\n", (double) 13/2);
int i = int(3.14);
int i = int(); // weist undefinierten Wert zu
120
Typumwandlung und -identifizierung
Beispiele
const int* p;
int* q;
p = q; // korrekt: Zuweisung eines int*-Objekts
// an const int*
q = p; // Fehler: const int* an int*
q = const_cast <int*> (p); // ok.
121
Sprachkonzepte und Syntax
Beispiele
#include <iostream>
using namespace std;
class Basis {
public:
virtual void func() {cout << "basisklasse" << endl;}
};
class Abgeleitet : public Basis {
public:
void func_abg() {cout << "abgeleitete Klasse" << endl;}
};
int main() {
Abgeleitet *p_abg = new Abgeleitet;
Basis *p_bp = new Basis;
122
Typumwandlung und -identifizierung
Beispiele
#include <iostream>
using namespace std;
class Basis {
public:
void func() {cout << "basisklasse" << endl;}
};
class Abgeleitet : public Basis {
public:
void func_abg() {cout << "abgeleitete Klasse" << endl;}
};
int main() {
Abgeleitet *p_abg = new Abgeleitet;
Basis *p_bp = new Basis;
123
Sprachkonzepte und Syntax
Warnung
● Werden Integer-Typen in Zeiger umgewandelt oder umgekehrt, ist nicht si-
chergestellt, daß der Wert des konvertierten Objektes korrekt interpretiert
werden kann.
● Es ist allerdings sichergestellt, daß bei einer nachfolgenden Rückkonvertierung
der ursprüngliche Wert wieder erscheint (natürlich vorausgesetzt, daß zwi-
schen den Konvertierungen keine Zuweisung an die Variable erfolgte).
● Entsprechendes gilt, wenn Zeiger auf Funktionen in Zeiger auf Funktionen an-
deren Typs oder in Zeiger auf Objekte umgewandelt werden.
● Werden Zeiger oder Referenzen konvertiert, sind undefinierte Klassenbezeich-
ner in der Typangabe erlaubt.
Typidentifizierung typeid
Der Operator typeid erzeugt für das ihm übergebene Objekt eine entsprechende
Instanz der Klasse type_info (definiert in typeinfo). In dieser Instanz, die vom Ope-
rator als Referenz zurückgeliefert wird, sind Informationen zum Datentyp des
übergebenen Objekts abgelegt. Die type_info-Objekte können direkt mit Hife der
Operatoren == und != verglichen werden. Zudem kann die Methode name() aufge-
rufen werden, die einen String zurückliefert, der den Typ des typeid-Operanden
identifiziert.
Warnung
Laut ANSI-Standard sind Typen, die sich nur in den CV-Qualifizierern unterschei-
den (const, volatile) identisch. Einige Compiler differenzieren hier aber.
Beispiele
#include <iostream>
#include <typeinfo>
using namespace std;
int main() {
demo d1();
const demo d2();
if(typeid(d1) == typeid(d2))
cout << "gleich" << endl;
if(typeid(d1).name() == typeid(d2).name())
cout << typeid(d1).name() << endl;
return 0;
}
124
Sonstige Operatoren
Sonstige Operatoren
sizeof-Operator sizeof
Der sizeof-Operator liefert als Ergebnis die Größe seines Operanden in Byte
zurück. Der Rückgabewert ist vom vorzeichenlosen Integer-Typ size_t. Als Ope-
rand kann sowohl ein Datentyp als auch eine Variable übergeben werden.
Typische Einsatzgebiete für den sizeof-Operator sind Speicherbedarfberechnungen
für die dynamische Speicherallokation sowie die Berechnung der Anzahl an Ele-
menten in einem Array.
Warnung
● Für Referenzen liefert der sizeof-Operator die Größe des referenzierten Ob-
jektes.
● Nicht zulässig sind: Funktionen, Bitfelder, undefinierte Klassen, Arrays mit
fehlender Dimensionsangabe sowie der Typ void.
● Wenn einer der Typen char, unsigned char oder signed char als Argument ver-
wendet wird, ist das Ergebnis per Definition immer 1.
● Die Größe eines Zeichenliterals (sizeof('Z')) entspricht in C der Größe von
int, in C++ der Größe von char.
● Wird sizeof auf ein Array angewendet, ist das Ergebnis die Gesamtgröße des
Arrays in Bytes. Doch Vorsicht! Wenn sizeof innerhalb einer Funktion benutzt
wird, um die Größe eines Arrays zu ermitteln, das an einen Parameter der
Funktion übergeben wurde, liefert sizeof die Größe des Zeigers auf das Array
zurück, da Arraynamen als Zeiger übergeben werden.
● Handelt es sich beim Argument um eine Klasse, Struktur oder Union, wird die
tatsächliche Größe zurückgegeben, in der auch Füllbytes zur Ausrichtung an
Speichergrenzen enthalten sein können. Das Ergebnis der sizeof-Operation
kann dann von der Summe des Speicherplatzbedarfs der einzelnen Elemente
verschieden sein.
Beispiele
int main() {
int feld[123];
return 0;
}
125
Sprachkonzepte und Syntax
Adreß-Operator &
Wenn der Operator »&« mit einem Operanden benutzt wird, liefert er die Adresse
seines Operanden zurück. Als Operand kann jeder Bezeichner eingesetzt werden,
der einen L-Wert verkörpert.
Warnung
● Der Operator kann nicht auf das Element eines Bitfeldes oder auf ein Objekt,
das mit der Speicherklasse register definiert wurde, angewendet werden.
● Funktions- und Array-Namen können direkt als Adressen interpretiert wer-
den, weswegen für sie die Anwendung des Adreß-Operators nicht erforderlich
ist.
Beispiele
// Integer-Wert von Tastatur einlesen
int zahl;
scanf("%d", &zahl);
Auswertung
● Wenn die Auswertung der Bedingung nicht 0 (also wahr) ergibt, wird
Ausdruck1 ausgeführt.
● Ergibt die Auswertung der Bedingung 0 (also unwahr), wird Ausdruck2 ausge-
wertet.
126
Sonstige Operatoren
Beispiele
int max, eins, zwei;
eins = 1;
zwei = 2;
max = (eins > zwei) ? eins : zwei;
Die gleiche Zuweisung kann auch als if-else-Anweisung formuliert werden:
if (eins > zwei)
max = eins;
else
max = zwei;
Warnung
● Das Ergebnis der durch den Komma-Operator getrennten Ausdrücke hat den
gleichen Wert und Typ wie der rechte Operand.
● Die Operanden können einen beliebigen Typ besitzen; Typumwandlungen
werden nicht durchgeführt.
● In Listen müssen die entsprechenden Ausdrücke geklammert werden.
Beispiele
func(int par1, float par2) {..};
Das nächste Beispiel verwendet den Komma-Operator im Reinitialisierungsteil
einer for-Schleife, um bei jedem Schleifendurchlauf nicht nur eine, sondern beide
Schleifenvariablen i und j zu inkrementieren.
for (i=j=0; i<MAXWERT; i++, j++) { ...
Im dritten Beispiel wird zuerst der linke Operand (i++) ausgewertet. Anschließend
wird das Ergebnis von zahl2/4 der Variablen zahl1 zugewiesen.
zahl1 = (i++, zahl2 / 4);
Wird der Operator in Listen eingesetzt, müssen die Anweisungen geklammert wer-
den.
func(i, (f=3.14, f+0.0015));
127
Sprachkonzepte und Syntax
Synonyme
In C++ wurden für einige Operatoren synonyme Bezeichnungen eingeführt.
Synonym Operator
bitand &
and &&
bitor |
or ||
xor ^
compl ~
and_eq &=
or_eq |=
xor_eq ^=
not !
not_eq !=
128
Überladung von Operatoren
129
Sprachkonzepte und Syntax
Anwendung
Operatoren können innerhalb der Deklaration ihrer Klasse oder außerhalb im
Dateibereich überladen werden.
Bei Überladung im Klassenbereich ist der erste Operator automatisch ein Objekt
der Klasse und wird bei der Definition der Operatorfunktion nicht mehr als Para-
meter aufgeführt. Im Klassenbereich überladene Operatoren haben Zugriff auf die
private und protected Elemente der Klasse (siehe nachfolgende Beispiele).
Bei Überladung im Dateibereich müssen alle Operanden bei der Definition der
Operatorfunktion als Parameter aufgeführt werden. Im Dateibereich überladene
Operatoren haben keinen Zugriff auf die private und protected Elemente der
Klasse. Man kann dem aber abhelfen, indem man die Operatorfunktion in der
Klasse als friend deklariert (siehe Überladung der Stream-Operatoren).
Operatoren, die aneinandergereiht werden können (beispielsweise var1 = var2 =
var3;), müssen dazu eine Referenz auf ihren linken Operanden als Rückgabewert
zurückliefern.
Warnung
● Es können keine neuen Operatoren definiert werden.
● Folgende Operatoren können nicht überladen werden: ::, ?:, ., .*, #, ##, defi-
ned, typeid, die C++-Cast-Operatoren.
● Folgende Operatoren können nur in einem Klassenbereich überladen werden:
=, (), [], -> .
● Mindestens ein Operand eines überladenen Operators muß eine Klasse oder
eine Referenz auf eine Klasse sein. (Die Funktionsweise der Operatoren für die
elementaren Datentypen kann also nicht geändert werden.)
● Die allgemeine Auslegung des Operators (Anzahl Operanden, Priorität, Vorga-
beargumente) kann nicht verändert werden.
130
Überladung von Operatoren
Beispiele
class person {
int alter;
public:
...
operator ++ () { //Praefix-Inkrement
++alter;
return *this;
}
};
Die Deklaration eines int-Parameters für den Postfix-Inkrement-Operator spezifi-
ziert keinen wirklichen zweiten Operanden, sondern dient nur zur Unterscheidung
vom Präfix-Inkrement-Operator.
Beispiele
class person { .. };
class adressbuch {
/* enthält als Datenelemente eine Menge von person-Einträgen,
die nicht als statisches Array, sondern als
dynamische Liste oder Baum verwaltet werden */
...
public:
person& operator[] (int);
};
person& adressbuch::operator[] (int i) {
class person *gefunden;
/* durchsucht dynamische Struktur */
...
return *gefunden;
};
int main() {
class adressbuch persoenlich;
class person eintrag;
...
eintrag = persoenlich[3];
return 0;
}
131
Sprachkonzepte und Syntax
Programmsteuerung
Programmsteuerung
Beschreibung
Je komplexer Programme werden, desto öfter ist es erforderlich, je nach Situation und Zustand
des Programms zu verschiedenen Anweisungen zu verzweigen.
Zur Steuerung des Programmflußes gibt es veschiedene Konzepte:
Verzweigungen
Schleifen
Exceptions
Bedingte Kompilation
Anwendung
● Verzweigungen. Verzweigungen ermöglichen es dem Programmierer, einen
oder mehrere Anweisungsblöcke nur in Abhängigkeit von bestimmten Bedin-
gungen ausführen zu lassen.
● Schleifen. Schleifen ermöglichen es dem Programmierer, einen Anweisungs-
block mehrmals hintereinander ausführen zu lassen.
● Exceptions. Exeptions und das Konzept der Exceptions-Behandlung ermögli-
chen es einem Programmierer, die Fehlerbehandlung weitgehend von dem Pro-
grammfluß des eigentlichen Programmcodes zu trennen. Dazu gehört auch,
daß der Ort der Fehlerentstehung nicht mehr mit dem Ort der Fehlerbehand-
lung zusammenfallen muß.
● Bedingte Kompilation. Mit Hilfe von Präprozessor-Direktiven kann der Pro-
grammierer steuern, welche Codeblöcke in Abhängigkeit von Präprozessor-
Schaltern kompiliert und in das ausführbare Programm aufgenommen werden
sollen und welche nicht.
Die if-Bedingung
Beschreibung
Die if-Bedingung kontrolliert, ob eine nachfolgende Anweisung oder ein Anweisungsblock
ausgeführt wird oder nicht.
132
Die if-else-Verzweigung
Anwendung
Auf das Schlüsselwort if folgt in Klammern eine Bedingung. Bei Ausführung des
Programms wird diese Bedingung ausgewertet. Ergibt die Bewertung das Ergebnis
true (also einen Wert ungleich Null), wird die zu if gehörende Anweisung ausge-
führt. Liefert die Auswertung des Ausdrucks als Ergebnis false, wird die Ausfüh-
rung des Programms mit der ersten Anweisung hinter der Verzweigung fortgesetzt.
Syntax
if (Bedingung) if (Bedingung)
Anweisung; {
Anweisungsblock;
}
● Bedingung: Die Bedingung, die ausgewertet wird, muß einen booleschen Wert
ergeben. Hier kann beispielsweise eine Ganzzahl, eine arithmetische Operati-
on, ein Vergleich oder der Aufruf einer Funktion mit entsprechendem Rückga-
betyp stehen.
● Anweisung/Anweisungsblock: Auf die if-Bedingung kann eine einzelne An-
weisung oder ein Anweisungsblock folgen. Eine einzelne Anweisung muß im-
mer mit einem Semikolon (dem Anweisungsbegrenzer) beendet werden. Wenn
ein Anweisungsblock ausgeführt werden soll, muß dieser in geschweifte Klam-
mern eingeschlossen werden.
Warnung
Nie ein Semikolon hinter die Bedingung setzen. Dies würde der Compiler als eine
leere Anweisung interpretieren. Die if-Bedingung bezöge sich dann nur auf diese
leere Anweisung.
Beispiele
if (cZeichen == 'a')
printf("Das Zeichen ist a.");
if ( isdigit(cZeichen) )
printf("Das Zeichen ist eine Zahl");
Die if-else-Verzweigung
Beschreibung
Die if-else-Verzweigung regelt, welcher von zwei Anweisungsblöcken in Abhängigkeit von
einer Bedingung ausgeführt werden soll.
133
Sprachkonzepte und Syntax
Anwendung
Die einfache if-Bedingung kann nur steuern, ob ein einzelner Anweisungsblock
ausgeführt werden soll oder nicht. Es gibt aber auch Fälle, in denen man – je nach-
dem, ob die Bedingung true oder false ergibt – den einen oder anderen Anwei-
sungsblock ausführen möchte.
Diese Sprachkonstruktion wird durch das Schlüsselwort else eingeleitet.
if (Bedingung) if (Bedingung)
Anweisung; { Anweisungsblock }
else else
Anweisung; { Anweisungsblock }
Beispiele
if (cZeichen == 'a')
printf("Das Zeichen ist a.");
else
printf("Das Zeichen ist nicht a.");
if-else-Ketten
Beschreibung
Sprachkonstrukte, in denen der else-Teil einer if-else-Verzweigung selbst wiederum eine if-
else-Verzweigung ist.
Anwendung
Mit den Schlüsselworten if und else ist es möglich, sogenannte else-if-Ketten zu
erstellen, bei denen mehrere Ausdrücke überprüft werden können.
if (Bedingung)
Anweisung;
else if (Bedingung)
Anweisung;
else if (Bedingung)
Anweisung;
else
Anweisung;
134
switch-Verzweigung
Beispiele
printf("Geben Sie ein: Zahl Operator Zahl <Return>\n");
scanf("%f %c %f", &zahl1, &Operator, &zahl2);
if (Operator == '+')
printf("= %f", zahl1 + zahl2);
else if (Operator == '-')
printf("= %f", zahl1 – zahl2);
else if (Operator == '*')
printf("= %f", zahl1 * zahl2);
...
Verweise
Siehe switch-Verzweigung
switch-Verzweigung
Beschreibung
Komplexe Sprunganweisung, die in Abhängigkeit von einem Ausdruck zu verschiedenen Ein-
sprungmarken in einen Anweisungsblock verzweigt.
Anwendung
Eine einfachere und meist auch übersichtlichere Programmiertechnik als die im
vorigen Abschnitt beschriebenen if-else-Ketten bietet die switch-Anweisung. Auch
mit ihr kann ein Programm zwischen mehreren Alternativen auswählen – allerdings
i.G. zur if-else-Kette nur in Abhängigkeit vom Wert eines Ausdrucks.
switch(Ausdruck)
{
case Konstante1: Anweisung;
break;
case Konstante2: Anweisung;
break;
case Konstante3: Anweisung;
break;
case Konstante4: Anweisung;
break;
default: Anweisung;
}
● Ausdruck: Ausdruck ist ein ganzzahliger Wert (auch Aufzählungstyp), der mit
allen innerhalb der switch-Anweisung stehenden case-Marken verglichen wird.
Hier kann auch der Aufruf einer Funktion stehen, die eine Ganzzahl als Ergeb-
nis zurückgibt. Gleichzeitig kann hier, wie bei der if-Anweisung, eine Zuwei-
sung des Funktionsergebnisses erfolgen.
● case Konstante: Konstanten, die mit dem Ausdruck verglichen werden.
135
Sprachkonzepte und Syntax
Beispiele
#include <stdio.h>
int main(){
float zahl1, zahl2;
char Operator;
switch (Operator)
{
case '+':
136
Schleifen
printf("\n\n");
return 0;
}
Verweise
Siehe if-Anweisung
Schleifen
for, while
Beschreibung
Schleifen werden eingesetzt, wenn ein Anweisungsblock mehrere Male hintereinander ausge-
führt werden soll.
Schleifen bestehen aus
● einer Abbruchbedingung, die festlegt, wann die Ausführung der Schleife zu be-
enden ist, und
● einem in geschweifte Klammern eingefaßten Anweisungsblock.
Anwendung
In C/C++ gibt es while, for und do-while-Schleifen. Prinzipiell aber läßt sich jede
Schleife als while-Schleife formulieren. Unabhängig von der verwendeten Schleife
kann diese auf mehrere Weisen verlassen werden:
● Abbruchbedingung der Schleife wird erfüllt.
● Abbruch durch break , return oder exit().
● Sprung aus Schleife heraus durch goto oder longjmp().
137
Sprachkonzepte und Syntax
Warnung
Es ist Aufgabe des Programmierers sicherzustellen, daß eine Schleife auch wieder
verlassen wird, da das Programm sonst in einer Endlosschleife verharren kann.
Die for-Schleife
Beschreibung
Mit dem Schlüsselwort for wird eine Schleife eingeleitet, die durch einen dreiteiligen Schlei-
fenkopf kontrolliert wird. Dieser Schleifenkopf steht in runden Klammern und enthält die drei
Elemente Initialisierung, Bedingung und Veränderung, die durch Semikolon voneinander
getrennt werden.
Anwendung
Die for-Schleife wird immer dann eingesetzt, wenn die gewünschten Wiederho-
lungen des Anweisungsblocks abzählbar sind (im Gegensatz zur while-Schleife, die
auch eingesetzt werden kann, wenn die Anzahl der Wiederholungen nicht berech-
net werden kann). In der Praxis sieht dies meist so aus, daß man eine eigene
Variable definiert (die sogenannte Schleifenvariable), diese zu Beginn der Schleife
initialisiert und dann bei jedem Durchgang der Schleife um einen bestimmten
Betrag erhöht oder erniedrigt, bis sie einen bestimmten Wert übersteigt oder unter-
schreitet, und dadurch die Schleifenbedingung nicht mehr erfüllt ist. Die Syntax der
for-Schleife ist speziell auf diese Formulierung einer Schleife abgestimmt.
Syntax
for (Initialisierung; Bedingung; Reinitialisierung)
Anweisung;
● Initialisierung: Die im Initialisierungsteil stehenden Anweisungen werden
ausgeführt, bevor die Schleife beginnt. Dort werden üblicherweise die Schlei-
fen- oder Zählvariablen initialisiert. Es ist auch möglich, in dieser Anweisung
mehrere Variablen zu initialisieren. Die Zuweisungen werden dann durch
Kommata voneinander getrennt.
● Bedingung: Der Bedingungsteil enthält einen Ausdruck, der wahr sein muß,
damit der zur for-Schleife gehörende Anweisungsteil ausgeführt wird.
● Reinitialisierung: Die hier stehenden Anweisungen werden nach jedem Durch-
lauf des zu for gehörenden Anweisungsblocks abgearbeitet. Hier wird meist
die Zählervariable erhöht oder vermindert. Es kann dort jedoch auch jede an-
dere Anweisung aufgenommen werden. Stehen hier mehrere Anweisungen,
werden sie durch Kommata getrennt.
138
Die while-Schleife
● Anweisung: Der Anweisungsteil kann aus einer einzelnen Anweisung oder aus
einem Anweisungsblock bestehen. Eine einzelne Anweisung muß immer mit
einem Semikolon (dem Anweisungsbegrenzer) beendet werden. Wenn ein An-
weisungsblock ausgeführt werden soll, muß dieser in geschweifte Klammern
eingeschlossen werden.
Warnung
Eine Sonderform der for-Schleife stellt die Endlosschleife dar.
for(;;)
Sie erhält man, wenn alle drei Elemente der Definition der for-Schleife wegfallen,
und wenn nur die Semikolons, die die Elemente trennen, stehenbleiben. Endlos-
schleifen dieser Art können, da keine Abbruchbedingung vorhanden ist, nur mit
break, return oder goto verlassen werden.
Beispiele
#include <stdio.h>
int main() {
int zaehler;
for(zaehler = 0; zaehler < 10; zaehler++)
printf("Der Wert von zaehler beträgt: %d\n", zaehler);
return 0;
}
Verweise
Siehe Abbruchbefehle
Siehe while-Schleife
Die while-Schleife
Beschreibung
Die while-Schleife ist die allgemeinste Form der Schleife, mit der man einen Anweisungsblock
in Abhängigkeit von einer Schleifenbedingung mehrfach ausführen lassen kann.
Anwendung
Die while-Schleife gleicht in der Syntax der if-Bedingung, nur daß die Bedingung
nicht kontrolliert, ob der Anweisungsblock überhaupt ausgeführt wird, sondern
wie oft er ausgeführt wird.
139
Sprachkonzepte und Syntax
Syntax
while (Bedingung)
Anweisung;
● Bedingung: Die Bedingung, die ausgewertet wird, muß einen Booleschen Wert
ergeben. Hier kann beispielsweise eine Ganzzahl, eine arithmetische Operati-
on, ein Vergleich oder der Aufruf einer Funktion mit entsprechendem Rückga-
betyp stehen.
● Anweisung: Das Element Anweisung kann eine einzelne Anweisung sein oder
aus einem Anweisungsblock bestehen. Eine einzelne Anweisung muß immer
mit einem Semikolon (dem Anweisungsbegrenzer) beendet werden. Wenn ein
Anweisungsblock ausgeführt werden soll, muß dieser in geschweifte Klam-
mern eingeschlossen werden.
Beispiele
Die while-Schleife ist die allgemeinste Form der Schleife. So kann man beispiels-
weise die folgende for-Schleife
for (i=1; i <= 5; i++)
printf("%d ", i);
140
Die do-while-Schleife
● Liefert die Auswertung der Bedingung der while-Schleife bereits beim Eintritt
den Wert false, werden die zur Schleife gehörenden Anweisungen nie ausge-
führt.
Verweise
Siehe Abbruchbefehle
Siehe for-Schleife
Die do-while-Schleife
Beschreibung
Neben der while-Schleife gibt es noch das Konstrukt der do-while-Schleife, die mit dem
Schlüsselwort do eingeleitet wird und bei der die Schleifenbedingung am Ende des Anwei-
sungsblocks steht.
Anwendung
Der wichtigste Unterschied zur while-Schleife besteht darin, daß der Anweisungsteil
der do-Schleife mindestens einmal ausgeführt wird, da die Bewertung des Aus-
drucks, der die Bedingung zum Abbruch oder der Schleife enthält, immer nach dem
Durchlaufen des Anweisungsteils stattfindet.
Syntax
do
Anweisung;
while (Bedingung);
Beispiele
#include <stdio.h>
int main() {
int zahl = 99;
do {
printf("Geben Sie eine Zahl ein. ");
printf("99 um Programm zu beenden.\n");
scanf("%d", &zahl);
printf("Die eingelesene Zahl ");
printf("war: %d\n", zahl);
} while (zahl != 99);
return 0;
}
141
Sprachkonzepte und Syntax
Verweise
Siehe for-Schleife
Siehe while-Schleife
Anwendung
Grundsätzlich kontrolliert die Schleifenbedingung, wie oft der Anweisungsblock
einer Schleife auszuführen ist. Darüber hinaus gibt es aber auch die Möglichkeit,
einzelne Schleifendurchgänge gezielt zu überspringen oder eine Schleife vorzeitig
abzubrechen.
continue Mit der continue Anweisung wird zum Ende des Schleifenblocks
gesprungen. Die Ausführung der nach continue stehenden Anweisungen
unterbleibt und der nächste Schleifendurchgang beginnt.
break Das Schlüsselwort break wurde bereits zusammen mit der switch-Anwei-
sung vorgestellt. Neben der Beendigung der switch-Verzweigung können
Sie auch die Ausführung einer Schleife mittels break beenden. Im Gegen-
satz zu continue wird dabei nicht nur der aktuelle Schleifendurchgang
abgebrochen, sondern die Schleife wird ganz verlassen.
Neben continue und break gibt es noch weitere Schlüsselwörter und Funktionen, die
man zum Verlassen einer Schleife – oder allgemein eines Anweisungsblocks – ver-
wenden kann.
return Mit dem Schlüsselwort return kann die Ausführung einer Funktion
unterbrochen und sofort an der Stelle fortgesetzt werden, an der die
Funktion aufgerufen wurde.
exit() Mit der Funktion exit() kann ein Programm an beliebiger Stelle abge-
brochen werden. Dies wird meist benutzt, wenn ein schwerwiegender
Fehler aufgetreten ist, der den weiteren Programmablauf sinnlos oder
unmöglich macht.
throw Löst eine Exception aus und springt zum nächsten passenden Exception-
Handler (nur für die Fehlerbehandlung).
goto Mit goto kann zu einem beliebigen anderen Punkt innerhalb der aktuellen
Funktion verzweigt werden, der durch eine Sprungmarke gekennzeichnet
wurde. Die Sprungmarke erhält einen Namen und wird, wie die Marken
der switch-Anweisung, mit einem Doppelpunkt abgeschlossen.
longjmp() Setzt das Programm in einen Zustand zurück, der zuvor durch einen
Aufruf von setjmp() abgespeichert wurde.
142
Funktionen
Beispiele
Überspringen einzelner Iterationen mit continue:
#include <stdio.h>
int main() {
int zahl;
do {
printf("Geben Sie eine Zahl ein. ");
printf("99 um Programm zu beenden.\n");
scanf("%d", &zahl);
if (zahl < 0)
continue;
printf("Die eingelesene Zahl ");
printf("war: %d\n", zahl);
} while (zahl != 99);
return 0;
}
Vorzeitiges Abbrechen einer Schleife mit break:
int main() {
int zahl;
for (zahl = 3; zahl < 15; zahl++) {
if (zahl == 8)
break;
printf("zahl hat folgenden Wert: %d\n", zahl);
}
return 0;
}
Verweise
Siehe for-Schleife
Siehe while-Schleife
Funktionen
Funktionen
Beschreibung
C-Programme bestehen aus einer beliebigen Anzahl von Funktionen, deren Namen innerhalb
der Konventionen von C (siehe Grundlagenteil) frei gewählt werden dürfen.
143
Sprachkonzepte und Syntax
Anwendung
Sinn einer Funktionsdefinition ist es, einen Anweisungsblock, der eine bestimmte
Aufgabe erledigt (beispielsweise die Ausgabe auf Konsole, die Berechnung des Sinus,
etc.), mit einem Namen zu verbinden. Wird dann irgendwo im Programm die Funk-
tion über ihren Namen aufgerufen, wird die Programmausführung mit der ersten
Anweisung aus dem Anweisungsteil der Funktion fortgesetzt. Nach Abarbeitung der
Funktion springt die Programmausführung in die Zeile des Funktionsaufrufs zurück.
Die Aufteilung des Quelltextes in Funktionen ermöglicht es, redundanten Code zu
vermeiden, häufig benötigte Funktionen zu sogenannten Bibliotheken zusammenzu-
fassen und die Programme modularer und damit wartungsfreundlicher zu gestalten.
Zum Datenaustausch mit der aufrufenden Funktion kann eine Funktion eine belie-
bige Anzahl Parameter und einen Rückgabwert definieren.
Funktionen können an beliebiger Stelle im Quelltext definiert werden (nicht aber
innerhalb anderer Funktionen). Bevor man eine Funktion aufrufen kann, muß sie
aber dem Compiler bekannt sein. Dies erreicht man, indem man die Funktionsdefi-
nition an den Anfang der Quelltextdatei setzt oder indem man die Funktion an
beliebiger Stelle definiert und lediglich eine Vorwärtsdeklaration der Funktion an
den Programmanfang setzt. Letzteres System liegt auch der Verwendung von Hea-
der-Dateien für Bibliotheken zugrunde.
Beispiele
#include <stdio.h> /* Deklarationen für printf, scanf, fflush */
double fakul(int zahl); /* Vorwärtsdeklaration zu fakul() */
int main() {
int zahl;
double fakultaet;
return fakultaet;
}
144
Funktionsdeklaration und -definition
Anwendung
Bei der Funktionsdefinition wird ein Anweisungsblock mit einem Funktionsnamen
verbunden, so daß beim Aufruf des Funktionsnamens im Programmcode der
Anweisungsblock der Funktion ausgeführt wird. Zudem wird durch Angabe der
Parameter und des Rückgabetyps der Funktion festgelegt, wie die Funktion Daten
beim Aufruf übernimmt und bei ihrer Rückkehr zurückliefert.
Syntax
Typ func_name (PARAMETERLISTE)
{
FUNKTIONSKöRPER
}
● Typ: Mit der Typangabe wird festgelegt, welchen Rückgabewert die Funktion
hat. Arrays und Funktionstypen sind als Rückgabetyp nicht zulässig, wohl
aber Zeiger auf diese Objekte.
● func_name: Der Name der Funktion. Dieser Name muß in C, nicht aber in
C++, eindeutig sein (siehe Überladung).
● PARAMETERLISTE: In einer Definition stehen hier durch Kommata getrennt
die einzelnen Parameter mit ihren Typen. In einer Deklaration reicht die Anga-
be der Parametertypen, die der Compiler zur Typenüberprüfung und zur Auf-
lösung überladener Namen braucht (C++). In C++ können Vorgabeargumente
an die Parameter vergeben werden.
● FUNKTIONSKÖRPER: Der Funktionskörper ist ein Anweisungsblock, der in
geschweifte Klammern eingeschlossen wird und bei Aufruf der Funktion aus-
geführt wird.
145
Sprachkonzepte und Syntax
Warnung
● Funktionen haben standardmäßig die Speicherklasse extern. Darüber hinaus
kann man Funktionen auch als static deklarieren.
● Die standardmäßige extern-Deklaration von Funktionen bewirkt, daß die
Funktionen externe Bindung haben (es sei denn, es gibt im Quelltext eine vor-
angehende static-Deklaration der Funktion). Alle extern-Deklarationen einer
bestimmten Funktion beziehen sich daher über Dateigrenzen hinweg auf ein
und dieselbe Definition der Funktion. Auf diese Weise ist es möglich, über
eine Vorwärtsdeklaration in einer Quelltextdatei eine Verbindung zu einer
Funktion herzustellen, die in einer anderen Quelltextdatei oder einer Biblio-
thek definiert ist .
● Deklariert man eine Funktion als static, hat die Funktion interne Bindung,
d. h., der Name der Funktion ist nur innerhalb der eigenen Quelltextdatei be-
kannt. Auf diese Weise kann man in den verschiedenen Quelltextdateien eines
Programmes gleichnamige Funktionen definieren (aber natürlich nur eine pro
Datei), ohne daß es zu Linker-Fehlern wegen Mehrfachdefinitionen kommt.
● Funktionen, die keinen Wert zurückgeben sollen, erhalten die Typangabe void.
● Funktionen, für die kein Rückgabetyp angegeben wurde, bekommen in C au-
tomatisch den Rückgabetyp int zugewiesen (in C++ ist dies ein Fehler).
● Werden in einer Funktionsdeklaration, die nicht Teil einer Definition ist, keine
Parameter spezifiziert, wird dies unter C als Funktion mit beliebig vielen Para-
metern interpretiert, in C++ als Funktion ohne Parameter. Durch Angabe des
Schlüsselworts void statt einer Parameterliste kann in C eindeutig eine Funkti-
on ohne Parameter deklariert werden.
● Neben dem überflüssigen Schlüsselwort auto ist register die einzige Speicher-
klassenangabe, die für Parameter vergeben werden kann. Dadurch wird beim
Aufruf der Funktion, sofern möglich, das so deklarierte Argument in ein Pro-
zessorregister geladen.
● Die Angabe ... am Ende der Parameterliste bedeutet, daß noch beliebig viele
Argumente übergeben werden können.
● Funktionsname und die Parameterliste bilden zusammengenommen die Signa-
tur der Funktion.
● Innerhalb des Funktionskörpers können eigene Variablen definiert werden,
die, wenn nicht anders angegeben, die Speicherklasse auto besitzen und loka-
len Gültigkeitsbereich haben. Diese lokalen Variablen werden beim Aufruf der
Funktion auf dem Stack erzeugt und beim Verlassen der Funktion automatisch
wieder entfernt.
● Soll der Wert einer lokalen Variablen auch nach dem Verlassen der Funktion
erhalten bleiben, kann die Speicherklasse static benutzt werden. Meist wird
dies benutzt, um die Werte lokaler Variablen von Funktionsaufruf zu Funkti-
onsaufruf weiterzureichen.
146
Die Funktion main()
● In C++ kann man Funktionen als inline deklarieren, um den Compiler anzu-
weisen, wenn möglich, die Funktionsaufrufe nicht durch einen Sprung in den
Anweisungsteil der Funktion, sondern direkt durch Anweisungen, die mit der
Ausführung der Funktion identisch sind, zu ersetzen. Dies ist allerdings nur
eine Empfehlung an den Compiler.
● In C++ kann man mit Hilfe des Schlüsselwortes throw bei der Funktionsdekla-
ration eine Liste der Exceptions angeben, die in der Funktion ausgelöst wer-
den dürfen. Treten in der Funktion Exceptions anderer Typen auf, wird eine
unexpected-Exceptions ausgelöst.
Beispiele
int main();
int func1(char* s, int n);
void func2();
Vorgabeargumente in C++:
int func3(double par, char* s = "Vorgabe", int n = 2);
Überladene Funktionen in C++:
void func(int n);
int func(int n, int m);
int func(float f);
Warnung
Die alte auf Kernighan/Ritchie zurückgehende Form der Funktionsdefinition, bei
der die Parameter unter dem Funktionsnamen definiert wurden, ist in C obsolet
und in C++ nicht mehr möglich.
// func_name(a,b)
// int a, double b;
// { ...
Verweise
Siehe Klassen, Methoden
147
Sprachkonzepte und Syntax
Anwendung
Der ANSI-Standard sieht folgende Definitionen vor:
int main() { }
int main(int argc, char *argv[]) { }
Die meisten Compiler erlauben aber auch void als Rückgabewert:
void main() { }
void main(int argc, char *argv[]) { }
Beispiele
#include <stdio.h>
#include <stdlib.h>
148
Datenaustausch zwischen Funktionen
return( EXIT_SUCCESS );
}
Nachstehend sehen Sie die Ausgabe des Programms, wenn der Name des Pro-
gramms [Link] ist, und es mit folgender Befehlszeile aufgerufen wurde:
C:\CC>main eins zwei drei
Befehlszeilen-Argumente:
argv[0] C:\CC\[Link]
argv[1] eins
argv[2] zwei
argv[3] drei
Verweise
Siehe Grundlagenteil, Aufbau eines C/C++-Programms
Anwendung
Parameter Parameter sind spezielle Variablen einer Funktion, denen beim
Aufruf der Funktion Werte zugewiesen werden. Werden als
Parameter Zeiger definiert, kann die Funktion auf diesem Weg
auch Daten zurückliefern.
Rückgabewert Ein einzelner Wert, den die Funktion an den Aufrufer zurück-
gibt.
Globale Variablen Eine weitere Möglichkeit, Daten zwischen Funktionen auszu-
tauschen, läuft über die globalen Variablen. Dieser Weg ist
sehr einfach, hat aber den Nachteil, daß die Unabhängigkeit
und Abgeschlossenheit der Funktion dadurch beeinträchtigt
wird.
Statische Variablen Sollte es erforderlich sein, daß eine lokale Variable nicht nach
dem Verlassen der Funktion gelöscht werden darf, damit ihr
Wert beim nächsten Aufruf der Funktion noch erhalten ist,
wird die Variable als static deklariert.
149
Sprachkonzepte und Syntax
Verweise
Siehe nachfolgende Abschnitte
Der Rückgabewert
Beschreibung
Funktionen können das Ergebnis ihrer Berechnung über den Rückgabewert zurückliefern. Dazu
wird der Typ des Rückgabewerts im Funktionskopf spezifiert. Mittels der Anweisung
return (ergebnis);
wird der Wert dann an die aufrufende Funktion zurückgeliefert.
Anwendung
Es gibt zwei Möglichkeiten, das Konzept des Rückgabewertes sinnvoll zu nutzen:
● Das Ergebnis der Funktion wird einer Variablen der aufrufenden Funktion zu-
gewiesen.
● Die Funktion meldet zurück, ob sie ihre Aufgabe erfolgreich gelöst hat, oder
ob in der Funktion ein Fehler aufgetreten ist.
Warnung
Funktionen, die keinen Wert zurückliefern, erhalten den Rückgabetyp void. Eine
solche Funktion kann return nur ohne Wert aufrufen: return; .
Verweise
Siehe Parameter
Siehe Kategorie Programmsteuerung, Abbruchbefehle für Schleifen
Parameter
Beschreibung
Die Parameter dienen dazu, Werte von der aufrufenden Funktion an die aufgerufene Funktion
zu übergeben. Parameter sind stets lokale Variablen, deren Gültigkeitsbereich der äußerste
Block der Funktion ist. Zur Übergabe von Daten an Parameter benutzt C standardmäßig ein Ver-
fahren, das man »call by value« nennt.
150
Parameter
Beispiele
#include <stdio.h>
void change(int param) {
printf("\tParam nach Funktionsaufruf: %d\n",param);
param = param*param;
printf("\tParam nach Berechnung: %d\n",param);
}
int main() {
int var = 10;
printf("var vor Funktionsaufruf: %d\n",var);
change(var);
printf("var nach Funktionsaufruf: %d\n",var);
return 0;
}
liefert folgende Ausgabe:
var vor Funktionsaufruf: 10
Param nach Funktionsaufruf: 10
Param nach Berechnung: 100
var nach Funktionsaufruf: 10
Parameter Argument
Zeiger:
Typ * ptr (Zeiger vom Typ typ*)
typ * &var (Adresse einer Variablen vom Typ typ)
Referenz, nur C++:
151
Sprachkonzepte und Syntax
Parameter Argument
typ & var (Variable vom Typ typ)
Beispiele
#include <stdio.h>
int main() {
int var = 10;
change1(var); printf("var : %d\n",var);
change2(&var); printf("var : %d\n",var);
change3(var); printf("var : %d\n",var);
return 0;
}
liefert folgende Ausgabe:
var : 10
var : 100
var : 10000
Warnung
Gelegentlich werden Zeiger übergeben, ohne daß eine Änderung des übergebenen
Wertes erwünscht wäre. Dies kann zum Beispiel bei der Übergabe von Arrays der
Fall sein, die immer als Zeiger übergeben werden, oder wenn Zeiger auf größere
Datenstrukturen übergeben werden, um das Kopieren zu sparen. In solchen Fällen
kann durch den Spezifizierer const in der Parameterdeklaration die entsprechende
Variable vor dem Überschreiben geschützt werden.
Tip
In C++ werden statt Zeigern häufig Referenzen zur effizienten Übergabe von Argu-
menten an Funktionen benutzt.
Verweise
Siehe Rückgabewert
152
Funktionsargumente und Vorgabe
Anwendung
Auf diese Weise kann der Aufruf für häufig übergebene Argumente vereinfacht
werden.
Warnung
● Auf einen Parameter mit Vorgabeargument dürfen keine Parameter ohne Vor-
gabeargumente mehr folgen.
● Bei einer Redeklaration dürfen weitere Vorgabeargumente angegeben werden,
es dürfen jedoch keine bereits deklarierten Vorgabeargumente redeklariert
werden.
● Als Vorgabeargumente können auch Ausdrücke oder Variablen deklariert
werden. Es dürfen jedoch keine lokalen Variablen verwendet werden.
● Die Reihenfolge, in der die Funktionsargumente ausgewertet werden, ist nicht
festgelegt und kann somit von Compiler zu Compiler verschieden sein.
Beispiele
int func1(int n, int m = 3);
void func2(char *s = "Vorgabe");
char* func3(int x, int y=4);
char* func3(int x = 2, int y); // gueltige Redeklaration
int func4(int a = 0, int b); // Fehler
153
Sprachkonzepte und Syntax
Stack-Aktionen
● Solange eine Funktion abgearbeitet wird, bleibt ihr Stack-Frame auf dem
Stack liegen.
● Werden aus einer Funktion heraus weitere Funktionen aufgerufen, werden
deren Stack-Frames auf den Stack-Frame der jeweils zuvor aufgerufenen Funk-
tion draufgepackt.
154
Funktionen und der Stack
● Wird eine Funktion beendet, wird ihr Stack-Frame vom Stack entfernt.
● Der Stack ist also immer das genaue Abbild der zur Zeit noch in Ausführung
befindlichen Funktionen. Die Stapelreihenfolge der Funktionen zeigt an, wel-
che Funktion von welcher anderen Funktion aufgerufen wurde.
Stack-Aufbau
Für einen von oben nach unten wachsenden Stack gilt:
● Die unterste Funktion ist die aktuelle Funktion, deren Anweisungen gerade
abgearbeitet werden.
● Die darüberliegende Funktion hat die unterste Funktion aufgerufen und war-
tet nun, daß die aufgerufene Funktion beendet wird.
● Die oberste Funktion ist die Eintrittsfunktion main().
● Die einzelnen Stack-Frames von oben nach unten gelesen zeigen an, über wel-
che Funktionen die aktuelle Funktion aufgerufen wurde.
Der genaue Aufbau der Stack-Frames hängt von dem Rechner ab, für den das Pro-
gramm kompiliert wurde (die Abbildung ist also nur als eine Art allgemeines Modell
zu verstehen). Sie können der Stack-Verwaltung Ihres Rechners aber ein wenig nach-
spüren, indem Sie sich der Debug-Tools Ihres Compilers bedienen (Stack-Anzeige)
oder sich die Adressen der Parameter und lokalen Variablen ausgeben lassen.
Beispiele
#include <stdio.h>
#include <stdlib.h>
int main()
{
func(1,0,0);
return 0;
}
155
Sprachkonzepte und Syntax
Ausgabe
1. Aufruf von func
Adresse von par3 = 0065FE00
Adresse von par2 = 0065FDFC
Adresse von par1 = 0065FDF8
Adresse von lokal1 = 0065FDEC
Adresse von lokal2 = 0065FDE8
Adresse von lokal3 = 0065FDE4
2. Aufruf von func
Adresse von par3 = 0065FDE0
Adresse von par2 = 0065FDDC
Adresse von par1 = 0065FDD8
Adresse von lokal1 = 0065FDCC
Adresse von lokal2 = 0065FDC8
Adresse von lokal3 = 0065FDC4
Erläuterung
Die obige Ausgabe ist das Abbild einer sich selbst aufrufenden Funktion.
Die Adressen der Parameter werden in umgekehrter Reihenfolge ausgegeben, weil
der Compiler den letzten Parameter zuerst auf dem Stack ablegt.
Wie man der Ausgabe entnehmen kann, wird der Stack im Speicher von oben nach
unten aufgebaut, d. h., der Stack-Frame der Funktion, die als letztes aufgerufen
wird, und der damit den obersten Stack-Frame bildet, liegt im Speicher an der nied-
rigsten Speicheradresse.
Der Stack-Frame für den ersten Aufruf von func() beginnt an der Adresse
0065FE00, der Stack-Frame für den zweiten Aufruf an der Adresse 0065FDE0. Im
Stackrahmen werden zuerst die drei int-Parameter abgelegt. Jeder int-Parameter
belegt 4 Byte (wie für 32-Bit-Systeme üblich). Dann folgt ein Leerraum, in dem
Daten abgelegt werden, auf die wir keinen direkten Zugriff haben (vermutlich die
Rücksprungadresse und ein Zeiger auf den Beginn des vorangehenden Stack-Fra-
mes). Danach folgen die lokalen Variablen, die gemäß ihrem Datentyp wiederum
jeweils 4 Byte belegen.
Warnung
● Wenn in C/C++ eine Funktion aufgerufen wird, wird für die Funktion Spei-
cherplatz reserviert. Die Einrichtung und Verwaltung des Speicherbereichs der
Funktion kostet auch Laufzeit. Diesen Zeitverlust bezeichnet man als Function
Overhead.
● In dem für die Funktion bereitgestellten Speicherbereich liegen die Speicherzel-
len der Funktionsparameter, der lokalen Variablen und der Rücksprungadres-
se, die sicherstellt, daß nach Abarbeitung der Funktion wieder an die richtige
Stelle im Programm zurückgesprungen wird. Bei Beenden der Funktion gibt
156
Funktionen mit beliebig vielen Argumenten
Verweise
Siehe Kategorie Variablen und Datentypen, Gültigkeitsbereiche
Beschreibung
C/C++ erlaubt auch die Definition von Funktionen mit unbekannter Parameterzahl. Das kommt
nicht gänzlich überraschend, denn schließlich erlauben auch einige gängige Bibliotheksfunk-
tionen eine variable Anzahl von Argumenten: printf() und scanf().
Anwendung
Die Implementierung von Funktionen mit beliebig vielen Argumenten beruht auf
zwei Elementen:
double mittel(int anzahl, ...)
● Der Ellipse. Die Ellipse ... in der Parameterliste zeigt an, daß bei Aufruf noch
eine beliebige Zahl von Argumenten folgen kann. Die Ellipse muß am Ende
der Parameterdefinition stehen, und ihr muß ein ordentlicher Parameter vor-
ausgehen, an dem man innerhalb der Funktion ablesen kann, wie viele Para-
meter folgen.
● Die va_Makros aus <stdarg.h>. Diese werden benötigt, um die Argumente zu
übernehmen und auszuwerten.
Beispiele
double mittel(int anzahl, ...) {
double summe = 0;
va_list ap;
int loop;
157
Sprachkonzepte und Syntax
va_start(ap, anzahl);
for(loop=1;loop<= anzahl;loop++)
summe += va_arg(ap,int);
va_end(ap);
return summe/anzahl;
}
Anwendung
Aufrufe von Funktionen bedingen eine zeitliche Verzögerung, den sogenannten
Function Overhead. Man kann dies vermeiden, indem man Makros statt Funktio-
nen einsetzt. Ein Makroaufruf wird vom Compiler beim Übersetzen durch die
Makrodefinition ersetzt. Makros bringen jedoch einige Probleme mit sich:
● Sie nehmen keine Typüberprüfung vor, und
● Ihre Formulierung ist fehleranfälliger als die Definition von Funktionen.
C++ bietet daher die Alternative, Funktionen als inline zu deklarieren, indem das
Schlüsselwort inline einfach an den Anfang des Funktionskopfes gestellt wird. Das
Schlüsselwort inline weist den Compiler an, ähnlich wie bei einem Makro, die
Funktionsaufrufe durch die Funktionskörper zu ersetzen. Der Nachteil gegenüber
dem Gebrauch von Makros liegt darin, daß die inline-Direktive vom Compiler nur
als Empfehlung angesehen wird, die er nicht beachten muß.
Warnung
● Allgemein ist zum Gebrauch von Makros und Inline-Funktionen zu sagen, daß
sie zwar die Laufzeit eines Programms beschleunigen, dafür aber den Code
aufblähen. Sie eignen sich daher vor allem für kleinere Funktionen, die nicht
allzu oft aufgerufen werden.
● Methoden von Klassen, die innerhalb der Klasse definiert werden, werden
vom Compiler automatisch als Inline-Funktionen behandelt.
158
Spezifizierer für Funktionen
Verweise
Siehe Funktionen und der Stack
static Die Verwendung von static als Schlüsselwort vor der Typangabe einer
Funktion verengt deren Sichtbarkeit auf die Datei, in der sie definiert ist.
extern Die Verwendung von extern als Schlüsselwort vor der Typangabe einer
Funktion macht sie in allen Dateien sichtbar, die zu dem Programm gehören
(Funktionen sind per Voreinstellung extern).
- Fehlt die Angabe, hat eine Funktion standardmäßig die Speicherklasse
extern.
159
Sprachkonzepte und Syntax
Methoden können nicht als extern deklariert werden. extern ist im Grunde ein
Bezug auf eine globale Deklaration, die üblicherweise in externen Bindung resul-
tiert. Dies ist für Methoden weder erlaubt noch sinnvoll.
Beispiele
extern int func1();
static int func2();
inline int func3();
class demo {
static int func4();
int func5() const;
int func6() volatile;
virtual int func7();
};
Verweise
Siehe Funktionsdeklaration und -definition
Siehe Inline-Funktionen
Siehe Kategorie Klassen, Methoden
Überladung
Beschreibung
C++ erlaubt die Definition mehrerer Funktionen (oder Operatoren) gleichen Namens, sofern die
Funktionen sich in Anzahl oder Typ der Parameter unterscheiden. Die Definition mehrerer
Funktionen gleichen Namens bezeichnet man als Überladung.
160
Überladung
● Ein Typ T kann nicht von seiner Referenz T& unterschieden werden.
● Ein Typ T kann nicht von const T oder volatile T unterschieden werden, wohl
aber T* von const T*.
Findet der Compiler keine exakte Übereinstimmung, sucht er die bestmögliche
Übereinstimmung.
● Zuerst wendet der Compiler die arithmetischen Promotionen auf die Argu-
mente an.
● Dann versucht er es mit Standardkonvertierungen (double zu int, int zu double,
Abgeleitet* zu Basis*, etc.),
● Am Schluß berücksichtigt er noch benutzerdefinierte Konvertierungen für
Klassen.
Warnung
Überladene Funktionen müssen in einem gemeinsamen Gültigkeitsbereich liegen,
sonst findet keine Überladung, sondern die übliche Verdeckung statt.
Der Rückgabetyp spielt bei der Überladung keine Rolle – überladene Funktionen
können also nicht anhand des Rückgabetyps unterschieden werden.
Findet der Compiler für ein Set von Argumenten zwei oder mehr überladene Ver-
sionen, die alle gleich gut zu den Argumenten passen, gibt er eine Fehlermeldung
aus, daß er die Überladung nicht eindeutig auflösen kann.
void func(char) {};
void func(short) {};
161
Sprachkonzepte und Syntax
{
func(c); // ruft func(char) auf
func(s); // ruft func(short) auf
func(i); // Fehler: ambiguity
}
Das Problem liegt hier darin, daß es keine überladene Funktion für den Datentyp
int gibt, daß aber sowohl char als auch short durch integrale Promotion in int ver-
wandelt werden können.
Verweise
Siehe Kategorie Variablen und Datentypen, Gültigkeitsbereiche
Siehe Überladen, Überschreiben, Verdecken
Anwendung
Die Überladung von Funktionen wird eingesetzt, um das Verhalten einer Routine
an die ihr übergebenen Parametertypen anzupassen. Der Vorteil für den Program-
mierer besteht darin, daß er nicht mehrere Funktionsnamen für eine Routine zu
vergeben braucht, und der Compiler die Aufgabe übernimmt, die Parameter zu
checken und die richtige Version der Routine aufzurufen.
Warnung
Überladene Funktionen müssen in einem gemeinsamen Gültigkeitsbereich liegen,
sonst findet keine Überladung, sondern die übliche Verdeckung statt.
Beispiele
int max(int a, int b) {
return ( a > b ? a : b);
}
const char* max(const char* s1, const char* s2) {
return (strcmp(s1,s2) ? s1 : s2);
}
int max(int a, char* s) {
return ( a > strlen(s) ? a : strlen(s));
}
162
Überladung von Methoden
Warnung
● Ererbte Funktionen können in abgeleiteten Klassen nicht überladen werden.
● In der abgeleiteten Klasse deklarierte Funktionen verdecken gleichnamige Funk-
tionen der Basisklassen, die weiterhin über den Bereichsoperator aufrufbar sind.
● Soll eine Überladung simuliert werden, müssen die Versionen der Basisklasse
zuerst überschrieben werden.
Beispiele
class basis {
public:
void func(char * s);
void func(char c);
};
class abgeleitet : public basis {
public:
void func(int wert);
}
int main() {
class abgeleitet abg;
[Link]("Test"); // Fehler
[Link]('c'); // Fehler
[Link](3.2); // wird als 3 interpretiert
[Link]::func("Test");
return 0;
}
163
Sprachkonzepte und Syntax
Überschriebene Methoden
● liegen in verschiedenen Gültigkeitsbereichen, wobei die überschriebene Met-
hode in einer Basisklasse und die überschreibende Methode in einer von der
Basisklasse abgeleiteten Klasse definiert ist.
● haben identische Namen und Parametertypen.
● werden üblicherweise als virtual deklariert.
● dienen der Implementierung polymorphen Verhaltens in Klassenhierarchien.
● sind über den Gültigkeitsbereichoperator weiterhin erreichbar.
Verdeckte Methoden
● liegen in verschiedenen Gültigkeitsbereichen, wobei die überschriebene Me-
thode in einer Basisklasse und die überschreibende Methode in einer von der
Basisklasse abgeleiteten Klasse definiert ist.
● haben nicht-identische Namen und Parametertypen.
● sind über den Gültigkeitsbereichoperator weiterhin erreichbar.
Klassen
Klassen
Beschreibung
C++ basiert auf der Sprache C. Die vollständige Aufwärtskompatibilität garantiert, daß C++ die
Syntax von C vollkommen einschließt. Objektorientiertes Programmieren ist daher nicht gleich-
zusetzen mit Programmieren in C++, sondern beginnt erst mit der Verwendung der objektorien-
tierten Konzepte, um die C++ den C-Standard erweitert. Die wichtigsten dieser Konzepte
(Kapselung, Vererbung, Polymorphie, Templates) gehen zurück auf den neuen Datentyp class.
Anwendung
Klassen dienen dazu, Datenelemente und Elementfunktionen (Methoden) in einem
Datentyp zu kapseln. Sie gestatten es, verschiedene Zugriffsberechtigungen für die
einzelnen Elemente zu vergeben, und können durch Vererbung Klassenhierarchien
aufbauen.
164
Klassen
Syntax
klassentyp klassenname [: BASISKLASSEN]
{
ELEMENTLISTE
} instanzen;
● klassentyp: Als Klassentyp können neben dem Schlüsselwort class auch struct
und union verwendet werden. Die Verwendung der Schlüsselwörter struct und
union beruht darauf, daß in C++ Strukturen und Unions spezielle Klassen dar-
stellen. Dies erleichtert die Verwendung von C-Modulen in C++-Programmen,
sollte den Programmierer aber nicht dazu verführen, beide Konzepte zu vermi-
schen. Es ist empfehlenswert, Klassen stets als class zu deklarieren und Unions
und Strukturen nur gemäß der C-Konvention zu verwenden.
● klassenname: Name der zu deklarierenden Klasse.
● :BASISKLASSEN: Durch Kommata getrennte Liste von Klassen, deren Ele-
mente übernommen (geerbt) werden. Der Zugriff der abgeleiteten Klasse auf
die ererbten Elemente kann durch die Spezifizierer public, protected und priva-
te modifiziert werden. Ein Eintrag in dieser Liste hat folgende Syntax:
[virtual] [public, protected, private] basisklassenname
● ELEMENTLISTE: In der Elementliste werden Datenelemente und Methoden
der Klasse deklariert und unter Umständen auch schon definiert. Der Zugriff
auf die Elemente kann durch die Spezifizierer public, protected und private ge-
regelt werden. Alle Elemente haben ihre Klasse als Gültigkeitsbereich.
● instanzen: Hinter der abschließenden Klammer können durch Kommata ge-
trennt bereits Instanzen, also Variablen der Klassentyps, eingerichtet werden.
Warnung
● Eine Basisklasse muß deklariert sein, bevor sie zur Vererbung herangezogen
werden kann!
● Ein Zugriffsspezifizierer gilt für alle folgenden Klassenelemente bis zum Auf-
treten eines neuen Zugriffsspezifizierers.
● Zugriffsspezifizierer können nicht kombiniert werden.
● Zugriffsspezifizierer dürfen in der Klassendeklaration mehrfach auftauchen.
● Klassenelemente am Anfang der Deklaration, für die kein Zugriffsspezifizierer
angegeben wurde, gelten automatisch als private.
Beispiele
class beispiel {
int wert; // private
public:
beispiel() {wert = 1;}; // Konstruktor
protected:
165
Sprachkonzepte und Syntax
Verweise
Siehe Variablen und Datentypen, Strukturen
Siehe Variablen und Datentypen, Unions
Siehe Vererbung und Polymorphie
Beispiel
Objekte, die gleiche Merkmale und Verhaltensweisen aufweisen, können in einer
Klasse zusammengefaßt werden. So könnte eine Klasse videorecorder folgenderma-
ßen aussehen:
class videorecorder {
/* Merkmale */
char *hersteller;
int anzahl_videokoepfe;
boolean zeitlupe, longplay, zweikanalton;
public:
/* Verhaltensweisen */
void anschalten();
void abspielen();
void aufnahme();
void in_zeitlupe_abspielen();
void ausschalten();
};
Bei der Bildung einer Variablen der Klasse – im folgenden als Instanzbildung
bezeichnet – werden den Merkmalen Werte zugewiesen. Auf diese Weise entsteht
durch Spezialisierung eine Instanz, die nur noch einen besonderen Videorecorder
repräsentiert. (Ein weiteres Beispiel wäre die Klasse Mensch und ihre Instanzen, näm-
lich jeder einzelne von uns – die Individuen. Eine Geburt wäre folglich eine Instanz-
bildung.)
166
Kapselung
Verweise
Siehe Kapselung
Siehe Instanzbildung
Kapselung
Beschreibung
Die Zusammenfassung von Datenelementen und Methoden wird als Kapselung bezeichnet.
Zudem verbinden sich mit dem Begriff noch zwei weitere Designkriterien:
Information hiding und
Abgeschlossenheit
Information hiding
Klassen sollten vornehmlich über ihre Methoden angesprochen werden. Diese
Funktionen bilden die Schnittstelle zwischen Klasse und Programm. (Die genaue
Festlegung der Schnittstelle erfolgt über die Vergabe von Zugriffsspezifizierern.)
Nach der Implementierung der Klasse ist es für den Programmierer wichtig, daß er
die Klasse nur noch über ihre Schnittstelle einzusetzen braucht, ohne sich weitere
Gedanken um deren Implementierung machen zu müssen. Für die fehlerlose Bear-
beitung der Funktionsaufrufe und das korrekte Verhalten der Klasse, trägt diese
selbst Sorge. Wurde zum Beispiel eine Klasse videorecorder implementiert, um
Videorecorder über den Computer anzusteuern, braucht der Programmierer nur
noch eine Instanz der Klasse zu bilden und kann danach die Instanz einsetzen wie
einen realen Videorecorder:
my_recorder.anschalten();
my_recorder.in_zeitlupe_abspielen();
my_recorder.ausschalten();
Die Ansteuerung des Videorecorders über die parallele Schnittstelle oder die Kon-
trolle, ob der Videorecorder überhaupt über Zeitlupe verfügt, nimmt die Klasse
selbst vor, d. h.,sie versteckt solche Details vor dem Programmierer und entlastet
ihn dadurch.
Abgeschlossenheit
Aus der Forderung des Information hidings ergibt sich das Kriterium der Abge-
schlossenheit. Die Schnittstelle einer Klasse sollte möglichst vollständig sein, in dem
Sinne, daß die Klasse auch sinnvoll eingesetzt werden kann. Eine Klasse videorecor-
der, die über keine Funktion in_zeitlupe_abspielen() verfügt, wäre von vornherein
zur Bedienung von Videorecordern mit Zeitlupe ungeeignet.
167
Sprachkonzepte und Syntax
Umgekehrt sollten in einer Klasse nur Daten und Funktionen enthalten sein, die die
Objekte der Klasse auch wirklich kennzeichnen. Eine Methode berechne_bruch()
würde in der Klasse videorecorder keinen Sinn machen.
Verweise
Siehe Praxisteil, Kategorie Klassen
Datenelemente
Beschreibung
Variablen, die innerhalb einer Klasse definiert werden, stellen die Datenelemente der Klasse
dar.
Anwendung
Wird eine Instanz von der Klasse gebildet, wird der Instanz Speicher für die Daten-
elemente zur Verfügung gestellt. Jede Instanz hat also ihre eigene Kopie der Daten-
elemente, die man daher auch Instanzvariablen nennt. Gleichzeitig wird die
Instanzbildung dazu genutzt, die Datenelemente zu initialisieren. Diese Aufgabe
übernimmt der Konstruktor. Klassen stellen einen eigenen Gültigkeitsbereich dar,
d. h., die Instanzvariablen verfallen mit ihrer Instanz (wofür der Destruktor Sorge
trägt), und Namen aus anderen Gültigkeitsbereichen werden verdeckt. Neben der
Deklaration von Datenelementen bekannter Typen ist es auch möglich, innerhalb
einer Klasse eine lokale Typdefinition vorzunehmen.
Warnung
Datenelemente
● können als public, protected oder private deklariert werden.
● werden bei der Instanzbildung eingerichtet und zusammen mit der Instanz auf-
gelöst.
● können als static, const, volatile oder mutable deklariert werden.
Beispiele
class demo {
int anzahl; // private Daten
int *feld;
public:
char *str; // public Daten
...
168
Statische Datenelemente
Verweise
Siehe Konstruktor und Destruktor
Siehe Zugriffsspezifizierer
Statische Datenelemente
Beschreibung
Statische Datenelemente werden bei der Instanzbildung nicht kopiert. Statt dessen greifen alle
Instanzen auf die gleiche Variable zu.
Anwendung
Statische Elemente müssen außerhalb der Klasse, im umgebenden namespace (oder
Dateibereich), definiert werden und können nicht nur über Instanzen, sondern auch
über den Klassennamen angesprochen werden:
Warnung
Statische Elemente können nicht als auto, register oder extern deklariert werden.
Beispiele
class Demo {
public:
static int instanzenzaehler;
Demo() {instanzenzaehler++;}
~Demo() {instanzenzaehler--;}
};
int Demo::instanzenzaehler = 0;
int main() {
Demo lok;
cout << Demo::instanzenzaehler << endl;
cout << [Link] << endl;
return 0;
}
Verweise
Siehe Statische Methoden
169
Sprachkonzepte und Syntax
Konstante Datenelemente
Beschreibung
Datenelemente, die als const deklariert werden, können nach der Instanzbildung nicht mehr
verändert werden.
Warnung
const-Datenelemente müssen in der Konstruktorliste initialisiert werden.
Beispiele
class Demo {
public:
const int j; // konstante Instanzvariable
Demo() : j(2) // Initialisierung
{
...
};
Verweise
Siehe Konstante Methoden
Siehe Kategorie Konstanten
Anwendung
Eingebettete Objekte werden im Zuge der Instanzbildung des ihnen übergeordneten
Objekts erzeugt und mit diesem aufgelöst.
Zur Einrichtung des eingebetteten Objekts muß ein Konstruktor des eingebetteten
Objekts aufgerufen werden. Dies kann ein Standardkonstruktor sein, der Program-
mierer muß sich dann nicht um die Einrichtung kümmern. Es kann auch ein Kon-
struktor mit Argumenten sein, der Programmierer muß dann den Konstruktor des
übergordneten Objekts um eine Konstruktorliste erweitern, in der der Konstruktor
des eingebetteten Objekts aufgerufen wird. (Beachten Sie, daß der Konstruktor
über den Objektnamen und nicht wie bei Basisklassen über den Klassennamen auf-
gerufen wird.)
Zur Auflösung des eingebetteten Objekts wird sein Destruktor aufgerufen.
170
Klasseninstanzen als Datenelemente
Warnung
● Eine Klasse kann keine Instanzen von Klassen als Element enthalten, wenn
diese Klassen nicht zuvor definiert wurden.
● Da die Definition einer Klasse mit dem Semikolon abschließt, folgt daraus,
daß eine Klasse keine Instanz ihres eigenen Typs als Element enthalten kann.
Wohl aber ist es möglich, Zeiger oder Referenzen auf nicht definierte Klassen
zu definieren, sofern der Klassenname bekannt ist.
● Die umliegende Klasse hat keine besonderen Zugriffsrechte auf die Elemente
des eingebetteten Objekts.
Beispiele
Zeiger auf Objekte von noch nicht definierten Klassen:
class demo;
class beispiel {
int a;
class beispiel falsch; // kann von Compiler nicht
// aufgelöst werden
class beispiel* richtig;
class demo& auch_richtig;
};
Instanziierung eingebetteter Objekte durch den Standardkonstruktor:
class A {
public:
int i;
A() {i = 1;} // Standardkonstruktor
};
class B {
public:
int n;
A obj;
B() {n = 2;}
};
Instanziierung eingebetteter Objekte über Konstruktorliste:
class A {
public:
int i;
A(int i_par) {i = i_par;}
};
class B {
public:
int n;
A obj;
B(int p1, int p2) : obj(p1) {n = p2;}
};
171
Sprachkonzepte und Syntax
Verweise
Siehe Lokale und verschachtelte Klassen
Siehe Konstruktor
Siehe Vererbung und Polymorphie, Vererbung versus Einbettung
Warnung
● Eine eingeschlossene Klasse kann Typen und statische Elemente der einschlie-
ßenden Klasse direkt benutzen.
● Eingeschlossene Klassen dürfen keine statischen Elemente enthalten.
● Die eingeschlossene Klasse hat keine besonderen Zugriffsrechte auf die Ele-
mente der einschließenden Klasse, d. h., sie kann nur über Instanzen der einge-
schlossenen Klasse auf deren Elemente zugreifen (Ebenso hat auch die
einschließende Klasse keine besonderen Zugriffsrechte auf die eingeschlossene
Klasse).
Beispiele
int i;
class global {
static int n;
public:
int i;
static float f;
class intern {
void func(global &glob) {
i = 3; // Fehler
f = 3; // korrekt
::i = 3; // i aus Dateibereich
glob.i = 3; // i aus Klasse global
n = 3; // Fehler
}
...
172
Methoden
Verweise
Siehe Klasseninstanzen als Datenelemente
Methoden
Beschreibung
Funktionen, die als Elemente einer Klasse definiert werden, bezeichnet man als Methoden.
Anwendung
Methoden können sowohl innerhalb als auch außerhalb der Klassendeklaration
definiert werden.
● Methoden, die innerhalb der Klassendefinition definiert werden, werden auto-
matisch als inline interpretiert. Auch wenn das Schlüsselwort inline nur als
Empfehlung für den Compiler gedacht ist, ergibt sich daraus, daß innerhalb
einer Klassendefinition nur kurze Funktionen definiert werden sollten. Zum
einen, um Speicherplatz zu sparen, zum anderen, um die Klassendefinition
übersichtlich zu halten.
● Bei der Definition außerhalb der Klassendefinition muß der Klassenname mit
dem Bereichsoperator vorangestellt werden.
173
Sprachkonzepte und Syntax
Warnung
Methoden
● können als public, protected oder private deklariert werden.
● haben Zugriff auf alle Elemente der Klasse.
● stellen neben Friends die einzige Möglichkeit dar, auf private Elemente ihrer
Klasse zuzugreifen.
● können als virtual deklariert werden.
● können als inline deklariert werden.
● können als const deklariert werden. Methoden, die als const deklariert sind,
sind die einzigen Methoden, die von const-deklarierten Instanzen aufgerufen
werden können. (Das Schlüsselwort const wird der Parameterliste nachge-
stellt).
● können als volatile deklariert werden. Methoden, die als volatile deklariert
sind, sind die einzigen Methoden, die von volatile-deklarierten Instanzen auf-
gerufen werden können. (Das Schlüsselwort volatile wird der Parameterliste
nachgestellt).
● können nur von Methoden der gleichen Klasse überladen werden.
Verweise
Siehe Überladung
Siehe Kategorie Vererbung und Polymorphie, Überschreibung und virtuelle Metho-
den
Statische Methoden
Beschreibung
Statische Methoden sind Methoden, die mit dem Schlüsselwort static deklariert werden. Stati-
sche Methoden sind ebenso wie statische Datenelemente klassen- und nicht instanzspezifisch.
Statische Methoden besitzen keinen this-Zeiger und können daher nur andere statische Ele-
mente (Daten wie Methoden) aufrufen.
Anwendung
Statische Methoden können über Instanzen oder den Klassennamen aufgerufen
werden.
Warnung
Statische Methoden können nicht als virtual deklariert werden.
174
Konstante Methoden
Beispiele
class Demo {
private:
static int standardwert;
public:
static void std_setzen(int i) {
if( i > 0 && i < 100 )
standardwert = i;
}
};
int Demo::standardwert = 1;
int main()
{
Demo obj1, obj2;
Demo::std_setzen(33);
return 0;
}
Verweise
Siehe Statische Datenelemente
Konstante Methoden
Beschreibung
Konstante Methoden sind Methoden, die mit dem Schlüsselwort const deklariert werden.
Methoden, die als const deklariert werden, können Elementdaten nicht ändern (es sei denn,
diese sind explizit als mutable deklariert) und können Zeiger oder Referenzen auf Elementda-
ten nur als const zurückgeben.
Anwendung
const-Methoden sind die einzigen Methoden, die von const-deklarierten Instanzen
aufgerufen werden können. (Manche Compiler geben bei Zuwiderhandlung aller-
dings nur eine Warnung aus).
Das Schlüsselwort const wird der Parameterliste nachgestellt.
Beispiele
class Demo {
public:
int i;
const int j;
mutable int n;
Demo() : j(2) {} // Initialisierung
void inkr() const {
i++; // Fehler
175
Sprachkonzepte und Syntax
j++; // Fehler
n++; // ok
}
void func() {...}
};
Konstante Klasseninstanzen:
const demo obj2;
[Link](); // Fehler
[Link](); // o.k.
Verweise
Siehe Konstante Datenelemente
Zugriffsspezifizierer
Beschreibung
Die Zugriffsspezifizierer public, private und protected regeln, wie von innerhalb und außer-
halb der Klasse auf deren Elemente zugegriffen werden kann.
Anwendung
Die Zugriffsspezifizierer sind daher ein wichtiges Instrument der Kapselung. Erst
durch diese Spezifizierer kann eine Klasse vor Mißbrauch geschützt werden. Die
Zugriffsspezifizierer werden sowohl bei der Klassendefinition wie auch bei der Ver-
erbung eingesetzt.
176
Zugriffsspezifizierer
Spezifizierer Bedeutung
public Das Element kann von jeder Methode der eigenen und abgeleiteten Klas-
sen benutzt werden. Der Zugriff von außen erfolgt über den Namen der
Instanz und einem der Zugriffsoperatoren:
instanz_name.elementname
referenz_der_instanz.elementname
zeiger_auf_instanz->element_name
private Das Element kann nur von Methoden und Friends der Klasse, in der es
deklariert wurde, benutzt werden.
protected Es gilt das gleiche wie für private. Zusätzlich ist jedoch die Benutzung
durch Methoden von Klassen, die von der deklarierten Klasse abgeleitet
sind, möglich. Gibt es keine abgeleiteten Klassen, sind private und pro-
tected identisch.
Spezifizierer Bedeutung
public Für die geerbten Elemente gelten die gleichen Zugriffsrechte, die in der
Basisklasse festgelegt wurden.
private Alle geerbten Elemente sind von außen als private anzusehen.
protected public-Elemente werden als protected-Elemente angesehen.
Warnung
● Ein Zugriffsspezifizierer gilt für alle folgenden Klassenelemente bis zum Auf-
treten eines neuen Zugriffsspezifizierers.
● Zugriffsspezifizierer können nicht kombiniert werden.
● Zugriffsspezifizierer dürfen in der Klassendeklaration mehrfach auftauchen.
● Klassenelemente am Anfang der Deklaration, für die kein Zugriffsspezifizierer
angegeben wurde, gelten automatisch als private.
● Zu den Zugriffsspezifizierern im weiteren Sinne zählt auch das Schlüsselwort
friend (siehe Zugriff von außerhalb der Klasse).
177
Sprachkonzepte und Syntax
Verweise
Siehe nachfolgende Abschnitte
Siehe Vererbung und Polymorphie, Zugriffsbeschränkung bei der Vererbung
Beschreibung
Zugriff innerhalb einer Klasse bedeutet, daß innerhalb des Funktionskörpers von Methoden auf
andere Elemente (Daten oder Funktionen) der eigenen Klasse zugegriffen wird. Dies ist der
innerste Bereich, der praktisch keinen Beschränkungen unterliegt. Der Zugang zu den Elemen-
ten erfolgt direkt über deren Namen.
Warnung
● Methoden, die als const deklariert sind, können auf alle Datenelemente zugrei-
fen, aber nur mutable-Datenelemente verändern.
● Statische Methoden können nur statische Elementdaten direkt ansprechen.
(Dies liegt daran, daß statische Methoden keinen this-Zeiger besitzen.) Nicht-
statische Elemente müssen über eine existierende Instanz (die beispielsweise
als Argument übergeben werden kann) angesprochen werden.
● Für geerbte Elemente aus Basisklassen gelten die Zugriffsrechte, die in der Ba-
sisklasse festgelegt wurden.
Beispiele
class demo {
private:
int wert1, wert2;
int func1() {return wert1*wert2;}
178
Zugriff von außerhalb der Klasse
public:
...
void func2(int i) {
wert1=i+1;
wert2 = func1();
}
};
Verweise
Siehe nachfolgende Abschnitte
Siehe this-Zeiger
Beschreibung
Von außerhalb kann auf Elemente der Klasse T nur über eine Instanz der Klasse T in Verbin-
dung mit einem der Operatoren . -> .* ->* oder über Friends der Klasse zugegriffen werden.
179
Sprachkonzepte und Syntax
class demo {
int wert;
friend int func(demo&); // Friend-Deklaration
};
// Friend-Funktion
int func(demo& objekt) {
return [Link];
}
int main() {
class demo d;
cout << func(d);
return 0;
}
Warnung
● Beachten Sie die Feinheit, daß die Deklaration als friend in der Klasse vorge-
nommen werden muß. Die Klasse bestimmt also selbst, welche Funktionen
friend sind und welche nicht, und kann ihre Daten immer noch vor unkontrol-
liertem Gebrauch schützen.
● Private Elemente, die über keine public-Methoden verfügen, können über fri-
end-Funktionen erreicht werden.
180
Zugriff auf Basisklassenelemente
● Neben der Deklaration einzelner Funktionen als friend können Sie auch sämt-
liche Funktionen einer Klasse auf einen Schlag als friend deklarieren, indem
Sie die ganze Klasse als friend deklarieren.
Verweise
Siehe Kategorie Operatoren, Datenzugriff
181
Sprachkonzepte und Syntax
Verweise
Siehe Kategorie Vererbung und Polymorphie, Zugriffsbeschränkung und Zugriffs-
rechte
182
Der Konstruktor
Der Konstruktor
klassenname() {}
Beschreibung
Jede Instanzbildung eines Klassenobjekts ist mit dem Aufruf eines Konstruktors verbunden.
Anwendung
Der Programmierer kann im Anweisungsteil des Konstruktors für die Initialisierung
der Datenelemente und für Eingangsarbeiten (beispielsweise der Reservierung von
dynamischem Speicher) sorgen.
Durch Definition eines oder mehrerer eigener Konstruktoren (Überladung) kann
die Instanzbildung gesteuert und an die Übergabe verschiedener Argumenttypen
angepaßt werden.
Der Standardkonstruktor
Um sicherzustellen, daß jede Klasse über einen Konstruktor verfügt, weist der
Compiler Klassen ohne explizit deklarierten Konstruktor einen Standardkonstruk-
tor zu (Konstruktor, der ohne Argument aufgerufen werden kann).
Wird ein Konstruktor explizit definiert, steht der Standardkonstruktor des Compi-
lers nicht mehr zur Verfügung; der Programmierer kann aber einen eigenen Stan-
dardkonstruktor definieren.
Der Standardkonstruktor vereinfacht die Einrichtung eingebetteter und geerbter
Objekte sowie von Arrays von Klassenobjekten, die ansonsten nur durch Angabe
von Konstruktorlisten bzw. Initialisierungslisten zu bewerkstelligen ist.
Warnung
● Ein Konstruktor hat immer den gleichen Namen wie seine Klasse.
● Ein Konstruktor hat keinen Rückgabewert (auch nicht void).
● Konstruktoren können nicht als virtual, static, const, mutable oder volatile
deklariert werden.
● Konstruktoren können überladen werden. Die Überladung wird meist dazu ge-
nutzt, dem Konstruktor Argumente für die Initialisierung der Datenelemente
der Klasse zu übergeben.
● Konstruktoren werden nicht vererbt.
● Es können keine Zeiger auf Konstruktoren definiert werden.
● Konstruktoren können nach der Instanzbildung nicht mehr aufgerufen wer-
den.
183
Sprachkonzepte und Syntax
Beispiele
class demo {
int privat;
public:
demo(int i) {privat = i;}
explicit demo(float f) {privat = (int) f;};
};
int main() {
class demo instanz(100);
class demo instanz2 = 100;//implizite Konvertierung
class demo instanz3(3.2);
class demo instanz4 = 3.2;//Fehler: explicit
class demo instanz5; //Fehler, Standardkonstruktor
//nicht mehr verfügbar
return 0;
}
Verweise
Siehe Kopierkonstruktor
Siehe Destruktor
Siehe Klasseninstanzen als Datenelemente
Siehe Kategorie Vererbung und Polymorphie, Vererbung und Konstruktor
Der Kopierkonstruktor
klassenbezeichner(klassenbezeichner&)
Beschreibung
Der Kopierkonstruktor ist ein Konstruktor, der Instanzen seiner Klasse auf der Grundlage ande-
rer Instanzen der Klasse erzeugt. Die Instanz, die als Grundlage für die neu anzulegende
Instanz verwendet werden soll, wird dem Konstruktor als Parameter übergeben.
184
Der Kopierkonstruktor
Anwendung
Der Kopierkonstruktor wird aufgerufen, wenn Sie eine Klasseninstanz mit einer
anderen Klasseninstanz (der gleichen Klasse) initialisieren. Wurde innerhalb der
Klasse kein eigener Kopierkonstruktor deklariert, wird der Standardkopierkon-
struktor aufgerufen, der die Klassenelemente 1:1 kopiert.
Der Kopierkonstruktor ist eine von zwei Möglichkeiten, Klasseninstanzen zu
kopieren. Die zweite Option ist der Zuweisungsoperator =, der ebenfalls als 1:1-
Kopierer vordefiniert ist und bei Bedarf überladen werden muß.
Beachten Sie, daß Kopierkonstruktoren implizit auch bei der Übergabe von Klas-
senobjekten an Funktionen/Methoden und bei der Zurücklieferung von Klassenob-
jekten als Rückgabewerte von Funktionen/Methoden aufgerufen werden (sofern
nicht Zeiger oder Referenzen verwendet werden).
Warnung
1:1-Kopieren wie vom Standard-Kopierkonstruktor vorgenommen, führt meist zu
Fehlern, wenn die Klasse Zeiger enthält. Dies liegt einfach daran, daß für einen
Zeiger die in dem Zeiger aufbewahrten Adressen kopiert werden, so daß nach der
Kopierinitialisierung die beiden Zeiger der Vorlage und der Kopie auf das gleiche
Objekt verweisen.
Beispiele
#include <iostream>
using namespace std;
class demo {
int i;
int* p;
public:
demo(int wert) {
i = wert;
p= &i;
}
demo(const demo& inst) { // Kopierkonstruktor
i = inst.i; p = &i;
}
};
int main() {
demo a(3);
demo b(a); // Verwendung des Kopierkonstruktors
return 0;
}
185
Sprachkonzepte und Syntax
Verweise
Siehe Konstruktor
Der Destruktor
~klassenname() {}
Beschreibung
Destruktoren werden automatisch aufgerufen, wenn Klasseninstanzen ihre Gültigkeit verlieren
(beispielsweise bei Verlassen des Gültigkeitsbereichs oder bei delete-Aufrufen für Zeiger auf
Klasseninstanzen). Sie lösen die Instanz auf und geben den reservierten Speicher frei.
Warnung
Für Destruktoren gelten ähnliche Regeln wie für Konstruktoren:
● Destruktoren tragen immer den Namen ihrer Klasse, jedoch mit vorangehen-
der Tilde.
● Ein Destruktor hat keinen Rückgabewert (auch nicht void).
● Destruktoren können nicht als static, const, mutable oder volatile deklariert
werden.
● Eine Klasse ohne explizit deklarierten Destruktor bekommt einen Standardde-
struktor zugewiesen.
● Destruktoren werden nicht vererbt.
● Es können keine Zeiger auf Destruktoren definiert werden.
Destruktoren unterscheiden sich von Konstruktoren:
● Destruktoren können keine Argumente übergeben werden, woraus folgt:
● Destruktoren können überschrieben, aber nicht überladen werden.
● Destruktoren können als virtual deklariert werden.
● Basisklassen sollten im Zweifelsfalle einen virtuellen Destruktor definieren.
● Destruktoren von Klassen, die von Basisklassen mit virtuellem Destruktor ab-
geleitet sind, sind automatisch virtuell.
● Destruktoren können explizit aufgerufen werden, was aber selten notwendig ist.
Verweise
Siehe Konstruktor
186
Standardmethoden
Standardmethoden
Es gibt 5 Methoden, für die der Compiler automatisch Standardversionen erzeugt,
wenn die Klasse keine eigenen Implementierungen vorsieht.
● Standardkonstruktor
● Destruktor
● Kopierkonstruktor
● Zuweisungsoperator
● Adreßoperator (liefert den Wert des this-Zeigers zurück).
Der this-Zeiger
this
Beschreibung
Der this-Zeiger ist ein vom Compiler definierter Zeiger, der in allen nicht-statischen Methoden
einer Klasse verfügbar ist und jeweils auf das aktuelle Objekt der Klasse verweist, über das die
Methode aufgerufen wurde.
Anwendung
Werden mehrere Instanzen einer Klasse gebildet, bekommt jede Instanz eine eigene
Kopie der Datenelemente der Klasse. Die Methoden der Klasse stehen aber nur ein-
mal im Arbeitsspeicher und werden von allen Instanzen einer Klasse gemeinsam
benutzt. Da die Methoden üblicherweise auf den Elementdaten der Klasse operie-
ren und diese instanzspezifisch sein sollen, muß sichergestellt werden, daß die
jeweilige Methode nur auf die Daten zugreift, die zur aufrufenden Instanz gehören.
Der Compiler weist aus diesem Grunde jeder Instanz einen Zeiger auf sich selbst zu
– den this-Zeiger. Bei jedem Aufruf einer Methode wird dieser Zeiger automatisch
an die Methode übergeben. Somit ist der this-Zeiger in jeder Methode verfügbar
(mit Ausnahme statischer Methoden).
Beispiele
#include <iostream>
using namespace std;
class demo {
public:
void func() { cout << this; }
};
187
Sprachkonzepte und Syntax
int main() {
class demo d1;
cout << "This-Zeiger der Instanz d1 = ";
[Link]();
return 0;
}
Verweise
Siehe Klassen, Methoden
Instanzbildung
klassentyp obj;
Beschreibung
Als Instanzbildung bezeichnet man die Einrichtung von Klassenobjekten (Variablen eines Klas-
sentyps). Bei der Instanzbildung wird ein konkretes Objekt einer Klasse gebildet, indem den
Datenelementen Werte zugeordnet werden. Für die Einrichtung des Speichers und die Initiali-
sierung der Datenelemente ist der Konstruktor verantwortlich, der automatisch bei der Instanz-
bildung aufgerufen wird.
Beispiele
class demo {
int privat;
public:
demo() {}; // Standardkonstruktor
demo(int i) {privat = i;}
};
int main() {
188
Vererbung
Verweise
Siehe Konstruktor
Vererbung
Beschreibung
Vererbung ist ein weiteres, ganz wesentliches Konzept der objektorientierten Programmierung,
welches es ermöglicht, neue Klassen auf der Basis bereits vorhandener Klassen zu definieren.
Anwendung
Die einfachste Form der Vererbung besteht aus einer Basisklasse und einer abgelei-
teten Klasse. Durch die Vererbung wird festgelegt, daß die abgeleitete Klasse –
zusätzlich zu den in ihrer Definition aufgeführten Eigenschaften (Datenelemente
und Methoden) – über sämtliche Elemente der Basisklasse verfügt. Auf diese Weise
kann praktisch jede Klasse von jeder anderen Klasse abgeleitet werden, was jedoch
nicht immer sinnvoll ist.
Zusätzlich zu den mit dem Klassenkonzept und der Kapselung verbundenen Vortei-
len bringt die Vererbung weitere Annehmlichkeiten mit sich:
● Gemeinsame Eigenschaften von Klassen brauchen durch Verlegung in eine Ba-
sisklasse nur einmal implementiert zu werden, wodurch auch die Wartbarkeit
des Quellcodes erleichtert wird.
● Umgekehrt gewährt die Ableitung von Basisklassen ein einheitliches Erschei-
nungsbild verwandter Klassen.
Verschiedene Konzepte erlauben es, die Gestaltung von Klassenhierarchien flexibel
zu gestalten:
● Polymorphie (virtuelle Funktionen)
● Friends
189
Sprachkonzepte und Syntax
Andere Konzepte dienen dazu, die Klassen vor Mißbrauch zu schützen und Klas-
senhierarchien strenger zu organisieren:
● Zugriffsmodifizierer
● abstrakte Klassen
Syntax
class klassenname : BASISKLASSENLISTE
{
Liste der Klassenelemente
};
● BASISKLASSENLISTE: In der Basisklassenliste werden, durch Kommata von-
einander getrennt, die Basisklassen aufgeführt, deren Eigenschaften geerbt
werden sollen. Ein Eintrag in dieser Liste hat folgende Syntax:
[virtual] [public, protected, private] Basisklassenname
● Die Zugriffsspezifizierer public, protected und private regeln bei der Vererbung
nicht den Zugriff aus den Methoden der abgeleiteten Klassen auf die geerbten
Elemente (dies wird schon durch die Zugriffsspezifizierer in der Deklaration
der Basisklasse geregelt), sondern welche Zugriffsrechte die abgeleitete Klasse
für die geerbten Elemente nach außen weitergibt (beispielsweise, wenn über
eine Instanz der abgeleiteten Klasse auf diese Elemente zugegriffen wird, oder
wenn die abgeleitete Klasse selbst als Basisklasse benutzt wird). Wird kein Zu-
griffsspezifizierer angegeben, wird die Klasse private vererbt.
● Das Schlüsselwort virtual ist nur für die Mehrfachvererbung von Bedeutung.
Warnung
Eine Basisklasse muß deklariert sein, bevor sie zur Vererbung herangezogen werden
kann!
Sinnvolle Klassenhierarchien gründen darauf, daß
● in Basisklassen die gemeinsamen Eigenschaften der abgeleiteten Klassen zu-
sammengefaßt sind,
● abgeleitete Klassen natürliche Erweiterungen und/oder Spezialisierungen ihrer
Basisklassen sind,
● man Objekte der abgeleiteten Klassen immer auch als Objekte ihrer Basisklas-
sen ansehen kann.
Beispiele
class Basis {
public:
void func1() {cout << "Basisklasse" << endl;}
};
class Abgeleitet : public Basis {
190
Vererbung versus Einbettung
public:
void func2() {cout << "Abgeleitete Klasse" << endl;}
};
int main() {
Abgeleitet obj;
obj.func1();
obj.func2();
return 0;
}
Verweise
Siehe Zugriffsbeschränkung bei der Vererbung
Vererbung Einbettung
class X class X
{ {
... ...
}; };
class Y: public class X class Y
{ {
... class X var;
}; ...
};
Vererbung bringt Ihnen die Vorteile des Die Verwendung von Elementobjekten ist
Polymorphismus, der Zugriffsbeschnei- dagegen einfacher und besser zu über-
dungen und die Möglichkeit, Instanzen der schauen.
abgeleiteten Klasse wie Objekte der Basis-
klasse zu behandeln.
Tip
Sind Sie sich einmal unschlüssig, ob Sie die Funktionalität einer Klasse auf dem
Weg über die Vererbung oder durch die Deklaration eines Elementobjekts zur Ver-
fügung stellen, versuchen Sie sich klar zu machen, in welcher Beziehung die
191
Sprachkonzepte und Syntax
Objekte, die die Klassen repräsentieren, zueinander stehen. Stellen Sie sich einfach
die Frage:
»Kann man ein Objekt der Klasse Y auch als ein Objekt der Klasse X betrachten,
oder sieht es vielmehr so aus, daß zu einem Objekt der Klasse Y auch ein Objekt
der Klasse X gehört«
Auf einen kurzen Nenner gebracht, heißt das
» ist ein Y ein X «(Vererbung)
oder
» enthält Y ein X «(Einbettung)
Für drei Klassen Auto, Motor und Sportwagen würde dies beispielsweise bedeuten, daß
man die Klasse Sportwagen von der Klasse Auto ableiten würde (denn jeder Sportwa-
gen ist auch ein Auto). Dagegen enthält jedes Auto einen Motor, man würde also in
der Klasse Auto ein Objekt der Klasse Motor einbetten (und damit auch an die Klasse
Sportwagen vererben).
Verweise
Siehe Praxisteil, Kategorie Vererbung und Polymorphie
Beschreibung
Die Zugriffsspezifizierer public, protected und private können dazu benutzt werden, bei der
Vererbung die Zugriffsrechte der geerbten Elemente zu verändern.
Anwendung
Die folgende Tabelle zeigt wie sich die Zugriffsrechte für die geerbten Elemente bei
Verwendung der Zugriffsmodifizierer public, protected und private ändern. Die
Zugriffsspezifizierer der Vererbung regeln dabei nicht den Zugriff aus den Metho-
den der abgeleiteten Klassen auf die geerbten Elemente (dies wird schon durch die
Zugriffsspezifizierer in der Deklaration der Basisklasse geregelt). Die Zugriffsspezi-
fizierer der Vererbung betreffen nur die Zugriffsrechte, die die abgeleitete Klasse
für die geerbten Elemente nach außen weitergibt (beispielsweise, wenn über eine
Instanz der abgeleiteten Klasse auf diese Elemente zugegriffen wird, oder wenn die
abgeleitete Klasse selbst als Basisklasse benutzt wird). Ausgangsbasis sind die
Zugriffsrechte, die in der Basisklasse vorgesehen wurden. Diese können durch die
Zugriffsspezifizierer der Vererbung verschärft werden.
192
Zugriffsbeschränkung bei der Vererbung
Warnung
Wird kein Zugriffsspezifizierer angegeben, wird die Klasse private vererbt.
Beispiele
#include <iostream>
using namespace std;
class Basis {
int w_priv; // private
public:
int w_pub;
};
int main() {
class Abgeleitet obj;
return 0;
}
Verweise
Siehe Kategorie Klassen, Zugriffsspezifizierer
Siehe Zugriffsrechte für einzelne Elemente auflockern
193
Sprachkonzepte und Syntax
Beispiele
class Basis {
int w_priv; // private
public:
int w_pub1;
int w_pub2;
int w_pub3;
};
class Abgeleitet: private Basis {
// Redeklaration der Zugriffsrechte
public:
Basis::w_pub1; // ist wieder public
using Basis::w_pub2; // ist wieder public
};
int main() {
class Abgeleitet obj;
cout << obj.w_pub1 << endl; // Zugriff auf geerbte Elemente
cout << obj.w_pub2 << endl;
cout << obj.w_pub3 << endl; // kein Zugriff
cout << obj.w_priv << endl; // kein Zugriff
...
Tip
Der neue ANSI-Standard empfiehlt die Redeklaration durch die using-Anweisung.
Verweise
Siehe Kategorie Klassen, Zugriffsspezifizierer
194
Vererbung und Konstruktor
Zugriffsrechten, etc. Dieses Konzept ist die Grundlage für die in der objektorientierten Pro-
grammierung sehr gebräuchlichen Reduzierung eines abgeleiteten Objekts in ein Objekt einer
seiner Basisklassen.
Anwendung
int main()
{
class Abgeleitet obj(11);
195
Sprachkonzepte und Syntax
int abg_wert;
Abgeleitet(int i) { abg_wert = i;}
Abgeleitet(int i, int n) : Basis(n) { abg_wert = i;}
};
int main()
{
class Abgeleitet obj(1,2);
int main()
{
class Abgeleitet obj(11);
196
Nicht vererbbare Methoden
Verweise
Siehe Kategorie Klassen, Der Konstruktor
Siehe Mehrfachvererbung
Polymorphie
Beschreibung
Der Begriff der Polymorphie ist eng an das Konzept der Vererbung gebunden. Er bezeichnet das
Phänomen, daß eine Methode in verschiedenen abgeleiteten Klassen einer Hierarchie unter-
schiedlich implementiert sein kann.
Anwendung
Auf diese Weise können einander ähnliche Klassen über eine Reihe gleichlautender
und gleichartig zu benutzender Funktionen verfügen, die es dem Programmierer
erlauben, Instanzen dieser Klassen gleich zu behandeln, ohne auf klassenspezifische
197
Sprachkonzepte und Syntax
Beispiele
class ZeichenObjekt {
protected:
struct Punkt referenzpunkt;
virtual int zeichne(struct Punkt p) {
// zeichne Referenzpunkt an Koordinate p
...
}
};
Verweise
Siehe Überschreibung und virtuelle Methoden
Siehe Basisklassenzeiger
198
Überschreibung und virtuelle Methoden
Anwendung
Der Compiler erkennt das Überschreiben einer Methode daran, daß neben dem
Methodennamen auch Anzahl und Typen der Parameter übereinstimmen. Über-
schriebene Methoden bzw. Methoden, die überschrieben werden sollen, werden in
der Basisklasse sowie in der abgeleiteten Klasse üblicherweise als virtual deklariert.
Das Schlüsselwort virtual modifiziert dabei die Art und Weise, in der der Compiler
eine Bindung zwischen einer Instanz und ihren Elementen herstellt..
199
Sprachkonzepte und Syntax
Beispiele
#include <iostream>
using namespace std;
class Basis {
public:
virtual void identifziere()
{cout << "Dies ist die Basisklasse\n";};
};
int main() {
Abgeleitet abgeleitet_klasse;
Basis *zeiger = new Basis; // Zeiger vom Typ 'Zeiger auf Basis'
zeiger = &abgeleitet_klasse;
zeiger->identifiziere();
}
Ausgabe: »Dies ist die abgeleitete Klasse«
Warnung
● Für Klassen, die virtuelle Methoden enthalten (polymorphe Klassen) legt der
Compiler eine virtuelle Tabelle an, in der alle virtuellen Methoden eingetragen
sind. Zudem erhält die Klasse einen Zeiger auf ihre virtuelle Tabelle. Wird für
ein Objekt der Klasse eine virtuelle Methode aufgerufen, greift der Compiler
über diesen Zeiger auf die virtuelle Methode zu und entnimmt dieser die
korrekte Adresse für den Aufruf der virtuellen Methode. Auf diese Weise ist
sichergestellt, daß auch für Zeiger auf Klassenobjekte immer die zu dem Ob-
jekt passende Implementierung aufgerufen wird. Die späte Bindung erzeugt
damit zusätzlichen Objektcode und bedingt längere Laufzeiten.
● Konstruktoren können nicht als virtual deklariert werden.
● Statische Methoden können nicht als virtual deklariert werden.
Verweise
Siehe Vererbung und Destruktor
200
Vererbung und Destruktor
Anwendung
Aus den vorangehenden Ausführungen zur späten Bindung und den oben aufge-
führten Gründen sollten Klassen, die Teil einer Vererbungshierarchie sind, über
einen virtuellen Destruktor verfügen.
Da der Destruktor, den der Compiler standardmäßig zuweist, nicht als virtual
deklariert ist, sollte man in Basisklassen von Klassenhierarchien einen eigenen vir-
tuellen Destruktor definieren, auch wenn man keinen Code in den Anweisungsteil
schreibt.
Beispiele
class Basis {
...
public:
virtual ~Basis() {}
};
Abstrakte Methoden
Abstrakte oder "rein virtuelle" Methoden werden als virtual deklariert und auf 0
gesetzt. Sie dienen lediglich als Vorgabe einer Schnittstelle für abgeleitete Klassen
und haben keinen Definitionskörper. Sie müssen daher in den abgeleiteten Klassen
definiert werden.
virtual Typ name (PARAMETERLISTE) = 0;
201
Sprachkonzepte und Syntax
Abstrakte Klassen
Klassen, die über abstrakte Methoden verfügen, werden automatisch zu abstrakten
Klassen, mit der Konsequenz, daß von ihnen keine Instanz erzeugt werden kann.
Sie stehen in Klassenhierarchien stets ganz oben, um geeignete Schnittstellen vorzu-
geben und so der Hierarchie ein einheitliches Gepräge zu verleihen.
Warnung
Es ist zu beachten, daß Klassen, die von einer abstrakten Klasse abgeleitet wurden,
und für die es versäumt wurde, die abstrakten Methoden zu überschreiben (und
damit mit einem Definitionskörper zu versorgen), selbst zu abstrakten Klassen wer-
den.
Beispiele
class Basis {
public:
virtual void func() = 0;
...
};
class Abgeleitet: public Basis {
public:
virtual void func() { ... }
};
Basisklassenzeiger
Beschreibung
Da in einer abgeleiteten Klasse die Elemente der Basisklassen als Unterobjekte enthalten sind,
kann man ein abgeleitetes Objekt wie eines seiner Basisklassenobjekte behandeln, es quasi auf
sein Basisklassenunterobjekt reduzieren.
Insbesondere in Verbindung mit Basisklassenzeigern und virtuellen Methoden ist dies ein
äußerst nützliches Konzept, das in vielen Fällen äußerst effektive und elegante generische
Lösungen erlaubt.
Anwendung
Ein Basisklassenzeiger ist wie ein generischer Zeiger, dem man die Adressen abge-
leiteter Objekte zuweisen kann. (Unter der Voraussetzung, daß das Basisklassenun-
terobjekt in dem abgeleiteten Objekt eindeutig identifizierbar und zugänglich ist.)
Mit Hilfe dieser generischen Zeiger kann man
202
RTTI – Laufzeittypidentifizierung
int main() {
class ZeichenObjekt *geomFig[10];
geomFig[0] = new Kreis;
geomFig[1] = new Rechteck;
...
● generische Funktionen/Methoden implementieren, denen man Objekte ver-
schiedener abgeleiteter Klassen mit gemeinsamer Basisklasse als Argumente
übergeben kann.
void markieren(const ZeichenObjekt& objekt) { ... }
RTTI Laufzeittypidentifizierung
Beschreibung
Um sinnvoll mit Basisklassenzeigern auf abgeleitete Objekte arbeiten zu können, muß es eine
Möglichkeit geben, wieder auf die volle Funktionalität des abgeleiteten Objekts zuzugreifen.
Das eigentliche Problem bei der Rückverwandlung ist die Typidentifizierung: welchem abgelei-
teten Klassentyp gehört das Objekt an, auf das der Basisklassenzeiger verweist.
Anwendung
Für die Typidentifizierung gibt es in C++ verschiedene Möglichkeiten:
Virtuelle Methoden Über einen Basisklassenzeiger soll für ein abgeleitetes Objekt eine in
der abgeleiteten Klasse überschriebene Methode aufgerufen werden.
base_ptr = &abg_obj;base_ptr->ueberschriebeneMethode();
Die Typidentifizierung erfolgt automatisch durch den Compiler.
Soweit möglich und sinnvoll sollte man diese Form der Typidentifi-
zierung nutzen.
203
Sprachkonzepte und Syntax
dynamic_cast Über einen Basisklassenzeiger soll für ein abgeleitetes Objekt eine in
der abgeleiteten Klasse neu definierte Methode oder ein neu definier-
tes Datenelement aufgerufen werden.
base_ptr = &abg_obj;
if(abg_ptr = dynamic_cast<Abgleitet *>(base_ptr)) {
abg_ptr->neueMethode();
abg_ptr->Datenelement();
}
base_ptr = &abg_obj;
if(typeid(*base_ptr) == typeid(Abgeleitet)) {
cout << "Objekt ist vom Typ Abgeleitet";
}
Mehrfachvererbung
Beschreibung
Mehrfachvererbung bedeutet, daß eine Klasse mehr als eine direkte Basisklasse hat.
class Abgeleitet: public Basis1, public Basis2
Anwendung
Die Mehrfachvererbung ist interessant, wenn man ein Objekt einer abgeleiteten
Klasse als Objekt mehrerer Basisklassen verstehen kann oder, anders ausgedrückt,
wenn ein Objekt in sich die Eigenschaften mehrerer direkter Basisklassen vereinigt.
Ein typisches Beispiel wäre ein Amphibienfahrzeug, daß sowohl ein Auto als auch
ein Boot darstellt.
204
Virtuelle Basisklassen
Beispiele
class Basis1 {
public:
void func();
};
class Basis2 {
public:
void func();
};
int main() {
Abgeleitet abg;
[Link](); // Fehler
abg.Basis1::func(); // korrekt
...
Verweise
Siehe Virtuelle Basisklassen
Virtuelle Basisklassen
Beschreibung
Virtuelle Basisklassen sind Basisklassen, die mit dem Schlüsselwort virtual vererbt werden.
Für virtuelle Basisklassen stellt der Compiler sicher, daß die Elemente der Basisklassen in allen
abgeleiteten Klassen nie mehr als einmal auftauchen.
205
Sprachkonzepte und Syntax
Anwendung
Kreisschlüsse in der Vererbungshierarchie führen dazu, daß Elemente mehrmals
vererbt werden.
Das obige Vererbungsschema zeigt wie die Klasse Amphibienfahrzeug jeweils zwei
Vorkommen der Elemente max_geschw und get_geschw() der Basisklasse Fahrzeug
erbt: einmal auf dem Weg über die Klasse Boot und einmal über Auto. Dies kann in
bestimmten Klassenhierarchien sinnvoll sein (beispielsweise für das Amphibienfahr-
zeug, das als Boot und Auto unterschiedliche Maximalgeschwindigkeiten hat). Oft-
mals ist es jedoch unerwünscht. Man kann dies vermeiden, indem man die Basis-
klasse als virtual vererbt.
Beispiele
class Basis {
...
};
class Abgeleitet_1a : virtual public Basis {
...
};
class Abgeleitet_1b : virtual private Basis {
...
};
class Abgeleitet_2 : public Abgeleitet_1a, Abgeleitet_1b {
...
};
206
Templates
Warnung
Virtuell geerbte Elemente können nicht auf dem Weg über die direkten Basisklas-
senkonstruktoren eingerichtet werden. Statt dessen muß für virtuelle Basisklassen
ein entsprechender Konstruktor wie ein Basisklassenkonstruktor direkt in die Kon-
struktorliste aufgenommen werden. Der Programmierer steht damit vor den
gewohnten zwei Alternativen:
● Er kann die Initialisierung dem Standardkonstruktor der virtuellen Basisklasse
überlassen – falls ein Standardkonstruktor verfügbar ist.
● Er kann einen Konstruktor der virtuellen Basisklasse in die Konstruktorliste
aufnehmen.
class Fahrzeug
class Boot : virtual public Fahrzeug
class Auto : virtual public Fahrzeug
class Amphibienfahrzeug : public Boot, public Auto
{
public:
Amphibienfahrzeug(int preis) : Fahrzeug (preis) { }
};
Eine Basisklasse kann einer abgeleiteten Klasse gleichzeitig virtuell wie nicht-virtu-
ell vererbt werden.
● Jeder Pfad, über den die Basisklasse nicht-virtuell vererbt wird, erzeugt in der
abgeleiteten Klasse ein eigenes Basisklassenobjekt.
● Alle Pfade, über die die Basisklasse virtuell vererbt wird, erzeugen in der abge-
leiteten Klasse ein gemeinsames Basisklassenobjekt.
Templates
Templates
Beschreibung
Template bedeutet übersetzt Schablone. Templates sind vorgefertigte, typunabhängige Muster
für Klassen oder Funktionen. Wo immer in einer Klassen- oder Funktionsdeklaration ein Daten-
typ erforderlich ist, kann in der Template-Deklaration ein Platzhalter stehen. Diese Platzhalter
werden im Kopf der Template-Deklaration aufgelistet und bei der Instanzbildung durch die
gewünschten Typen ersetzt, woraufhin der Compiler eine entsprechende Instanz (Spezialisie-
rung) der Templateklasse erzeugt, d. h., eine Klassen- oder Funktionsdefinition erzeugt.
207
Sprachkonzepte und Syntax
Anwendung
Templates erinnern an Makros, sind diesen jedoch in puncto Vielseitigkeit und
Sicherheit überlegen. Compiler, die Templates unterstützen, haben daher meist die
üblichen C-Makros als Templates implementiert.
Templates werden oft mit Hilfe von überladenen Operatoren und Methoden imple-
mentiert, um einen typengerechten Einsatz dieser Funktionen / Operatoren inner-
halb der Template-Elementfunktionen zu gewähren.
Warnung
● Werden Platzhalter für Typen durch ein anderes Schlüsselwort als class oder
typename eingeführt, erwartet der Compiler für diesen Platzhalter eine entspre-
chende Konstante. Gleitkommatypen sind nicht zugelassen.
● Um in einer Quelltextdatei ein Template zu verwenden, das in einer anderen
Quelltextdatei des Programms definiert ist, müßten Sie im Prinzip die Templa-
te-Definiton über eine Header-Datei in die Quelltextdatei aufnehmen. Alterna-
tiv können Sie das Template auch mit dem Schlüsselwort export definieren.
Um das Template in anderen Quelltextdateien verwenden zu können, brau-
chen Sie dann nur noch die Template-Deklaration anzugeben.
Beispiele
// [Link]
export template<class T> int func(T a, T b) // Template-Definition
{
if (a == b)
return 1;
else
return 0;
}
// [Link]
template<class T> int func(T a, T b); // Template-Deklaration
int var1, var2;
...
func(var1, var2);
208
Funktionentemplates
Verweise
Siehe nachfolgende Abschnitte
Funktionentemplates
Beschreibung
Funktionentemplates sind typunabhängige Vorlagen für Funktionen, aus denen der Compiler
bei Bedarf durch Spezialisierung für vorgegebene Datentypen echte Funktionen erzeugen kann.
Anwendung
Funktionentemplates haben gegenüber der Überladung von Funktionen den Vor-
teil, daß der Anweisungsteil nur einmal aufgesetzt werden muß. (Voraussetzung ist
natürlich, daß die Anweisungen für alle Datentypen, für die das Template zu
instanziieren ist, gleich sind). Ansonsten kann man natürlich auch Funktionentem-
plates überladen.
Syntax
template <TYPENLISTE>
Rückgabetyp funktionsname(PARAMETERLISTE) { };
● TYPENLISTE: In der Typenliste werden durch Kommata getrennt, die später
zu ersetzenden Platzhalter aufgelistet. Jedem Platzhalter wird dabei das
Schlüsselwort class (oder typename) vorangestellt.
● Die weitere Deklaration folgt der Syntax zur Funktionsdeklaration, wobei
allerdings statt definierter Typen bereits die Platzhalter verwendet werden
können.
Beispiele
template<class T> T max(T a, T b) {
return a > b ?: a, b;
}
Instanziierung:
cout << max(3, -14) << endl;
Warnung
Durch mehrfache Instanziierung und Überladung kann es zu Uneindeutigkeiten
(ambiguities) kommen, d. h. der Compiler kann für einen Funktionsaufruf nicht
mehr entscheiden, welche Implementierung der Funktion aufzurufen ist.
209
Sprachkonzepte und Syntax
Verweise
Siehe Instanzbildung und Spezialisierung
Klassentemplates
Beschreibung
Klassentemplates sind typunabhängige Vorlagen für Klassen, aus denen der Compiler bei
Bedarf durch Spezialisierung für vorgegebene Datentypen echte Klassen erzeugen kann.
Anwendung
Das beste Beispiel für den Einsatz von Klassentemplates sind die Container der
Laufzeitbibliothek, die alle als Templates definiert sind. Dies erlaubt es, den Daten-
typ der Elemente, die im Container verwahrt werden sollen, als Template-Parame-
ter zu definieren. Der Container kann dann unabhängig vom Typ der Elemente
implementiert und bei Bedarf für die gewünschten Datentypen instanziiert werden.
Syntax
template <TYPENLISTE> class klassenname { };
● TYPENLISTE: In der Typenliste werden durch Kommata getrennt, die später
zu ersetzenden Platzhalter aufgelistet. Jedem Platzhalter ist dabei das Schlüs-
selwort class (oder typename) vorangestellt.
Warnung
● Methoden innerhalb von Klassentemplates sind automatisch Funktionentem-
plates, d. h., sie können die Platzhalter des Klassentemplates gebrauchen, ohne
daß eine explizite Template-Deklaration für diese Platzhalter erforderlich ist.
● Friend-Funktionen, die in Klassentemplates deklariert werden, sind nicht au-
tomatisch Funktionentemplates, d. h., standardmäßig sind solche Funktionen
Friends zu allen typisierten Klassen, die aus dem Template gebildet werden.
Erst wenn eine friend-Funktion in ihrer Deklaration einen Platzhalter des
Klassentemplates enthält, gibt es für jede typisierte Klasse eine eigene friend-
Funktion. Man kann friend-Funktionen auch als spezialisierte Templates
deklarieren, um so anzuzeigen, daß die friend-Deklaration nur für die angege-
benen Spezialisierungen des Templates gelten.
● Friend-Templates dürfen nicht im Template definiert werden.
● Werden in einem Template statische Elemente definiert, erhält jede Spezialisie-
rung des Templates seinen eigenen Satz von statischen Elementen.
210
Methoden in Klassentemplates
● Templates können sowohl von Templates als auch von normalen Klassen ab-
geleitet werden und können wiederum ihrerseits als Basisklasse für andere
Templates oder Klassen verwendet werden.
● Benutzerdefinierte Namen in Template-Deklarationen werden standardmäßig
als Bezeichner für Variablen aufgefaßt. Damit ein Name als Typbezeichner er-
kannt wird, muß der Name innerhalb des Templates oder im umgebenden
Gültigkeitsbereich definiert worden sein oder durch das Schlüsselwort typename
gekennzeichnet werden.
● Template-Klassenelemente können nicht als virtual deklariert werden.
● Lokale Klassen dürfen keine Template-Klassenelemente enthalten.
Beispiele
template <class T> class demo {
T var;
public:
demo() { var = 1.5;}
T func() { T tmp;
tmp=var++;
return tmp;
};
};
Instanziierung:
demo<double> obj;
Verweise
Siehe Instanzbildung und Spezialisierung
Methoden in Klassentemplates
Beschreibung
Methoden von Klassentemplates sind automatisch Funktionentemplates, d. h., sie können die
Platzhalter des Klassentemplates gebrauchen, ohne daß eine explizite Template-Deklaration
für diese Platzhalter erforderlich ist. Innerhalb des Templates unterscheidet sich ihre Syntax
praktisch nicht von Methoden gewöhnlicher Klassen. Außerhalb des Klassentemplates, zum
Beispiel zur ausgelagerten Definition, müssen sie als Element ihres Klassentemplates gekenn-
zeichnet sein:
211
Sprachkonzepte und Syntax
Syntax
template <TYPENLISTE> Rückgabetyp
klassenname<TYPENLISTE>::funkt_name(PARAMETERLISTE)
{ };
Warnung
Gemäß dem neuen ANSI-C++-Standard können innerhalb von Klassentemplates
auch Funktionentemplates mit eigenen Platzhaltern deklariert werden. Dieses Kon-
zept ist allerdings recht schwierig zu implementieren und wird nicht von allen
Compilern unterstützt.
Methoden von Klassentemplates müssen prinzipiell in der gleichen Datei definiert
werden wie das Klassentemplate. Um beide Teile zu trennen, muß man da Schlüs-
selworte verwenden (siehe Einleitung zu Templates).
Beispiele
template<class T, class S> class demo {
T var1;
S var2;
public:
T func();
};
Verweise
Siehe Klassentemplates
212
Implizite Instanziierung
Anwendung
Um dem Compiler anzuzeigen, daß er für einen bestimmten Satz von Datentypen
aus einem Template eine Spezialisierung erzeugen soll, gibt es drei Möglichkeiten:
● Implizite Instanziierung
● Explizite Instanziierung
● Explizite Spezialisierung
Verweise
Siehe nachfolgende Abschnitte
Implizite Instanziierung
Beschreibung
Bei der impliziten Instanzbildung überläßt der Programmierer fast die gesamte Arbeit dem
Compiler. Der Programmierer muß lediglich dafür Sorge tragen, daß der Compiler alle Informa-
tionen hat, um den Platzhaltern des Templates konkrete Datentypen zuweisen zu können.
Anwendung
Für Funktionentemplates genügt es meist, die Funktion mit entsprechenden Argu-
menten aufzurufen. Der Compiler entnimmt die Typinformation dann den Argu-
menten.
Typen für Klassen oder Rückgabewerte von Funktionen können nicht auf diese
Weise abgeleitet werden. In so einem Fall muß man die Typen für die Platzhalter in
spitzen Klammern explizit angeben.
int main() {
demo_func(13,14);
demo_func<int>(13.2,14.3);
return 0;
}
Erläuterung
demo_func(13,14);
213
Sprachkonzepte und Syntax
Der Compiler erkennt, daß eine Spezialisierung des Templates demo_func benötigt
wird. Anhand der Typen der Aufrufargumente kann er die gewünschten Typen für
die Platzhalter T1 und T2 bestimmen. Der Compiler erzeugt also eine Spezialisie-
rung demo_func<int, int> und ruft diese mit den Argumenten (13,14) auf
demo_func<int>(13.2,14.3);
Der Compiler erkennt, daß eine weitere Spezialisierung des Templates demo_func
benötigt wird. Den Typ für den ersten Platzhalter T1 entnimmt er den Templatear-
gumenten, die in spitzen Klammern übergeben wurden. Den Typ für den zweiten
Platzhalter T2 entnimmt er dem Typ des zugehörigen Aufrufarguments. Der Com-
piler erzeugt also eine Spezialisierung demo_func<int, double> und ruft diese mit den
Argumenten (13.2,14.3) auf.
Warnung
Bei der Instanziierung von Funktionen aus Funktionentemplates berücksichtigt der
Compiler keine Standardkonvertierungen. Wenn ein Funktiontemplate zwei Para-
meter des gleichen Platzhaltertyps definiert, kann man das Template nicht instanzi-
ieren, indem man ihm zwei Argumente unterschiedlicher Typen übergibt – auch
wenn diese durch Standardkonvertierungen ineinander umwandelbar sind.
Eine einmal erzeugte Spezialisierung eines Funktionentemplates kann wie jede
Funktion mit konvertierbaren Argumenten aufgerufen werden.
int main() {
demo_class<int> obj; // implizite Instanziierung
return 0;
}
Verweise
Siehe explizite Instanziierung und Spezialisierung
214
Explizite Instanziierung
Explizite Instanziierung
Die explizite Instanziierung ist eine Aufforderung an den Compiler, die gewünschte
Spezialisierung des Templates sofort zu erzeugen, auch wenn diese Spezialisierung
noch gar nicht benötigt wird.
Eingeleitet wird die explizite Instanziierung durch das Schlüsselwort template. Die
Argumente für die Templateparameter werden allerdings nicht an das Schlüssel-
wort template, sondern an den Namen der Funktion oder Klasse angehängt (dies
dient der Unterscheidung zur expliziten Spezialisierung).
// Explizite Instanziierung
template void demo_func(int, int);
template void demo_func<int, double>(int, double);
int main() {
demo_func(13,14);
demo_func<int>(13.2,14.3);
...
int main() {
demo_class<int> obj;
...
Verweise
Siehe implizite Instanziierung und Spezialisierung
215
Sprachkonzepte und Syntax
Explizite Spezialisierung
Beschreibung
Während wir unter einer Spezialisierung einfach eine konkrete Funktion oder Klasse verstehen,
die auf der Basis eines Templates generiert wurde, sprechen wir von expliziter Spezialisierung,
wenn
● einzelne oder alle Platzhalter eines Templates durch konkrete Datentypen er-
setzt werden, und wenn
● für dieses stärker typabhängige Template eine eigene Definition vorgesehen
wird.
Syntax
Die Syntax der Spezialisierung erfordert zwei Templateparameterlisten in spitzen
Klammern:
template <erste_Liste> Name <zweite_Liste>
● In der ersten Liste, die auf das Schlüsselwort template folgt, werden die Tem-
plateparameter aufgeführt, die in der Spezialisierung noch weiter verwendet
werden.
● In der zweiten Liste, die auf den Namen der Spezialisierung folgt, werden Ar-
gumente für die Templateparameter des primären Templates übergeben.
Diese Syntax erlaubt auch die partielle Spezialisierung:
template <class T1, class T2> class demo {...};
template <class T> class demo<T, char> {...};
template <class T> class demo<T*, T> {...};
template <> class demo<int, int> {...};
Die erste Zeile enthält die Definition des primären Templates.
Darunter folgen zwei partielle Spezialisierungen, die nur noch einen Platzhalter ver-
wenden. In der Templateargumentenliste wird festgelegt, welche Datentypen oder
Platzhalter mit den Platzhaltern des primären Templates korrespondieren.
Die letzte Zeile definiert eine vollständige explizite Spezialisierung.
Warnung
● Explizite Spezialisierungen haben stets Vorrang vor impliziten oder expliziten
Instanziierungen.
● Eine explizite Instanzbildung oder Spezialisierung muß im gleichen Namensbe-
reich (namespace) erfolgen wie das zu spezialisierende Template.
● Für Klassentemplates kann man auch einzelne Methoden explizit spezialisie-
ren.
216
Explizite Spezialisierung
Die obige Syntax mit dem vorangehenden Schlüsselwort template und der nachfol-
genden Templateparameterliste ist noch recht neu. Die meisten Compiler erlauben
Spezialisierungen nur in Form einer vereinfachten Syntax ohne das Schlüsselwort
template:
// aeltere Form der Spezialisierung
int vergleich<char*>(char *a, char *b) {
return(strcmp(a,b));
}
Beispiele
// Funktionentemplate
template <class T> int vergleich(T a, T b) {
cout << "Erstes Template:\t";
return(a > b);
}
Verweise
Siehe implizite und explizite Instanziierung
Der Präprozessor
Beschreibung
Neben der reinen Sprachdefinition beschreibt der ANSI-C-Standard unter anderem auch die
Phasen, die erfolgen müssen, damit der Sourcecode eines Programms in den von der Maschine
ausführbaren Code übersetzt werden kann. Eines der beim Übersetzungsvorgang beteiligten
Programme ist der sogenannte Präprozessor, der der Name läßt es bereits vermuten vorbe-
reitende Arbeiten an dem Quellcode durchführt. (In neueren Compilern ist das Präprozessing
kein getrennter Prozeß mehr, sondern wird beim Kompilieren mit ausgeführt.) Erst nachdem
der Präprozessor den Code bearbeitet hat, wird er zur eigentlichen Code-Generierung an den
Compiler weitergeleitet.
Anwendung
Der Präprozessor führt neben einfachen Quelltextersetzungen, die automatisch
ablaufen, weitere Aufgaben aus:
● Kommentare werden entfernt (und durch Leerzeichen ersetzt).
● Zeilenumbrüche, denen ein Backslash vorangeht, werden entfernt.
217
Sprachkonzepte und Syntax
Direktive Bedeutung
defined Operator, der testet, ob ein Makro definiert ist
# Operator zur Zeichenkettenbildung
## Operator zur Grundsymbolverbindung
#define definiert ein Symbol oder Makro
#elif else-if-Operator
#else else-Operator
#endif Ende der #if-Direktive
#error erzeugt eine Fehlermeldung
#if if-Operator
#ifdef Äquivalent zu #if defined
#ifndef Äquivalent zu #if !defined
#include Datei einbinden
#line Aktuelle Zeile verändern
#pragma Anweisung für den Compiler
#undef Definition eines Symbols entfernen
218
Quellcode einfügen und ersetzen
Beschreibung
Die für den Programmierer wichtigste Direktive an den Präprozessor ist sicherlich die Direktive
#include. Mit ihr wird der Präprozessor angewiesen, die als Argument angegebene Datei in die
aktuelle Datei einzukopieren.
Anwendung
Meist wird hiermit eine sogenannte Header-Datei aufgenommen, die Deklaratio-
nen, symbolische Konstanten, Makros und/oder Typdefinitionen enthalten kann.
Das Einbinden der Datei kann an jeder beliebigen Stelle der Sourcedatei erfolgen.
Es existiert jedoch eine stillschweigende Übereinkunft darüber, daß das Einbinden
am Anfang der Datei stattfindet.
Die Verwendung von Header-Dateien empfiehlt sich besonders für Programme, die
aus mehreren Quelltextdateien bestehen. Die gemeinsam benutzbaren Typdefinitio-
nen, Konstanten, Funktionsdeklarationen können auf diese Weise durch eine ein-
zeilige Anweisung allen beteiligten Dateien bekanntgemacht werden.
Syntax
Zwei verschiedene Formen der #include-Direktive sind möglich:
#include <datei>
Der Compiler sucht nach der angegebenen Datei in bestimmten in der Entwick-
lungsumgebung des Compilers spezifizierten Verzeichnissen.
#include "datei"
Der Compiler sucht nach der angegebenen Datei in einer compilerspezifischen Rei-
henfolge. Üblicherweise wird zuerst im aktuellen Verzeichnis gesucht.
Beispiele
#include <stdio.h>
#include "Unterverzeichnis\typen.h"
Verweise
Siehe Grundlagenteil, Verwendung der Standardbibliotheken
219
Sprachkonzepte und Syntax
Makros definieren
#define makroname
Beschreibung
Mit der Präprozessor-Direktive #define wird die Definition eines Makros eingeleitet.
Anwendung
Eine Makrodefinition besitzt die folgende Form:
#define makroname neuer_text
Der Präprozessor ersetzt, nachdem er die Makrodefinition zur Kenntnis genommen
hat, jedes Vorkommen von makroname mit neuer_text.
Der Name eines Makros wird nach den gleichen Regeln wie ein Variablenname
gebildet. Es hat sich jedoch eingebürgert, Makronamen in Großbuchstaben zu
schreiben. Diese Nomenklatur – wird sie konsequent eingehalten – macht auf den
ersten Blick deutlich, ob es sich um einen Variablen-/Funktionsnamen oder ein
Makro handelt.
Warnung
Die Festlegung des Ersatztextes hört am Ende der Zeile auf. Um auch Makros
schreiben zu können, die sehr lang und komplex sind, ist es möglich, vor der Zei-
lenschaltung das Zeichen Backslash »\« einzufügen und die Definition des Makros
auf der bzw. den folgenden Zeilen fortzuführen.
Wird kein Ersatztext angegeben, wird nur der Makroname eingeführt, der als eine
Art Compiler-Schalter bei der bedingten Kompilierung eingesetzt werden (und
jederzeit mit #undef makroname wieder entfernt werden) kann.
Beispiele
#define GROESSE 20
int feld[GROESSE];
...
for (int i = 0; i < GROESSE; i++) { ...
Verweise
Siehe Argumente in Makros
Siehe Direktiven zur bedingten Kompilierung
Siehe Kategorie Konstanten, #define
220
Argumente in Makros
Argumente in Makros
#define name()
Beschreibung
Es ist auch möglich, in Makros Argumente zu verwenden, innerhalb des Makros mit den Argu-
menten zu arbeiten und das gleiche Makro für verschiedene Argumente zu verwenden.
Anwendung
Auf diese Weise können Funktionen durch Makroaufrufe ersetzt werden, wodurch
der leidige Function Overhead vermieden und typunabhängige Implementierungen
möglich werden.
Warnung
Die Übergabe von Argumenten führt aber schnell zu unerwünschten Nebeneffek-
ten, so daß in C++ der Deklaration von inline-Funktionen zur Vermeidung des
Function Overheads beziehungsweise die Programmierung von überladenen und
Operatoren sowie von Templates zur Erreichung typunabhängiger Implementierun-
gen der Vorzug zu geben ist.
Beispiele
#define flaeche(a,b) (a*b) // falsch
ergebnis = flaeche(4,6); // liefert 24
ergebnis = flaeche(3+1,5+1); // liefert 9!
Erläuterung
Das falsche Ergebnis resultiert aus der falschen Definition des Makros. Der Präpro-
zessor ersetzt die zweite Zuweisung durch
ergebnis = 3+1*5+1
und dies führt zu dem falschen Ergebnis, da die Multiplikation die höhere Priorität
hat.
Alle Argumente, die in einer Makrodefinition vorkommen, sollten daher geklam-
mert werden, um diese Nebeneffekte, die manchmal schwer zu finden sind, zu ver-
meiden.
Richtig wäre:
#define flaeche(a,b) ((a)*(b)) /* so ist's richtig */
Verweise
Siehe Kategorie Templates, Funktionentemplates
221
Sprachkonzepte und Syntax
Anwendung
Mit Hilfe der bedingten Kompilierung kann man beispielsweise verschiedene Ver-
sionen eines Programms aufbauen. Diese Versionen können sein:
● eine Version, die Debugging-Code enthält,
● Programme, die auf unterschiedlicher Hardware laufen oder
● Versionen, die mit unterschiedlichen Compilern arbeiten sollen.
Die Direktiven zur bedingten Kompilierung werten einen Makronamen aus, um zu
ermitteln, welche Bereiche der Quelldatei vom Präprozessor an den Compiler wei-
tergeleitet bzw. aus dem Sourcecode ausgeschlossen werden sollen.
Der Anweisungsblock zur bedingten Kompilierung umfaßt mehrere Zeilen:
● Die Zeile, in der die zu testende Bedingung steht. Sie wird mit #if, #ifdef oder
#ifndef eingeleitet.
● Zeilen, die den Code beinhalten, wenn die auszuwertende Bedingung den Wert
wahr ergibt (optional).
● Eine optionale else-Zeile, die mit #else oder #elif eingeleitet wird.
● Zeilen, die den Code beinhalten, wenn die auszuwertende Bedingung den Wert
unwahr ergibt (optional).
● Eine Zeile, mit der der Block zur bedingten Kompilierung abgeschlossen wird:
die #endif-Anweisung.
#if
Die Präprozessor-Direktive #if leitet die bedingte Kompilierung ein. Danach steht
ein konstanter Ausdruck, der ausgewertet wird. Ergibt die Auswertung wahr, wird
der nachfolgende Teil (entweder bis zum nächsten #elif, #else oder #endif) an den
Compiler weitergeleitet.
#elif
Die Direktive #elif ist eine Abkürzung für else if. Dieser Ausdruck wird nur dann
ausgewertet, wenn die Auswertung der vorhergehenden Direktive das Resultat
unwahr erbrachte. #elif kann in einem Block zur bedingten Kompilierung mehr-
mals vorkommen. Ergibt die Auswertung wahr, wird der nachfolgende Teil (entwe-
der bis zum nächsten #elif, #else oder #endif) an den Compiler weitergeleitet.
222
Direktiven zur bedingten Kompilierung
#else
#else kann in einem Anweisungsblock nur einmal vorkommen. Die hinter #else ste-
henden Anweisungen werden bis zum abschließenden #endif an den Compiler wei-
tergeleitet, wenn keine der vorhergehenden Auswertungen das Ergebnis wahr
erbrachte.
Beispiele
#if defined(ZIELSYSTEM) && (MAXSPALTEN==80)
#define ARRAY_GROESSE 160
#elif !defined(ZIELSYSTEM)
#define ERROR1
#error Datei kann nicht kompiliert werden.
#endif
223
Sprachkonzepte und Syntax
Zeichenkettenbildung und
Grundsymbolverbindung
Zeichenkettenbildung #
Der Operator zur Zeichenkettenbildung (string-izing operator) wird bei funktions-
ähnlichen Makros benutzt. Er bewirkt, daß ein dem Makro übergebenes Argument
in eine Zeichenkette umgewandelt wird.
#define makestring(s) printf(#s "\n")
int main() {
makestring(Dies wird ein String);
makestring("Dies wird noch ein String");
...
wird vom Präprozessor umgesetzt zu:
int main() {
printf("Dies wird ein String" "\n");
printf("\"Dies wird noch ein String\"" "\n");
...
Die Ausgabe des Programms:
Dies wird ein String
"Dies wird noch ein String"
Grundsymbolverbindung ##
Mit dem Operator zur Grundsymbolverbindung (token-pasting operator) können
einzelne Token zu einem Grundsymbol verknüpft werden. Der Operator »##«
sowie alle zwischen den Token stehenden Zwischenraumzeichen werden vom Prä-
prozessor entfernt.
#define zeigevar(zahl) printf("%d\n", var ## zahl)
int main() {
int var3=3;
zeigevar(3);
...
wird vom Präprozessor umgesetzt zu:
int main() {
int var3=3;
printf("%d\n", var3);
return 0;
}
224
Sonstige Direktiven und Symbole
Beispiele
#if !defined AUTO && !defined FAHRRAD
#error Definieren Sie das gewünschte Transportmittel
#endif
Das vorstehende Beispiel könnte aus einem Programm stammen, bei dem über die
bedingte Kompilierung, je nach gewünschtem Transportmittel, anderer Code
erzeugt wird. Da das Programm nur einwandfrei kompiliert werden kann, wenn
entweder AUTO oder FAHRRAD definiert ist, wird mit dem defined-Operator
getestet, ob die Definition existiert. Ist dies nicht der Fall, wird der hinter #error
stehende Text ausgegeben.
Zeilen-Steuerdirektive1 #line
Mit der Zeilen-Steuerdirektive #line kann die Zeilennummer innerhalb einer Datei
eingestellt und der Name der Datei geändert werden. Diese Daten werden vom
Compiler benutzt, um auf eventuelle Fehler zu verweisen.
Durch die Verwendung von #line werden die Werte in den Symbolen __LINE__ und
__FILE__ geändert.
Diese Direktive wird üblicherweise von Programmgeneratoren benutzt, um Fehler
in dem erzeugten C-Code mit der Zeile und dem Dateinamen der Ursprungsdatei
zu verknüpfen.
#line <Zeile> ["dateiname"]
● Zeile: Eine Ganzzahlkonstante, auf die der interne Zähler des Compilers ge-
setzt wird.
● dateiname: Dieses Argument ist optional und kann einen in Anführungszei-
chen eingeschlossenen Dateinamen enthalten.
Beispiele
#line 200
#line 200 "ursprung.c"
225
Sprachkonzepte und Syntax
Pragma-Direktiven #pragma
Die #pragma-Direktive ist eine compilerspezifische Direktive, d. h., die Verarbeitung
der Direktive hängt nicht vom ANSI-Standard, sondern vom verwendeten Compi-
ler ab.
Pragma-Direktiven, die nicht zur Implementierung gehören, werden ignoriert. Da
dies stillschweigend geschieht, muß bei der Portierung von Code auf eine andere
Implementierung mit anderen Pragmas besonders sorgfältig vorgegangen werden.
Makro Bedeutung
__DATE__ Datum der Kompilierung der Datei
__FILE__ Name der Sourcedatei
__LINE__ Aktuelle Zeile in der Sourcedatei
__STDC__ Compiler entspricht ANSI-C-Standard
__TIME__ Zeit der Kompilierung der Datei
__cplusplus C++ -Code
Exception-Behandlung
Exception-Behandlung
Beschreibung
Unter Exception-Behandlung versteht man eine mit C++ in die Sprache eingeführte Form der
Fehlerbehandlung. Die Exception-Behandlung ist nicht auf Klassen oder andere Konzepte der
objektorientierten Programmierung angewiesen, arbeitet mit diesen aber besonders effektiv
zusammen:
226
Exception-Behandlung
Der zweite Vorteil liegt darin, daß die Weiterreichung der Exception nicht über den
Rückgabetyp, die Parameter oder irgendwelche globale Variablen erfolgt. Die für
den korrekten Einsatz der Funktion benötigte Schnittstelle wird also nicht belastet
oder aufgebläht. Dies ist besonders wichtig für Elemente wie zum Beispiel Kon-
struktoren, die keine Werte zurückliefern können.
Da Exceptions Objekte eines bestimmten Datentyps sind, können Sie Informa-
tionen vom Ort des Fehlers zum Ort der Fehlerbehandlung übertragen.
Viertens wird der Quellcode übersichtlicher, da der eigentliche Algorithmus und
die Fehlerbehandlung getrennt ablaufen.
227
Sprachkonzepte und Syntax
Beispiele
1: #include <iostream>
2: #include <string.h>
3: using namespace std;
228
Exception-Behandlung
4: class exception {
5: int fakt1, fakt2;
6: public:
7: exception(int i, int j){fakt1=i; fakt2=j;}
8: void ausgabe() {
9: cout << "fakt1 = " << fakt1 << endl;
10: cout << "fakt2 = " << fakt2 << endl;
11: }
12: };
13: float division(int zaehler, int fakt1, int fakt2) {
14: try {
15: if(fakt1*fakt2 == 0) {
16: throw exception(fakt1,fakt2);
17: }
18: }
19: catch(exception& fehlerinstanz) {
20: [Link]();
21: throw "Fehler aufgetreten\n";
22: }
23: return zaehler/(fakt1*fakt2);
24: }
25: int main() {
26: try {
27: float bruch;
28: bruch = division(12,3,0);
29: cout << bruch << endl;
30: }
31: catch (...) {
32: cout << "Exception aufgetreten!" << endl;
33: }
34: return 0;
35: }
Ausgabe des Programms:
fakt1 = 3;
fakt2 = 0;
Exception aufgetreten!
Erläuterung
Die Klasse exception wird definiert, um eine an den Fehler angepaßte Exception
auslösen zu können. Über ihre Datenelemente werden die fehlerrelevanten Informa-
tionen transferiert, ihre Elementfunktion garantiert eine saubere Fehlerbehandlung.
In Zeile 16 wird die Exception vom Typ der Klasse exception ausgelöst und eine
entsprechende Instanz gebildet. Der normale Programmablauf wird daraufhin
unterbrochen. Block für Block wird verlassen und nach einem Handler gesucht, der
bereits in Zeile 19 gefunden wird.
229
Sprachkonzepte und Syntax
Die erste Fehlermeldung wird ausgegeben, und eine zweite Exception, diesmal vom
Typ char*, wird ausgelöst. Wieder wird der Programmablauf unterbrochen, die
return-Anweisung wird nicht ausgeführt.
In Zeile 31 werden alle Exceptions aufgefangen – soweit nicht schon behandelt.
Die zweite Fehlermeldung wird ausgegeben.
Verweise
Siehe Kategorie Funktionen, Funktionen und der Stack
Exceptions auslösen
throw
Beschreibung
Als Anweisung eingesetzt, dient das Schlüsselwort throw dazu, Exceptions auszulösen.
Bei der Funktionsdeklaration kann das Schlüsselwort verwendet werden, um anzugeben, wel-
che Art von Exceptions die deklarierte Funktion auslösen kann.
Anwendung
230
Exceptions auslösen
Warnung
● Wird in einer Funktion eine Exception ausgelöst, deren Typ nicht in der throw-
Liste aufgeführt ist (vermutlich durch eine in der Funktion aufgerufene Funk-
tion), wird die Funktion unexpected()aufgerufen.
● Eine Funktion, die ohne throw deklariert wurde, kann jede Exception auslösen.
● Eine Funktion, die mit throw() deklariert wurde, kann keine Exception auslö-
sen.
● Eine Funktion, die eine Exception der Klasse A auslösen kann, kann auch Ex-
ceptions einer von A abgeleiteten Klasse auslösen.
Beispiele
class my_exception // Definition einer Exception-Klasse
{
int fakt1, fakt2;
public:
my_exception(int i, int j){fakt1=i; fakt2=j;}
void ausgabe() {
cout << "fakt1 = " << fakt1 << endl;
cout << "fakt2 = " << fakt2 << endl;
}
};
Verweise
Siehe Exceptions abfangen
Siehe Handler-Bereich festlegen
231
Sprachkonzepte und Syntax
Exceptions abfangen
catch
Beschreibung
Das Schlüsselwort catch zeigt den Beginn einer Behandlungsroutine für Exceptions eines
bestimmten Typs an. Hinter catch steht in Klammern der Exception-Typ, der abgefangen wird.
Anwendung
Mit Hilfe des Schlüsselwortes catch können Exceptions, die in einem vorangehen-
den try-Block ausgelöst wurden, abgefangen werden. Der Typ der ausgelösten
Exception muß mit dem Typ des catch-Handlers übereinstimmen (gewisse Stan-
dardkonvertierungen werden berücksichtigt).
Hinter catch steht in Klammern der Exception-Typ, der abgefangen wird. Der Typ
der ausgelösten Exception muß mit dem Typ des Handlers übereinstimmen. Die
Anweisung catch (...) fängt alle Exceptions auf.
Wird in dem try-Block eine Exception ausgelöst, die von ihrem Datentyp zu einem
catch-Handler paßt, wird der Anweisungsblock des catch-Handlers ausgeführt.
Warnung
● Auf einen try-Block können mehrere Handlerdefinitionen, jeweils mit catch
eingeleitet, folgen. Die Handler werden der Reihe nach überprüft, bis eine
Übereinstimmung gefunden wird.
● Die Anweisung catch (...) fängt alle Exceptions auf. Der Handler catch (...)
sollte daher nur am Ende einer Handler-Liste stehen.
Beispiele
try {
... // Code, in dem Exceptions auftreten können
}
catch (...) { // alle Exceptions abfangen
cout << "Exception aufgetreten!" << endl;
}
Verweise
Siehe Exceptions auslösen
Siehe Handler-Bereich festlegen
232
Handler-Bereich festlegen
Handler-Bereich festlegen
try
Beschreibung
Gültigkeitsbereiche von Handlern fallen nicht mit den üblichen Blöcken zusammen, sondern
werden durch das Schlüsselwort try eingeleitet und in geschweifte Klammern gefaßt. An den
try-Block schließt sich direkt das Schlüsselwort catch mit der Liste der Handler an.
Anwendung
Viele C++-Bibliotheken sind so implementiert, daß die Funktionen und Methoden
der Bibliothek im Falle gravierender Fehler Exceptions auslösen. Wenn Sie diese
(oder selbst definierte und ausgelöste) Exceptions abfangen wollen, müssen Sie die
Anweisungen, die zur Auslösung der Exceptions führen können, in einen try-Block
fassen und an den try-Block einen oder mehrere catch-Handler anfügen.
Beispiele
try {
... // Code, in dem Exceptions auftreten können
}
Verweise
Siehe Exceptions auslösen
Siehe Exceptions abfangen
Verwandte Funktionen
Beschreibung
Mit der Exception-Behandlung sind die Funktionen unexpected() und terminate() sowie
set_unexpected() und set_terminate() verbunden.
233
Sprachkonzepte und Syntax
Anwendung
● Die Funktionen unexpected() und terminate() werden benötigt, um im Falle ei-
nes Versagens der Exception-Behandlung das Programm abzubrechen. Dies ist
zum Beispiel der Fall, wenn innerhalb einer Funktion eine Exception ausgelöst
wird, die die Funktion nicht behandeln soll (throw-Deklaration). In diesem Fall
wird die Funktion unexpected() aufgerufen, die wiederum standardmäßig ter-
minate() aufruft.
● Die Funktion terminate() wird direkt aufgerufen, wenn Stack-Probleme auf-
tauchen oder für eine ausgelöste Exception kein Handler gefunden wurde. Die
Funktion terminate() ruft standardmäßig die Funktion abort() zum Beenden
des Programmes auf.
● Die Funktionen set_unexpected() und set_terminate() dienen dazu, die Funktions-
aufrufe aus unexpected() und terminate() auf eigene Funktionen umzulenken.
Beispiele
#include <iostream>
#include <string>
using namespace std;
234
C-Strings
int main() {
set_unexpected(unerwartete_Ausnahme); // unexpected-Handler
// registrieren
func(); // unexpected-Exception
// provozieren
return 0;
}
Verweise
Siehe Exceptions auslösen
Zeichenketten
C-Strings
Beschreibung
C kennt keinen eigenen Datentyp für Zeichenketten (Strings). Statt dessen werden Strings ein-
fach als Folgen von Zeichen interpretiert. Ein solcher String beginnt an einer bestimmten Adresse
im Speicher und endet mit dem Auftreten des sogenannten Nullterminierungszeichen '\0'.
Anwendung
Definiert werden Zeichenketten als Zeiger oder Arrays für einen der Datentypen
char (für 7- oder 8-Bit-Zeichensätze wie ASCII oder ANSI) oder wchar_t (für 16-Bit-
Zeichensätze wie UNICODE).
char *ptr;
char str1[25];
235
Sprachkonzepte und Syntax
Die Deklaration als Array hat den Vorteil, daß man gleich mit der Deklaration der
Stringvariablen auch Speicher reserviert. Diesen muß man bei der Definition eines
Zeigers auf eine Zeichenkette nachträglich selbst reservieren (mit malloc() oder new)
– mit dem Vorzug, daß die Größe des Speicherbereichs zur Laufzeit ermittelt und
bei Bedarf auch neuer Speicher reserviert werden kann.
Zur Manipulation der Zeichenketten sind in der C-Laufzeitbibliothek eine Reihe
von Funktionen definiert, die alle mit str... beginnen und in der Header-Datei
string.h deklariert sind.
Warnung
Wenn Sie einen C-String in Form eines Arrays definieren, beachten Sie, daß der
String nicht mit dem Array, sondern mit dem Nullterminierungszeichen '\0' endet.
Wenn Sie also eine Zeichenkette in ein Array kopieren wollen, achten Sie darauf,
daß das Array groß genug ist, um alle Zeichen der Zeichenkette einschließlich des
Nullterminierungszeichens '\0' aufzunehmen. Wenn Sie mit strlen() die Länge
einer Zeichenkette ermitteln wollen, die in einem Array abgelegt ist, erhalten Sie
die Anzahl der Zeichen im String (ohne Nullterminierungszeichen) und nicht die
Größe des Arrays zurück. Wenn Sie mit printf() eine Zeichenkette, die in einem
Array abgelegt ist, ausgeben, werden alle Zeichen von der Adresse des Arrays bis
zum nächsten Nullterminierungszeichen '\0' ausgegeben.
Den String-Funktionen der C-Laufzeitbibliothek haftet das Manko an, daß die
Speicherverwaltung gänzlich dem Programmierer überlassen wird. Will man also
beispielsweise mit Hilfe von strcpy() einen String B in einen String A kopieren,
muß zuvor sichergestellt werden, daß der Speicherplatz, der für String A reserviert
wurde, groß genug ist, um auch String B aufnehmen zu können. Zur Reservierung
von Speicher für Strings gibt es mehrere Möglichkeiten.
Beispiele
#include <stdio.h>
#include <string.h>
int main()
{
char string1[] = "C und C++";
char string2[] = "C++ und C";
return 0;
}
236
Die Klasse string
Verweise
Siehe Die Klasse string
Beschreibung
In C++ kann man zur Programmierung mit Text auf die Klasse string (wstring für Wide Charac-
ter-Strings) zurückgreifen.
Anwendung
Die Klasse string geht zurück auf das Template basic_string, das in der Header-
Datei <string> definiert ist:
template<class charT, ... > class basic_string;
Was wir der Einfachheit halber als string-Klasse bezeichnen, ist also in Wirklich-
keit nichts anderes als ein Alias für die Instanziierung des Templates für den Zei-
chentyp char.
typedef basic_string<char> string;
Analog gibt es eine entsprechende Typdefinition wstring für den Zeichentyp
wchar_t.
Zur Manipulation der Strings verwenden Sie die in basic_string definierten Metho-
den und Operatoren. Die Verwendung dieser Methoden und Operatoren erleichtert
nicht nur die Arbeit mit String (im Vergleich zu den C-Strings), sie ist auch wesent-
lich sicherer, da die Implementierung der string-Klasse für die korrekte Speicher-
verwaltung sorgt.
Zur Unterstützung bestehenden C-Codes verfügt die Klasse string über eine
Methode c_str(), die den in einem string-Objekt gekapselten Text als C-String
zurückliefert.
Beispiele
#include <iostream>
#include <string>
using namespace std;
int main()
{
string str1("C und C++");
string str2 = "C++ und C";
237
Sprachkonzepte und Syntax
return 0;
}
Verweise
Siehe Die Klasse string
Beschreibung
Der Datentyp wchar_t (in C noch mittels typedef definiert) für »wide characters« wurde einge-
richtet, um mit Zeichensätzen arbeiten zu können, die entgegen dem ASCII-Zeichensatz nicht
durch 8 Bit codiert werden könne (beispielsweise UNICODE).
Die Wide characters sind von den Multibyte-Zeichen zu unterscheiden. Während
die Wide characters zu den Integer-Typen gehören, werden Multibyte-Zeichen als
Folge von Bytes behandelt. Die Anzahl der Bytes, die zu einem Multibyte-Zeichen
gehören, kann dabei variieren. Dies kann sehr speichersparend sein, beispielsweise
wenn man in einer Datei deutschen Text (für dessen Zeichen man nur 1 Byte benö-
tigt) mit chinesischen Schriftzeichen (für deren Codierung mindestens 2 Byte benö-
tigt werden) mischt. Alle gängigen Multibyte-Codierungsverfahren verwenden
daher irgendwelche Escape-Sequenzen, die dazu dienen, zwischen verschiedenen
Zeichensätzen hin- und herzuschalten und anzuzeigen, ob die nachfolgenden Zei-
chen durch eines oder zwei oder mehrere Bytes codiert werden. Innerhalb eines
Programmes werden Multibyte-Zeichen allerdings wegen ihrer variablen Länge und
unbequemen Handhabung kaum verwendet. Meist wandelt man daher Multibyte-
Zeichen beim Einlesen der Datei in WideCharacter-Zeichen um, arbeitet mit diesen
und schreibt das Ergebnis dann wieder als Multibyte-Zeichen in die Datei zurück.
Anwendung
Die C-Bibliothek enthält etliche Methoden zur Programmierung mit Multibyte-Zei-
chen und Wide characters. Die Multibyte-Funktionen erkennt man an der Zeichen-
folge »mb«, wie in mblen(), mbrlen(), mbtowc(), wctomb() oder mbstowcs(),
wcstombs(), mbsinit(). Die Wide character-Funktionen erkennt man an dem »w« im
Funktionsnamen, wie in wprintf(), wmemcpy() oder wcscpy().
238
Formatierte und unformatierte E/A
Anwendung
Bei der formatierten Ein- und Ausgabe können die Daten in ihrem ursprünglichen
Datenformat ein- und ausgegeben werden:
int integer = 3;
char zeichen = 'A';
printf("%d",integer); // formatierte Ausgabe in C
printf("%c",zeichen);
cout << integer; // formatierte Ausgabe in C++
cout << zeichen;
Bei der unformatierten Ein- und Ausgabe werden die Daten dagegen als eine Folge
von Bytes behandelt:
fwrite(&zeichen, sizeof(char), 1, stdout); // C
fwrite(&integer, sizeof(int), 1, stdout);
[Link](zeichen); // C++
[Link]((char *) &integer, sizeof(int));
Bei der formatierten Ein- und Ausgabe können die Daten durch explizite Typum-
wandlung im Zuge der Ausgabe auch umformatiert werden. Zudem kann die Aus-
gabe mit Hilfe von Sonderzeichen (\n für Zeilenumbruch, \t für Tabulator) und spe-
ziellen Formatierungsanweisungen weiter formatiert werden.
Warnung
Ein- und Ausgabe sind betriebssystemspezifische Vorgänge. Aus diesem Grund sind
sie auch nicht fest (in Form von Schlüsselworten) in der Sprache verankert, sondern
durch Funktionen/Klassen der Laufzeitbibliothek implementiert. Diese unterstützen
aber nur die Ein- und Ausgabe für Konsolenprogramme. Für Windows-Programme
(unter UNIX XWindows oder OSF Motif) kann man diese Funktionen nicht nut-
zen, sondern muß auf spezielle Funktionen zurückgreifen, die in den APIs der Win-
dows-Systeme enthalten sind.
239
Sprachkonzepte und Syntax
Beispiele
Umformatierung bei der formatierten Ausgabe:
char zeichen = 'A';
printf("%d",zeichen); // Ausgabe: 65
cout << (int) zeichen; // Ausgabe: 65
Verwendung von Sonderzeichen und speziellen Formatierungsanweisungen:
// Feldbreite der Ausgabe auf 5 Zeichen setzen
printf("%5d",integer);
printf("%5c\n",zeichen); // Ausgabe: 3 A
Verweise
Siehe Referenz der Laufzeitbibliotheken, Beispiele zu Header-Dateien
Streams in C
Beschreibung
Streams sind Datenströme, über die Daten von einer Quelle zu einem Ziel bewegt werden.
Die Stream-Objekte, mit denen wir arbeiten, bezeichnen jeweils ein Ende eines
Datenstroms (Quelle oder Ziel), verfügen über interne Informationen über die
Abwicklung des Datenaustauschs und sind standardmäßig mit einem Zwischenpuf-
fer verbunden.
Anwendung
In C stehen die folgenden Standard-Stream-Objekte zur Verfügung:
Zur Definition eigener Streams, insbesondere zur Ein- und Ausgabe in Dateien,
steht der in <stdio.h> definierte Datentyp FILE zur Verfügung.
240
Streams in C
C-Funktion Beschreibung
fclose Datenstrom schließen.
feof Testet Datenstrom auf Dateiende.
ferror Testet Datenstrom auf Fehler.
fflush Leert Puffer eines Datenstroms.
fgetc Liest Zeichen von einem Datenstrom.
fgetpos Ermittelt Positionszeiger eines Datenstroms.
fgets Liest eine Zeile von einem Datenstrom.
fopen Öffnet einen Datenstrom.
fprintf Formatierte Ausgabe an einen Datenstrom.
fputc Schreibt ein Zeichen an Datenstrom.
fputs Schreibt einen String an Datenstrom.
freopen Öffnet einen Datenstrom erneut.
fscanf Liest formatiert von Datenstrom.
fseek Positioniert Dateizeiger neu.
fsetpos Positioniert Dateizeiger neu.
ftell Liest Position des Dateizeigers.
getc Liest Zeichen aus Datenstrom.
getchar Liest Zeichen aus Datenstrom stdin.
gets Liest String von stdin.
printf Formatierte Ausgabe an stdout.
putc Schreibt Zeichen in Datenstrom.
putchar Schreibt Zeichen an Datenstrom stdout.
puts Schreibt Zeichenkette an Datenstrom stdout.
rewind Positioniert Dateizeiger auf Anfang des Datenstroms.
scanf Formatierte Eingabe von stdin.
241
Sprachkonzepte und Syntax
C-Funktion Beschreibung
setbuf Einrichtung eines eigenen Datenstrompuffers
setvbuf Datenstrompufferung und Puffergröße verändern.
sprintf Formatierte Ausgabe in einen String.
sscanf Formatierte Eingabe aus einem String.
ungetc Zeichen wieder zurück an Datenstrom schicken.
Streams in C++
Beschreibung
Streams sind Datenströme, über die Daten von einer Quelle zu einem Ziel bewegt werden.
Die Stream-Objekte, mit denen wir arbeiten, bezeichnen jeweils ein Ende eines Datenstroms
(Quelle oder Ziel), verfügen über interne Informationen über die Abwicklung des Datenaus-
tauschs und sind standardmäßig mit einem Zwischenpuffer verbunden.
Anwendung
In C++ stehen die folgenden Standard-Stream-Objekte zur Verfügung:
Formatierung
Formatieren läßt sich die Ausgabe
mittels der folgenden Stream-Methoden
242
Streams in C++
Methode Beschreibung
width() Mit Hilfe der Methode width() kann man für die Ausgabe des nächsten
Werts eine minimale Breite festlegen.
Umfaßt die Ausgabe weniger Stellen, als width() als Argument übergeben
wurde, werden Füllzeichen eingefügt. Das endgültige Format hängt dann
vom ausgewählten Füllzeichen (siehe fill()) und der Ausrichtung (left,
right, internal) ab.
fill() Mit der Methode fill() können Sie ein Füllzeichen festlegen. Füllzeichen
werden verwendet, wenn Sie für eine Ausgabe eine Feldbreite wählen (siehe
oben), die größer ist als die eigentliche Ausgabe.
precision() Mit der Methode precision() kann die Anzahl der Ziffernstellen bei der
Ausgabe von Fließkommazahlen festgelegt werden. Standardwert sind dabei
6 Stellen.
Allerdings ist dabei zu unterscheiden, ob die Fließkommazahlen im Stan-
dardmodus ausgegeben werden, oder ob zuvor eines der Format-Flags fixed
oder scientific gesetzt wurde.
Im Standardmodus legt precision() die Gesamtzahl der Ziffern fest.
Im fixed- oder scientific-Modus legt precision() die Zahl der Nach-
kommastellen fest.
● mittels Formatierungsflags, die über die Methoden setf() und unsetf() gesetzt
und gelöscht werden können. Die Formatierungsflags sind als Elemente der
Klasse ios_base (in nicht ganz aktuellen Compilern ios) definiert:
243
Sprachkonzepte und Syntax
244
Streams in C++
Fehlerbehandlung
Zur Fehlerbehandlung enthält jeder Stream die folgenden Statusbits, die im Falle
eines Fehlers von den Streams aus 1 gesetzt werden.
Statusbit Fehler
ios_base::goodbit Kein Fehler aufgetreten, alles ist in Ordnung. (In Wirklichkeit kein
Bit, sondern der Wert 0).
ios_base::eofbit Beim Einlesen wurde das EOF-Zeichen erreicht (kann bei der Eingabe
von Tastatur zur Not durch Strg+D oder Strg+Z simuliert werden).
ios_base::failbit Bei der Eingabe konnte das erwartete Zeichen (beispielsweise wegen
falschem Format) nicht eingelesen werden.
Bei der Ausgabe konnte das gewünschte Zeichen nicht ausgegeben
werden.
ios_base::badbit Der Stream kann aus irgendeinem Grund nicht mehr korrekt arbeiten
(meist ist dies der Fall, wenn es Probleme mit dem zugrundeliegenden
Puffer (basic_streambuf-Objekte) gibt).
Zu den Statusbits gibt es die folgenden Methoden, mit denen der Zustand der Stre-
ams abgefragt werden kann.
Methode Beschreibung
bool good() true, wenn kein Statusbit gesetzt wurde
bool eof() true, wenn eofbit gesetzt wurde
bool fail() true, wenn failbit oder badbit gesetzt wurde
bool bad() true, wenn badbit gesetzt wurde
bool operator!() true, wenn failbit oder badbit gesetzt wurde
iostate rdstate() Liefert den gesamten Streamstatus zurück
245
Sprachkonzepte und Syntax
Pufferung
Beschreibung
Streams sind grundsätzlich gepuffert, d. h., die Eingaben oder Ausgaben erfolgen nicht direkt
zum Ziel des Streams, sondern werden im Speicher zwischengepuffert.
Der Sinn der Pufferung ist es, die Ein- und Ausgabe effizienter zu gestalten. Meist
greift man bei der Ein- oder Ausgabe auf externe Geräte zu (Tastatur, Bildschirm,
Festplatte, Laufwerk). Diese Zugriffe sind stets um ein Vielfaches langsamer als
Zugriffe auf Speicherbereiche. Man kann den Datenaustausch aber beschleunigen,
indem man die Daten Zeichen für Zeichen in einem Puffer im RAM zwischenspei-
chert und dann in möglichst großen zusammenhängenden Blöcken überträgt.
Anwendung
Jeder Puffer hat eine festgelegte Größe. Ist der Puffer voll, leert er sich selbst.
Darüber hinaus gibt es aber auch Möglichkeiten, einen Puffer direkt leeren zu las-
sen.
● Durch Aufruf der Methode flush().
● Der Tastaturpuffer (Streams stdin, cin) kann durch Drücken der Eingabe-
Taste geleert werden.
● Der Konsolenpuffer (Streams stdout, cout, clog) wird bei Ausgabe des New-
line-Zeichens geleert (cout << "\n"; oder cout << endl;). Zudem ist der Ausga-
bepuffer cout (stdout) mit dem Eingabepuffer cin (stdin) verbunden, so daß
vor jeder erwarteten Eingabe der Ausgabepuffer geleert wird.
● Die Fehlerausgabe cerr (stderr) ist nicht gepuffert.
Hinter den Puffern stehen in C++ Klassen, die alle auf das Klassentemplate
basic_streambuf zurückgehen. Die Verbindung zwischen einem Stream und seinem
Puffer wird bei der Instanzbildung des Streams durch den Konstruktor hergestellt.
Nach der Initialisierung kann der Stream über die Methode rdbuf() auf seinen Puf-
fer zugreifen,
● entweder um sich eine Referenz auf den eigenen Puffer zurückliefern zu lassen
und dann diesen über seine public-Schnittstelle zu manipulieren (beispielsweise
zur Anpassung der Puffergröße mit setbuf() )
● oder um den Stream mit einem anderen Puffer zu verbinden (beispielsweise
mit dem Puffer eines anderen Streams).
246
assert.h
Die C-Standardbibliothek
Die Header-Dateien
Um die C-Funktionen in Ihren Programmen aufrufen zu können, müssen Sie zuvor
die Funktionsdeklarationen dem Compiler bekannt machen. Dazu dienen die Hea-
der-Dateien, in denen die Funktionen thematisch geordnet sind, und die Sie mittels
der #include-Direktive in Ihre Programme aufnehmen können.
Im folgenden werden die Funktionen nach Header-Dateien geordnet vorgestellt,
wobei die Namen der C-Konvention verwendet wurden. Nach dem neuen C++-
Standard wird den Dateinamen der C-Header-Dateien jeweils ein »c« vorangestellt
und die Extension weggelassen (stdlib.h wird also zu cstdlib). Der Unterschied zu
den C-Headern ist dabei, daß die Elemente in den C++-Headern im Namensbereich
std deklariert sind.
assert.h
Beschreibung
Enthält allein das Makro assert, das zum Debuggen verwendet werden kann.
Enthaltene Elemente
assert // Prüft eine Bedingung und bricht bei Nichterfüllung
// das Programm ab.
Beispiel
#include <stdio.h>
#include <assert.h>
int main(int argc, char **argv)
{
int i = 3, j = 2;
double erg;
// ... weitere Anweisungen
assert(j != 0); // Division durch Null vermeiden
erg = (double) i/j;
printf("Division ergibt : %f\n",erg);
return 0;
}
247
Die C-Standardbibliothek
ctype.h
Beschreibung
Enthält die Funktionen zur Klassifizierung (is...) und Konvertierung (to...) einfacher Zeichen.
Die Funktionen dieser Header-Datei verwendet man üblicherweise zur Aufbereitung oder Kon-
trolle von Benutzereingaben über die Tastatur. So können Sie testen, ob der Anwender wie
vom Programm gewünscht eine Zahl als Ziffernfolge oder unerlaubter Weise als ausgeschrie-
benes Wort eingegeben hat. Oder Sie können Benutzereingaben mit Hilfe der Funktionen tolo-
wer()/toupper() in Klein- oder Großbuchstaben verwandeln.
Enthaltene Elemente
isalnum // Testet, ob Zeichen eine Ziffer oder ein Buchstabe ist.
isalpha // Testet, ob Zeichen ein Buchstabe ist.
iscntrl // Testet, ob Zeichen ein Kontrollzeichen ist.
isdigit // Testet, ob Zeichen eine Zahl ist.
isgraph // Testet, ob Zeichen darstellbar ist.
islower // Testet, ob Zeichen ein Kleinbuchstabe ist.
isprint // Testet, ob Zeichen druckbar ist.
ispunct // Testet, ob Zeichen ein Interpunktionszeichen ist.
isspace // Testet, ob Zeichen ein Zwischenraumzeichen ist.
isupper // Testet, ob Zeichen ein Großbuchstabe ist.
isxdigit // Testet, ob Zeichen eine Hexadezimalziffer ist.
tolower // Wandelt Groß- in Kleinbuchstaben um.
toupper // Wandelt Klein- in Großbuchstaben um.
Beispiel
char zeichen, *str;
...
for(i = 0; i < strlen(str); i++)
str[i] = tolower(str[i]);
if(isprint(zeichen))
putchar(zeichen);
errno.h
Beschreibung
Enthält verschiedene Makros, die von verschiedenen Bibliotheksfunktionen zur Benachrichti-
gung über aufgetretene Fehler verwendet werden.
248
float.h
Enthaltene Elemente
EDOM // Wird im Falle eines ungültigen Funktionsarguments von den
// mathematischen Funktionen in errno kopiert.
EILSEQ // Wird im Falle eines Codierungsfehlers von Multibyte in
// Wide Character oder umgekehrt von den Funktionen
// mbrtowc() bzw. wcrtomb() in errno kopiert.
ERANGE // Wird im Falle eines ungültigen Ergebniswertes von den
// mathematischen Funktionen in errno kopiert.
errno // Wird im Fehlerfall von den mathematischen Funktionen
// gesetzt.
Beispiel
#include <stdio.h>
#include <math.h>
#include <errno.h>
int main(int argc, char **argv)
{
int i = -3;
double wurzel;
errno = 0;
wurzel = sqrt(i);
if(errno == EDOM)
puts("Domain Error bei Aufruf von sqrt()\n");
else
printf("Wurzel von %d ist %f\n",i,wurzel);
return 0;
}
float.h
Beschreibung
Enthält verschiedene Makros, die zu verschiedenen implementierungsspezifischen Konstanten
expandieren. Aufgeführt sind nur die Konstanten für den Datentyp float. Die Konstanten für
double und long double beginnen mit den Suffixen DBL beziehungsweise LDBL. (FLT_ROUNDS
gilt für alle drei Gleitkommatypen).
Enthaltene Elemente
FLT_DIG // Anzahl der signifikanten Ziffern in der Mantisse,
// wenn dargestellt zur Basis 10
FLT_EPSILON // Differenz zwischen 1 und der nächstgrößeren
// darstellbaren Zahl.
FLT_MANT_DIG // Anzahl der Ziffern in der Mantisse, wenn dargestellt
// zur Basis FLT_RADIX
FLT_MAX // Größte positive Zahl.
FLT_MAX_10_EXP // Größte positive Zahl für den Exponenten zur Basis 10.
249
Die C-Standardbibliothek
ios646.h
Beschreibung
Synonyme für bestimmte Operatoren.
Enthaltene Elemente
Synonym für
and && Logische UND-Verknüpfung
and_eq &= Bitweise UND-Verknüpfung und Zuweisung
bitand & Bitweise UND-Verknüpfung
bitor | Bitweises ODER
compl ~ Komplement
not ! Nicht-Operator, Verneinung
not_eq != vergleicht zwei arithmetische Operanden auf Ungleichheit
or || Logisches ODER
or_eq |= Bitweises ODER und Zuweisung des Ergebnisses
xor ^ Bitweises exklusives ODER
xor_eq ^= Bitweises exklusives ODER und Zuweisung des Ergebnisses
250
limits.h
limits.h
Beschreibung
Enthält Konstanten, die Größe und Wertebereiche der elementaren Datentypen festlegen (die
Werte sind implementierungsspezifisch und werden vom Compiler festgelegt).
Enthaltene Elemente
CHAR_BIT // Anzahl der Bits in kleinstem Datentyp
CHAR_MIN // kleinster Wert für Objekte vom Typ char
CHAR_MAX // größter Wert für Objekte vom Typ char
INT_MIN // kleinster Wert für Objekte vom Typ int
INT_MAX // größter Wert für Objekte vom Typ int
LONG_MIN // kleinster Wert für Objekte vom Typ long int
LONG_MAX // größter Wert für Objekte vom Typ long int
MB_LEN_MAX // maximale Anzahl von Bytes in Multibyte-Zeichen
SCHAR_MIN // kleinster Wert für Objekte vom Typ signed char
SCHAR_MAX // größter Wert für Objekte vom Typ signed char
SHRT_MIN // kleinster Wert für Objekte vom Typ short int
SHRT_MAX // größter Wert für Objekte vom Typ short int
UCHAR_MAX // größter Wert für Objekte vom Typ unsigned char
UINT_MAX // größter Wert für Objekte vom Typ unsigned int
ULONG_MAX // größter Wert für Objekte vom Typ unsigned long int
USHRT_MAX // größter Wert für Objekte vom Typ unsigned short int
locale.h
Beschreibung
Enthält die Funktionen localeconv() und setlocale() zum Einstellen und Abfragen landes-
spezifischer Eigenheiten. Rückgabetyp von localeconv() ist die Struktur lconv. Die LC-Makros
können setlocale() als Argument übergeben werden, um spezielle Facetten einer Lokale aus-
zuwählen.
Enthaltenen Elemente
LC_ALL // Alle Kategorien landesspez. Einstellungen.
LC_COLLATE // Für String-Vergleiche.
LC_CTYPE // Für die Zeichenklassifizierung und -umwandlung.
LC_MONETARY // Für Währungsformate.
LC_NUMERIC // Für Zahlenformate, beispielsweise Dezimalpunkt in
// Gleitkommazahlen.
LC_TIME // Für Datums- und Zeitangaben.
struct lconv // Die Struktur lconv .
localeconv // Die Struktur lconv initialisieren.
setlocale // Landesspezifische Werte abfragen und verändern.
251
Die C-Standardbibliothek
Beispiel
Aktuelle Lokale-Einstellungen abfragen:
struct lconv ll;
struct lconv *conv = ≪
conv = localeconv();
printf("Dezimalpunkt : %s\n", conv->decimal_point);
Lokale wechseln
setlocale(LC_ALL, "de_DE");
math.h
Beschreibung
Deklariert die mathematischen Funktionen. Während unter C nur die double-Versionen der
Funktionen verfügbar sind, sind unter C++ zusätzlich für die Datentypen float und long
double überladen.
Enthaltene Elemente
HUGE_VAL // Makro, das zu einem double-Wert expandiert, der von den
// math. Funktionen im Falle eines Überlaufes
// zurückgeliefert wird.
acos // Arkuskosinus berechnen.
asin // Arkussinus berechnen.
atan // Arkustangens von x berechnen.
atan2 // Arkustangens von x/y berechnen.
ceil // Rundet auf nächste Ganzzahl auf.
cos // Kosinus berechnen.
cosh // Kosinus hyperbolicus berechnen.
exp // Exponentialfunktion berechnen.
fabs // Ermittelt Absolutwert.
floor // Größte Ganzzahl ermitteln, die kleiner oder gleich dem
// Argument ist.
fmod // Rest einer Gleitkomma-Division berechnen.
frexp // Exponentialwert berechnen.
ldexp // Gleitkommazahl multiplizieren.
log // Natürlichen Logarithmus berechnen.
log10 // Logarithmus zur Basis 10 berechnen.
modf // Argument in ganzzahligen und gebrochenen Teil zergliedern
pow // Zahl potenzieren.
sin // Sinus berechnen.
sinh // Sinus hyperbolicus berechnen.
sqrt // Quadratwurzel berechnen.
tan // Tangens berechnen.
tanh // Tangens hyperbolicus berechnen.
252
setjmp.h
Beispiel
double zahl;
printf("Geben Sie ein Zahl: \n\n");
scanf("%lf", &zahl); fflush(stdin);
printf(" Quadrat von %lf = %lf\n",zahl,zahl*zahl);
printf(" %lf^3 = %lf\n",zahl,pow(zahl,3));
printf(" Log.e von %lf = %lf\n",zahl,log(zahl));
printf(" Log.10 von %lf = %lf\n",zahl,log10(zahl));
printf(" Sinus von %lf (RAD) = %lf\n",zahl,sin(zahl));
printf(" Sinus von %lf (GRAD) = %lf\n",zahl,sin(2*3.1415*zahl/360));
setjmp.h
Beschreibung
Definiert den Datentyp jmp_buf, der von dem Makro setjmp() und der Funktion longjmp()
benutzt wird.
Enthaltene Elemente
jmp_buf // Nimmt die Werte der aktuellen Umgebung, typischerweise
// die Inhalte der Prozessorregister sowie Stack- und
// Framezeiger auf, um einen nicht lokalen Sprung zu
// ermöglichen.
longjmp // Aufrufumgebung gemäßt jmp_buf-Argument wiederherstellen
// nach nicht lokalem Sprung.
setjmp // Aufrufumgebung in jmp_buf-Argument sichern. Umgebung
// kann mittels longjmp() wiederhergestellt werden.
Beispiel
#include <stdio.h>
#include <setjmp.h>
#include <stdlib.h>
253
Die C-Standardbibliothek
func(sprung);
return 0;
}
signal.h
Beschreibung
Definiert Konstanten und Funktionen, die für die Signalbearbeitung (Interrupts, Segmentation
faults, etc.) erforderlich sind. Die SIG_-Konstanten sind kompatibel zum zweiten Parameter von
signal(), dem ansonsten eine Signalbehandlungsfunktion übergeben wird. Die SIG-Konstan-
ten kategorisieren die Signale und dienen als Argumente für den ersten Parameter der
signal()-Funktion.
Enthaltenen Elemente
SIG_DFL // Standardverarbeitung
SIG_ERR // Rückgabewert von signal(), wenn Fehler auftritt
SIG_IGN // Signal ignorieren
SIGABRT // Unnormales Programmende
SIGFPE // Gleitkommafehler
SIGILL // Unzulässige Anweisung
SIGINT // Strg+C-Interrupt
SIGSEGV // Unzulässiger Speicherzugriff (Segmentation Fault)
SIGTERM // An Programm gesendete Beendigungsanfrage
raise // Sendet ein Signal.
signal // Installiert Signalbehandlungsfunktion für die
// Verarbeitung eines SIG-Signals.
Beispiel
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
void Signalbearbeitung(int par) {
/* Signalbehandlung reinstallieren */
signal(SIGFPE, Signalbearbeitung);
printf("Signal abgefangen!\n");
printf("Programmdaten werden zur Analyse abgespeichert\n");
exit(1);
}
int main(int argc, char** argv) {
/* Signalbehandlung reinstallieren */
signal(SIGFPE, Signalbearbeitung);
int n, i = 3265;
printf("Geben Sie eine ganze Zahl ein: \n");
scanf("%d",&n);
fflush(stdin);
254
stdarg.h
i = i/n;
printf("%d\n", i);
return 0;
}
stdarg.h
Beschreibung
Definiert die Makros, mit denen Funktionen mit einer variablen Anzahl von Argumenten verar-
beitet werden können.
Enthaltene Elemente
va_list // Array-Typ für va_arg, va_end und va_start.
va_arg // Ermittelt Zeiger auf nächstes Argument in der Liste.
va_end // Setzt Zeiger nach Bearbeitung der Argumente zurück.
va_start // Makro, das der Funktion einen korrekten Rücksprung
// ermöglicht..
stddef.h
Beschreibung
Definiert einige wichtige Typen und Makros, die vor allem bibliotheksintern verwendet werden.
Enthaltene Elemente
NULL // Wert des Null-Zeigers
offsetof // Ermittelt den Offset eines Elements in einer Struktur.
ptrdiff_t // ganzzahliger, vorzeichenbehafteter Datentyp, der das
// Ergebnis der Subtraktion zweier Zeiger
// repräsentieren kann
size_t // vorzeichenloser Ganzzahltyp, der von sizeof als
// Ergebnistyp verwendet wird.
wchar_t // Zeichentyp für umfangreichere Zeichensätze (16 bis
// 32-Bit)
stdio.h
Beschreibung
Enthält die Funktionen zur Ein- und Ausgabe (Konsole, Tastatur, Dateien), sowie etliche ver-
wandte Konstanten und Datentypen.
255
Die C-Standardbibliothek
Enthaltene Funktionen
clearerr // Fehlerbedingung aus Stream entfernen.
fclose // Stream schließen.
feof // Testet Stream auf Dateiende.
ferror // Testet Stream auf Fehler.
fflush // Leert Puffer eines Streams.
256
stdlib.h
stdlib.h
Beschreibung
Sammelsurium häufig benötigter Bibliotheksfunktionen, zu denen u. a. die dynamische Spei-
cherverwaltung und die Prozeßkontrollroutinen gehören.
257
Die C-Standardbibliothek
Enthaltene Funktionen
abort // Beendet Programm unverzüglich.
abs // Ermittelt Absolutwert einer Integerzahl (In C++ für
// long int, float und long double überladen).
atexit // Funktion registrieren, die beim Programmende
// ausgeführt werden soll.
atof // Wandelt String in Fließkommazahl um.
atoi // Wandelt String in Integerzahl um.
atol // Wandelt String in long int um.
bsearch // Binäre Suche durchführen.
calloc // Speicher allokieren und initialisieren.
div // Ganzzahldivision durchführen (In C++ für long überladen).
exit // Programm beenden.
free // Dynamisch angeforderten Speicher freigeben.
getenv // Eintrag in Programm-Umgebung lesen.
labs // Absolutwert einer Zahl vom Typ long int ermitteln.
ldiv // Ganzzahldivision mit Zahlen vom Typ long int (In C++ für
// long überladen).
malloc // Speicher anfordern.
mblen // Länge eines Multibyte-Zeichens ermitteln.
mbstowcs // Zeichenkette mit Zeichen, die aus mehreren Bytes
// bestehen, in Wide Character-String umwandeln.
mbtowc // Zeichen, das aus mehreren Bytes besteht, in
// Wide Character umwandeln
qsort // QuickSort durchführen.
rand // Pseudo-Zufallszahl erzeugen.
realloc // Speicherblock neu zuordnen.
srand // Pseudo-Zufallszahl erzeugen.
258
string.h
string.h
Beschreibung
Enthält die Funktionen zur Manipulation von Zeichenketten (Strings).
Enthaltenen Elemente
NULL // Wert des NULL-Zeigers.
size_t // vorzeichenloser Ganzzahltyp, der von sizeof als
// Ergebnistyp verwendet wird.
memchr // Sucht in einem Speicherbereich nach erstem Vorkommen
// eines Zeichens.
memcmp // Vergleicht zwei Speicherbereiche.
memcpy // Kopiert Anzahl Zeichen von einem Speicherbereich in einen
// anderen.
memmove // Kopiert Zeichen von einem Speicherbereich in einen
// anderen, der sich mit dem Ursprungsbereich überlappen darf
memset // Initialisiert einen Speicherbereich mit einem Zeichen.
strcat // Fügt Zeichenkette an eine andere an.
strchr // Ermittelt Zeiger auf erstes Vorkommen eines Zeichens in
// String.
strcmp // Vergleicht zwei Zeichenketten.
strcoll // Vergleicht zwei Zeichenketten.
strcpy // Kopiert einen String in einen anderen.
strcspn // Sucht in Zeichenkette nach Zeichen, die in anderer
// Zeichenkette nicht enthalten sind.
strerror // Übersetzt eine Fehlernummer in eine Zeichenkette.
strlen // Ermittelt die Länge einer Zeichenkette.
strncat // Fügt n Zeichen einer Zeichenkette an andere an.
strncmp // Vergleicht einen String mit einem Teil eines anderen
// Strings.
strncpy // Kopiert n Zeichen eines Strings in einen anderen.
strpbrk // Sucht nach erstem Vorkommen eines beliebigen Zeichens aus
// einer Zeichenkette in einer anderen Zeichenkette.
strrchr // Ermittelt Zeiger auf letztes Vorkommen eines Zeichens in
// einer Zeichenkette.
strspn // Ermittelt Index des ersten Zeichens in einer Zeichenkette,
// das nicht zum Zeichensatz einer zweiten
// Zeichenkette gehört
259
Die C-Standardbibliothek
Beispiel
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char** argv)
{
char str[3][21] = {"String1", "String2", "String3"};
char *p_str;
int bytes;
// Strings aneinanderhaengen
// Speicherbereich ermitteln
bytes = (strlen(str[0]) + strlen(str[1]) +
strlen(str[2]) + 1)*sizeof(char);
// Speicher allokieren
p_str = (char*) malloc(bytes);
strcpy(p_str,str[0]);
strcat(p_str,str[1]);
strcat(p_str,str[2]);
printf("String = %s enthaelt %d Bytes\n",p_str,bytes);
free(p_str);
return 0;
}
time.h
Beschreibung
Enthält die Datentypen time_t und clock_t sowie die Datenstruktur tm und die allgemeinen
Zeitfunktionen.
Anwendung
Für Zeitnahmen geht man üblicherweise so vor, daß man sich die Startzeit und die
Endzeit von der Funktion time() als Werte des Datentyps time_t zurückliefern läßt.
Die Differenz läßt man sich von der Funktion difftime() errechnen.
Um Zeit und/oder Datum abzufragen, kann man beispielsweise die Funktion asc-
time() verwenden. Für die Umwandlung des Datums in einen ausgabefähigen String
nutzt man die Funktion strftime().
260
time.h
Enthaltene Funktionen
asctime // Wandelt eine als Struktur gespeicherte Zeit in eine
// Zeichenkette um.
clock // Ermittelt, wieviel Ticks seit dem Start des aufrufenden
// Prozesses verbraucht wurden.
ctime // Wandelt Zahl vom Typ time_t in Zeichenkette um.
difftime // Ermittelt die Differenz zwischen zwei Zeiten.
gmtime // Berechnet aus lokaler Zeit und definierter Zeitdifferenz
// die Greenwich Mean Time (GMT).
localtime // Wandelt einen Zeitwert vom Typ time_t in die Lokalzeit um
mktime // Wandelt Zeit aus Struktur in Kalenderzeit um.
strftime // Formatiert Zeit nach landesspezifischen Bedingungen.
time // Gibt aktuelle Zeit an Variable vom Typ time_t zurück.
Beispiel
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(int argc, char** argv)
{
time_t start, ende;
char eingabe[100];
int ergebnis;
start = time(NULL);
puts("Wieviel ist 7 * 23: \n");
fgets(eingabe,100,stdin);
sscanf(eingabe,"%d\n",&ergebnis);
ende = time(NULL);
printf("Sie haben %d sec. benoetigt\n",(int) difftime(ende,start));
if(ergebnis == 161)
puts("Die Loesung ist korrekt \n");
else
printf("Die korrekte Antwort ist 161 (nicht %d)\n", ergebnis);
return 0;
}
261
Die C-Standardbibliothek
wchar.h
Beschreibung
Enthält die Funktionen zur Bearbeitung von Wide Character und Multibyte-Strings (inklusive
Ein- und Ausgabe).
Enthaltene Funktionen
btowc // Wandelt ein 1-MultiByte-Zeichen in ein
// Wide Character-Zeichen um.
fgetwc // Liest Zeichen von einem Stream.
fgetws // Liest eine Zeile von einem Stream.
fputwc // Schreibt ein Zeichen in Stream.
fputws // Schreibt einen String in Stream.
fwide // Kann einen Stream nachträglich für Byte- oder
// Wide Character-Zeichen einrichten.
fwprintf // Formatierte Ausgabe an stdout.
fwscanf // Liest formatiert von Stream.
getwc // Liest Zeichen aus Stream.
getwchar // Liest Zeichen aus Stream stdin.
mbrlen // Länge eines Multibyte-Zeichens ermitteln.
mbrtowc // Multibyte-Zeichen in Wide Character umwandeln.
mbsinit // Ermittelt, ob sein Argument einen anfänglichen
// Konvertierungsmodus anzeigt.
mbsrtowcs // Multibyte-Zeichenkette in Wide Character-String umwandeln
putwc // Schreibt Zeichen in Stream.
putwchar // Schreibt Zeichen an Stream stdout.
swprintf // Formatierte Ausgabe in einen String.
swscanf // Formatierte Eingabe von einem String.
ungetwc // Zeichen wieder zurück an Stream schicken.
vfwprintf // Formatierte Ausgabe an Stream.
vswprintf // Formatierte Ausgabe in String.
vwprintf // Formatierte Ausgabe an stdout.
wcrtomb // Wide Character in Multibyte-Zeichen umwandeln.
262
wctype.h
wctype.h
Beschreibung
Enthält die Funktionen zur Klassifizierung und Konvertierung von Wide Character-Zeichen,
sowie einige Hilfstypen.
263
Die C-Standardbibliothek
Enthaltene Elemente
wctrans_t // Hilfstyp für Zeichenabbildungen.
wctype_t // Hilfstyp für die Zeichenklassifizierung.
WEOF // Konstante, die das Ende einer Datei anzeigt
wint_t // Integer-Typ für die Codierung von Zeichen aus
// erweiterten Zeichensätzen
iswalnum // Testet, ob Zeichen eine Ziffer oder ein Buchstabe ist.
iswalpha // Testet, ob Zeichen ein Buchstabe ist.
iswcntrl // Testet, ob Zeichen ein Kontrollzeichen ist.
iswctype // Testet, ob Zeichen einer bestimmten Klasse angehört.
// Die Klasse wird durch einen Aufruf von wctype()
// spezifiziert.
iswdigit // Testet, ob Zeichen eine Zahl ist.
iswgraph // Testet, ob Zeichen druckbar ist (Leerzeichen
// ausgenommen).
iswlower // Testet, ob Zeichen ein Kleinbuchstabe ist.
iswprint // Testet, ob Zeichen druckbar ist.
iswpunct // Testet, ob Zeichen ein Interpunktionszeichen ist.
iswspace // Testet, ob Zeichen ein Zwischenraumzeichen ist.
iswupper // Testet, ob Zeichen ein Großbuchstabe ist.
iswxdigit // Testet, ob Zeichen eine Hexadezimalziffer ist.
towctrans // Konvertiert ein Wide Character Zeichen.
towlower // Wandelt Groß- in Kleinbuchstaben um.
towupper // Wandelt Klein- in Großbuchstaben um.
wctrans // Ermittelt eine Abbildung von einem Wide Character-
// Zeichensatz in einen anderen (nach LC_TYPE).
wctype // Wird zusammen mit iswctype() verwendet und erlaubt die
// Identifizierung einer Klasse anhand eines Strings.
Beschreibung
Die Funktion abort() bewirkt einen unnormalen Programmabbruch, was bedeutet, daß im
Gegensatz zur Funktion exit() nicht sichergestellt ist, daß Dateipuffer geleert, offene Streams
geschlossen und mit tmpfile() erzeugte temporäre Dateien entfernt werden. Außerdem wer-
den die Programmbeendigungsroutinen, die mit atexit() eingerichtet worden sind, nicht auf-
gerufen. Dafür wird die Funktion raise() mit der Konstanten SIGABRT als Argument aufgerufen,
für das man eine Signalbehandlungsroutine einrichten kann.
264
wctype.h
Parameter
void abort(void);
Verwandte Funktionen
assert(), atexit(), exit(), raise()
abs <stdlib.h>
Absolutwert berechnen
Beschreibung
Die Funktion abs() gibt den Betrag ihres ganzzahligen Argumentes als Funktionswert zurück.
Der Betrag einer Zahl ist ihr Abstand zur Null.
Parameter
int abs(int n);
● Rückgabewert. Betrag des Arguments n.
Verwandte Funktionen
fabs(), labs()
acos <math.h>
Bogenkosinus berechnen
Beschreibung
Die Funktion acos() berechnet den Bogenkosinus (Umkehrfunktion des Kosinus) für das über-
gebene Argument.
Parameter
double acos(double zahl);
● zahl. Argument, für das der Arkuskosinus berechnet wird (muß im Bereich
zwischen -1.0 und 1.0 liegen)
● Rückgabewert. Arkuskosinus des Arguments im Bereich [0,p].
Verwandte Funktionen
asin(), atan(), cos(), sin(), tan()
asctime <time.h>
Uhrzeit in Zeichenkette
265
Die C-Standardbibliothek
Beschreibung
Die Funktion asctime() wandelt die in der Zeitstruktur tm enthaltenen Zeitinformationen in
eine Zeichenkette um. Die erzeugte Zeichenkette besitzt das folgende Format (für Lokale "C"):
Mon Jul 31 [Link] 1989\n\0
Parameter
char *asctime (const struct tm *zeit);
● Rückgabewert. Zeiger auf die erzeugte Zeichenkette.
Verwandte Funktionen
ctime(), gmtime(), localtime(), setlocale()
asin <math.h>
Bogensinus berechnen
Beschreibung
Die Funktion asin() berechnet den Bogensinus (Umkehrfunktion des Sinus) für das überge-
bene Argument.
Parameter
double asin(double zahl);
● zahl. Argument, für das der Arkussinus berechnet wird (muß im Bereich zwi-
schen -1.0 und 1.0 liegen)
● Rückgabewert. Arkussinus des Arguments im Bereich [-p /2, + p /2].
Verwandte Funktionen
acos(), atan(), cos(), sin(), tan()
assert <assert.h>
Diagnosemeldung ausgeben
Beschreibung
Das Makro assert überprüft den Wert eines übergebenen Ausdrucks. Liefert diese Überprüfung
das Ergebnis falsch (0), gibt assert() eine Diagnosemeldung auf den Standardfehler-Stream
stderr aus und ruft anschließend die Funktion abort() auf, um das Programm abzubrechen.
Die Meldung von assert beinhaltet den Dateinamen und die Zeilennummer, in der das Makro
aufgerufen wurde. Die Informationen werden den Konstanten __FILE__ und __LINE__ entnom-
men. Durch Setzen des Schalters NDEBUG (#define NDEBUG) können nachfolgende assert-Auf-
rufe unterdrückt werden.
266
wctype.h
Parameter
void assert(int ausdruck);
● ausdruck. Der zu überprüfende Ausdruck.
Verwandte Funktionen
abort(), exit(), raise(), signal()
Beschreibung
Die Funktion atan() berechnet die Bogentangente einer Zahl. atan2() berechnet die
Bogentangente von zahl1/zahl2.
Parameter
double atan(double zahl);
double atan2(double zahl1, double zahl2);
● Rückgabewert. atan() liefert Arcustangens von zahl im Bereich [-p /2, + p /2],
atan2()liefert Arcustangens von zahl1/zahl2 im Bereich [-p , + p ].
Verwandte Funktionen
acos(), asin(), cos(), sin(), tan()
atexit <stdlib.h>
Funktion bei exit aufrufen
Beschreibung
Mit der Funktion atexit() können Sie eine Funktion registrieren lassen, die beim Program-
mende aufgerufen werden soll. Hiermit kann die Abarbeitung von notwendigen Aufräumarbei-
ten bei Beendigung eines Programms eingerichtet werden.
Die mit atexit() registrierten Funktionen werden aufgerufen, wenn das Programm mit exit()
beendet oder von main() aus die return-Anweisung erfolgt. Wurden mehrere Funktionen durch
aufeinanderfolgende Aufrufe von atexit() registriert, werden sie in der umgekehrten Reihen-
folge ihrer Registrierung aufgerufen.
Parameter
int atexit(void (*func)(void));
● Rückgabewert. Die Funktion atexit() gibt eine Null zurück, wenn die überge-
bene Funktion registriert werden konnte.
267
Die C-Standardbibliothek
Verwandte Funktionen
abort(), exit()
atof <stdlib.h>
Umwandlung: Zeichenkette in double
Beschreibung
Die Funktion atof() (ascii to float) wandelt die Zeichenkette, auf die string zeigt, in eine Gleit-
kommazahl doppelter Genauigkeit um und gibt diese Zahl als Funktionswert zurück. Führende
Leerzeichen und Tabulatoren werden übersprungen, die Umwandlung wird bei dem ersten Zei-
chen, das nicht mehr als Ziffer erkannt wird, abgebrochen.
Parameter
double atof(const char *string);
● Rückgabewert. Korrespondierender double-Wert.
Verwandte Funktionen
atoi(), atol(), strtod()
atoi <stdlib.h>
Umwandlung: String in int
Beschreibung
Die Funktion atoi() (ascii to int) wandelt den übergebenen String in eine Zahl vom Datentyp
int um. Führende Zwischenraumzeichen werden übersprungen, ein eventuell vorhandenes
Vorzeichen jedoch berücksichtigt. Beim ersten nicht als Ziffer identifizierbaren Zeichen wird
die Umwandlung abgebrochen und die bis dahin ermittelte Zahl zurückgegeben.
Parameter
int atoi(const char *string);
● Rückgabewert. Korrespondierender int-Wert oder Null.
Verwandte Funktionen
atof(), atol(), strtod(), strtol()
atol <stdlib.h>
Umwandlung: String in long
268
wctype.h
Beschreibung
Die Funktion atol() (ascii to long) wandelt den übergebenen String in eine Zahl vom Datentyp
long um. Führende Zwischenraumzeichen werden übersprungen, ein eventuell vorhandenes
Vorzeichen jedoch berücksichtigt. Beim ersten nicht als Ziffer identifizierbaren Zeichen wird
die Umwandlung abgebrochen und die ermittelte Zahl zurückgegeben.
Parameter
long atol(const char *string);
● Rückgabewert. Korrespondierender long int -Wert oder Null.
Verwandte Funktionen
atof(), atoi(), strtod(), strtol()
bsearch <stdlib.h>
Binäre Suche
Beschreibung
Mit der Funktion bsearch() kann eine binäre Suche in einem sortierten Datenfeld durchgeführt
werden. Der bei der Suche notwendige Vergleich wird durch eine Funktion durchgeführt, deren
Adresse an bsearch() übergeben wird. Diese Funktion muß zwei Elemente miteinander ver-
gleichen und folgende Werte an bsearch() zurückgeben:
< 0 Das erste Element ist kleiner als das zweite.
0 Beide Elemente sind identisch.
> 0 Das erste Element ist größer als das zweite.
Parameter
void *bsearch (const void *suchobj, const void *basis,
size_t anzahl, size_t breite,
int (*vgl) (const void *elem1, const void *elem2));
● suchobj. Objekt, für das eine Übereinstimmung gesucht wird (Wird als erstes
Argument an vgl() übergeben).
● basis. Zeiger auf Anfang des Feldes, in dem gesucht werden soll.
● anzahl. Anzahl der Elemente in Feld.
● breite. Größe jedes Elements in Bytes.
● vgl. Zeiger auf Funktion, die zwei Elemente vom Typ const void* vergleicht.
● Rückgabewert. Ist die Suche erfolgreich, gibt die Funktion einen Zeiger auf
das erste Elemente in dem Feld zurück, das dem Suchkriterium genügt. Konnte
kein passendes Element gefunden werden, wird ein NULL-Zeiger zurückgege-
ben.
269
Die C-Standardbibliothek
Warnung
Wenn das Feld noch nicht sortiert ist, kann vorher die Funktion qsort() aufgerufen
werden.
Verwandte Funktionen
qsort()
btowc <wchar.h>
1-Byte-Zeichen umwandeln
Beschreibung
Wandelt ein 1-MultiByte-Zeichen in ein Wide Character-Zeichen um.
Parameter
wint_t btowc(int c);
● Rückgabewert. Wide Character-Repräsentation des übergebenen Zeichens.
WEOF, wenn das Zeichen kein gültiges 1-MultiByte-Zeichen im anfänglichen
Konvertierungsstatus oder EOF war.
Verwandte Funktionen
wctob()
calloc <stdlib.h>
Speicher zuordnen
Beschreibung
Mit calloc() kann Speicherplatz für ein Feld von anzahl Elemente der Größe groesse einge-
richtet und mit Nullen initalisiert werden.
Parameter
void *calloc(size_t anzahl, size_t groesse);
● Rückgabewert. Konnte die Speicheranforderung erfüllt werden, gibt die Funk-
tion einen Zeiger auf den allokierten Speicherbereich, anderenfalls einen
NULL-Zeiger zurück.
Verwandte Funktionen
malloc(), realloc()
270
wctype.h
ceil <math.h>
Rundungsfunktion
Beschreibung
Die Funktion ceil() berechnet den kleinstmöglichen ganzzahligen Wert, der größer oder
gleich ihrem double-Argument ist und gibt ihn zurück.
Parameter
double ceil(double zahl);
● Rückgabewert. Aufgerundeter Wert.
Verwandte Funktionen
floor(), fmod()
clearerr <stdio.h>
Fehleranzeige zurücksetzen
Beschreibung
Die Funktion setzt das Fehler- und Dateiende-Flag für einen Stream zurück.
Parameter
void clearerr(FILE *stream);
Verwandte Funktionen
feof(), ferror()
clock <time.h>
Dauer des aufrufenden Prozesses
Beschreibung
Die Funktion gibt die vom aufrufenden Prozeß verbrauchte Prozessorzeit als Wert vom Typ
clock_t zurück. Der Konstanten CLOCKS_PER_SEC entspricht die Anzahl der Ticks pro Sekunde.
Wenn der von clock() zurückgegebene Wert durch die Konstante CLOCKS_PER_SEC geteilt wird,
erhält man die Prozessorzeit in Sekunden.
Parameter
clock_t clock(void);
● Rückgabewert. Liefert die seit einem implementierungsspezifischen Zeitpunkt
vergangene Prozessorzeit. Kann die Anzahl der Ticks nicht ermittelt werden,
wird der Wert -1 zurückgeliefert.
271
Die C-Standardbibliothek
Verwandte Funktionen
difftime(), time()
Beschreibung
Die Funktionen cos() und cosh() berechnen den Kosinus bzw. den Kosinus hyperbolicus des
übergebenen Arguments (Winkel in Bogenmaß) und sind für alle reellen Zahlen definiert.
Parameter
double cos(double zahl);
double cosh(double zahl);
● Rückgabewert. cos() liefert den Kosinus des Arguments im Bereich [-1, 1].
cosh() liefert den Kosinus hyperbolicus des Arguments im Bereich [1, 8].
Warnung
Der Kosinus hyperbolicus steigt sehr schnell an.
Verwandte Funktionen
asin(), atan(), atan2(), sin(), sinh()
Siehe Beispiel zu Header-Datei math.h
ctime <time.h>
Zeit in Zeichenkette
Beschreibung
Die Funktion ctime() wandelt die als Variable vom Typ time_t übergebene Kalenderzeit in eine
Zeichenkette um. Die erzeugte Zeichenkette besitzt das lokal verwendete Format, beispiels-
weise:
Fre Jun 30 [Link] 1988\n\0 // für die C-Lokale
Entspricht dem Aufruf asctime(localtime(ptr_zeit));.
Parameter
char * ctime(const time_t *ptr_zeit);
● Rückgabewert. Zeiger auf die erzeugte Zeichenkette.
Verwandte Funktionen
asctime(), gmtime(), localtime()
272
wctype.h
difftime <time.h>
Differenz zwischen zwei Zeiten
Beschreibung
Die Funktion difftime() ermittelt die Differenz zwischen zwei Zeiten vom Typ time_t und gibt
das Ergebnis in Sekunden zurück.
Parameter
double difftime(time_t neuezeit, time_t altezeit);
● Rückgabewert. Differenz zwischen beiden Zeiten.
Verwandte Funktionen
asctime(), ctime(), localtime(), time()
Siehe Beispiel zu Header-Datei time.h
div <stdlib.h>
Quotient und Rest zweier Ganzzahlen
Beschreibung
Die Funktion div() teilt eine Ganzzahl (zahl1) durch eine zweite (zahl2) und gibt das Ergebnis
als eine Variable vom Strukturtyp div_t zurück.
Parameter
div_t div(int zahl1, int zahl2);
● Rückgabewert. Die Funktion gibt eine Variable vom Typ div_t zurück, in der
Quotient (.quot) und Divisionsrest (.rem) festgehalten sind.
Verwandte Funktionen
ldiv()
exit <stdlib.h>
Prozeß beenden
Beschreibung
Die Funktion exit() beendet ein Programm, nachdem die mit atexit() registrierten Funktio-
nen in der umgekehrten Folge ihrer Registrierung abgearbeitet, der Streampuffer geleert,
offene Dateien geschlossen und mit tmpfile() erzeugte temporäre Dateien entfernt wurden.
Das Argument status spezifiziert einen Statuscode (z. B. die ANSI-C-Konstanten EXIT_FAILURE
oder EXIT_SUCCESS), der an das aufrufende Programm übergeben wird. Unter MS-DOS kann in
Batchdateien dieser Wert mit IF ERRORLEVEL abgefragt werden.
273
Die C-Standardbibliothek
Parameter
void exit(int status);
Verwandte Funktionen
abort(), atexit(), system()
exp <math.h>
Exponential berechnen
Beschreibung
Die Funktion exp() berechnet die Exponentialfunktion ihres Arguments. Sie ist das Gegenstück
der Funktion log().
Parameter
double exp(double zahl);
● Rückgabewert. Die Funktion liefert bei Erfolg den Exponentialwert (e^zahl),
HUGE_VAL bei zu großem Ergebniswert.
Verwandte Funktionen
log(), log10(), pow()
Siehe Beispiel zu Header-Datei math.h
fabs <math.h>
Gleitkomma-Absolutwert berechnen
Beschreibung
Die Funktion fabs() berechnet den Betrag einer Gleitkommazahl und gibt ihn zurück.
Parameter
double fabs(double zahl);
● Rückgabewert. Betrag des Arguments.
Verwandte Funktionen
abs(), ceil(), floor(), fmod(), labs()
fclose <stdio.h>
Stream schließen
274
wctype.h
Beschreibung
Die Funktion schließt den Stream, dessen Zeiger ihr als Argument übergeben wurde. Dabei wird
der mit dem Stream verbundene Puffer geleert, im Puffer befindliche ausgegebene Daten in die
Datei geschrieben, im Puffer befindliche gelesene Daten gelöscht.
Parameter
int fclose(FILE *stream);
● Rückgabewert. Bei Erfolg gibt die Funktion eine Null zurück, sonst EOF.
Verwandte Funktionen
fflush(), setbuf(), setvbuf()
feof <stdio.h>
Stream auf Dateiende prüfen
Beschreibung
Die Funktion feof() prüft, ob das Dateiende-Flag des Streams, dessen Zeiger übergeben
wurde, gesetzt ist.
Parameter
int feof(FILE *stream);
● Rückgabewert. Wenn die gegenwärtige Position das Dateiende ist, wird ein
Wert ungleich Null zurückgegeben, sonst Null.
Verwandte Funktionen
ferror(), perror()
ferror <stdio.h>
Stream auf Fehler prüfen
Beschreibung
Die Funktion ferror() prüft, ob ein Schreib- oder Lesefehler für den Datenstrom stream aufge-
treten ist. Entsprechende Fehler-Flags werden nicht zurückgesetzt (dies kann durch Aufruf von
rewind() oder Schließen des Streams geschehen).
Parameter
int ferror(FILE *stream);
● Rückgabewert. Im Fehlerfall ein Wert ungleich Null, sonst Null.
275
Die C-Standardbibliothek
Verwandte Funktionen
feof(), fopen(), perror(), rewind()
fflush <stdio.h>
Stream entleeren
Beschreibung
Diese Funktion leert den Puffer, der mit dem übergebenen Stream verbunden ist. Handelt es
sich um einen Ausgabe-Stream, werden die gepufferten Daten in die zugehörige Datei
geschrieben. Nach ANSI C ist das Verhalten undefiniert, wenn es sich um einen Eingabe-Stream
handelt. Die meisten Compiler leeren dann den Puffer.
Parameter
int fflush(FILE *stream);
● Rückgabewert. Bei Erfolg wird eine Null zurückgegeben, ansonsten EOF.
Verwandte Funktionen
fclose(), setbuf(), setvbuf()
Beschreibung
Die Funktion liest ein Zeichen aus dem Datenstrom, auf den stream zeigt, und rückt den Datei-
zeiger vor.
Parameter
int fgetc(FILE *stream);
wint_t fgetwc(FILE *stream);
● Rückgabewert. Die Funktion gibt das gelesene Zeichen als int-Wert ohne Vor-
zeichen zurück; EOF (WEOF) kann einen Fehler oder das Ende der Datei bedeu-
ten.
Verwandte Funktionen
gets(), fputc(), ungetc()
fgetpos <stdio.h>
Stream-Positionsangabe holen
276
wctype.h
Beschreibung
Die Funktion fgetpos() kopiert den Wert des Stream-Positionszeigers in die Variable, auf die
pos zeigt. Der Datentyp von pos ist fpos_t, der in der Header-Datei <stdio.h> definiert ist.
Parameter
int fgetpos(FILE *stream, fpos_t *pos);
● Rückgabewert. Im Fehlerfall ein Wert ungleich Null, sonst Null.
Verwandte Funktionen
fsetpos(), ftell()
Beschreibung
Die Funktion liest so lange Zeichen von stream, bis entweder anz-1 Zeichen gelesen wurden,
das Zeichen für Zeilenvorschub (\n) gelesen oder das Dateiende erreicht wurde. Die Funktion
terminiert den eingelesenen String automatisch durch Anhängung des Nullterminierungszei-
chens (\0).
Parameter
char *fgets(char *zkette, int anz, FILE *stream);
wchar_t *fgetws(wchar_t *zkette, int anz, FILE *stream);
● Rückgabewert. Die Funktion gibt, wenn erfolgreich, einen Zeiger auf zkette
zurück, im Fehlerfall oder bei frühzeitigem Dateiende einen NULL-Zeiger.
Verwandte Funktionen
fputs(), gets(), puts()
floor <math.h>
Abrunden
Beschreibung
Die Funktion floor() berechnet den größtmöglichen ganzzahligen Wert, der kleiner/gleich
dem Argument ist, und gibt ihn zurück.
Parameter
double floor(double zahl);
● Rückgabewert. Abgerundeter Wert für zahl.
277
Die C-Standardbibliothek
Verwandte Funktionen
ceil()
fmod <math.h>
Gleitkomma-Rest berechnen
Beschreibung
Die Funktion fmod() teilt x durch y und gibt den Rest der Division zurück.
Parameter
double fmod(double x, double y);
● Rückgabewert. Gleitkommarest der Division.
Verwandte Funktionen
ceil(), fabs(), floor(), modf()
fopen <stdio.h>
Datei öffnen
Beschreibung
Die Funktion fopen() öffnet eine Datei und initialisiert den Stream, der mit der Datei verbun-
den ist. Das Argument modus legt fest, in welchem Modus die Datei geöffnet werden soll.
Modus Beschreibung
r Zum Lesen öffnen.
w Zum Schreiben öffnen (Datei wird überschrieben oder bei Bedarf erzeugt).
a Zum Schreiben an das Dateiende öffnen (Datei wird bei Bedarf erzeugt).
r+ Datei soll zum Lesen und Schreiben geöffnet werden und muß existieren.
w+ Leere Datei soll zum Lesen und Schreiben geöffnet werden (Datei wird
überschrieben oder bei Bedarf erzeugt).
a+ Zum Lesen und Anhängen öffnen (Datei wird bei Bedarf erzeugt).
Parameter
FILE *fopen(const char *datei, const char *modus);
● Rückgabewert. Die Funktion gibt einen Zeiger auf eine Struktur vom Typ FILE
zurück. Dieser Zeiger wird dann an die weiteren Funktionen, die auf dem St-
ream operieren sollen, als Argument übergeben. Konnte die Datei nicht geöff-
net werden, wird ein NULL-Zeiger zurückgegeben.
278
wctype.h
Warnung
Die Modusspezifikation kann durch Anhängen von t oder b jeweils explizit im
Text- oder Binärmodus geöffnet werden (betrifft Codierung des Zeilenumbruchs).
Dateistreams, die zum Lesen und Schreiben geöffnet wurden, müssen fflush() oder
eine Funktion zur Positionierung des Dateizeigers (fseek(), rewind()) ausführen,
bevor zwischen Lesen und Schreiben gewechselt werden kann.
Verwandte Funktionen
fclose(), ferror(), freopen()
Beschreibung
Die Funktion erzeugt aus ihren Argumenten eine Zeichenkette, die in den Datenstrom, auf den
stream zeigt, geschrieben wird. Die Formatierung der Zeichenkette erfolgt wie für printf()
beschrieben.
Parameter
int fprintf(FILE *stream, const char *format...);
int fwprintf(FILE *stream, const wchar_t *format...);
● stream. Zeiger auf FILE-Struktur des Ausgabe-Streams.
● format. Formatzeichenkette (siehe printf()).
● .... Variable Anzahl von Argumenten.
● Rückgabewert. Die Funktion gibt die Anzahl der ausgegebenen Zeichen zu-
rück. Im Fehlerfall wird ein negativer Wert zurückgeliefert (meist EOF (WEOF)).
Verwandte Funktionen
fscanf(), fputs(), fwrite(), printf()
Beschreibung
Die Funktion gibt ein einzelnes Zeichen an einen Stream aus.
Parameter
int fputc(int zeichen, FILE *stream);
wint_t fputwc(wchar_t zeichen, FILE *stream);
279
Die C-Standardbibliothek
● Rückgabewert. Die Funktion gibt das geschriebene Zeichen zurück. Ist der
Rückgabewert EOF (WEOF), ist ein Fehler aufgetreten.
Verwandte Funktionen
fgetc(), fgets(), putc(), ungetc()
Beschreibung
Die Funktion schreibt eine Zeichenkette an einen Stream. Das den String beendende Nulltermi-
nierungszeichen wird nicht mit ausgegeben.
Parameter
int fputs(const char *zkette, FILE *stream);
int fputws(const wchar_t *zkette, FILE *stream);
● Rückgabewert. Die Funktion gibt im Erfolgsfall einen nicht-negativen Wert
zurück. Ist der Rückgabewert EOF (WEOF), ist ein Fehler aufgetreten.
Verwandte Funktionen
fputc(), fprintf(), putc(), putchar(), getc(), gets()
fread <stdio.h>
Daten aus Stream lesen
Beschreibung
Für Binärdateien. Die Funktion fread() liest anzahl Elemente der Größe groesse (in Bytes) aus
einem Stream ein nach puffer. Mit ihr können beispielsweise in der Datei enthaltene Struktu-
ren in ein entsprechendes Feld von Strukturen eingelesen werden.
Parameter
size_t fread (void *puffer, size_t groesse,
size_t anzahl, FILE *stream);
● Rückgabewert. Anzahl der fehlerfrei gelesenen Datenelemente.
Verwandte Funktionen
fopen(), fwrite(), printf(), scanf()
free <stdlib.h>
Speicher freigeben
280
wctype.h
Beschreibung
Die Funktion gibt den Speicherbereich frei, auf den addr verweist und der zuvor mit einer der
Funktionen malloc(), calloc() oder realloc() angefordert wurde.
Parameter
void free(void *addr);
Tip
Der Funktion kann auch ein Zeiger auf Null übergeben werden, in welchem Falle
jedoch kein Code ausgeführt wird.
Verwandte Funktionen
malloc(), calloc(), realloc()
Siehe Praxisteil, Kategorie Zeiger und dynamische Speicherverwaltung, Speicheral-
lokation mit malloc()
freopen <stdio.h>
Dateizeiger neu zuordnen
Beschreibung
Die Funktion schließt die Datei, die mit dem übergebenen Datenstrom stream verbunden ist.
Anschließend wird dem Stream die durch das Argument pfad angegebene Datei mit den ange-
gebenen Zugriffsberechtigungen (siehe fopen()) zugeordnet. Diese Funktion wird üblicher-
weise verwendet, um die Umleitung der Standard-Streams (stdin, stdout, stderr) in Dateien
vorzunehmen.
Parameter
FILE *freopen(const char *pfad, const char *modus, FILE *stream);
● Rückgabewert. Die Funktion gibt bei Erfolg einen Zeiger zur neu geöffneten
Datei zurück, bei Versagen einen NULL-Zeiger.
Verwandte Funktionen
fopen(), fclose()
frexp <math.h>
Gleitkommazahl aufteilen
Beschreibung
Die Funktion frexp() zerlegt eine Gleitkommazahl in eine normalisierte Mantisse und ihren
Exponenten zur Basis 2 auf. Die Mantisse ist größer/gleich 0.5 und kleiner als 1.
281
Die C-Standardbibliothek
Parameter
double frexp(double zahl, int *exp);
● Rückgabewert. Die Funktion gibt die Mantisse zurück. Der Exponent wird in
die Variable geschrieben, auf die *exp zeigt.
Verwandte Funktionen
exp(), ldexp()
Beschreibung
Die Funktion liest Daten formatiert aus dem Datenstrom stream ein. Sie benutzt das Argument
format (siehe scanf()), um die eingelesenen Zeichen in die richtigen Datentypen umzuwan-
deln. Die eingelesenen Daten werden dann an die Speicherstellen geschrieben, die mit den
weiteren Funktionsargumenten übergeben werden. Für jedes weitere Funktionsargument muß
in der Formatzeichenkette ein Typbezeichner angegeben worden sein.
Parameter
int fscanf(FILE *stream, const char *format,...);
int fwscanf(FILE *stream, const wchar_t *format,...);
● stream. Zeiger auf FILE-Struktur des Eingabe-Streams.
● format. Formatzeichenkette (siehe printf()).
● .... Variable Anzahl von Argumenten.
● Rückgabewert. Die Funktion gibt die Anzahl der erfolgreich umgewandelten
und zugewiesenen Felder zurück. Ist der Rückgabewert EOF, wurde versucht,
das Dateiende einzulesen.
Verwandte Funktionen
fprintf(), scanf(), sscanf()
fseek <stdio.h>
Dateizeiger positionieren
Beschreibung
Die Position bewegt den Dateizeiger eines Streams zu einer bestimmten Stelle.
282
wctype.h
Parameter
int fseek(FILE *stream, long offset, int urprung);
● offset. Definiert die Entfernung in Bytes, die der Dateizeiger von der Stelle, die
im Argument ursprung kodiert ist, bewegt werden soll. Für binäre Dateien ist
dies die Anzahl der Zeichen, die der Dateizeiger bewegen soll (kann auch ne-
gativ sein), für Textdateien sollte der Wert Null oder von ftell() zurückgelie-
fert worden sein, wobei Ursprung gleich SEEK_SET sein muß.
● ursprung. Eine von drei Konstanten, die als Bzeug für den offset dienen:
SEEK_CUR Ab der aktuellen Position.
SEEK_END Ab dem Ende der Datei.
SEEK_SET Ab dem Anfang der Datei.
● Rückgabewert. Die Funktion gibt eine Null zurück, wenn der Dateizeiger be-
wegt werden konnte, sonst einen Wert ungleich Null.
Verwandte Funktionen
ftell(), rewind()
fsetpos <stdio.h>
Positionsanzeige bestimmen
Beschreibung
Mit der Funktion fsetpos() können Sie die Positionsanzeige des Streams auf einen Wert
zurücksetzen, wie er beispielsweise bei einem Aufruf der Funktion fgetpos() ermittelt wurde.
Parameter
int fsetpos(FILE *stream, const fpos_t *pos);
● pos. Position, auf die der Positionszeiger gesetzt werden soll (abgespeicherter
Rückgabewert der Funktion fgetpos() ).
● Rückgabewert. Die Funktion gibt im Erfolgsfall eine Null zurück, im Fehler-
fall einen Wert ungleich Null.
Verwandte Funktionen
fseek(), fgetpos()
ftell <stdio.h>
Stream-Zeigerposition ermitteln
283
Die C-Standardbibliothek
Beschreibung
Die Funktion ftell() gibt den aktuellen Wert des Positionszeigers zurück, der mit dem Argu-
ment stream verbunden ist.
Parameter
long ftell(FILE *stream);
● Rückgabewert. Die Funktion gibt die aktuelle Position zurück. Der Rückgabe-
wert unterscheidet sich, je nachdem, ob es sich um eine Binär- oder eine Textda-
tei handelt. Für eine Binärdatei gibt die Funktion die Anzahl der Bytes vom
Dateianfang bis zur aktuellen Position zurück. Für eine Textdatei ist der Wert
nur zur Weitergabe an fseek() geeignet. Im Fehlerfall ist der Rückgabewert -1L.
Verwandte Funktionen
fgetpos(), fseek(), rewind()
fwide <wchar.h>
Stream-Orientierung
Beschreibung
Ermittelt und ändert möglicherweise die Orientierung eines Streams. Ist modus = 0 wird die
Orientierung nicht geändert, ist modus > 0 wird versucht, eine Wide Character-Orientierung
herzustellen, ist modus < 0 wird versucht, eine Byte-Orientierung herzustellen
Parameter
int fwide (FILE *stream, int modus);
● Rückgabewert. Ein Wert > 0 zeigt an, daß der Stream Wide Characterorien-
tiert ist, ein Wert < 0 zeigt an, das der Stream byteorientiert ist.
Verwandte Funktionen
fgetwc(), fgetws(), fwscanf(), getwc(), fputwc(), wscanf(), fwprintf(), fputwc(),
fputws(), putwc(), wprintf()
fwrite <stdio.h>
In einen Stream schreiben
Beschreibung
Für Binärdateien. Die Funktion fwrite() schreibt anzahl Datenelemente der Größe groesse (in
Bytes) aus dem Speicherbereich, auf den puffer verweist, in den Datenstrom stream. Nach dem
Schreibvorgang wird der Stream-Positionszeiger auf den neuen Stand gebracht.
284
wctype.h
Parameter
size_t fwrite (const void *puffer, size_t groesse,
size_t anzahl, FILE *stream);
● Rückgabewert. Anzahl der tatsächlich geschriebenen Datenelemente.
Verwandte Funktionen
fread(), write()
Beschreibung
Die Funktionen getc() und getwc() lesen ein Zeichen aus einem Stream ein, getchar() und
getwchar() lesen ein Zeichen aus dem Stream stdin. Das Makro getchar() entspricht dem Auf-
ruf getc(stdin), das Makro getwchar() dem Aufruf getwc(stdin).
Parameter
int getc(FILE *stream);
wint_t getwc(FILE *stream);
int getchar(void);
wint_t getwchar(void);
● Rückgabewert. Die Funktionen geben das eingelesene Zeichen zurück; EOF
(WEOF) wird beim Erreichen des Dateiendes oder bei Auftreten eines Fehlers zu-
rückgeliefert.
Verwandte Funktionen
fgetc(), putc(), putchar(), ungetc()
getenv <stdlib.h>
Wert aus Umgebung holen
Beschreibung
Die Funktion getenv() untersucht die betriebssystemspezifische Umgebung eines Programms.
Sie sucht nach einem Eintrag, der mit dem Argument varname identisch ist, und gibt bei Erfolg
einen Zeiger auf die entsprechende Umgebungsvariable zurück.
Parameter
char *getenv(const char *varname);
● varname. Umgebungsvariable, nach der gesucht wird.
● Rückgabewert. Liefert einen Zeiger auf die Definition der Umgebungsvaria-
blen zurück, oder einen NULL-Zeiger, wenn die Variable nicht definiert ist.
285
Die C-Standardbibliothek
Verwandte Funktionen
setlocale(), localeconv()
gets <stdio.h>
Zeile von stdin lesen
Beschreibung
Die Funktion gets() liest eine Zeichenkette vom Standardeingabe-Stream und speichert sie an
der mit str übergebenen Adresse. Das Einlesen wird beendet, wenn die Funktion das Zeichen
für Zeilenvorschub oder EOF entdeckt. Das Zeichen für Zeilenvorschub wird entfernt und durch
das Nullterminierungszeichen (\0) ersetzt, mit dem das Ende des Strings markiert wird.
Parameter
char *gets(char *str);
● Rückgabewert. Zeiger auf eingelesenen String; im Fehlerfall ein NULL-Zeiger.
Warnung
Beachten Sie, daß der Speicherbereich, auf den str zeigt, groß genug sein muß, um
den String aufzunehmen, da die Funktion ansonsten den Speicher überschreibt.
Verwandte Funktionen
fgets(), fputs(), puts()
gmtime <time.h>
Zeitwert in Struktur umwandeln
Beschreibung
Die Funktion gmtime() erwartet als Argument die Adresse einer Variablen vom Typ time_t. Die
in dieser Variablen gespeicherte Kalenderzeit (meist erhalten durch einen Aufruf der Funktion
time()), wird von der Funktion in Greenwich Mean Time (auch UTC genannt) umgewandelt und
in der Struktur tm abgelegt.
Parameter
struct tm *gmtime(const time_t *zeit);
● Rückgabewert. Die Funktion gibt einen Zeiger auf eine Struktur vom Typ tm
zurück, in der Datum und Zeit abgelegt sind. Im Fehlerfall gibt die Funktion
einen NULL-Zeiger zurück.
Verwandte Funktionen
asctime(), ctime(), localtime(), time()
286
wctype.h
Beschreibung
Die Funktionen aus der is...()-Gruppe überprüfen die Zugehörigkeit eines Zeichens zu
bestimmten Zeichengruppen. Die entsprechenden isw..()-Funktionen stellen die gleiche
Funktionalität für Wide Character-Zeichen zur Verfügung.
Name Testet auf
isalnum // Buchstaben und Ziffern (isalpha || isdigit)
isalpha // Buchstaben (A-Z, a-z) (isupper || islower)
iscntrl // Steuerzeichen (0x00-0x1f oder 0x7F).
isdigit // Ziffer (0-9).
isgraph // Ausgebbares Zeichen (0x21-0x7E) (isprint ohne isspace)
islower // Kleinbuchstabe (a-z).
isprint // Druckbares Zeichen (0x20-0x7E).
ispunct // Interpunktionszeichen (isprint ohne isspace und isalnum)
isspace // Whitespace-Zeichen (' ', '\f', '\n', '\r', '\t', '\v').
isupper // Großbuchstabe (A-Z).
isxdigit // Hexadezimalzahl (A-F, a-f, 0-9).
Parameter
int is...(int zeichen);
int isw...(wint_t widezeichen);
● Rückgabewert. Die Funktionen geben einen Wert ungleich Null (true) zurück,
wenn das übergebene Zeichen zu der von der Funktion überprüften Klasse von
Zeichen gehört.
Verwandte Funktionen
localeconv(), setlocale()
iswctype <wctype.h>
Wide Character-Klasse feststellen
Beschreibung
Testet, ob ein Zeichen einer bestimmten Klasse angehört. Die Klasse wird durch einen Aufruf
von wctype spezifiziert:
iswctype(wc, wctype("digit")) // = iswcdigit(wc)
Parameter
int iswctype(wint_t wc, wctype_t beschreibung);
● Rückgabewert. Liefert einen Wert ungleich Null, wenn das Wide Character-
Zeichen wc die beschriebene Eigenschaft hat.
287
Die C-Standardbibliothek
Verwandte Funktionen
wctype()
labs <stdlib.h>
Absolutwert einer long-Zahl bestimmen
Beschreibung
Die Funktion ermittelt den Betrag einer long-Ganzzahl und gibt ihn zurück. Der Betrag einer
Zahl ist ihr Abstand zu Null.
Parameter
long int labs(long int zahl);
● Rückgabewert. Betrag des Arguments.
Verwandte Funktionen
abs(), fabs()
ldexp <math.h>
Exponential berechnen
Beschreibung
ldexp berechnet den Wert von zahl*2^exp.
Parameter
double ldexp(double zahl, int exp);
● Rückgabewert. Liefert den Wert von zahl*2^exp; HUGE_VAL bei Überlauf.
Verwandte Funktionen
log(), log10(), pow()
ldiv <stdlib.h>
Quotient und Rest zweier long-Zahlen
Beschreibung
Die Funktion ldiv() teilt eine long-Ganzzahl durch eine andere und gibt das Ergebnis in Form
einer Struktur vom Typ ldiv_t zurück:
Parameter
ldiv_t ldiv(long int zahl1, long int zahl2);
288
wctype.h
● Rückgabewert. Die Funktion gibt eine Struktur vom Typ ldiv_t zurück, in der
sich der Quotient (.quot) und der Divisionsrest (.rem) befinden.
Verwandte Funktionen
div()
localeconv <locale.h>
Lokale Einstellung numerischer Formate
Beschreibung
Über die Funktion localeconv() können lokale Einstellungen zur Formatierung numerischer
Werte, insbesondere der Darstellung von Währungsangaben, abgefragt werden. Die Einstellun-
gen werden in einer lconv-Struktur abgelegt.
Parameter
struct lconv *localeconv(void);
● Rückgabewert. Zeiger auf die gefüllte Struktur lconv.
Verwandte Funktionen
setlocale()
Siehe Beispiel zu Header-Datei locale.h
localtime <time.h>
Uhrzeit auf Ortszeit einstellen
Beschreibung
Die Funktion wandelt die Kalenderzeit zeit in eine Struktur vom Typ tm um. Hierbei wird, im
Gegensatz zu der Funktion gmtime(), die Ortszeit berücksichtigt.
Parameter
struct tm *localtime(const time_t *zeit);
● Rückgabewert. Zeiger auf eine Struktur vom Typ tm oder einen NULL-Zeiger,
falls zeit nicht interpretiert werden konnte.
Verwandte Funktionen
asctime(), gmtime(), time()
289
Die C-Standardbibliothek
Beschreibung
Die Funktion log() berechnet den natürlichen Logarithmus ihres Arguments zur Basis e,
log10() den Logarithmus ihres Arguments zur Basis 10.
Parameter
double log(double x);
double log10(double x);
● Rückgabewert. Die Funktionen geben den jeweiligen Logarithmus von x zu-
rück. Da der Logarithmus nur für positive Werte größer Null definiert ist,
wird bei Werten von x < 0 EDOM in errno geschrieben; bei 0 als Argument wird
HUGE_VAL zurückgeliefert.
Verwandte Funktionen
exp(), pow()
Siehe Beispiel zu Header-Datei math.h
longjmp <setjmp.h>
Programmzustand wiederherstellen
Beschreibung
Mit der Funktion longjmp() wird die Umgebung wiederhergestellt, die beim Aufruf von set-
jmp() im Array umg gespeichert wurde. Die Ausführung wird danach nicht an der Stelle fortge-
führt, an der longjmp() aufgerufen wird, sondern dort, wo setjmp() aufgerufen wurde.
Parameter
void longjmp(jmp_buf umg, int wert);
Warnung
Die Funktion, in der der vorangehende Aufruf von setjmp() erfolgte, muß zum
Zeitpunkt des Sprungs durch longjmp() aktiv, d. h. auf dem Stack abgelegt sein.
Verwandte Funktionen
setjmp()
Siehe Beispiel zu Header-Datei setjmp.h
malloc <stdlib.h>
Speicherblock anfordern
290
wctype.h
Beschreibung
Die Funktion malloc() fordert einen Speicherblock von der übergebenen Größe an. Der von der
Funktion zurückgegebene Zeiger ist vom Typ *void und muß explizit in den gewünschten Typ
umgewandelt werden.
Parameter
void *malloc(size_t groesse);
● Rückgabewert. void-Zeiger auf den allokierten Speicherbereich oder NULL-
Zeiger, wenn Speicher nicht allokiert werden konnte.
Verwandte Funktionen
calloc(), free(), realloc()
Beschreibung
Die Funktion mblen() ermittelt die Länge eines Multibyte-Zeichens. Die Funktion mbrlen()
ermittelt, nach wieviel Byte das Multibyte-Zeichen vollständig ist. Es werden maximal n Bytes
geprüft.
Parameter
int mblen(const char *mb, size_t n);
size_t mbrlen(const char *mb, size_t n, mbstate_t *ps);
● Rückgabewert. Die Funktion mblen() liefert die Anzahl der Bytes des Multiby-
te-Zeichens mb zurück. Handelt es sich um kein gültiges Multibyte-Zeichen,
wird ein negativer Wert zurückgegeben. Die Funktion mbrlen() liefert die An-
zahl der Bytes bis zum Abschluß des Multibyte-Zeichens mb zurück. Handelt es
sich um kein gültiges Multibyte-Zeichen oder tritt ein Fehler auf, wird ein ne-
gativer Wert zurückgegeben.
Verwandte Funktionen
mbstowcs(), mbtowc(), mbrtowc()
mbsinit <wchar.h>
Konvertierungsstatus abfragen
Beschreibung
Ermittelt, ob das mbstate_t-Objekt, auf das der Parameter verweist, einen anfänglichen Kon-
vertierungsstatus beschreibt.
291
Die C-Standardbibliothek
Parameter
int mbsinit(const mbstate_t *ps);
● Rückgabewert. Ein Wert ungleich Null zeigt an, daß ein NULL-Zeiger oder
ein Zeiger auf einen anfänglichen Konvertierungsstatus übergeben wurde; an-
sonsten wird Null zurückgeliefert.
Verwandte Funktionen
mbstowcs()
mbstowcs,mbsrtowcs <stdlib.h><wchar.h>
Konvertiert Multibyte-String
Beschreibung
Die Funktion mbstowcs() konvertiert den übergebenen Multibyte-String mb_string, der im
anfänglichen Shift-Status beginnt (der Zustand, in dem die Zeichen aus dem C-Zeichensatz 1:1
codiert sind), in ein Feld von Elementen des Typs wchar_t. Die Funktion mbsrtowcs() konver-
tiert einen Multibyte-String, der im durch ps gegebenen Konvertierungsmodus ist. Es werden
maximal n Wide Character-Zeichen eingelesen.
Parameter
size_t mbstowcs(wchar_t *wc, const char *mb_str, size_t n);
size_t mbsrtowcs(wchar_t *wc,const char *mb_str,size_t n,mbstate_t *ps);
● Rückgabewert. Liefert die Anzahl der umgewandelten Elemente zurück (ohne
mögliches Nullterminierungszeichen (\0)). Treten ungültige Multibyte-Sequen-
zen auf, wird ein negativer Wert zurückgegeben.
Verwandte Funktionen
mbstowcs(), mbtowc(), mbrtowc()
mbtowc,mbrtowc <stdlib.h><wchar.h>
Konvertiert Multibyte-Zeichen zu wchar_t
Beschreibung
Beide Funktionen konvertieren das übergebene Multibyte-Zeichen mb_char in eine Wide Cha-
racter-Repräsentation und speichern das Ergebnis in wc. Die Funktion mbtowc() bestimmt dabei
die Anzahl der Bytes in dem Multibyte-Zeichen, die Funktion mbrtowc() ermittelt, nach wieviel
Byte das Multibyte-Zeichen vollständig ist. Es werden maximal n Bytes konvertiert.
Parameter
int mbtowc(wchar_t *wc, const char *mb_char, size_t n);
size_t mbrtowc(wchar_t *wc,const char *mb, size_t n, mbstate_t *ps);
292
wctype.h
● Rückgabewert. Die Funktion mbtowc() liefert die Anzahl der Bytes des Multi-
byte-Zeichens mb zurück. Handelt es sich um kein gültiges Multibyte-Zeichen,
wird ein negativer Wert zurückgegeben. Die Funktion mbrtowc() liefert die An-
zahl der Bytes bis zum Abschluß des Multibyte-Zeichens mb zurück. Handelt es
sich um kein gültiges Multibyte-Zeichen oder tritt ein Fehler auf, wird ein ne-
gativer Wert zurückgegeben.
Verwandte Funktionen
mbstowcs(), mblen(), mbrtowc()
Beschreibung
Die Funktion untersucht einen Speicherbereich daraufhin, ob das übergebene Zeichen vor-
kommt. Die Suche schreitet so lange voran, bis entweder das Zeichen gefunden oder anzahl
Zeichen untersucht worden sind.
Parameter
C:
void *memchr(const void *puffer, int zeichen, size_t anzahl);
wchar_t *wmemchr(const wchar_t *puffer, wchar_t zeichen, size_t anzahl);
C++:
const void *memchr(const void *puffer, int zeichen, size_t anzahl);
const wchar_t *wmemchr(const wchar_t *puffer, wchar_t zeichen,
size_t anzahl);
void *memchr(void *puffer, int zeichen, size_t anzahl);
wchar_t *wmemchr(wchar_t *puffer, wchar_t zeichen, size_t anzahl);
● puffer. Anfangsadresse des zu durchsuchenden Speicherbereichs.
● zeichen. Das zu suchende Zeichen.
● anzahl. Maximal zu überprüfende Zeichen.
● Rückgabewert. Zeiger auf das gefundene Zeichen oder NULL-Zeiger.
Verwandte Funktionen
memcmp(), memset(), memcpy()
293
Die C-Standardbibliothek
Beschreibung
Die Funktion vergleicht zeichenweise den Inhalt von puf1 mit dem von puf2. Der Vergleich wird
so lange durchgeführt, bis entweder ein Unterschied entdeckt oder die mit anzahl übergebene
Zeichenzahl überprüft wurde.
Parameter
int memcmp(const void *puf1, const void *puf2, size_t anzahl);
int wmemcmp(const wchar_t *puf1, const wchar_t *puf2, size_t anzahl);
● Rückgabewert. Die Funktion hat drei mögliche Rückgabewerte:
Verwandte Funktionen
strcmp(), strncmp()
Beschreibung
Die Funktion kopiert Zeichen von einem Speicherbereich in einen anderen. Es werden anzahl
Zeichen kopiert. (Beide Speicherbereiche dürfen sich nicht überlappen.)
Parameter
void *memcpy(void *ziel, const void *quelle, size_t anzahl);
wchar_t *wmemcpy(wchar_t *ziel, const wchar_t *quelle, size_t anzahl);
● Rückgabewert. Zeiger auf ziel.
Verwandte Funktionen
memchr(), memmove(), memset()
Beschreibung
Diese Funktion kopiert den Inhalt eines Speicherbereichs in einen anderen (beide Speicherbe-
reiche dürfen sich überlappen). Es wird die als Argument übergebene Anzahl von Bytes kopiert.
294
wctype.h
Parameter
void *memmove(void *ziel, const void *quelle, size_t anzahl);
wchar_t *wmemmove(wchar_t *ziel, const wchar_t *, size_t anzahl);
● Rückgabewert. Zeiger auf ziel.
Verwandte Funktionen
memchr(), memchr(), memset()
Beschreibung
Die Funktion initialisiert einen Speicherbereich mit einem bestimmten Zeichen. Die Anzahl der
zu initialisierenden Speichereinheiten wird über das Argument anzahl festgelegt.
void *memset(void *puffer, int zeichen, size_t anzahl);
wchar_t *wmemset(wchar_t *puffer, int zeichen, size_t anzahl);
● Rückgabewert. Zeiger auf puffer.
Verwandte Funktionen
memchr(), memcmp(), memmove()
mktime <time.h>
Konvertiert Zeit von tm zu time_t
Beschreibung
Die Funktion mktime() konvertiert eine Zeitangabe, wie sie in der Struktur tm abgelegt ist, in
den Typ time_t.
Parameter
time_t mktime(struct tm *zeit);
● Rückgabewert. Die Funktion liefert die konvertierte Zeitangabe vom Typ
time_t zurück. Konnte die Zeitangabe nicht konvertiert werden, wird -1 zu-
rückgegeben.
Verwandte Funktionen
time(), gmtime(), localtime()
modf <math.h>
Gleitkommawert aufteilen
295
Die C-Standardbibliothek
Beschreibung
Die Funktion modf() teilt eine Gleitkommazahl wert in einen ganzzahligen Vorkomma-Anteil
und einen Nachkomma-Anteil auf.
Parameter
double modf(double wert, double *p_int);
● Rückgabewert. Der Nachkomma-Anteil wird zurückgegeben. Der Ganzzahlteil
wird an der Stelle gespeichert, auf die p_int zeigt.
Verwandte Funktionen
fmod(), frexp(), ldexp()
perror <stdio.h>
Fehlermeldung ausgeben
Beschreibung
Die Funktion perror() erzeugt eine Fehlermeldung, in dem sie den übergebenen String und die
Fehlermeldung, die dem derzeitigen Wert der Variablen errno entspricht, zusammenfügt und
dann an den Datenstream stderr ausgibt.
Parameter
void perror(const char *zkette);
Verwandte Funktionen
ferror(), clearerror(), strerror()
pow <math.h>
Potenz ermitteln
Beschreibung
Die Funktion berechnet x ^ y.
Parameter
double pow(double x, double y);
double pow(double x, int y);
● Rückgabewert. Bei erfolgreicher Ausführung liefert die Funktion die Potenz
von x hoch y zurück. Ist x < 0 und y keine ganzzahlige Zahl wird EDOM in errno
gschrieben; bei zu großem Ergebniswert wird HUGE_VAL zurückgeliefert
296
wctype.h
Verwandte Funktionen
sqrt()
Beschreibung
Die Funktion gibt formatierte Daten an den Datenstream stdout aus. Zur Ausgabe wird eine
Formatzeichenkette untersucht. Normaler Text und Escape-Sequenzen in diesem String werden
einfach ausgegeben.
Findet printf() (wprintf()) in der Formatzeichenkette das Zeichen % mit einem
gültigen Formattyp und optionalen zusätzlichen Angaben, wird das zugehörige
wahlfreie Argument von printf() (wprintf()) in den angegebenen Typ umgewandelt
und in die Zeichenkette eingefügt.
Das allgemeine Format für die Typangabe sieht folgendermaßen aus:
% [Flag] [Breite] [Genauigkeit] [Typvorsatz] Formattyp
Die einzelnen Elemente der Typangabe und ihre Wirkung:
Formattyp Datentyp
c // Einzelnes Zeichen.
s // Nullzeichenterminierte Zeichenkette.
// Für wprintf() wird im Falle des Typvorsatzes l (siehe
// unten) die Wide Character-Zeichenkette in
// Multibyte-Zeichen umgewandelt.
d, i // Dezimale Ganzzahl.
u // Dezimale Ganzzahl ohne Vorzeichen.
o // Oktale Ganzzahl ohne Vorzeichen.
x // Hexadezimale Ganzzahl, ohne Vorzeichen und ohne Präfix
// (0x), Ausgabe mit Kleinbuchstaben.
X // Hexadezimale Ganzzahl, ohne Vorzeichen und ohne Präfix
// (0X), Ausgabe mit Großbuchstaben.
f // Gleitkommazahl, dezimale Schreibweise.
e,E // Gleitkommazahl, Exponential-Schreibweise:
// [-][Link]±xx bzw. [-][Link]±xx
g,G // Gleitkommazahl, die kürzeste Darstellung wird gewählt
// (f oder e).
p // Ausgabe als Zeiger.
n // Gibt die Anzahl der bis dahin ausgegebenen Zeichen aus.
% // Keine Konvertierung, das Zeichen % wird ausgegeben.
Folgende Zeichen können Sie als Flag verwenden, um das Formatelement zu erwei-
tern:
Flags Wirkung
- // Die Ausgabe erfolgt linksbündig. Wenn dieses Zeichen nicht
// angegeben wird, erfolgt die Ausgabe automatisch
// rechtsbündig, d.h., es werden Leerzeichen vorangestellt.
297
Die C-Standardbibliothek
298
wctype.h
Vor dem Formattyp können verschiedene Typvorsätze stehen, die Angaben über
die Größe des Parameters machen.
Typvorsatz Bedeutung
h // Wenn als Formattyp d, i, o, x oder X angegeben wird, ist
// der Parameter vom Typ short int. Beim Formattyp u wird
// mit dem Typvorsatz h eine Variable vom Typ short unsigned
// int erwartet.
l // Bei den Formattypen d, i, o, x oder X wird ein Parameter
// vom Typ long int, bei u vom Typ long unsigned int
// erwartet.
// Bei den Formattypen e, E, f, g, und G wird eine Variable
// des Typs double anstelle von float erwartet.
// Für wprintf() wird für einen c-Parameter ein
// wint_t- statt eines int-Arguments und für einen
// s-Parameter ein wchar_t-Zeiger statt eines char-Zeigers
// erwartet. Zudem wird die automatische Konvertierung von
// Wide Character in Multibyte eingeschaltet.
L // Bei den Formattypen e, E, f, g, und G wird eine Variable
// des Typs long double erwartet.
// Für wprintf() wird für einen s-Parameter ein
// wchar_t-Zeiger statt eines char-Zeigers als Argument
// erwartet.
Die nachstehenden Escape-Sequenzen werden von der Funktion printf() (wprintf())
wie folgt umgewandelt:
Sequenz Wirkung
\a // Signalton.
\v // Vertikaltabulator.
\b // Rückschritt.
\' // Apostroph.
\f // Seitenvorschub.
\" // Anführungszeichen.
\n // Neue Zeile.
\\ // Schrägstrich links.
\r // Wagenrücklauf.
\ddd // ASCII-Zeichen in Oktal-Schreibweise.
\t // Horizontaltabulator.
\xdd // ASCII-Zeichen in Hexadezimal-Schreibweise.
Parameter
int printf(const char *format,...);
int wprintf(const wchar_t *format,...);
● Rückgabewert. Anzahl der ausgegebenen Zeichen.
Verwandte Funktionen
sprintf(), vsprintf()
Siehe Praxisteil, Kategorie Ein- und Ausgabe, Formatierte Ein- und Ausgabe in C
299
Die C-Standardbibliothek
Beschreibung
Die Funktion schreibt ein einzelnes Zeichen in einen Stream.
Parameter
int putc(int zeichen, FILE *stream);
wint_t putwc(wchar_t zeichen, FILE *stream);
● Rückgabewert. Die Funktion gibt das geschriebene Zeichen zurück. Der Rück-
gabewert EOF (WEOF) deutet auf einen Fehler oder das Ende der Datei hin.
Verwandte Funktionen
putchar(), printf(), puts()
Beschreibung
Die Funktion schreibt ein einzelnes Zeichen an den Datenstream stdout. Es entspricht somit
dem Aufruf von putc(zeichen,stdout), bzw. putwc(zeichen,stdout).
Parameter
int putchar(int zeichen);
wint_t putwchar(wchar_t zeichen);
● Rückgabewert. Die Funktion gibt das ausgegebene Zeichen zurück. Im Fehler-
fall ist der Rückgabewert EOF (WEOF).
Verwandte Funktionen
putc(), printf(), puts()
puts <stdio.h>
Zeichenkette an stdout schreiben
Beschreibung
Die Funktion puts() schreibt eine Zeichenkette an den Datenstream stdout. Das Nullterminie-
rungszeichen (\0) des Strings wird durch das Zeilenvorschubzeichen (\n) ersetzt.
Parameter
int puts(const char *zkette);
300
wctype.h
Verwandte Funktionen
fputs(), gets()
qsort <stdlib.h>
Quicksort ausführen
Beschreibung
Mit der Funktion qsort() kann ein Datenfeld sortiert werden. Die Funktion verwendet dazu den
QuickSort-Algorithmus. Der beim Sortieren notwendige Vergleich wird durch eine Funktion
durchgeführt, deren Adresse an qsort() übergeben wird. Diese Funktion muß zwei Elemente
miteinander vergleichen und folgende Werte an qsort() zurückgeben:
negativ Das erste Element ist kleiner als das zweite.
Null Beide Elemente sind identisch.
positiv Das erste Element ist größer als das zweite.
Parameter
void qsort (void *basis, size_t anzahl, size_t laenge,
int (*vgl)(const void *elem1, const void *elem2));
● basis. Zeiger auf Anfang des Arrays.
● anzahl. Anzahl der Array-Elemente.
● laenge. Größe jedes Elementes in Bytes.
● vgl. Zeiger auf Funktion, die zwei Elemente vom Typ const void* vergleicht.
Verwandte Funktionen
bsearch()
raise <signal.h>
Signal an ausführendes Programm
Beschreibung
Die Funktion raise() sendet ein Signal an das aufrufende Programm. Über die Funktion
signal() ist es möglich, eigene Routinen einzurichten, die nach der Auslösung eines Signals
aufgerufen werden. Für das zu erzeugende Signal (und somit für das Argument sig) können die
symbolischen Konstanten SIG... (siehe Header signal.h) verwendet werden.
Parameter
int raise(int sig);
301
Die C-Standardbibliothek
Verwandte Funktionen
abort(), signal()
rand <stdlib.h>
Pseudo-Zufallszahl generieren
Beschreibung
Die Funktion rand() erzeugt eine Pseudo-Zufallszahl. Die erzeugte Zahl liegt im Bereich von 0
bis RAND_MAX. Die Funktion generiert immer die gleiche Folge von Zufallszahlen, es sei denn,
Sie ändern den Anfangswert mit der Funktion srand(). Der Aufruf von rand() ohne den vorhe-
rigen Aufruf von srand() hat die gleiche Wirkung, wie wenn vorher srand() mit dem Argument
1 aufgerufen worden ist.
Parameter
int rand(void);
● Rückgabewert. Erzeugte Pseudo-Zufallszahl.
Verwandte Funktionen
srand()
realloc <stdlib.h>
Speicherblock neu zuordnen
Beschreibung
Mit der Funktion realloc() kann die Größe eines zuvor mit malloc() oder calloc() angefor-
derten Speicherblocks angepaßt werden. Der Inhalt des alten Speicherblocks bleibt dabei
erhalten, seine Adresse kann sich jedoch ändern.
Parameter
void *realloc(void *puffer, size_t groesse);
● puffer. Zeiger auf den zu vergrößernden oder verkleinernden Speicherblock.
● groesse. Neue Größe für den Speicherblock.
● Rückgabewert. Die Funktion gibt einen Zeiger zum neu zugeordneten Spei-
cherblock zurück oder einen NULL-Zeiger, wenn der Speicher nicht eingerich-
tet werden konnte.
Verwandte Funktionen
calloc(), free(), malloc()
302
wctype.h
remove <stdio.h>
Datei löschen
Beschreibung
Die Funktion remove() löscht die Datei (sofern Schreibrecht besteht), deren Name ihr überge-
ben wurde. Die Datei sollte dazu geschlossen sein.
Parameter
int remove(const char *dateiname);
● Rückgabewert. Die Funktion gibt eine Null zurück, wenn die Datei gelöscht
wurde, sonst einen Wert ungleich 0.
Verwandte Funktionen
rename(), tmpfile(), tmpnam()
rename <stdio.h>
Datei umbenennen
Beschreibung
Die Funktion rename() ändert einen Dateinamen von altname in neuname. Beide Argumente
müssen einen gültigen Pfadnamen beinhalten.
Parameter
int rename(const char *altname, const char *neuname);
● Rückgabewert. Die Funktion gibt eine Null zurück, wenn die Datei umbe-
nannt werden konnte, sonst einen Wert ungleich 0.
Verwandte Funktionen
remove(), tmpfile(), tmpnam()
rewind <stdio.h>
Streampositionszeiger zum Anfang
Beschreibung
Die Funktion rewind() setzt die Dateipositionsanzeige auf den Anfang der Datei und löscht
eventuell gesetzte Fehlerflags. Die Funktion entspricht damit den Aufrufen:
fseek(stream, 0L, SEEK_SET);
clearerr(stream);
Parameter
void rewind(FILE *stream);
303
Die C-Standardbibliothek
Verwandte Funktionen
fseek(), ftell()
Beschreibung
Die Funktion liest formatierte Daten vom Datenstream stdin. Sie benutzt das Argument format,
um die eingelesenen Zeichen in die richtigen Datentypen umzuwandeln. Die eingelesenen
Daten werden dann an die Speicherstellen geschrieben, die mit den weiteren Funktionsargu-
menten übergeben werden. Für jedes weitere Funktionsargument muß in der Formatzeichen-
kette ein Typbezeichner angegeben worden sein.
Typbezeichner besitzen folgendes allgemeine Format, wobei die Angaben in eckigen
Klammern optional sind:
%[*][Breite][Größe]Typ
● %: Markiert den Anfang eines Typbezeichners. Das Prozentzeichen und der
Typ sind die Elemente, aus denen jeder Typbezeichner mindestens zusammen-
gesetzt sein muß.
● *: Steht nach dem Prozentzeichen ein Stern (*), wird die Zuweisung des näch-
sten Eingabefeldes unterdrückt.
● Breite: Die Breite ist eine positive Dezimal-Ganzzahl, mit der die maximal zu
lesenden Zeichen angegeben werden.
● Größe: Dieses Feld im Typbezeichner kann verwendet werden, um die Größe
der Variablen anzugeben.
● Typ:
Formattyp Datentyp
c // Einzelnes Zeichen.
s // Zeichenkette.
// Ist der Typvorsatz l gesetzt (siehe oben), werden
// eingelesene Multibyte-Zeichenfolge in Wide Characters
// umgewandelt.
d // Dezimale Ganzzahl.
i // Dezimale, oktale (0) oder hexadezimale (0x, 0X) Ganzzahl.
u // Dezimale Ganzzahl ohne Vorzeichen.
o // Oktale Ganzzahl ohne Vorzeichen.
x // Hexadezimale Ganzzahl, ohne Vorzeichen und ohne Präfix
// (0x), Ausgabe der Kleinbuchstaben.
f // Gleitkommazahl, dezimale Schreibweise.
e,E // Gleitkommazahl, Exponential-Schreibweise:
// [-][Link]±xx bzw. [-][Link]±xx
g,G // Gleitkommazahl, die kürzeste Darstellung wird gewählt
// (f oder e).
p // Zeiger.
304
wctype.h
Parameter
int scanf(const char *format, ...);
int wscanf(const wchar_t *format, ...);
● Rückgabewert. Die Funktion gibt die Anzahl der umgewandelten und eingele-
senen Felder zurück (kann auch 0 sein) oder EOF (WEOF), wenn versucht wurde,
das Ende der Zeichenkette zu lesen, oder ein Fehler aufgetreten ist.
Verwandte Funktionen
fscanf(), printf(), sscanf(), vsprintf()
setbuf <stdio.h>
Stream-Puffer
Beschreibung
Mit der Funktion setbuf() kann für die Zwischenspeicherung eines Streams ein eigener Puffer
eingerichtet werden, der den automatisch zugeordneten Puffer ersetzt. Dazu muß das Funkti-
305
Die C-Standardbibliothek
onsargument puffer auf einen Speicherbereich zeigen, der mindestens BUFSIZ Bytes groß ist. Ist
das Argument ein NULL-Zeiger, wird keine Zwischenspeicherung durchgeführt.
Parameter
void setbuf(FILE *stream, char *puffer);
Verwandte Funktionen
setvbuf()
setjmp <setjmp.h>
Programmstatus speichern
Beschreibung
Die Funktion setjmp() dient zur Vorbereitung eines nicht lokalen Sprungs (aus einer Funktion
heraus). Alle wichtigen Informationen zum späteren Rücksprung an die aktuelle Stelle werden
in den Puffer umg gespeichet.
Parameter
int setjmp(jmp_buf umg);
● Rückgabewert. Nach dem Sichern der Umgebung ist der Rückgabewert 0.
Nach einem späteren longjmp()-Aufruf liefert die Funktion einen Wert ungleich
0, um eine Endlosschleife zu vermeiden:
Verwandte Funktionen
longjmp()
Siehe Beispiel zu Header-Datei setjmp.h
setlocale <locale.h>
Ändern einer Locale-Einstellung
Beschreibung
Mit dieser Funktion kann die lokale Einstellung zu dem verwendeten Zeichensatz, den Wäh-
rungsangaben, etc. abgefragt oder gewechselt werden. Dem ersten Parameter können die LC...-
Konstanten (siehe Header-Datei locale.h) übergeben werden, um auszuwählen, welche Kate-
gorien von den Änderungen betroffen sein sollen. Der zweite Parameter zeigt auf den Namen
der lokalen Einstellung, die für die angegebenen Kategorien eingerichtet werden soll (bei-
spielsweise "C" für die minimale Umgebung oder "" für die Systemumgebung).
Wird an den Parameter lokale ein NULL-Zeiger übergeben, wird ein String für die
Kategorie der aktuellen lokalen Einstellungen zurückgeliefert.
306
wctype.h
Parameter
char *setlocale(int kategorie, char *lokale);
● kategorie. Eine der LC-Konstanten aus locale.h zur Auswahl eines Teilgebiets
der lokalen Einstellungen.
● lokale. Name der Lokale.
● Rückgabewert. Bei Erfolg gibt die Funktion einen Zeiger auf den String mit
den Kategorien und Einstellungen zurück. Im Fehlerfall wird ein NULL-Zeiger
zurückgeliefert, und die Locale-Einstellung bleibt unverändert.
Verwandte Funktionen
localeconv()
setvbuf <stdio.h>
Stream-Pufferung
Beschreibung
Mit der Funktion setvbuf() kann die Zwischenspeicherung für einen Stream festgelegt werden.
Gegenüber der Funktion setbuf() haben Sie hier mehr Einstellmöglichkeiten.
Parameter
int setvbuf(FILE *stream, char *buffer,
int buf_typ, size_t buf_groesse);
● stream. Stream, für den Puffer gesetzt werden soll.
● buffer. Nullzeiger (der Puffer wird von setvbuf eingerichtet) oder Zeiger auf
selbst allokierten Puffer.
● buf_typ. Kann den Wert einer von drei symbolischen Konstanten annehmen,
die in der Datei <stdio.h> definiert sind. Wenn das Argument buf_typ den
Wert _IONBF besitzt, werden die Optionen buffer und buf_groesse ignoriert und
die Flags des Streams auf diesen Modus eingestellt. Bei den beiden anderen
Werten wird zuerst der Wert des Arguments buffer überprüft. Steht dort ein
NULL-Zeiger, allokiert die Funktion einen Zwischenspeicher von der Größe,
die in buf_groesse angegeben ist. Anderenfalls sollte buffer auf einen Speicher-
bereich zeigen, der von Ihnen in buf_groesse Bytes allokiert wurde.
_IOFBF Zeigt an, daß ein Stream voll gepuffert werden soll. Das bedeutet, daß so
lange Daten im Zwischenspeicher abgelegt werden, bis er voll ist.
_IOLBF Stream wird zeilenweise gepuffert.
_IONBF Stream wird nicht gepuffert.
307
Die C-Standardbibliothek
● Rückgabewert. Bei Erfolg gibt die Funktion eine Null zurück. Im Fehlerfall
oder bei ungültigen Parametern ist der Rückgabewert ungleich Null.
Warnung
Die Funktion muß aufgerufen werden, nachdem der Stream mit einer geöffneten
Datei verbunden wurde und bevor irgendwelche Operationen auf dem Stream aus-
geführt wurden.
Verwandte Funktionen
setbuf()
signal <signal.h>
Unterbrechungssignal-Handhabung
Beschreibung
Mit der Funktion signal() können Bearbeitungsroutinen festgelegt werden, die immer dann
aufgerufen werden, wenn ein bestimmtes Signal auftritt.
Parameter
void (*signal(int sig, void(*funkt)(int)))(int);
● sig. Die Funktion erhält als erstes Argument eine SIG..-Konstante (siehe Hea-
der-Datei signal.h), die das Signal beschreibt, dessen Behandlung geändert
werden soll.
● funkt. Das zweite Argument ist ein Zeiger auf eine Funktion, die keinen Wert
zurückgibt, jedoch die Nummer des Signals erhält. Ruft diese Bearbeitungs-
funktion irgendeine Funktion der C-Laufzeitbibliothek außer signal() auf, ist
das Verhalten implementierungsspezifisch. Statt eines Funktionszeigers kön-
nen auch folgende Konstanten benutzt werden:
SIG_DFL Bezeichnet die Standardbearbeitung.
SIG_IGN Signal ignorieren. Das Unterbrechungssignal wird ignoriert. Diese Kon-
stante sollte nicht gemeinsam mit SIGFPE eingesetzt werden, da dies das
Fließkomma-Arithmetik-Paket unbrauchbar macht.
SIG_ERR Wird benutzt, um eine Fehlerbedingung bei der Ausführung anzuzeigen.
● Rückgabewert. Im Erfolgsfall gibt die Funktion die Adresse der vorherigen Be-
handlungsroutine für die Signale des angegebenen Typs zurück. Im Fehlerfall
wird der Wert der Konstanten SIG_ERR zurückgegeben und die globale Variable
errno auf einen positiven Wert gesetzt.
308
wctype.h
Verwandte Funktionen
raise()
Siehe Beispiel zu Header-Datei signal.h
Beschreibung
Die Funktion sin() berechnet den Sinus, sinh() den Sinus hyperbolicus ihres Arguments.
Parameter
double sin(double x);
double sinh(double x);
● Rückgabewert. sin() liefert den Sinus des Arguments im Bereich [-1, 1].
sinh() liefert den Sinus hyperbolicus des Arguments im Bereich [-8 , 8 ].
Warnung
Der Sinus hyperbolicus steigt und fällt sehr schnell.
Verwandte Funktionen
asin(), cos(), cosh()
Siehe Beispiel zu Header-Datei math.h
Beschreibung
Die Funktion nimmt eine formatierte Ausgabe in eine Zeichenkette vor. Die Formatzeichenkette
hat den für printf() beschriebenen Aufbau.
Parameter
int sprintf(char *zkette, const char *format, ...);
int swprintf(wchar_t *zkette, size_t n, const wchar_t *format, ...);
● zkette. Zeiger auf String, in den Ausgabe erfolgen soll.
● n. Maximale Anzahl an Zeichen, die geschrieben werden (nur für swprintf()).
● format. Formatzeichenkette (siehe printf()).
● .... Variable Anzahl von Argumenten.
● Rückgabewert. Die Funktion gibt die Anzahl der ausgegebenen Zeichen zu-
rück, ohne die abschließende Null. Im Fehlerfall wird EOF (WEOF) zurückgelie-
fert.
309
Die C-Standardbibliothek
Verwandte Funktionen
printf(), sscanf(), vprintf(), vsprintf()
sqrt <math.h>
Quadratwurzel berechnen
Beschreibung
Die Funktion sqrt() berechnet die Quadratwurzel ihres Arguments und gibt diesen Wert
zurück.
Parameter
double sqrt(double zahl);
● Rückgabewert. Quadratwurzel des Arguments. Da die Wurzel nur für positive
Werte größer Null definiert ist, wird bei Werten von x < 0 EDOM in errno ge-
schrieben.
Verwandte Funktionen
pow()
srand <stdlib.h>
Zufallszahlengenerator initialisieren
Beschreibung
Die Funktion srand() verwendet ihr Argument, um den Startpunkt einer Reihe von Zufallszah-
len festzulegen, die dann von rand() zurückgegeben werden. Wird die Funktion zweimal mit
dem gleichen Wert aufgerufen, erzeugt sie die gleiche Folge von Zufallszahlen.
Parameter
void srand(unsigned int zahl);
Verwandte Funktionen
rand()
Beschreibung
Die Funktion liest formatierte Daten aus einem String ein. Sie verwendet die Formatzeichen-
kette, um die eingelesenen Daten in die richtigen Typen umzuwandeln. Die weiteren wahlfreien
Argumente müssen Adressen sein, an die die eingelesenen Daten geschrieben werden sollen.
310
wctype.h
Die Formatzeichenkette kann das gleiche Muster enthalten, wie unter scanf()
beschrieben.
Parameter
int sscanf(const char *str, const char *format, ...);
int swscanf(const wchar_t *str, const wchar_t *format, ...);
● puffer. Zeiger auf String, aus dem die Daten ausgelesen werden.
● format. Formatierungsstring (siehe scanf()).
● Rückgabewert. Die Funktion gibt die Anzahl der umgewandelten und eingele-
senen Felder zurück oder EOF (WEOF), wenn versucht wurde, das Ende der Zei-
chenkette zu lesen.
Verwandte Funktionen
fscanf(), scanf(), sprintf()
Beschreibung
Die Funktion kopiert alle Zeichen des Strings, auf den quelle zeigt (inklusive des den String
beendenden \0-Zeichens), an das Ende der Zeichenkette, auf die ziel zeigt. Das Terminations-
zeichen des ersten Strings wird überschrieben.
Parameter
char *strcat(char * ziel, const char * quelle);
wchar_t *wcscat(wchar_t * ziel, const wchar_t * quelle);
● Rückgabewert. Zeiger auf die verbundene Zeichenkette.
Verwandte Funktionen
strncat(), strcpy(), strspn()
Siehe Praxisteil, Kategorie Zeichenketten, Programmieren mit C-Strings
Beschreibung
Die Funktion sucht nach dem ersten Vorkommen eines Zeichens in einer Zeichenkette. Das
Nullterminierungszeichen am Ende der Zeichenkette ist in die Suche eingeschlossen.
311
Die C-Standardbibliothek
Parameter
C:
char *strchr(const char *zkette, int zeichen);
wchar_t *wcschr(const wchar_t *zkette, wchar_t zeichen);
C++:
const char *strchr(const char *zkette, int zeichen);
const wchar_T *wcschr(const wchar_t *zkette, wchar_t zeichen);
char *strchr(char *zkette, int zeichen);
wchar_t *wcschr(wchar_t *zkette, wchar_t zeichen);
● Rückgabewert. Die Funktion gibt einen Zeiger auf zeichen zurück, wenn es ge-
funden wurde, anderenfalls einen NULL-Zeiger.
Verwandte Funktionen
strrchr(), strcspn(), strpbrk(), strspn()
Beschreibung
Die Funktion vergleicht jedes Zeichen von zkette1 mit dem Zeichen an der korrespondierenden
Position von zkette2. Der Vergleich wird so lange fortgeführt, bis entweder zwei unterschiedli-
che Zeichen gefunden oder das Ende der Zeichenkette erreicht wurde.
Parameter
int strcmp(const char *zkette1, const char *zkette2);
int wcscmp(const wchar_t *zkette1, const wchar_t *zkette2);
● Rückgabewert. Die Funktion hat drei mögliche Rückgabewerte, in denen das
Ergebnis des Vergleichs kodiert ist:
< 0 zkette1 < zkette2
0 zkette1 == zkette2
> 0 zkette1 > zkette2
Verwandte Funktionen
strncmp(), strcoll()
Beschreibung
Die Funktion vergleicht den String zkette1 mit dem String zkette2 nach den lokalen Einstel-
lungen der Kategorie LC_COLLATE.
312
wctype.h
Parameter
int strcoll(const char *zkette1, const char *zkette2);
int wcscoll(const wchar_t *zkette1, const wchar_t *zkette2);
● Rückgabewert. Die Funktion hat drei mögliche Rückgabewerte, in denen das
Ergebnis des Vergleichs kodiert ist:
< 0 zkette1 < zkette2
0 zkette1 == zkette2
> 0 zkette1 > zkette2
Verwandte Funktionen
strcmp()
Beschreibung
Die Funktion kopiert alle Zeichen der Zeichenkette quelle (inklusive des beendenden Nullter-
minierungszeichens) in den Speicherbereich, auf den ziel zeigt. Das Verhalten der Funktion ist
nicht definiert, wenn der Speicherbereich, auf den ziel zeigt, vom Speicherbereich überlappt
wird, auf den quelle zeigt.
Parameter
char *strcpy(char *ziel, const char *quelle);
wchar_t *wcscpy(wchar_t *ziel, const wchar_t *quelle);
● Rückgabewert. Zeiger auf die ziel-Zeichenkette.
Verwandte Funktionen
strncpy()
Beschreibung
Die Funktion bestimmt die Länge des vorangehenden Teil-Strings von zkette1, der keine Zei-
chen aus zkette2 enthält.
Parameter
size_t strcspn(const char *zkette1,const char *zkette2);
size_t wcscspn(const wchar_t *zkette1, const wchar_t *zkette2);
● Rückgabewert. Länge des gefundenen Präfix von zkette1.
313
Die C-Standardbibliothek
Verwandte Funktionen
strspn(), strncmp()
strerror <string.h>
System-Fehlermeldung holen
Beschreibung
Die Funktion strerror() dient der Unterstützung beim Generieren von Fehlermeldungen. Übli-
cherweise erhält sie als Argument die globale Variable errno, die von einigen Funktionen der
Laufzeitbibliothek gesetzt wird, wenn bei der Abarbeitung der entsprechenden Funktion ein
Fehler auftrat. Die Funktion strerror() schreibt die zu dem Wert von fehler gehörende Feh-
lermeldung in einen statischen Puffer und liefert einen Zeiger auf diesen Puffer zurück.
Eine Ausgabe der Fehlermeldung erfolgt mit dieser Funktion nicht.
Parameter
char *strerror(int fehler);
● Rückgabewert. Zeiger auf die Fehlermeldung, die dem Argument fehler ent-
spricht.
Verwandte Funktionen
perror()
Beschreibung
Die Funktion übernimmt die Zeitangabe aus der Variablen zeit der Struktur tm, konvertiert sie
entsprechend der in dem Parameter format enthaltenen Formatierungsanweisungen und der
lokalen Einstellung (LC_TIME) und gibt sie in die Zeichenkette str aus.
Folgende Formatierungsangaben sind für den Parameter format zulässig:
%% // Prozentzeichen %.
%a // Abgekürzter Name des Wochentags.
%A // Voller Name des Wochentags.
%b // Abgekürzter Name des Monats.
%B // Voller Name des Monats.
%c // Datum und Zeit.
%d // Tag des Monats (01 – 31).
%H // Stunde (00 -23).
%I // Stunde (01 – 12).
%j // Tag des Jahres (001 – 366).
%m // Monat (01 – 12).
%M // Minute (00 – 59).
%p // AM oder PM.
314
wctype.h
Parameter
size_t strftime(char *str, size_t maxsize,
const char *format, const struct tm *zeit);
size_t wcsftime(wchar_t *str, size_t maxsize,
const wchar_t *format, const struct tm *zeit);
● str. Ausgabe-String, in den die umformatierte Datums/Zeitangabe geschrieben
wird..
● maxsize. Maximale Anzahl von Zeichen, die in str geschrieben werden dürfen.
● format. Formatierungs-String, der aus oben aufgeführten Formatierungsanwei-
sungen bestehen kann.
● zeit. Umzuformatierende Datum/Zeitangabe.
● Rückgabewert. Die Funktion liefert die Anzahl, der nach str geschriebenen
Zeichen zurück. Werden mehr Zeichen benötigt, als durch maxsize freigestellt,
wird Null zurückgeliefert. Die konvertierte Zeitangabe wird über den Parame-
ter str zur Verfügung gestellt.
Verwandte Funktionen
localtime(), time(), gmtime(), setlocale()
Beschreibung
Die Funktion ermittelt die Länge der übergebenen Zeichenkette. Das den String beendende
Nullterminierungszeichen wird nicht mitgezählt.
Parameter
size_t strlen(const char *zkette);
size_t wcslen(const wchar_t *zkette);
● Rückgabewert. Länge der Zeichenkette (ohne Nullterminierungszeichen).
315
Die C-Standardbibliothek
Verwandte Funktionen
strcpy(), sizeof-Operator
Beschreibung
Die Funktion kopiert anzahl Zeichen des Strings, auf den quelle zeigt, an das Ende des Strings,
auf den ziel zeigt. Das Kopieren wird beendet, wenn entweder anzahl Zeichen übertragen oder
das Ende von ziel erreicht wurde.
Parameter
char *strncat(char * ziel, const char *quelle, size_t anzahl);
wchar_t *wcsncat(wchar_t * ziel, const wchar_t *quelle, size_t anzahl);
● Rückgabewert. Zeiger auf ziel.
Verwandte Funktionen
strcat(), strncpy()
Beschreibung
Die Funktion vergleicht die ersten anzahl Zeichen der Strings zkette1 und zkette2. Der Ver-
gleich endet, wenn entweder ein Nullterminierungszeichen eingelesen wird oder ein Zeichen-
paar gefunden wurde, das nicht identisch ist.
Parameter
int strncmp (const char *zkette1, const char *zkette2, size_t anzahl);
int wcsncmp (const wchar_t *zkette1, const wchar_t *zkette2,
size_t anzahl);
● Rückgabewert. Die Funktion hat drei mögliche Rückgabewerte, in denen das
Ergebnis des Vergleichs kodiert ist:
< 0 zkette1 < zkette2
0 zkette1 == zkette2
> 0 zkette1 > zkette2
Verwandte Funktionen
strcmp(), strcoll()
316
wctype.h
Beschreibung
Die Funktion kopiert anzahl Zeichen aus dem Speicherbereich, auf den quelle zeigt, in den
Speicherbereich, auf den ziel zeigt. Wenn quelle weniger als anzahl Zeichen besitzt, wird so
lange das Nullterminierungszeichen kopiert, bis anzahl Zeichen geschrieben wurde.
Der Speicherbereich, auf den ziel zeigt, muß anzahl Zeichen groß sein. Anderenfalls
kann es passieren, daß durch die Funktion andere Daten oder Code überschrieben
werden.
Parameter
char *strncpy(char *ziel, const char *quelle, size_t anzahl);
wchar_t *wcsncpy(wchar_t *ziel, const wchar_t *quelle, size_t anzahl);
● Rückgabewert. Zeiger auf ziel.
Verwandte Funktionen
strcat(), strncat(), strspn()
Beschreibung
Die Funktion überprüft die Zeichenkette zkette1 daraufhin, ob in ihr ein beliebiges Zeichen aus
der Zeichenkette zkette2 vorkommt.
Parameter
C:
char *strpbrk(const char *zkette1, const char *zkette2);
wchar_t *wcspbrk(const wchar_t *zkette1, const wchar_t *zkette2);
C++:
const char *strpbrk(const char *zkette1, const char *zkette2);
const wchar_t *wcspbrk(const wchar_t *zkette1, const wchar_t *zkette2);
char *strpbrk(char *zkette1, const char *zkette2);
wchar_t *wcspbrk(wchar_t *zkette1, const wchar_t *zkette2);
● Rückgabewert. Die Funktion gibt einen Zeiger zum ersten entsprechenden
Zeichen in zkette1 oder einen NULL-Zeiger zurück, wenn kein identisches
Zeichen gefunden wird.
Verwandte Funktionen
strchr(), strrchr(), strstr()
317
Die C-Standardbibliothek
Beschreibung
Die Funktion tastet die übergebene Zeichenkette daraufhin ab, ob in ihr ein bestimmtes Zeichen
vorkommt. Das abschließende Nullterminierungszeichen ist in die Suche eingeschlossen und
kann ebenfalls das Zeichen sein, nach dem gesucht wird.
Parameter
C:
char *strrchr(const char *zkette, int zeichen);
wchar_t *wcsrchr(const wchar_t *zkette, wchar_t zeichen);
C++:
const char *strrchr(const char *zkette, int zeichen);
const wchar_T *wcsrchr(const wchar_t *zkette, wchar_t zeichen);
char *strrchr(char *zkette, int zeichen);
wchar_t *wcsrchr(wchar_t *zkette, wchar_t zeichen);
● Rückgabewert. Die Funktion gibt einen Zeiger zum letzten (d. h. am weitesten
rechts liegenden) Vorkommen von zeichen in zkette zurück, wenn das Zeichen
gefunden wurde. Anderenfalls wird ein NULL-Zeiger zurückgegeben.
Verwandte Funktionen
strcspn(), strpbrk(), strspn()
Beschreibung
Die Funktion untersucht, bis zu welcher Position zkette1 ausschließlich aus Zeichen besteht,
die in zkette2 enthalten sind.
Parameter
size_t strspn(const char *zkette1, const char *zkette2);
size_t wcsspn(const wchar_t *zkette1, const wchar_t *zkette2);
● Rückgabewert. Länge des Präfix bis zum ersten ungleichen Zeichen.
Verwandte Funktionen
strcspn(), strpbrk(), strrchr()
318
wctype.h
Beschreibung
Die Funktion sucht nach zkette2 in zkette1.
Parameter
C:
char *strstr(const char *zkette1,const char *zkette2);
wchar_t *strstr(const wchar_t *zkette1, const wchar_t *zkette2);
C++:
const char *strstr(const char *zkette1, const char *zkette2);
const wchar_t *wcsstr(const wchar_t *zkette1, const wchar_t *zkette2);
char *strstr(const char *zkette1, const char *zkette2);
wchar_t *wcsstr(const wchar_t *zkette1, const wchar_t *zkette2);
● Rückgabewert. Zeiger zum ersten Vorkommen von zkette2 in zkette1 zurück,
bzw. einen NULL-Zeiger, wenn zkette2 nicht gefunden wurde.
Verwandte Funktionen
memchr(), strchr(), strcspn(), strrchr()
Beschreibung
Die Funktion wandelt einen String zkette in eine Gleitkommazahl doppelter Genauigkeit (Typ
double) um. Die Umwandlung wird beendet, nachdem das erste Zeichen, das nicht mehr als
Bestandteil der Zahl erkannt wird, oder **endzgr erreicht wurde.
Parameter
double strtod(const char *zkette, char **endzgr);
double wcstod(const wchar_t *zkette, wchar_t **endzgr);
● Rückgabewert. Die Funktion gibt den umgewandelten Wert zurück.
Verwandte Funktionen
strtol(), strtoul()
Beschreibung
Die Funktion ermittelt einzelne Grundsymbole in einer Zeichenkette. Um die Grundsymbole zu
finden, sucht sie nach den in zkette2 enthaltenen Trennzeichen.
319
Die C-Standardbibliothek
Ab dem zweiten Aufruf kann für zkette1 das Argument NULL übergeben werden.
Die Funktion sucht dann nach dem nächsten Grundsymbol ab der Stelle, die beim
ersten Aufruf intern gespeichert wurde.
Durch wiederholte Aufrufe der Funktion kann die Zeichenkette zkette1 in eine
Reihe Teil-Strings aufgesplittet werden, die jeweils durch Zeichen aus zkette2 abge-
schlossen werden.
Die Wide Character-Version benötigt einen zusätzlichen Zeiger auf wchar_t, um
Hilfsinformationen ablegen zu können.
char *strtok(char *zkette1, const char *zkette2);
wchar_t *wcstok(wchar_t *zkette1, const wchar_t *zkette2,
wchar_t ** zeiger);
● Rückgabewert. Zeiger auf das gefundene Grundsymbol oder NULL-Zeiger,
wenn keine Token mehr vorhanden sind.
Verwandte Funktionen
strpbrk(), strcspn(), strspn(), strstr()
Beschreibung
Die Funktion wandelt eine Zeichenkette in einen Wert vom Typ long um. Die Umwandlung wird
beendet, nachdem das erste Zeichen, das nicht mehr als Bestandteil der Zahl erkannt wird, oder
**endzgr erreicht wurde.
Parameter
long strtol(const char *zkette, char **endzgr, int basis);
long int wcstol(const wchar_t *zkette, wchar_t **endzgr, int basis);
● Rückgabewert. Gibt den umgewandelten Wert zurück.
Verwandte Funktionen
strtod(), strtoul(), sprintf(), atof()
Beschreibung
Die Funktion wandelt eine Zeichenkette in einen Wert vom Typ unsigned long um. Die
Umwandlung wird beendet, nachdem das erste Zeichen, das nicht mehr als Bestandteil der Zahl
erkannt werden konnte, oder **endzgr erreicht wurde.
320
wctype.h
Parameter
unsigned long int strtoul (const char *zkette, char **endzgr, int basis);
unsigned long int wcstoul (const wchar_t *zk,wchar_t **endzgr,int basis);
● Rückgabewert. Bei Erfolg der umgewandelten Wert, anderenfalls Null.
Verwandte Funktionen
strtod(), strtol()
Beschreibung
Die Funktion wandelt maximal anz Zeichen der Zeichenkette quelle um und schreibt das
Ergebnis nach ziel. Bei erfolgreicher Transformation liefern die Aufrufe:
strcmp(ziel, x)
und
strcoll(quelle, x)
danach das gleiche Ergebnis.
Parameter
size_t strxfrm (char *ziel, char *quelle, size_t anz);
size_t wcsxfrm (wchar_T *ziel, wchar_t *quelle, size_t anz);
● Rückgabewert. Anzahl der transformierten Zeichen.
Verwandte Funktionen
strcmp(), strcoll()
system <stdlib.h>
Betriebssystem-Befehl ausführen
Beschreibung
Mit der Funktion system() kann von einem C-Programm aus ein anderes Programm ausgeführt
werden. Der momentan laufende Prozeß wird unterbrochen, und der übergebene Systembefehl
an den Befehlsinterpreter, falls vorhanden, weitergeleitet.
Parameter
int system(const char *prgname);
● Rückgabewert. Implementierungsspezifisch.
321
Die C-Standardbibliothek
Beschreibung
Die Funktion tan() berechnet den Tangens und tanh() den Tangens hyperbolicus ihres Argu-
ments.
Parameter
double tan(double x);
double tanh(double x);
● Rückgabewert. tan() liefert den Tangens des Arguments im Bereich [ -8, 8 ].
tanh() liefert den Tangens hyperbolicus des Arguments im Bereich [-1, 1].
Warnung
Der Tangens nähert sich in der Umgebung der Vielfachen von p /2 den Werten -8
und 8.
Verwandte Funktionen
acos(), asin(), atan(), atan2(), sinh()
Siehe Beispiel zu Header-Datei math.h
time <time.h>
System-Uhrzeit holen
Beschreibung
Die Funktion time() ermittelt die aktuelle Kalenderzeit. Die Kalenderzeit ist die Anzahl der
Sekunden, die seit dem 1. Januar 1970, [Link] Uhr, vergangen sind.
Wenn das Argument p_zeit kein NULL-Zeiger ist, wird die Kalenderzeit auch an
die Adresse geschrieben, auf die p_zeit zeigt.
Parameter
time_t time(time_t *p_zeit);
● Rückgabewert. Anzahl der seit dem 1.1.1970, [Link] Uhr, verstrichenen
Sekunden.
Verwandte Funktionen
asctime(), ctime(), gmtime(), localtime()
Siehe Beispiel zu Header-Datei time.h
tmpfile <stdio.h>
Vorübergehende Datei anlegen
322
wctype.h
Beschreibung
Die Funktion tmpfile() erzeugt eine temporäre Datei. Die Datei wird im Modus wb+ geöffnet
und automatisch entfernt, wenn die Datei geschlossen wird oder das Programm endet.
Parameter
FILE *tmpfile(void);
● Rückgabewert. Zeiger auf eine FILE-Struktur. Konnte die Datei nicht geöffnet
werden, wird ein NULL-Zeiger zurückgegeben.
Verwandte Funktionen
tmpnam()
tmpnam <stdio.h>
Vorübergehenden Dateinamen schaffen
Beschreibung
Die Funktion tmpnam() erzeugt einen eindeutigen Namen für eine temporäre Datei. Erhält die
Funktion als Argument einen NULL-Zeiger, wird der Name in einen internen statischen Puffer
geschrieben, der von weiteren Aufrufen der Funktion überschrieben wird.
Ansonsten zeigt zkette auf einen Speicherbereich, in dem der Name abgelegt wer-
den soll. Der für den Dateinamen vorgesehene Speicherbereich muß mindestens
L_tmpnam Bytes groß sein. Sie sollten also diese Konstante bei der Definition eines
Arrays auf char als Größenangabe verwenden.
Parameter
char *tmpnam(char *zkette);
● Rückgabewert. Zeiger auf den temporären Namen.
Verwandte Funktionen
tmpfile()
Beschreibung
Die Funktion wandelt das übergebene Zeichen in einen Kleinbuchstaben um. Die Funktion
tolower() überprüft, ob der übergebene Buchstabe ein Großbuchstabe ist, zu dem ein Klein-
buchstabe existiert, und nimmt nur dann die Umwandlung vor.
323
Die C-Standardbibliothek
Parameter
int tolower(int zeichen);
wint_t towlower(wchar_t zeichen);
● Rückgabewert. Die Funktion gibt das umgewandelte Zeichen zurück. Wird ein
Kleinbuchstabe übergeben, wird dieser unverändert zurückgeliefert.
Verwandte Funktionen
toupper(), towupper()
Beschreibung
Die Funktion wandelt das übergebene Zeichen in einen Großbuchstaben um. Die Funktion
toupper() überprüft, ob der übergebene Buchstabe ein Großbuchstabe ist, zu dem ein Klein-
buchstabe existiert, und nimmt nur dann die Umwandlung vor.
Parameter
int toupper(int zeichen);
wint_t towupper(wchar_t zeichen);
● Rückgabewert. Die Funktion gibt das umgewandelte Zeichen zurück. Wird ein
Großbuchstabe übergeben, wird dieser unverändert zurückgeliefert.
Verwandte Funktionen
tolower(), towlower()
towctrans <wctype.h>
Wide Character-Abbildung
Beschreibung
Konvertiert ein Wide Character-Zeichen gemäß der durch die Parameterbeschreibung gegebe-
nen Abbildung. Argumente für die Parameterbeschreibung können mit Hilfe der Funktion
wctrans() erzeugt werden.
Parameter
wint_t towctrans(wint_t wc, wctrans_t beschreibung);
● Rückgabewert. Wert, auf den das Zeichen abgebildet wurde.
Verwandte Funktionen
wctrans()
324
wctype.h
Beschreibung
Die Funktion schreibt das eingelesene Zeichen zurück an den Stream. Die Funktion kann nicht
beliebig viele Male hintereinander ausgeführt werden. Bei gepufferter Ein- und Ausgabe wird
das Zeichen in den Puffer geschrieben und geht entsprechend bei Operationen, die den Puffer
löschen (fseek(), rewind(), fflush(), fsetpos()), verloren.
Parameter
int ungetc(int zeichen, FILE *stream);
wint_t ungetwc(wchar_t zeichen, FILE *stream);
● Rückgabewert. Die Funktion gibt das Argument zeichen zurück, wenn erfolg-
reich, sonst EOF (WEOF).
Verwandte Funktionen
getc(), getchar()
va_... <stdarg.h>
Variable Anzahl von Argumenten
Beschreibung
Die Makros va_arg(), va_end() und va_start() dienen zur Implementierung von Funktionen,
die mit einer variablen Anzahl von Argumenten aufgerufen werden, wie beispielsweise
printf() oder scanf().
Parameter
type va_arg(va_list arg_zgr, type);
void va_end(va_list arg_zgr);
void va_start(va_list arg_zgr, letzter_param);
Verwandte Funktionen
vfprintf(), vprintf(), vsprintf()
Beschreibung
Diese sechs Funktionen geben formatierte Daten aus. Sie sind mit den Funktionen fprintf(),
printf() und sprintf() nahezu identisch. Die variable Anzahl von Argumenten wird nicht als
Liste, sondern als Zeiger auf eine Liste von Argumenten übergeben.
325
Die C-Standardbibliothek
Die drei Funktionen unterscheiden sich durch das Ziel ihrer Ausgabe. vfprintf()
schreibt an einen beliebigen Stream, vprintf() an den Stream stdout und vsprintf()
in einen Speicherbereich.
Parameter
int vfprintf(FILE *stream, const char *format, va_list argzgr);
int vfwprintf(FILE *stream, const wchar_t *format, va_list argzgr);
int vprintf(const char *format, va_list argzgr);
int vwprintf(const wchar_t *format, va_list argzgr);
int vsprintf(char *puffer, const char *format, va_list argzgr);
int vswprintf(wchar_t *puffer, size_t n, const wchar_t *format,
va_list argzgr);
● Rückgabewert. Die drei Funktionen geben die Anzahl der geschriebenen Zei-
chen ohne das »\0«-Zeichen zurück. Im Fehlerfall wird ein negativer Wert zu-
rückgeliefert.
Verwandte Funktionen
fprintf(), printf(), sprintf(), va_arg(), va_end(), va_start()
Beschreibung
Beide Funktionen konvertieren die übergebene Folge von wchar_t-Zeichen in einen Multibyte-
String. Die Konvertierung bricht ab, wenn n Bytes konvertiert wurden oder ein Nullterminie-
rungszeichen oder ein ungültiges Multibyte-Zeichen aufgetreten ist. Werden genau n Bytes
ohne abschließendes Nullterminierungszeichen konvertiert, ist der String nicht nullterminiert.
Die Konvertierung berücksichtigt die lokale Einstellung der Kategorie LC_TYPE.
Die Funktion wcstomb() erzeugt eine Folge von Multibyte-Zeichen im anfänglichen
Shift-Status (Zustand in dem die Zeichen aus dem C-Zeichensatz 1:1 codiert sind).
Die Funktion wcsrtomb() erzeugt eine Folge von Multibyte-Zeichen im durch den
mbstate_t-Argument gegebenen Konvertierungsstatus.
Parameter
size_t wcstombs(char *mb_str, const wchar_t *wc, size_t n);
size_t wcsrtombs(char *mb_str,const wchar_t *wc,size_t n,mbstate_t *ps);
● Rückgabewert. Anzahl der geänderten Bytes (ohne Nullterminierungszei-
chen), bzw. -1 im Fehlerfall.
Verwandte Funktionen
wctomb(), wcrtomb()
326
wctype.h
wctob <wchar.h>
1-Byte-Repräsentation abfragen
Beschreibung
Bestimmt, ob es sich bei dem Zeichen c um ein Zeichen eines erweiterten Zeichensatzes han-
delt, dessen Multibyte-Darstellung im anfänglichen Shift-Status (Zustand in dem die Zeichen
aus dem C-Zeichensatz 1:1 codiert sind) ein einzelnes Byte ist.
Parameter
int wctob(wint_t c);
● Rückgabewert. 1-Byte-Repräsentation des übergebenen Zeichens. EOF, wenn
das Zeichen nicht mit einem MultiByte-Zeichen korrespondiert, das im an-
fänglichen Konvertierungsstatus nur aus einem Byte besteht.
Verwandte Funktionen
btowc()
Beschreibung
Beide Funktionen konvertieren das übergebene wchar_t-Zeichen in ein Multibyte-Zeichen. Die
Konvertierung bricht nach spätestens MB_CUR_MAX Zeichen ab. Die Konvertierung berücksichtigt
die lokale Einstellung der Kategorie LC_TYPE.
Parameter
int wctomb(char *mb_ch, const wchar_t *wc);
size_t wcrtomb(char *mb_ch, const wchar_t *wc, mbstate_t *ps);
● Rückgabewert. Anzahl der geänderten Bytes (ohne Nullterminierungszei-
chen), bzw. -1 im Fehlerfall.
Verwandte Funktionen
wcstombs()
wctrans <wctype.h>
Wide Character-Abbildung kennzeichnen
Beschreibung
Erzeugt einen Wert des Typ wctrans_t, der die durch den Parameter eigenschaft beschriebene
Abbildung von einem Wide Character-Zeichensatz in einen anderen (nach LC_TYPE) identifi-
ziert. Wird zusammen mit towctrans() benutzt.
327
Die C-Standardbibliothek
Parameter
wctrans_t wctrans(const char *eigenschaft);
● Rückgabewert. Wert, der eine gemäß LC_TYPE gültige Wide Character-Abbil-
dung repräsentiert und als zweites Argument an towctrans() übergeben werden
kann.
Verwandte Funktionen
towctrans()
wctype <wctype.h>
Wide Character-Klasse kennzeichnen
Beschreibung
Erzeugt einen wctype_t-Wert, der die Klasse von Wide Characters bezeichnet, die als Argument
übergeben wurde. Wird zusammen mit iswctype() verwendet und erlaubt die Identifizierung
einer Klasse anhand eines Strings.
Parameter
wctype_t wctype(const char *eigenschaft);
● Rückgabewert. Wert, der eine Wide Character-Klasse repräsentiert und als
zweites Argument an iswctype() übergeben werden kann.
Verwandte Funktionen
iswctype()
328
Die C++-Standardbibliothek
329
Die C++-Standardbibliothek
Die Header-Dateien
Ebenso wie in C viele wichtige und häufig gebräuchliche Funktionen fester
Bestandteil der C-Laufzeitbibliothek sind, umfaßt C++ standardmäßig eine Reihe
nützlicher Klassen und Klassenhierarchien. Diese Klassen sind ebenfalls Teil der
Laufzeitbibliothek. Um auf diese Klassen zugreifen zu können, müssen wiederum
die entsprechenden Header-Dateien mittels #include-Anweisungen eingebunden
werden.
Die C++-Klassen erweitern zum einen die Laufzeitbibliothek um neue Funktionali-
täten und Einsatzbereiche, zum anderen werden bestehende Konzepte objektorien-
tiert implementiert. Dies gilt insbesondere für die Stream-Klassen, die zur Regelung
des Datenflusses zwischen Arbeitsspeicher, Bildschirm und Festplatte dienen und
damit die Funktionen aus der Header-Datei stdio.h ersetzen.
Dies bedeutet aber nicht, daß die alten C-Funktionen nicht mehr verfügbar wären
oder man nicht beide Systeme mischen könnte. Ob Sie sich der C++-Klassen oder
der C-Funktionen bedienen, oder beide Konzepte nebeneinander in einem Pro-
gramm verwenden, ist gänzlich Ihnen überlassen. Alles andere würde auch der
Kompatibilität von C und C++ widersprechen. Teilweise wird die Mischung sogar
absichtlich unterstützt, indem Standard C-Funktionen überladen werden, um
zusammen mit den Klassen der Laufzeitbibliothek verwendet werden zu können.
Die Elemente der C++-Laufzeitbibliothek sind in dem Namensbereich std einge-
schlossen. Üblicherweise läßt man daher auf die #include-Anweisungen für die Hea-
der-Dateien die Anweisung
using namespace std;
folgen.
Warnung
Noch werden aber nicht alle Elemente der C++Bibliothek von allen Compilern
unterstützt. Manche Compiler unterstützen keine Namensbereiche oder haben
nicht alle Klassen der Laufzeitbibliothek im Namensbereich std deklariert. Manche
Compiler bieten Teile der Laufzeitbibliothek in den alten C-Headern an, beispiels-
weise iostream.h statt iostream.
algorithm
Beschreibung
Enthält eine ganze Reihe von Funktionentemplates, die die gängigsten Algorithmen zur
Anwendung auf Container-Elementen implementieren (Kopieren, Verschieben, Sortieren,
330
algorithm
Suchen, etc.). Unter Containern sind hier allerdings nicht nur die in der C++-Laufzeitbibliothek
definierten Container zu verstehen. Algorithmen können in gleicher Weise auch auf selbst defi-
nierte Container oder auch simple Arrays angwendet werden Voraussetzung ist lediglich, daß
für den Zugriff auf die Elemente im Container passende Iteratoren zur Verfügung stehen und
die Elemente geeignet sind, von den Algorithmen bearbeitet zu werden.
Enthaltene Funktionentemplates
adjacent_find() // Benachbarte Vorkommen aufspüren
binary_search() // Element in sortierter Sequenz suchen
copy() // Sequenz kopieren (beginnt mit erstem Element)
copy_backward() // Sequenz kopieren (beginnt mit letztem Element)
count() // Elemente in Sequenz zählen
count_if() // Bestimmte Elemente in Sequenz zählen
equal() // Elemente in Sequenz paarweise vergleichen
equal_range() // Einheitliche Sequenz suchen
fill() // Elemente in Sequenz einen Wert zuweisen
fill_n() // Den ersten n Elementen in Sequenz
// einen Wert zuweisen
find() // Wert in Sequenz suchen
find_end() // Letztes Vorkommen einer Teilsequenz suchen
find_first_of() // Element in Sequenz suchen
find_if() // Bestimmtes Element suchen
for_each() // Funktion auf Elemente anwenden
generate() // Sequenz einen berechneten Wert zuweisen
generate_n() // Ersten Elementen einer Sequenz einen
// berechneten Wert zuweisen
includes() // Sequenz enthalten in anderer Sequenz
inplace_merge() // Zwei Sequenzen vermengen
iter_swap() // Zwei Elemente tauschen
lexicographical_compare() // zwei Sequenz lexikographisch vergleichen
lower_bound() // Element in sortierte Sequenz einfügen
make_heap() // Sequenz in Heap umwandeln
max() // Maximum zweier Werte bestimmen
max_element() // Maximum einer Sequenz bestimmen
merge() // Zwei Sequenzen vermengen
min() // Minimum zweier Werte bestimmen
min_element() // Minimum einer Sequenz bestimmen
mismatch() // Ersten Elemente zweier Sequenzen, die
// nicht gleich sind, aufspüren
next_permutation() // Nächste Permutation erzeugen
nth_element() // ntes Element einsortieren
partial_sort() // Teilsequenz sortieren
partial_sort_copy() // Teilsequenz sortiert kopieren
partition() // Ausgewählte Elemente nach vorne kopieren
pop_heap() // Element von Heap entfernen
prev_permutation() // Vorangehende Permutation erzeugen
push_heap() // Element in Heap einfügen
random_shuffle() // Elemente in Sequenz neu verteilen
remove() // Elemente mit bestimmtem Wert entfernen
331
Die C++-Standardbibliothek
bitset
Beschreibung
Definiert ein Klassentemplate und einige überladene Operatoren zur Verwaltung und Bearbei-
tung von Bitfolgen feststehender Größe.
Enthaltene Klassentemplates
bitset // Für Bit-Folgen feststehender Größe
Überladene Operatoren
&, |, ^, <<, >>
332
complex
Beispiel
#include <iostream>
#include <bitset>
using namespace std;
complex
Beschreibung
Definiert das Klassentemplate complex einschließlich Spezialisierungen des Klassentemplates
für die Datentypen float, double und long double, für die Programmierung mit komplexen
Zahlen. Zudem sind etliche Funktionentemplates und überladene Operatoren für die Verwen-
dung mit complex-Objekten definiert.
Enthaltene Klassentemplates
complex // Klasse für komplexe Zahlen.
complex<double> // Spezialisierung für Datentyp double.
complex<float> // Spezialisierung für Datentyp float.
complex<long double> // Spezialisierung für Datentyp long double.
Enthaltene Funktionentemplates
abs() // Betrag berechnen.
arg() // Argument ermitteln.
conj() // Konjugiert Komplexe bestimmen.
cos() // Kosinus berechnen.
cosh() // Kosinus hyperbolicus berechnen.
exp() // Exponentialfunktion berechnen.
imag() // Imaginärteil bestimmen.
333
Die C++-Standardbibliothek
Überladene Operatoren
+, –, *, /, +, –, ==, !=, <<, >>
Beispiel
#include <complex>
using namespace std;
deque
Beschreibung
Definiert das Klassentemplate deque, das einen Container zur Verwaltung von Objekten beliebi-
ger Datentypen implementiert. Zusätzlich sind Funktionen (swap()) und Operatoren zur
Anwendung auf deque-Objekte definiert.
Enthaltene Templates
deque // Datenstruktur, die für Einfügen/Löschen am Anfang
// und Ende optimiert ist und schnellen direkten Zugriff
// auf beliebige Positionen zuläßt.
swap() // Zum Vertauschen der Elemente zweier deque-Container.
Überladene Operatoren
==, !=, <, >, >=, <=
Beispiel
#include <deque>
using namespace std;
class demo;
334
exception
exception
Beschreibung
Enthält verschiedene Klassen, Typdefinitionen und Funktionen, die mit der Exception-Behand-
lung in C++-Programmen in Zusammenhang stehen.
Enthaltene Funktionen
terminate() // Ruft Funktion zum Programmabbruch auf.
set_terminate() // Richtet eine Funktion zum Programmabbruch ein.
unexpected() // Ruft Funktion zur Behandlung unerwarteter
// Exceptions auf.
set_unexpected() // Richtet Funktion zur Behandlung unerwarteter
// Exceptions ein.
uncaught_exception() // Liefert true, wenn eine noch nicht abgefangene
// Exception ausgelöst wurde.
Verweise
Siehe Kategorie Sprachkonzepte, Exception-Behandlung
fstream
Beschreibung
Enthält Klassentemplates für Dateistreams und die dazugehörigen Puffer. Für die Zeichentypen
char und wchar_t sind bereits entsprechende Klassen aus den Templates instanziiert, die man
direkt in Programmen verwenden kann.
335
Die C++-Standardbibliothek
Enthaltene Klassentemplates
basic_fstream // Stellt HighLevel-Routinen zur Ein- und Ausgabe von
// und in Dateien zur Verfügung.
basic_ifstream // Stellt HighLevel-Routinen zum Einlesen aus einer
// Datei zur Verfügung.
basic_ofstream // Stellt HighLevel-Routinen zum Ausgeben in eine
// Datei zur Verfügung.
basic_filebuf // Von basic_streambuf abgeleiteter Puffer, der die
// Ein- und Ausgabe mit einer Datei verknüpft.
Enthaltene Klassen
fstream // typedef basic_fstream<char> fstream
wfstream // typedef basic_fstream<wchar_t> wfstream
ifstream // typedef basic_ifstream<char> ifstream
wifstream // typedef basic_ifstream<wchar_t> wifstream
ofstream // typedef basic_ofstream<char> ofstream
wofstream // typedef basic_ofstream<wchar_t> wofstream
filebuf // typedef basic_filebuf<wchar_t> filebuf
wfilebuf // typedef basic_filebuf<wchar_t> wfilebuf
functional
Beschreibung
Funktionsobjekte sind Klasseninstanzen, für die in den vielen Fällen lediglich der ()-Operator
definiert ist. Der Operator erlaubt es, Objekte dieser Klassen wie Funktionsaufrufe einzusetzen,
da die Anwendung des Operators auf eine Instanz der Klasse syntaktisch genauso aussieht wie
ein Funktionsaufruf. In der STL werden Funktionsobjekte häufig als Parameter zu den Algorith-
men eingesetzt.
Zur weiteren Unterstützung der Programmierung mit Funktionsobjekten sind in der Header-
Datei noch etliche Hilfsdatentypen, Klassen und Funktionen definiert.
Enthaltene Funktionsobjekte
divides // Funktionsobjekt zur Division.
equal_to // Funktionsobjekt zum Test auf Gleichheit.
greater // Funktionsobjekt, äquivalent zu >.
greater_equal // Funktionsobjekt, äquivalent zu >=.
less // Funktionsobjekt, äquivalent zu <.
less_equal // Funktionsobjekt, äquivalent zu <=.
logical_and // Funktionsobjekt, äquivalent zu &&.
logical_not // Funktionsobjekt, äquivalent zu !.
logical_or // Funktionsobjekt, äquivalent zu ||.
minus // Funktionsobjekt zur Subtraktion.
modulus // Funktionsobjekt zur Modulo-Berechnung
// (Rest der Division).
336
functional
Enthaltene Hilfselemente
binary_function // Basisklasse für Funktionsobjekte
// mit zwei Argumenten.
binary_negate // Hilfsklasse zur Negation einer Aussage
// mit zwei Argumenten.
bind1st() // Funktion, die das erste Argument eines
// Funktionsobjekts für zwei Argumente mit
// einem konstanten Wert verbindet.
bind2nd() // Funktion, die das zweite Argument eines
// Funktionsobjekts für zwei Argumente mit
// einem konstanten Wert verbindet.
binder1st // Hilfsklasse zur Bindung eines Wertes an das
// erste Argument eines Funktionsobjektes.
binder2nd // Hilfsklasse zur Bindung eines Wertes an das
// zweite Argument eines Funktionsobjektes.
mem_fun_t // Hilfsklasse zur Übergabe von Methoden ohne
// Argument an Funktionsobjekt-Parameter.
mem_fun1_t // Hilfsklasse zur Übergabe von Methoden mit
// einem Argument an Funktionsobjekt-Parameter.
mem_fun() // Hilfsfunktion zur Übergabe von Methoden ohne
// Argument an einen Funktionsobjekt-Parameter
mem_fun1() // Hilfsfunktion zur Übergabe von Methoden mit
// einem Argument an einen Funktionsobjekt-Parameter
mem_fun_ref_t // Hilfsklasse zur Übergabe von Methoden ohne
// Argument an Funktionsobjekt-Parameter
mem_fun1_ref_t // Hilfsklasse zur Übergabe von Methoden mit
// einem Argument an Funktionsobjekt-Parameter.
mem_fun_ref() // Hilfsfunktion zur Übergabe von Methoden ohne
// Argument an einen Funktionsobjekt-Parameter.
mem_fun1_ref() // Hilfsfunktion zur Übergabe von Methoden mit einem
// Argument an einen Funktionsobjekt-Parameter.
not1() // Negiert eine unäre Aussage (Funktionsobjekt
// mit Rückgabetyp bool).
not2() // Negiert eine binäre Aussage (Funktionsobjekt
// mit Rückgabetyp bool).
pointer_to_binary_function // Zur Erzeugung von Funktionsobjekten aus
// Zeigern auf Funktionen mit zwei Argumenten
pointer_to_unary_function // Zur Erzeugung von Funktionsobjekten aus
// Zeigern auf Funktionen mit einem Argument
ptr_fun() // Hilfsfunktion, die es ermöglicht eine Funktion an
// einen Binder oder einen Negator zu übergeben.
unary_function // Basisklasse für Funktionsobjekte mit
// einem Argument
unary_negate // Hilfsklasse zur Negation einer Aussage mit
// einem Argument
337
Die C++-Standardbibliothek
Beispiel
// Verwendung eines Funktionsobjekts
// Werte sortieren;
stable_sort([Link](), [Link](), less<int>());
iomanip
Beschreibung
Enthält Manipulatoren zur Konfiguration von Streams (werden wie Daten an Streams
geschickt).
Enthaltene Funktionen
resetiosflags // Formatierungsflag löschen.
setbase // Basis des Zahlensystems festlegen.
setfill // Füllzeichen festlegen.
setiosflags // Formatierungsflag setzen.
setprecision // Genauigkeit festlegen.
setw // Feldbreite festlegen.
Beispiel
#include <iomanip>
using namespace std;
Verweise
Siehe Kategorie Ein- und Ausgabe, Streams in C++
ios
Beschreibung
Enthält Typdefinitionen und Basisklassen für die Stream-Klassentemplates sowie eine Reihe
von Manipulatoren zur Konfiguration von Stream-Eingaben und -Ausgaben.
338
ios
Enthaltene Manipulatoren
boolalpha // bool-Typ berücksichtigen.
dec // Dezimaldarstellung.
hex // Hexadezimaldarstellung.
fixed // Feste Stellenzahl.
internal // Bestimmte Stellen mit Füllzeichen.
left // Linksbündige Ausgabe.
noboolalpha // bool-Typ nicht berücksichtigen.
noshowbase // Basis des Zahlensystems nicht anzeigen.
noshowpoint // Gleitkommazahlen ohne Dezimalpunkt.
noshowpos // Positive Zahlen ohne Vorzeichen.
noskipws // Whitespace miteinlesen.
nouppercase // Keine Konvertierung in Großbuchstaben.
oct // Oktaldarstellung.
right // Rechstbündige Ausgabe.
scientific // Darstellung mit Mantisse und Exponent.
showbase // Basis des Zahlensystems anzeigen.
showpoint // Gleitkommazahlen mit Dezimalpunkt.
showpos // Positive Zahlen mit Vorzeichen.
skipws // white space nicht einlesen.
uppercase // Bestimmte Zeichen als Großbuchstaben.
Beispiel
[Link](10);
cout << 1234.5 << endl;
[Link](10);
cout << left << 1234.5 << endl;
Ausgabe:
1234.5
1234.5
Verweise
Siehe Kategorie Ein- und Ausgabe, Streams in C++
339
Die C++-Standardbibliothek
iosfwd
Beschreibung
Enthält die folgenden Typdefinitionen (Instanziierungen von Stream-Klassen aus den Templa-
tes der Stream-Bibliothek) und die dafür erforderlichen Vorwärtsdeklarationen der Templates.
Enthaltene Klassendefinitionen
typedef basic_ios<char> ios;
typedef basic_ios<wchar_t> wios;
typedef basic_streambuf<char> streambuf;
typedef basic_istream<char> istream;
typedef basic_ostream<char> ostream;
typedef basic_iostream<char> iostream;
typedef basic_stringbuf<char> stringbuf;
typedef basic_istringstream<char> istringstream;
typedef basic_ostringstream<char> ostringstream;
typedef basic_stringstream<char> stringstream;
typedef basic_filebuf<char> filebuf;
typedef basic_ifstream<char> ifstream;
typedef basic_ofstream<char> ofstream;
typedef basic_fstream<char> fstream;
typedef basic_streambuf<wchar_t> wstreambuf;
typedef basic_istream<wchar_t> wistream;
typedef basic_ostream<wchar_t> wostream;
typedef basic_iostream<wchar_t> wiostream;
typedef basic_stringbuf<wchar_t> wstringbuf;
typedef basic_istringstream<wchar_t> wistringstream;
typedef basic_ostringstream<wchar_t> wostringstream;
typedef basic_stringstream<wchar_t> wstringstream;
typedef basic_filebuf<wchar_t> wfilebuf;
typedef basic_ifstream<wchar_t> wifstream;
typedef basic_ofstream<wchar_t> wofstream;
typedef basic_fstream<wchar_t> wfstream;
typedef fpos<char_traits<char>::state_type> streampos;
typedef fpos<char_traits<wchar_t>::state_type> wstreampos;
iostream
Beschreibung
Definiert eine Reihe von Stream-Objekten, die bei Start jedes Programmes automatisch einge-
richtet werden und zur Verfügung stehen.
Definitierte Standard-Stream-Objekte
istream cin // StandardEingabe-Stream für char
ostream cout // StandardAusgabe-Stream für char
340
istream
Beispiel
#include <string>
#include <iostream>
int main(int argc, char **argv)
{
string str;
int wert;
cout << "Geben Sie einen String und einen int-Wert ein" << endl;
cin >> str >> wert;
cout << left; // Manipulator
cout << setw(10) << "String =" << setw(10) << str << endl;
cout << setw(10) << "Wert =" << setw(10) << wert << endl;
return 0;
}
Verweise
Siehe Kategorie Ein- und Ausgabe, Streams in C++
istream
Beschreibung
Enthält das Klassentemplate basic_istream zur Unterstützung von Leseoperationen auf Stre-
ams, sowie zwei Instanziierungen des Templates für die Datentypen char und wchar_t, die man
in Programmen direkt verwenden kann.
Enthaltene Templates
basic_istream // Stellt HighLevel-Routinen zum Einlesen aus
// einem Stream zur Verfügung.
basic_iostream // Stream zu Lesen und Schreiben
// einem Stream zur Verfügung.
ws // Manipulator zum Überlesen von Whitespace
Enthaltene Klassen
istream // Spezialisierung für Datentyp char
wistream // Spezialisierung für Datentyp wchar_t
341
Die C++-Standardbibliothek
Beispiel
filebuf datei;
[Link]("[Link]", ios_base::in | ios_base::out);
istream dat_ein(&datei);
ostream dat_aus(&datei);
iterator
Beschreibung
Iteratoren dienen dazu, Elemente von Containern zu dereferenzieren. Ihr Einsatz ähnelt der
Indizierung von Arrays. Die meisten der Funktionen aus <algorithm> arbeiten mit Iteratoren. In
der Header-Datei sind einige Iteratoren (in Form von Templates) vordefiniert. Des weiteren
enthält die Datei verschiedene Strukturen für die Definition eigener Iteratoren und Hilfsfunk-
tionen für die Programmierung mit Iteratoren.
Hilfsfunktionen
advance() // Iterator verrücken
distance() // Distanz zwischen zwei Iteratoren ermitteln
back_inserter() // Liefert einen Back-Inserter für einen Container
front_inserter() // Liefert einen Front-Inserter für einen Container
inserter() // Liefert einen Inserter für einen Container
Iteratoren-Templates
back_insert_iterator // Iterator zum Einfügen am Ende einer
// Datenstruktur.
front_insert_iterator // Iterator zum Einfügen am Anfang einer
// Datenstruktur.
insert_iterator // Iterator zum Einfügen an beliebiger Stelle in
// eine Datenstruktur.
istream_iterator // Iterator zum Lesen aus einen Stream.
istreambuf_iterator // Iterator zum Lesen aus einen Streampuffer.
ostream_iterator // Iterator zum Schreiben in einen Stream.
ostreambuf_iterator // Iterator zum Schreiben in einen Streampuffer.
reverse_iterator // Random Access-Iterator, der die Datenstruktur
// in umgekehrter Richtung durchläuft.
Hilfsstrukturen
bidirectional_iterator_tag // Vordefinierte Struktur als Hilfe zur
// Erstellung eigener Iteratoren.
forward_iterator_tag // Vordefinierte Struktur als Hilfe zur
// Erstellung eigener Iteratoren.
input_iterator_tag // Vordefinierte Struktur als Hilfe zur
// Erstellung eigener Iteratoren.
iterator // Basisklasse zur Definition von Iteratoren
342
limits
Überladene Operatoren
Für reverse_iterator: // ==, <, !=, >, >=, <=, –, +
Für istream_iterator: // ==, !=
Für istreambuf_iterator: // ==, !=
Beispiel
deque<int> container(5);
typedef deque<int>::iterator iter;
...
for(iter i = [Link](); i != [Link](); i++) {
cout << *i << endl;
}
limits
Beschreibung
Enthält das Klassentemplate numeric_limits und seine Spezialisierungen für die verschiede-
nen Datentypen, die der Programmierer zum Abfragen implementierungsspezifischer Charakte-
ristika der elementaren Datentypen nutzen kann.
Enthaltene Elemente
float_round_style // Aufzählungstyp mit folgenden Werten:
// round_indeterminate (-1)
// round_toward_zero (0)
// round_to_nearest (1)
// round_toward_infinity(2)
// round_toward_neg_infinity(3)
numeric_limits // Template-Klasse mit Informationen zur
// implementierungsspezifischen Darstellung
// der numerischen Datentypen.
// Mit Spezialisierungen für:
// bool
// char, signed char, unsigned char, wchar_t
// short, int, long
// unsigned short, unsigned int, unsigned long
// float, double, long double
343
Die C++-Standardbibliothek
Beispiel
#include <limits>
using namespace std;
...
cout << "Int: " << setw(14) << numeric_limits<int>::min()
<< setw(14) << numeric_limits<int>::max() << endl;
list
Beschreibung
Definiert das Klassentemplate list, das einen Container zur Verwaltung von Objekten beliebi-
ger Datentypen implementiert. Zusätzlich sind Funktionen (swap()) und Operatoren zur
Anwendung auf list-Objekte definiert.
Überladene Operatoren
==, !=, <, >, >=, <=
Beispiel
#include <list>
using namespace std;
class demo;
list<int> container(5); // list-Container für int-Objekte
list<demo> container(5); // list-Container für demo-Objekte
locale
Beschreibung
In bestimmten Anwendungen ist es notwendig, lokale Einstellungen zu berücksichtigen (Dar-
stellungen von Zeichen oder Datumsangaben oder die Darstellung numerischer Werte). Die
einzelnen Bereiche werden als Kategorien bezeichnet, die wiederum in Facetten (Spezialisie-
rungen der entsprechenden Template-Klassen) untergliedert werden. Mit Hilfe der Klasse
locale und ihrer Methoden können verschiedene lokale Einstellungen und ihre Kategorien
oder Facetten erstellt und ausgewählt werden.
344
locale
Enthaltene Klassen
locale // Klasse zur Verwaltung lokaler Einstellungen.
codecvt // Kategorie ctype. Unterstützt die Konvertierung
// zwischen Codierungsformen.
codecvt_base // Definiert Aufzählungstyp für Ergebniswerte.
codecvt_byname // Auswahl spezifischer Implementierungen anhand des
// Namens der lokalen Einstellung.
collate // Klasse zur gleichnamigen Kategorie. Unterstützt den
// Vergleich und die Aufspaltung von Zeichenketten.
collate_byname // Auswahl spezifischer Implementierungen anhand des
// Namens der lokalen Einstellung.
ctype // Klasse zur gleichnamigen Kategorie. Unterstützt die
// Zeichenerkennung sowie das Einlesen und
// Formatieren von Zeichenketten.
ctype<char> // Spezialisierung für den Datentyp char.
ctype_base // Definiert Bitfeld zur Zeichenklassifizierung.
ctype_byname // Auswahl spezifischer Implementierungen anhand des
// Namens der lokalen Einstellung.
ctype_byname<char> // Spezialisierung für den Datentyp char.
messages // Klasse zur gleichnamigen Kategorie. Unterstützt das
// Herauslesen von strings aus Botschaftskatalogen.
messages_base // Definiert den Datentyp catalog.
messages_byname // Auswahl spezifischer Implementierungen anhand des
// Namens der lokalen Einstellung.
money_base // Definiert Aufzählunstyp part zur Formatierung von
// Währungsangaben und den Rückgabetyp pattern.
moneypunct // Kategorie monetary. Unterstützt die Punktsetzung
// in Währungsangaben.
moneypunct_byname // Auswahl spezifischer Implementierungen anhand des
// Namens der lokalen Einstellung.
money_get // Kategorie monetary. Unterstützt das Einlesen
// von Währungsangaben.
money_put // Kategorie monetary. Unterstützt die formatierte
// Ausgabe von Währungsangaben.
numpunct // Kategorie numeric. Unterstützt die Punktsetzung
// in numerischen Werten.
numpunct_byname // Auswahl spezifischer Implementierungen anhand des
// Namens der lokalen Einstellung.
num_get // Kategorie numeric. Unterstützt das Einlesen
// numerischer Werte.
num_put // Kategorie numeric. Unterstützt die Formatierung
// bei der Ausgabe numerischer Werte.
time_base // Aufzählungstyp zur Abfolge von Datumsangaben.
time_get // Kategorie time. Unterstützt das Einlesen von
// Zeitangaben in eine Variable des Typs tm.
time_get_byname // Auswahl spezifischer Implementierungen anhand
// des Namens der lokalen Einstellung.
time_put // Kategorie time. Unterstützt die Ausgabe von
// Zeitangaben.
time_put_byname // Auswahl spezifischer Implementierungen anhand
// des Namens der lokalen Einstellung.
345
Die C++-Standardbibliothek
Funktionentemplates
has_facet() // Testet, ob eine bestimmte Facette verfügbar ist
use_facet() // Auswahl einer Facette zu einer locale-Einstellung.
is... // Methoden zur Zeichenklassifizierung (siehe C-Header
// ctype.h)
tolower() // Umwandlung in Kleinbuchstaben.
toupper() // Umwandlung in Großbuchstaben.
map
Beschreibung
Definiert die Klassentemplates map und multimap, die Container zur Verwaltung von Objekten
beliebiger Datentypen implementieren. Zusätzlich sind Funktionen (swap()) und Operatoren
zur Anwendung auf map- und multimap-Objekte definiert.
Überladene Operatoren
==, <, !=, > , >=, <=
Beispiel
#include <map>
#include <string>
using namespace std;
class demo;
map<int, string> container; // map-Container für string-Objekte
mit int-Schlüssel
map<int, demo> container; // map-Container für demo-Objekte
mit int-Schlüssel
346
memory
memory
Beschreibung
Enthält verschiedene Klassen- und Funktionenstemplates zur Speicherverwaltung. Die meisten
dieser Elemente sind für die Implementierung eigener Container und Algorithmen gedacht.
Enthaltene Klassentemplates
allocator // Klasse zur Implementierung von Speichermanagern.
allocator<void> // Spezialisierung für void
auto_ptr // Zeigeklasse zur automatischen Freigabe
// dynamischen Speichers.
raw_storage_iterator // Zur Ablage in nicht initialisierten
// Speicherbereichen.
Enthaltene Funktionentemplates
get_temporary_buffer() // Temporären Speicher anfordern.
return_temporary_buffer() // Auf temporären Speicher zugreifen
uninitialized_copy() // Nicht-initialisierten Speicher füllen
uninitialized_fill() // Nicht-initialisierten Speicher füllen
uninitialized_fill_n() // Nicht-initialisierten Speicher füllen
Verweise
Siehe Praxisteil, Kategorie Zeiger und dynamische Speicherverwaltung, auto_ptr
new
Beschreibung
Enthält die überladenen Operatorfunktionen für new und delete, sowie verschiedene Hilfsele-
mente.
Überladene Operatoren
new // Speicher reservieren
new[] // Speicher für Feld reservieren
delete // Speicher freigeben
delete[] // Speicher für Feld freigeben
347
Die C++-Standardbibliothek
Enthaltene Hilfselemente
bad_alloc // Für Exception-Objekte, die bei gescheiterten
// Speicherreservierungen ausgelöst werden.
nothrow_t // Strukturtyp zur Übergabe an new-Operator.
nothrow // Hilfsstruktur als Argument für new
set_new_handler() // Fehlerbehandlungsroutine für new registrieren.
Verweise
Siehe Kategorie Operatoren, Die Operatoren new und delete
numeric
Beschreibung
Enthält verschiedene Funktionentemplates zur Ausführung numerischer Algorithmen auf Con-
tainer-Elementen.
Beispiel
#include <numeric>
#include <vector>
#include <iostream>
using namespace std;
vector<int> container;
int main() {
for(int i = 0; i < 7; i++)
container.push_back(i);
return 0;
}
348
ostream
ostream
Beschreibung
Enthält das Klassentemplate basic_ostream zur Unterstützung von Schreiboperationen auf
Streams, zwei Instanziierungen des Templates für die Datentypen char und wchar_t, die man in
Programmen direkt verwenden kann und verschiedene Manipulatoren.
Enthaltene Templates
basic_ostream // Stellt HighLevel-Routinen zum Schreiben in
// einem Stream zur Verfügung.
endl // Manipulator: Zeilenende
ends // Manipulator: Stringende
flush // Streampuffer leeren
Enthaltene Klassen
ostream // Spezialisierung für Datentyp char
wostream // Spezialisierung für Datentyp wchar_t
Beispiel
filebuf datei; // Datei zum Lesen und Schreiben
[Link]("[Link]",ios_base::in | ios_base::out); // öffnen
istream dat_ein(&datei); // Datei mit Eingabe-Stream verbinden
ostream dat_aus(&datei); // Datei mit Ausgabe-Stream verbinden
Verweise
Siehe Kategorie Ein- und Ausgabe, Streampuffer teilen
queue
Beschreibung
Definiert die Klassentemplates queue und priority_queue, die Container zur Verwaltung von
Objekten beliebiger Datentypen implementieren. Zusätzlich sind Operatoren zur Anwendung
auf queue-Objekte definiert.
349
Die C++-Standardbibliothek
Überladene Operatoren
==, <, !=, > , >=, <=
Beispiel
#include <queue>
using namespace std;
class demo;
queue<int> container(5); // queue-Container für int-Objekte
queue<demo> container(5); // queue-Container für demo-Objekte
set
Beschreibung
Definiert die Klassentemplates set und multiset, die Container zur Verwaltung von Objekten
beliebiger Datentypen implementieren. Zusätzlich sind Funktionen (swap()) und Operatoren
zur Anwendung auf set- und multiset-Objekte definiert.
Überladene Operatoren
==, <, !=, > , >=, <=
Beispiel
#include <set>
using namespace std;
class demo;
// set-Container für int-Objekte, sortiert mit < -Operator
set<int> container(5);
// set-Container für demo-Objekte, sortiert nach greater<demo>
set<demo, greater<demo> > container(5);
350
sstream
sstream
Beschreibung
Enthält Klassentemplates, die die Verbindung zwischen Strings und Streams herstellen, sowie
Instanziierungen der Templates für die Zeichentypen char und wchar_t. Stringstreams können
wie die C-Funktionen sprintf() und sscanf() eingesetzt werden.
Enthaltene Klassentemplates
basic_stringstream // Stellt HighLevel-Routinen zum Einlesen und
// Schreiben aus und in basic_string-Objekten zur
// Verfügung.
basic_istringstream // Stellt HighLevel-Routinen zum Einlesen aus
// basic_string-Objekten zur Verfügung.
basic_ostringstream // Stellt HighLevel-Routinen zum Schreiben in
// basic_string-Objekten zur Verfügung.
basic_stringbuf // Von basic_streambuf abgeleitete Pufferklasse
// für Objekte der Klasse basic_string.
Enthaltene Klassen
stringstream // typedef basic_stringstream<char> stringstream
wstringstream // typedef basic_stringstream<wchar_t> wstringstream
istringstream // typedef basic_istringstream<char> istringstream
wistringstream // typedef basic_istringstream<wchar_t> wistringstream
ostringstream // typedef basic_ostringstream<char> ostringstream
wostringstream // typedef basic_ostringstream<wchar_t> wostringstream
stringbuf // typedef basic_stringbuf<char> stringbuf
wstringbuf // typedef basic_stringbuf<wchar_t> wstringbuf
stack
Beschreibung
Definiert das Klassentemplate stack, das einen Container zur Verwaltung von Objekten beliebi-
ger Datentypen implementiert. Zusätzlich sind Operatoren zur Anwendung auf stack-Objekte
definiert.
Überladene Operatoren
==, !=, <, >, >=, <=
351
Die C++-Standardbibliothek
Beispiel
#include <stack>
using namespace std;
class demo;
stack<int> container(5); // stack-Container für int-Objekte
stack<demo> container(5); // stack-Container für demo-Objekte
stdexcept
Beschreibung
Definiert eine Reihe von Exceptions für Fehlermeldungen in C++-Programmen.
Enthaltene Exception-Klassen
domain_error // Für Exception-Objekte, die bei Auftreten
// unzulässiger Werte ausgelöst werden.
invalid_argument // Für Exception-Objekte, die bei Übergabe ungültiger
// Argumente ausgelöst werden.
length_error // Für Exception-Objekte, die ausgelöst werden, wenn
// die zulässige Größe von Datenstrukturen oder
// -typen überschritten wird.
logic_error // Für Exception-Objekte, die logische Fehler betreffen.
out_of_range // Für Exception-Objekte, die ausgelöst werden, wenn ein
// Argument nicht im vorgesehenen Bereich liegt.
overflow_error // Für Exception-Objekte, die bei arithmetischen
// Überläufen ausgelöst werden.
range_error // Für Exception-Objekte, die bei Verletzung von
// Gültigkeitsbereichen ausgelöst werden.
runtime_error // Für Exception-Objekte, die Laufzeitfehler betreffen.
underflow_error // Für Exception-Objekte, die bei arithmetischen
// Unterläufen ausgelöst werden.
streambuf
Beschreibung
Enthält das Template für die Streampuffer-Klassen, sowie zwei Instanziierungen des Templates
für die Datentypen char und wchar_t. Die Stream-Klassen verwenden Instanzen der Pufferklas-
sen für die eigentlichen Schreib- und Leseoperationen (dabei müssen die Ein- und Ausgaben
nicht wirklich gepuffert sein; der interne Puffer der Pufferklassen kann auch auf NULL gesetzt
sein).
352
string
Enthaltene Klassentemplates
basic_streambuf // Basisklasse für gepufferte LowLevel-Operationen.
Enthaltene Klassen
streambuf // typedef basic_streambuf<char> streambuf
wstreambuf // typedef basic_streambuf<wchar_t> wstreambuf
Verweise
Siehe Kategorie Ein- und Ausgabe, Pufferung
string
Beschreibung
Enthält das Klassentemplate basic_string, das alle wichtigen Methoden für die Programmie-
rung mit Strings bereitstellt, Instanziierungen des Templates für die Zeichentypen char und
wchar_t, sowie Operatoren und Funktionen für die Arbeit mit Strings.
Enthaltene Elemente
basic_string // Klassentemplate zur String-Behandlung.
char_traits // Klasse, die die Charkteristika eines
// Zeichentyps beschreibt
char_traits<char> // Spezialisierung für Datentyp char
char_traits<wchar_t> // Spezialisierung für Datentyp wchar_t
getline() // Zeile einlesen
swap() // Zum Vertauschen der Zeichen zweier Strings
string // Spezialisierung von basic_string für Datentyp char
wstring // Spezialisierung von basic_string für Datentyp wchar_t
Verweise
Siehe Kategorie Zeichenketten, Programmieren mit der Klasse string
353
Die C++-Standardbibliothek
typeinfo
Beschreibung
Enthält die Klasse type_info, mit deren Hilfe RTTI-Informationen in C++-Programmen zur Ver-
fügung gestellt werden, sowie zwei Exception-Klassen für die Fehlerbehandlung.
Enthaltene Klassen
type_info // Verwaltet Informationen (beschreibender String,
// Prioritätswert) zu Datentypen.
bad_cast // Für Exception-Objekte, die bei gescheiterten
// dynamic_cast-Operationen ausgelöst werden.
bad_typeid // Für Exception-Objekte, die ausgelöst werden, um einen
// Null-Zeiger in typeid-Ausdrücken anzuzeigen.
Verweise
Siehe Kategorie Vererbung und Polymorphie, RTTI – Laufzeittypidentifizierung
utility
Beschreibung
Enthält Templates, die die Arbeit mit Wertepaaren erleichtern und innerhalb der C++-Laufzeit-
bibliothek verwendet werden.
Enthaltene Templates
pair // Template-Klasse für Strukturen mit zwei Elementen
// unterschiedlicher Datentypen.
make_pair() // Funktion, die aus ihren zwei Argumenten ein pair erzeugt.
Überladene Operatoren
==, <, !=, >, >=, <=
valarray
Beschreibung
Definiert die Datenstruktur valarray, die ihre Elemente wie in einem Array verwaltet (der Spei-
cher wird allerdings dynamisch verwaltet). Die Klasse valarray erlaubt eine Vielzahl von Ope-
rationen, die jeweils auf sämtlichen Elementen des Arrays ausgeführt werden, sowie die
Möglichkeit, mit Hilfe der Hilfsklassen Teilmengen zu bilden.
354
valarray
Beispiel
#include <iostream>
#include <string>
#include <valarray>
using namespace std;
int main()
{
valarray<int> va(20);
for(int i = 0; i < 20; i++)
{
va[i] = i;
cout << va[i] << endl;
}
valarray<int> teil(5);
valarray<size_t> size(2);
355
Die C++-Standardbibliothek
size[0] = 3; size[1] = 4;
valarray<size_t> stride(2);
stride[0] = 5; stride[1] = 1;
teil = va[gslice(2,size,stride)];
cout << "\nTeilarray\n";
for(int i = 0; i < size[0]*size[1]; i++)
{
cout << teil[i] << endl;
}
return 0;
}
vector
Beschreibung
Definiert das Klassentemplate vector, das einen Container zur Verwaltung von Objekten belie-
biger Datentypen implementiert. Zusätzlich sind Funktionen (swap()) und Operatoren zur
Anwendung auf vector-Objekte definiert.
Überladene Operatoren
==, !=, <, >, >=, <=
Beispiel
#include <vector>
using namespace std;
class demo;
vector<int> container(5); // vector-Container für int-Objekte
vector<demo> container(5); // vector-Container für demo-Objekte
356
Allgemeine Eigenschaften
Die Container-Klassen
Allgemeine Eigenschaften
Beschreibung
Die Container-Klassen sollen dem Programmierer die Verwaltung größerer Datenmengen in
seinen Programmen erleichtern. Sie stellen somit eine komfortable Alternative zu den Arrays
und dynamischen Feldern dar und ersparen dem Programmierer die Implementierung eigener
höherer Datenstrukturen.
● Container können für Objekte elementarer oder selbst definierter Klassenty-
pen eingerichtet werden. Voraussetzung ist allerdings, daß Kopierkonstruktor
und Zuweisungsoperator des Klassentyps nicht durch private- oder protected-
Deklaration unzugänglich gemacht wurden. Weiterhin müssen für bestimmte
Aktionen auf den Elementen eines Containers die entsprechenden Operatoren
für den Klassentyp der Objekte überladen sein (beispielsweise die Vergleichs-
operatoren).
● In einem Container können nur Objekte eines Datentyps gespeichert werden.
● Der Container ermöglicht den Zugriff sowie das Einfügen und Löschen von
Objekten. Das Löschen des Containers impliziert auch das Löschen der in ihm
enthaltenen Objekte (handelt es sich dabei um Zeiger, werden natürlich nur
die Zeiger und nicht die Objekte, auf die die Zeiger verweisen, gelöscht).
● Der Container definiert nur die Methoden zur Verwaltung der Objekte nicht
zu deren Bearbeitung. Letzterem Zweck dienen die Algorithmen.
● Die verschiedenen Containertypen sind als Templates definiert, die für den
Datentyp der aufzunehmenden Objekte spezialisiert werden müssen.
● Die Größe eines Containers (sprich die Anzahl der Objekte, die er aufnehmen
kann) ist nicht statisch festgelegt. Zu diesem Zweck implementiert jeder Con-
tainer eine eigene dynamische Speicherverwaltung.
● Die einzelnen Containertypen unterscheiden sich in der Art und Weise, wie sie
die Daten verwalten (sortiert – unsortiert; geordnet – ungeordnet), welche
Möglichkeiten des Zugriffs sie gestatten (Zugriff am Anfang oder Ende der
Datenstruktur, indizierter Zugriff, etc.), welche Möglichkeiten des Zugriffs
besonders effizient sind.
357
Die C++-Standardbibliothek
Allgemeine Container-Eigenschaften
Bei dieser und den folgenden Auflistungen bezeichnet X einen beliebigen Contai-
nertyp, a und b sind Container, i und j Iteratoren.
Eigenschaft Beschreibung
X() Erzeugt einen anonymen Container der Größe 0
Xa Erzeugt den Container a der Größe 0
X a(b)
X a = b; Erzeugt a als Kopie von b
(&a)->~X() Destruktor wird auf alle Elemente angewendet
[Link]() Liefert Iterator auf erstes Element in Container
[Link]() Liefert Iterator hinter letztes Element
[Link]() Liefert die aktuelle Anzahl an Elementen
[Link]() Gibt an, ob der Container leer ist
[Link](b) Vertauscht die Elemente der Container a und b
a == b true, wenn beide Container gleich viele Elemente enthalten, die paarweise
gleich sind
a != b !(a == b)
a<b Lexikographischer Vergleich von a und b
a>b Lexikographischer Vergleich von a und b
a <= b !(a > b)
a >= b !(a < b)
358
Allgemeine Eigenschaften
Eigenschaft Beschreibung
X(n,t) Erzeugt Container mit n Kopien des Werts t
X a(n,t)
X(i,j) Erzeugt Container als Kopie der Folge [i,j) (mit i, ohne j)
X a(i,j)
[Link](p, ) Fügt vor eine Position p ein; entweder einen Wert t, n Kopien eines
Werts t oder eine Kopie der Folge [i,j)
[Link](p) Löscht das Element an der Position p
[Link](i,j) Löscht die Elemente im Bereich [i,j)
[Link]() Löscht alle Elemente im Container
Die folgenden Operationen werden nur von den sequentiellen Containern unter-
stützt, für die sie in konstanter Zeit implementiert werden können:
Entsprechend der internen Speicherverwaltung lassen sich – wie der Tabelle zu ent-
nehmen ist – nicht alle dieser Operationen für alle sequentiellen Container imple-
mentieren. Für einen vector-Container, der einem dynamischen Array sehr nahe
kommt, würde beispielsweise das Einfügen am Containeranfang (push_front())
erfordern, daß zuerst alle Elemente im Container, vom Containerende angefangen,
um eine Position nach hinten gerückt werden. Da dies nur in linearer und nicht in
konstanter Zeit zu schaffen ist, wird diese Operation von vector nicht unterstützt.
Assoziative Container
● In einem assoziativen Container werden die Elemente sortiert verwahrt (die
zugrundeliegende Datenstruktur kann dabei ein binärer Baum oder eine
Hashing-Tabelle sein).
● Die Sortierung richtet sich nach den Schlüsseln (keys) der Elemente und nach
einem bestimmten Sortierkriterium, dem Vergleichsobjekt (Compare).
● Für set und multiset fallen Wert und Schlüssel zusammen, d. h., der Wert ist
gleichzeitig auch der Schlüssel, nach dem sortiert wird.
359
Die C++-Standardbibliothek
● Für map und multimap wird jedem Element ein eigener Schlüssel zugewiesen,
und Element und Schlüssel werden im Container als Paar verwahrt.
● Die Sortierung erlaubt das schnelle Auffinden von Elementen nach ihrem Wert
oder einem zugehörigen Schlüssel.
● Assoziative Container arbeiten mit bidirektionalen Iteratoren.
● Assoziative Container sind set, multiset, map und multimap.
Eigenschaft Beschreibung
X(c) Pendants zu den Konstruktoren der sequentiellen Container, die als
X a(c) zusätzliches Argument ein Compare-Objekt als Vergleichskriterium
X(i,j,c) übernehmen. Ohne Compare-Objekt aufgerufen, wird das Standard-
X a(i,j,c) vergleichsobjekt des Containers (siehe Template-Definition) ver-
wendet.
[Link](... ) Verschiedene überladene Versionen zum Einfügen von Elementen in
den Container
[Link](... ) Verschiedene überladene Versionen zum Löschen von Elementen aus
dem Container
[Link]() Löscht alle Elemente im Container
[Link](k) Liefert einen Iterator auf das erste Element mit Schlüssel k
[Link](k) Liefert die Anzahl der Elemente mit Schlüssel k
a.lower_bound(k) Liefert einen Iterator auf das erste Element, dessen Schlüssel nicht
kleiner als k ist
a.upper_bound(k) Liefert einen Iterator auf das erste Element, dessen Schlüssel größer
als k ist
a.equal_range(k) Liefert die Iteratoren von lower_bound() und upper_bound() als Paar
(siehe make_pair() )
bitset
Flags verwalten (aus Header bitset)
Beschreibung
Die Klasse bitset dient zur Verwaltung einer bestimmten Zahl von Elementen (Bits), die nur
Werte von Null oder Eins annehmen.
Anwendung
Instanzen der Klasse bitset können zur übersichtlichen Verwaltung von Diagnose-
und Schaltervariablen (Flags) herangezogen werden. Gegenüber dem Einsatz der
von C stammenden Bitoperatoren oder der Bitfelder bieten die für bitset zur Verfü-
gung stehenden Methoden und Operatoren mehr Komfort.
360
bitset
Die Anzahl der Bits im Bitset ist unveränderlich und wird durch den Platzhalter N
bei der Spezialisierung des Templates festgelegt. Zur Verwaltung einer variablen
Zahl von Flags kann man auf den Container vector<bool> zurückgreifen.
bitset<4> options; // Bits initialisieren
Die einzelnen Bits im Bitset können direkt bei der Erzeugung des Bitsets mit den
Werten aus einem Integer oder einem String initialisiert werden.
bitset<4> options("0100");
Die Funktionen to_ulong() und to_string() wandeln in umgekehrter Weise ein
Bitset in einen Integer-Wert oder ein String-Objekt um. Die Funktionen set(),
reset(), flip() können zum Setzen aller Bits oder eines bestimmten Bits verwendet
werden. Zur Abfrage einzelner Bits dient die Funktion test(). Zur Manipulation
einzelner Bits ist zudem der Index-Operator [ ] implementiert. Die Operatoren &=,
|= und ^= verwenden ein zweites Bitset zur Manipulation ihrer Instanz.
Warnung
Die Klasse bitset fällt aus dem Rahmen der anderen Container (unterstützt keine
Iteratoren, verfügt nicht über die Grundeigenschaften, etc.).
Referenz
template<size_t N> class bitset {
public:
class reference {
friend class bitset;
reference();
public:
~reference();
reference& operator=(bool x); // für b[i] = x;
reference& operator=(const reference&); // für b[i] = b[j];
bool operator~() const; // dreht das Bit um
operator bool() const; // für x = b[i];
reference& flip(); // für b[i].flip();
};
// Konstruktoren:
bitset();
bitset(unsigned long val);
template<class charT, class traits, class Allocator>
explicit bitset(
const basic_string<charT,traits,Allocator>& str,
typename basic_string<charT,traits,Allocator>::size_type pos = 0,
typename basic_string<charT,traits,Allocator>::size_type n =
basic_string<charT,traits,Allocator>::npos);
// Operatoren:
bitset<N>& operator&=(const bitset<N>& rhs);
bitset<N>& operator|=(const bitset<N>& rhs);
bitset<N>& operator^=(const bitset<N>& rhs);
361
Die C++-Standardbibliothek
Verweise
Siehe Header-Datei bitset
deque
Sequentieller Container (aus Header deque)
Beschreibung
Die Abkürzung deque steht für double ended queue. Dahinter verbirgt sich eine Datenstruktur,
die üblicherweise auf einer Verkettung von Array-Blöcken basiert und ihre Elemente in einer
sequentiellen Folge anordnet.
Die Klasse deque gleicht der Klasse vector und bietet wie diese schnellen direkten Zugriff auf
einzelne Elemente ([]-Operator, Methode at()) sowie Einfügen und Löschen von Elementen an
beliebigen Positionen (insert(), erase()). Anders als der Zugriff auf bestehende Elemente ist
das Einfügen oder Löschen von Elementen allerdings recht zeitaufwendig, da diese Operationen
meist mit dem internen Umkopieren der Elemente im Container verbunden ist. Lediglich am
Anfang oder Ende der Datenstruktur kann in konstanter Zeit eingefügt oder gelöscht werden.
362
deque
Im Verleich zu vector ist der Zugriff auf beliebige Positionen etwas langsamer, dafür ist die
Speicherverwaltung meist günstiger.
Im Vergleich zu einem list-Container ist das Einfügen und Löschen an mittleren Positionen
zeitaufwendiger, dafür erlaubt deque den bequemen indizierten Zugriff auf bestimmte Positio-
nen (zum Lesen oder Schreiben).
Iteratoren für deque-Container sollten mindestens der forward_iterator-Kategorie angehören,
verschiedene Funktionen verlangen aber höhere Iteratorenkategorien. Einfüge- und Löschope-
rationen in der Mitte des Containers führen stets zur Ungültigkeit bestehender Iteratoren und
Referenzen auf Container-Elemente.
Anwendung
Hinter deque steht ein Klassentemplate, aus dem man zuerst eine Container-Klasse
erzeugt. Dabei übergibt man dem ersten Template-Parameter T den Datentyp der zu
verwaltenden Objekte.
deque<int> container;
Die überladenen Formen der Konstruktoren erlauben die Einrichtung leerer Contai-
ner oder Container, die mehrere Kopien eines Elements bzw. die Kopie einer
Sequenz von Elementen aus einem anderen Container enthalten.
Neue Elemente können mittels insert(), push_front(), push_back(), resize() oder
assign() eingefügt werden, wobei letztere Funktion den Container zuvor leert.
Bestehende Elemente können mittels erase(), pop_front(), pop_back(), resize()
oder clear() gelöscht werden.
Zugriff auf einzelne Elemente kann mit Hilfe zurückgelieferter Iteratoren geschehen
(begin(), end(), rbegin(), rend() sowie insert() ) oder über zurückgegebene Refe-
renzen (Operator [], at(), front(), back() ).
Schließlich ist es möglich, über die globalen Funktionen der Header-Datei <algo-
rithm> Container zu manipulieren, zu sortieren, in ihnen zu suchen, etc.
Referenz
template <class T, class Allocator = allocator<T> >
class deque {
public:
typedef typename Allocator::reference reference;
typedef typename Allocator::const_reference const_reference;
typedef implementation defined iterator;
typedef implementation defined const_iterator;
typedef typename Allocator::size_type size_type;
typedef typename Allocator::difference_type difference_type;
typedef T value_type;
typedef Allocator allocator_type;
typedef typename Allocator::pointer pointer;
363
Die C++-Standardbibliothek
364
list
void pop_back();
iterator erase(iterator position);
iterator erase(iterator first, iterator last);
void swap(deque<T,Allocator>&);
void clear();
};
list
Sequentieller Container (aus Header list)
Beschreibung
Das Klassentemplate list repräsentiert wie deque und vector einen sequentiellen Container
mit direktem Zugriff auf das erste und letzte Element sowie Einfügen und Löschen von Elemen-
ten an beliebigen Positionen.
Das Einfügen und Löschen von Elementen an beliebigen Positionen innerhalb des Containers
erfolgt für list schneller als für deque oder vector, da diese Operationen nicht mit dem Ver-
schieben der nachfolgenden Elemente verbunden ist. Dafür fehlt list der indizierte Zugriff auf
Elemente an einer bestimmten Position.
Iteratoren für list-Container sollten mindestens der forward_iterator-Kategorie angehören,
verschiedene Funktionen verlangen aber höhere Iteratorenkategorien. Einfüge- und Löschope-
rationen beeinträchtigen nicht die Gültigkeit bestehender Iteratoren und Referenzen auf Con-
tainer-Elemente.
Anwendung
Hinter list steht ein Klassentemplate, aus dem man zuerst eine Container-Klasse
erzeugt. Dabei übergibt man dem ersten Template-Parameter T den Datentyp der zu
verwaltenden Objekte.
list<int> container;
Die überladenen Formen der Konstruktoren erlauben die Einrichtung leerer Contai-
ner oder Container, die mehrere Kopien eines Elementes bzw. die Kopie einer
Sequenz von Elementen aus einem anderen Container enthalten.
Neue Elemente können mittels insert(), push_front(), push_back(), resize(),
assign() oder merge() eingefügt werden.
Bestehende Elemente können mittels erase(), pop_front(), pop_back(), resize(),
clear(), unique() oder remove(), remove_if() gelöscht werden.
Der Zugriff auf einzelne Elemente kann mit Hilfe zurückgelieferter Iteratoren
geschehen (begin(), end(), rbegin(), rend() sowie insert()) oder über zurückgege-
bene Referenzen (front(), back()).
365
Die C++-Standardbibliothek
Mittels der Funktion sort() können die Elemente sortiert werden, wobei die Art
der Sortierung durch den <-Operator oder eine selbstdefinierte Vergleichsfunktion
bestimmt werden kann. Mittels reverse() kann die Reihenfolge umgekehrt werden.
Schließlich ist es möglich, über die globalen Funktionen der Header-Datei <algo-
rithm> Container zu manipulieren, zu sortieren, in ihnen zu suchen, etc.
Referenz
template <class T, class Allocator = allocator<T> >
class list {
public:
typedef typename Allocator::reference reference;
typedef typename Allocator::const_reference const_reference;
typedef implementation defined iterator;
typedef implementation defined const_iterator;
typedef typename Allocator::size_type size_type;
typedef typename Allocator::difference_type difference_type;
typedef T value_type;
typedef Allocator allocator_type;
typedef typename Allocator::pointer pointer;
typedef typename Allocator::const_pointer const_pointer;
typedef std::reverse_iterator<iterator> reverse_iterator;
typedef std::reverse_iterator<const_iterator>
const_reverse_iterator;
// Konstruktoren und Zuweisung:
explicit list(const Allocator& = Allocator());
explicit list(size_type n, const T& value = T(),
const Allocator& = Allocator());
template <class InputIterator>
list(InputIterator first, InputIterator last,
const Allocator& = Allocator());
list(const list<T,Allocator>& x);
~list();
list<T,Allocator>& operator=(const list<T,Allocator>& x);
template <class InputIterator>
void assign(InputIterator first, InputIterator last);
template <class Size, class T>
void assign(Size n, const T& t = T());
allocator_type get_allocator() const;
// Iteratoren:
iterator begin();
const_iterator begin() const;
iterator end();
const_iterator end() const;
reverse_iterator rbegin();
const_reverse_iterator rbegin() const;
reverse_iterator rend();
const_reverse_iterator rend() const;
// Größe:
bool empty() const;
366
map und multimap
Beschreibung
Die Container map und multimap benutzen Schlüssel, um einen schnellen Zugriff auf ihre Ele-
mente zu gewähren. Die Idee dabei ist, daß den zu verwaltenden Objekten sogenannte Schlüs-
367
Die C++-Standardbibliothek
sel beigeordnet werden (man kennt dies beispielsweise von Arrays, bei denen die einzelnen
Elemente mit Indizes verbunden sind). Ähnlich den Indizes eines Arrays soll aus den Schlüsseln
auf die Lokation des Objekts geschlossen werden können.
In den Containern werden die Elemente nach ihren Schlüsseln sortiert abgelegt. Die Sortierung
erlaubt ein schnelles Auffinden von Elementen nach ihren Schlüsseln. Der Wert eines Schlüssels
eines eingefügten Elements darf nicht geändert werden, da dies die Sortierung zerstören würde.
Iteratoren auf map und multimap müssen von der Kategorie bidirectional sein.
Während die Klasse map nur eindeutige Schlüssel erlaubt, können in multimap mehrere Schlüssel
bezüglich der Vergleichsfunktion identisch sein. Dies bedeutet, daß ein Schlüssel auf mehrere
Objekte verweist, die dann noch extra durchsucht werden müssen, um ein bestimmtes Objekt her-
auszufinden. Dies bedeutet meist verlängerte Laufzeiten bei geringerem Speicherbedarf.
Die Klasse multimap verfügt über keinen Indexoperator [].
Anwendung
Hinter map und multimap stehen Klassentemplates, aus denen man zuerst Container-
Klassen erzeugen muß. Dabei übergibt man dem Template-Parameter Key den
Datentyp der Schlüssel und dem Template-Parameter T den Datentyp der zu ver-
waltenden Objekte.
map<int, string> container;
Zusätzlich kann man als dritten Template-Parameter ein Funktionsobjekt überge-
ben, das festlegt, wie die Elemente im Container anhand der Schlüssel sortiert wer-
den sollen.
map<int, string, greater<int> > container;
Die überladenen Formen der Konstruktoren erlauben die Einrichtung leerer Contai-
ner ebenso wie von Container, die eine Sequenz von Elementen aus einem anderen
Container erhalten. Die Objekte zur Allokation und zum Vergleich können selbst
definiert werden oder aus der Vorgabe übernommen werden.
Neue Elemente können mittels insert() eingefügt werden.
Bestehende Elemente können mittels erase() oder clear() gelöscht werden.
Zugriff auf einzelne Elemente kann mit Hilfe zurückgelieferter Iteratoren geschehen
(begin(), end(), rbegin(), rend(), find(), lower_bound(), upper_bound() sowie
insert()).
Schließlich ist es möglich, über die globalen Funktionen der Header-Datei <algo-
rithm> Container zu manipulieren, zu sortieren, in ihnen zu suchen, etc.
368
map und multimap
Referenz
map <map>
template <class Key, class T, class Compare = less<Key>,
class Allocator = allocator<T> >
class map {
public:
typedef Key key_type;
typedef T mapped_type;
typedef pair<const Key, T> value_type;
typedef Compare key_compare;
typedef Allocator allocator_type;
typedef typename Allocator::reference reference;
typedef typename Allocator::const_reference const_reference;
typedef implementation defined iterator;
typedef implementation defined const_iterator;
typedef typename Allocator::size_type size_type;
typedef typename Allocator::difference_type difference_type;
typedef Allocator::pointer pointer;
typedef Allocator::const_pointer const_pointer;
typedef std::reverse_iterator<iterator> reverse_iterator;
typedef std::reverse_iterator<const_iterator>
const_reverse_iterator;
class value_compare
: public binary_function<value_type,value_type,bool> {
friend class map;
protected:
Compare comp;
value_compare(Compare c) : comp(c) {}
public:
bool operator()(const value_type& x, const value_type& y) const {
return comp([Link], [Link]);
}
};
// Konstruktoren und Zuweisung:
explicit map(const Compare& comp = Compare(), const Allocator& =
Allocator());
template <class InputIterator>
map(InputIterator first, InputIterator last,
const Compare& comp = Compare(), const Allocator& =
Allocator());
map(const map<Key,T,Compare,Allocator>& x);
~map();
map<Key,T,Compare,Allocator>&
operator=(const map<Key,T,Compare,Allocator>& x);
// Iteratoren:
iterator begin();
const_iterator begin() const;
iterator end();
const_iterator end() const;
369
Die C++-Standardbibliothek
reverse_iterator rbegin();
const_reverse_iterator rbegin() const;
reverse_iterator rend();
const_reverse_iterator rend() const;
// Groesse:
bool empty() const;
size_type size() const;
size_type max_size() const;
// Zugriff auf Elemente:
reference operator[](const key_type& x);
// Einfügen und Löschen:
pair<iterator, bool> insert(const value_type& x);
iterator insert(iterator position, const value_type& x);
template <class InputIterator>
void insert(InputIterator first, InputIterator last);
void erase(iterator position);
size_type erase(const key_type& x);
void erase(iterator first, iterator last);
void swap(map<Key,T,Compare,Allocator>&);
void clear();
// Sonstiges:
key_compare key_comp() const;
value_compare value_comp() const;
iterator find(const key_type& x);
const_iterator find(const key_type& x) const;
size_type count(const key_type& x) const;
iterator lower_bound(const key_type& x);
const_iterator lower_bound(const key_type& x) const;
iterator upper_bound(const key_type& x);
const_iterator upper_bound(const key_type& x) const;
pair<iterator,iterator> equal_range(const key_type& x);
pair<const_iterator,const_iterator> equal_range(const key_type& x)
const;
};
multimap <map>
template <class Key, class T, class Compare = less<Key>,
class Allocator = allocator<T> >
class multimap {
public:
typedef Key key_type;
typedef T mapped_type;
typedef pair<const Key,T> value_type;
typedef Compare key_compare;
typedef Allocator allocator_type;
typedef typename Allocator::reference reference;
typedef typename Allocator::const_reference const_reference;
typedef implementation defined iterator;
typedef implementation defined const_iterator;
typedef typename Allocator::size_type size_type;
370
map und multimap
371
Die C++-Standardbibliothek
// Sonstiges:
key_compare key_comp() const;
value_compare value_comp() const;
iterator find(const key_type& x);
const_iterator find(const key_type& x) const;
size_type count(const key_type& x) const;
iterator lower_bound(const key_type& x);
const_iterator lower_bound(const key_type& x) const;
iterator upper_bound(const key_type& x);
const_iterator upper_bound(const key_type& x) const;
pair<iterator,iterator> equal_range(const key_type& x);
pair<const_iterator,const_iterator> equal_range(const key_type& x)
const;
};
priority_queue
Sequentieller Container (aus Header queue)
Beschreibung
Eine priority_queue ist eine Warteschlange, die sicherstellt, daß Lese- und Löschzugriffe
immer das Element höchster Priorität betreffen.
Warteschlangen werden üblicherweise zum differenzierten Abarbeiten zeitlich geordneter Ein-
gaben/Befehle eingesetzt. Die Eingaben werden aufgrund bestimmter Eigenschaften (Größe,
Wert einer Variablen etc.) mit einer Priorität versehen. Bei der Abarbeitung überspringen dann
Eingaben höherer Priorität alle anderen Eingaben, während Eingaben gleicher Priorität in der
Reihenfolge ihres zeitlichen Auftretens bearbeitet werden.
Anwendung
Die Klasse priority_queue implementiert keinen wirklich neuen Container. Statt
dessen verwendet sie eine protected-Instanz eines sequentiellen Containers und
macht nur diejenigen Methoden dieser Containerklasse zugänglich (durch Defini-
tion eigener public-Methoden, die lediglich die entsprechenden Methoden der Con-
tainerklasse aufrufen), die für die Implementierung einer Prioritätswarteschlange
nötig sind.
Hinter priority_queue steht ein Klassentemplate, aus dem man zuerst eine Contai-
ner-Klasse erzeugen muß. Dabei übergibt man dem ersten Template-Parameter T
den Datentyp der zu verwaltenden Objekte.
priority_queue<int> container;
Zusätzlich kann man als zweiten Template-Parameter einen Container spezifizie-
ren, der intern zur Verwahrung der Elemente verwendet wird. Der übergebene
Container muß über die Methoden empty(), size(), front(), back(), push_back(),
372
queue
Referenz
template <class T, class Container = vector<T>,
class Compare = less<Container::value_type> >
class priority_queue {
public:
typedef typename Container::value_type value_type;
typedef typename Container::size_type size_type;
typedef typename Container container_type;
protected:
Container c;
Compare comp;
public:
explicit priority_queue(const Compare& x = Compare(),
const Container& = Container());
template <class InputIterator>
priority_queue(InputIterator first, InputIterator last,
const Compare& x = Compare(),
const Container& = Container());
bool empty() const { return [Link](); }
size_type size() const { return [Link](); }
const value_type& top() const { return [Link](); }
void push(const value_type& x);
void pop();
};
queue
Sequentieller Container (aus Header queue)
Beschreibung
Eine queue oder Warteschlange ist eine sequentielle Datenstruktur, die das Einfügen neuer Ele-
mente nur an ihrem Ende, und das Löschen von Elementen nur am Anfang erlaubt eben ganz
so wie eine echte Warteschlange.
Warteschlangen werden üblicherweise zum differenzierten Abarbeiten zeitlich geordneter Ein-
gaben/Befehle eingesetzt.
373
Die C++-Standardbibliothek
Anwendung
Die Klasse queue implementiert keinen wirklich neuen Container. Statt dessen ver-
wendet sie eine protected-Instanz eines sequentiellen Containers und macht nur die-
jenigen Methoden dieser Containerklasse zugänglich (durch Definition eigener
public-Methoden, die lediglich die entsprechenden Methoden der Containerklasse
aufrufen), die für die Implementierung einer Warteschlange nötig sind.
Hinter queue steht ein Klassentemplate, aus dem man zuerst eine Container-Klasse
erzeugen muß. Dabei übergibt man dem ersten Template-Parameter T den Datentyp
der zu verwaltenden Objekte.
queue<int> container;
Zusätzlich kann man als zweiten Template-Parameter einen Container spezifizie-
ren, der intern zur Verwahrung der Elemente verwendet wird. Der übergebene
Container muß über die Methoden empty(), size(), front(), back(), push_back(),
pop_front() verfügen (wie beispielsweise list oder deque, aber nicht vector). Stan-
dardmäßig wird ein deque<T>-Container verwendet.
queue<int, list<int> > container;
Referenz
template <class T, class Container = deque<T> >
class queue {
public:
typedef typename Container::value_type value_type;
typedef typename Container::size_type size_type;
typedef typename Container container_type;
protected:
Container c;
public:
explicit queue(const Container& = Container());
bool empty() const { return [Link](); }
size_type size() const { return [Link](); }
value_type& front() { return [Link](); }
const value_type& front() const { return [Link](); }
value_type& back() { return [Link](); }
const value_type& back() const { return [Link](); }
void push(const value_type& x) { c.push_back(x); }
void pop() { c.pop_front(); }
};
374
set und multiset
Beschreibung
Die Klassen set und multiset sind praktisch identisch zu map und multimap, mit dem Unter-
schied, daß map (multimap) ihre Schlüssel einsetzen, um schnellen Zugriff auf Objekte eines
anderen Typs zu gewähren, wohingegen für set (multiset) die Werte (Objekte) selbst die
Schlüssel darstellen.
Für set und multiset gilt daher:
● value_type = key_type = Key.
● value_compare = key_compare = Vergl.
● Index-Operator [] ist nicht definiert.
Anwendung
Hinter set und multiset stehen Klassentemplates, aus denen man zuerst Container-
Klassen erzeugen muß. Dabei übergibt man dem Template-Parameter T den Daten-
typ der zu verwaltenden Objekte.
set<int> container;
Zusätzlich kann man als zweiten Template-Parameter ein Funktionsobjekt überge-
ben, das festlegt, wie die Elemente im Container sortiert werden soll.
set<int, greater<int> > container;
Referenz
set <set>
template <class Key, class Compare = less<Key>,
class Allocator = allocator<Key> >
class set {
public:
typedef Key key_type;
typedef Key value_type;
typedef Compare key_compare;
typedef Compare value_compare;
typedef Allocator allocator_type;
typedef typename Allocator::reference reference;
typedef typename Allocator::const_reference const_reference;
typedef implementation defined iterator;
typedef implementation defined const_iterator;
typedef typename Allocator::size_type size_type;
typedef typename Allocator::difference_type difference_type;
typedef typename Allocator::pointer pointer;
typedef typename Allocator::const_pointer const_pointer;
375
Die C++-Standardbibliothek
set <set>
template <class Key, class Compare = less<Key>,
class Allocator = allocator<Key> >
376
set und multiset
class multiset {
public:
typedef Key key_type;
typedef Key value_type;
typedef Compare key_compare;
typedef Compare value_compare;
typedef Allocator allocator_type;
typedef typename Allocator::reference reference;
typedef typename Allocator::const_reference const_reference;
typedef implementation defined iterator;
typedef implementation defined const_iterator;
typedef typename Allocator::size_type size_type;
typedef typename Allocator::difference_type difference_type;
typedef typename Allocator::pointer pointer;
typedef typename Allocator::const_pointer const_pointer;
typedef std::reverse_iterator<iterator> reverse_iterator;
typedef std::reverse_iterator<const_iterator>
const_reverse_iterator;
// Konstruktoren und Zuweisung:
explicit multiset(const Compare& comp = Compare(),
const Allocator& = Allocator());
template <class InputIterator>
multiset(InputIterator first, InputIterator last,
const Compare& comp = Compare(), const Allocator& =
Allocator());
multiset(const multiset<Key,Compare,Allocator>& x);
~multiset();
multiset<Key,Compare,Allocator>&
operator=(const multiset<Key,Compare,Allocator>& x);
allocator_type get_allocator() const;
// Iteratoren:
iterator begin();
const_iterator begin() const;
iterator end();
const_iterator end() const;
reverse_iterator rbegin();
const_reverse_iterator rbegin() const;
reverse_iterator rend();
const_reverse_iterator rend() const;
// Größe:
bool empty() const;
size_type size() const;
size_type max_size() const;
// Einfügen und Löschen:
iterator insert(const value_type& x);
iterator insert(iterator position, const value_type& x);
template <class InputIterator>
void insert(InputIterator first, InputIterator last);
void erase(iterator position);
size_type erase(const key_type& x);
377
Die C++-Standardbibliothek
stack
Sequentieller Container (aus Header stack)
Beschreibung
Ein Stack oder Keller ist eine sequentielle Datenstruktur, die Einfügen und Löschen nur an
ihrem Ende erlaubt.
Keller, Stapel oder Stack bezeichnen eine Datenstruktur, die Zugriffe nur auf ihrem Ende
erlaubt. Sie verhält sich also ähnlich wie ein Stapel Bücher, auf den sich weitere Bücher schich-
ten lassen und dessen oberstes Buch entfernt werden kann, während das Einschieben oder Ent-
fernen eines Buches in der Mitte des Stapels verboten ist. Für die Verarbeitung von Eingaben
bedeutet dies, daß die letzte Eingabe als erste abgearbeitet wird, also gerade umgekehrt wie
bei einer queue.
Anwendung
Die Klasse stack implementiert keinen wirklich neuen Container. Statt dessen ver-
wendet sie eine protected-Instanz eines sequentiellen Containers und macht nur die-
jenigen Methoden dieser Container-Klasse zugänglich (durch Definition eigener
public-Methoden, die lediglich die entsprechenden Methoden der Container-Klasse
aufrufen), die für die Implementierung eines Stacks nötig sind.
Hinter stack steht ein Klassentemplate, aus dem man zuerst eine Container-Klasse
erzeugen muß. Dabei übergibt man dem ersten Template-Parameter T den Datentyp
der zu verwaltenden Objekte.
stack<int> container;
Zusätzlich kann man als zweiten Template-Parameter einen Container spezifizie-
ren, der intern zur Verwahrung der Elemente verwendet wird. Der übergebene
Container muß über die Methoden empty(), size(), back(), push_back(),
pop_back() verfügen (wie beispielsweise list, vector oder deque). Standardmäßig
wird ein deque<T>-Container verwendet.
378
vector
Referenz
template <class T, class Container = deque<T> >
class stack {
public:
typedef typename Container::value_type value_type;
typedef typename Container::size_type size_type;
typedef typename Container container_type;
protected:
Container c;
public:
explicit stack(const Container& = Container());
bool empty() const { return [Link](); }
size_type size() const { return [Link](); }
value_type& top() { return [Link](); }
const value_type& top() const { return [Link](); }
void push(const value_type& x) { c.push_back(x); }
void pop() { c.pop_back(); }
};
vector
Sequentieller Container (aus Header vector)
Beschreibung
Die Klasse vector bietet wie ein Array schnellen, direkten Zugriff auf einzelne Elemente ([]-
Operator, at()-Methode) sowie Einfügen und Löschen von Elementen an beliebigen Positionen
(letzteres allerdings nur in linearer Zeit, da diese Operationen mit dem internen Verschieben
der anderen Container-Elemente verbunden sind). Schneller, in konstanter Zeit, kann man nur
am Ende der Datenstruktur einfügen oder löschen.
Im Gegensatz zu deque ist vector also nur für das Einfügen und Löschen am Ende der Daten-
struktur optimiert. Dafür ist der Zugriff auf beliebige Positionen etwas schneller als bei deque.
Im Vergleich zu einem list-Container ist das Einfügen und Löschen an mittleren Positionen
zeitaufwendiger, dafür erlaubt vector den bequemen indizierten Zugriff auf bestimmte Positio-
nen (zum Lesen oder Schreiben).
Iteratoren für vector-Container sollten mindestens der forward_iterator-Kategorie angehö-
ren, verschiedene Funktionen verlangen aber höhere Iteratorenkategorien. Einfüge- und
Löschoperationen führen unter Umständen zur Ungültigkeit bestehender Iteratoren und Refe-
renzen auf Container-Elemente.
379
Die C++-Standardbibliothek
Anwendung
Hinter vector steht ein Klassentemplate, aus dem man zuerst eine Container-Klasse
erzeugt. Dabei übergibt man dem ersten Template-Parameter T den Datentyp der zu
verwaltenden Objekte.
vector<int> container;
Die überladenen Formen der Konstruktoren erlauben die Einrichtung leerer Contai-
ner oder Container, die mehrere Kopien eines Elements bzw. die Kopie einer
Sequenz von Elementen aus einem anderen Container enthalten.
Neue Elemente können mittels insert(), push_back(), resize() oder assign() einge-
fügt werden, wobei letztere Funktion den Container zuvor leert.
Bestehende Elemente können mittels erase(), pop_back(), resize() oder clear()
gelöscht werden.
Der Zugriff auf einzelne Elemente kann mit Hilfe zurückgelieferter Iteratoren
geschehen (begin(), end(), rbegin(), rend() sowie insert() ) oder über zurückge-
gebene Referenzen (Operator [], at(), front(), back() ).
Schließlich ist es möglich, über die globalen Funktionen der Header-Datei <algo-
rithm> Container zu manipulieren, zu sortieren, in ihnen zu suchen, etc.
Referenz
template <class T, class Allocator = allocator<T> >
class vector {
public:
typedef typename Allocator::reference reference;
typedef typename Allocator::const_reference const_reference;
typedef implementation defined iterator;
typedef implementation defined const_iterator;
typedef typename Allocator::size_type size_type;
typedef typename Allocator::difference_type difference_type;
typedef T value_type;
typedef Allocator allocator_type;
typedef typename Allocator::pointer pointer;
typedef typename Allocator::const_pointer const_pointer
typedef std::reverse_iterator<iterator> reverse_iterator;
typedef std::reverse_iterator<const_iterator>
const_reverse_iterator;
// Konstruktoren und Zuweisung:
explicit vector(const Allocator& = Allocator());
explicit vector(size_type n, const T& value = T(),
const Allocator& = Allocator());
template <class InputIterator>
vector(InputIterator first, InputIterator last,
const Allocator& = Allocator());
vector(const vector<T,Allocator>& x);
~vector();
380
vector
381
Die C++-Standardbibliothek
Die Iteratoren-Klassen
Allgemeines
Beschreibung
Iteratoren sind Abstraktionen von Zeigern und dienen dazu, auf Elemente von Container
zugreifen zu können.
Anwendung
Iteratoren werden von den Algorithmen verwendet, um auf die Elemente aus den
verschiedensten Container zuzugreifen. Das Problem, das hierbei auftaucht und
weswegen die STL mit Iteratoren arbeitet, besteht darin, daß der Algorithmus mit
einer feststehenden Syntax über die Iteratoren auf die Elemente im Container
zugreifen und gegebenenfalls von Element zu Element springen möchte. Auf der
anderen Seite liegen den Containern unterschiedliche Datenstrukturen (dynamische
Arrays, Listen, Bäume, etc.) zugrunde, für die Operationen wie das Springen von
Element zu Element ganz unterschiedlich gelöst sind. Aus diesem Grunde imple-
mentieren die Container ihre Iteratoren selbst und halten sich dabei an die für Ite-
ratoren typische Schnittstelle, so daß diese von den Algorithmen verwendet werden
können.
Nach dem Leistungsumfang der Iteratoren unterscheidet man verschiedene Iterator-
Kategorien.
Die Iteratoren-Kategorien
Die Kategorie eines Iterators bestimmt seine Leistungsfähigkeit und damit sein Ein-
satzgebiet.
Kategorie output_iterator
Mit Output-Iteratoren kann man die Elemente eines Containers durchlaufen und
den Wert der Elemente verändern, nicht aber lesen. Außerdem können Sie sich mit
einem Input-Iterator von der Position seiner Initialisierung an nur in Richtung des
Container-Endes bewegen, d. h., Sie können einen Input-Iterator inkrementieren
(++), aber nicht dekrementieren (--).
Zum Einfügen neuer Werte in einen Container dienen spezielle Adaptionen – die
sogenannten Insert-Iteratoren, die Zuweisungen an das Element des Iterators in
eine Einfüge-Operation umsetzen.
382
Allgemeines
Anforderungen
● Kopierkonstruktor und Destruktor
● Zuweisung =
● Dereferenzierung zum Schreiben *i = t
● Inkrement ++i, i++
Kategorie input_iterator
Mit Input-Iteratoren kann man auf Container-Elemente zugreifen, um ihre Werte
auszulesen, aber man kann die Elemente nicht verändern. Außerdem können Sie
sich mit einem Input-Iterator von der Position seiner Initialisierung an nur in Rich-
tung des Container-Endes bewegen, d. h., Sie können einen Input-Iterator inkre-
mentieren (++), aber nicht dekrementieren (--).
Anforderungen an Iterator
● Kopierkonstruktor und Destruktor
● Zuweisung =
● Vergleich ==, wobei aus i == j auch *I == *j folgt (allerdings nicht ++i == ++j)
● Vergleich !=
● Dereferenzierung zum Lesen *i, j->m
● Inkrement ++i, i++
Kategorie forward_iterator
Forward-Iteratoren können zum Lesen und Schreiben verwendet werden. Mit For-
ward-Iteratoren kann man sich zwar auch nur mit Hilfe des Inkrement-Operators
in Richtung Container-Ende bewegen, doch kann man mit Kopien eines Forward-
Iterators einen Container mehrfach durchlaufen.
Anforderungen an Iterator (zusätzlich zu input_iterator)
● Konstruktor zum Erzeugen
● Dereferenzierung zum Schreiben: *i = t
Kategorie bidirectional_iterator
Bidirektionale Iteratoren verfügen über alle Eigenschaften von Forward-Iteratoren,
sowie die Möglichkeit, einen Container vorwärts wie rückwärts zu durchlaufen.
Anforderungen an Iterator (zusätzliche)
● Dekrement --i, i--
● *i--
383
Die C++-Standardbibliothek
Kategorie random_acces_iterator
Random Access-Iteratoren verfügen über alle Eigenschaften von Bidirectional-Itera-
toren, sowie Vergleichsoperationen und die Möglichkeit, auf Elemente direkt zuzu-
greifen, statt alle dazwischenliegenden Elemente zu durchlaufen.
Anforderungen an Iterator (zusätzliche)
● Vorwärtssprünge i += n, a + n
● Rückwärtssprünge i -= n, a- n
● Distanz i – j
● Indizierung i[n]
● Vergleiche i < j, i <= j, i > j, i >= j
reverse_iterator
aus <iterator>
Beschreibung
Eine Instanz der Klasse reverse_iterator ist eine Adaption eines bidirektionalen oder Random
Access-Iterators, mit dem man in umgekehrter Richtung durch einen Container laufen kann,
wobei gilt:
&*(reverse_iterator(i)) == &*(i-1)
Ein reverse_iterator ist somit ein Iterator, der eine Erhöhung in eine Verringerung und eine
Verringerung in eine Erhöhung umsetzt. So kann man eine Funktion, die einen Iterator von
vorne nach hinten durch eine Folge von Elementen laufen läßt, die Folge durch Übergabe eines
umkehrenden Iterators auch in umgekehrter Reihenfolge durchlaufen lassen.
Anwendung
Umkehrende Iteratoren kann man sich beispielsweise von den Container-Methoden
rbegin() und rend() zurückliefern lassen.
// Elemente eines Containers rueckwaerts ausgeben
typedef vector<int>::reverse_iterator r_iter;
for(r_iter i = [Link](); i != [Link](); i++)
cout << *i << endl;
384
Insert-Iteratoren
Referenz
template <class Iterator>
class reverse_iterator :
public iterator<iterator_traits<Iterator>::iterator_category,
iterator_traits<Iterator>::value_type,
iterator_traits<Iterator>::difference_type,
iterator_traits<Iterator>::pointer,
iterator_traits<Iterator>::reference> {
protected:
Iterator current;
public:
typedef Iterator iterator_type;
reverse_iterator();
explicit reverse_iterator(Iterator x);
Iterator base() const;
Reference operator*() const;
Pointer operator->() const;
reverse_iterator& operator++();
reverse_iterator operator++(int);
reverse_iterator& operator--();
reverse_iterator operator--(int);
reverse_iterator operator+ (Distance n) const;
reverse_iterator& operator+=(Distance n);
reverse_iterator operator- (Distance n) const;
reverse_iterator& operator-=(Distance n);
Reference operator[](Distance n) const;
};
Insert-Iteratoren
Beschreibung
Insert-Iteratoren sind Iteratoren-Adapter, die eine Kopiersyntax (Überschreiben) in eine Einfü-
geoperation umwandeln.
Anwendung
Auf diese Weise kann man Algorithmen, die Elemente mit Hilfe von Iteratoren
kopieren, durch Übergabe von Insert-Iteratoren auch zum Einfügen verwenden.
Insert-Iteratoren läßt man sich meist von einer der zugehörigen Funktionentempla-
tes back_inserter(), front_inserter(), inserter() (siehe unten) zurückliefern, denen
man bei der Instanziierung die Container-Klasse, auf der der Iterator operieren soll,
als Template-Parameter übergibt.
Die Iteratoren selbst verwenden eine Referenz auf den assoziierten Container und
Operatoren zum Durchlaufen und Einfügen in den Container.
385
Die C++-Standardbibliothek
Beispiel
copy([Link](), [Link](),
back_inserter(container));
oder auch
back_insert_iterator<vector<int> > b_iter(container);
b_iter = 333; // Ans Container-Ende anhaengen
back_insert_iterator <iterator>
Der Iterator wird direkt für einen Container erzeugt und ermöglicht das komforta-
ble Einfügen von Elementen am Ende des Containers.
Die Implementierung von back_insert_iterator benutzt zum Einfügen die push_back-
Methode des Containers. Folglich kann ein back_insert-Iterator nur auf Container
angewendet werden, für die diese Methode definiert ist (vector, deque, list).
template <class Container>
class back_insert_iterator :
public iterator<output_iterator_tag,void,void,void,void> {
protected:
Container& container;
public:
typedef Container container_type;
explicit back_insert_iterator(Container& x);
back_insert_iterator<Container>&
operator=(const typename Container::value_type& value);
back_insert_iterator<Container>& operator*();
back_insert_iterator<Container>& operator++();
back_insert_iterator<Container> operator++(int);
};
template <class Container>
back_insert_iterator<Container> back_inserter(Container& x);
front_insert_iterator <iterator>
Der Iterator wird direkt für einen Container erzeugt und ermöglicht das komforta-
ble Einfügen von Elementen am Anfang des Containers.
Die Implementierung von front_insert_iterator benutzt zum Einfügen die
push_front-Methode des Containers. Folglich kann ein front_insert-Iterator nur auf
Container angewendet werden, für die diese Methode definiert ist (deque, list).
template <class Container>
class front_insert_iterator :
public iterator<output_iterator_tag,void,void,void,void> {
protected:
Container& container;
public:
typedef Container container_type;
explicit front_insert_iterator(Container& x);
386
Stream-Iteratoren
front_insert_iterator<Container>&
operator=(const typename Container::value_type& value);
front_insert_iterator<Container>& operator*();
front_insert_iterator<Container>& operator++();
front_insert_iterator<Container> operator++(int);
};
template <class Container>
front_insert_iterator<Container> front_inserter(Container& x);
insert_iterator <iterator>
Der Iterator wird direkt für einen Container erzeugt und ermöglicht das komforta-
ble Einfügen von Elementen am Anfang des Containers.
template <class Container>
class insert_iterator :
public iterator<output_iterator_tag,void,void,void,void> {
protected:
Container& container;
typename Container::iterator iter;
public:
typedef Container container_type;
insert_iterator(Container& x, typename Container::iterator i);
insert_iterator<Container>&
operator=(const typename Container::value_type& value);
insert_iterator<Container>& operator*();
insert_iterator<Container>& operator++();
insert_iterator<Container>& operator++(int);
};
template <class Container, class Iterator>
insert_iterator<Container> inserter(Container& x, Iterator i);
Stream-Iteratoren
Beschreibung
Stream-Iteratoren sind Adapter, mit deren Hilfe man auf Iteratoren beruhende Algorithmen
(allgemeiner Funktionen) zum Einlesen aus oder Schreiben in Dateien nutzen kann. Die »Con-
tainer-Elemente«, auf die der Iterator zugreift, sind dann die Ein- und Ausgaben.
Anwendung
Bei der Instanziierung des Iterators aus seinem Klassentemplate wird als Template-
Parameter der Datentyp der »Container-Elemente« übergeben. Den Stream, auf
dem operiert wird, kann man dem Konstruktor übergeben.
387
Die C++-Standardbibliothek
Beispiel
// Über istream_iterator Container-Elemente einlesen
copy(istream_iterator<int>(cin), istream_iterator<int>(),
back_inserter(container));
ostream_iterator<int, char> (cout,"\n"));
// Über ostream_iterator Container-Elemente ausgeben
copy([Link](), [Link](),
ostream_iterator<int, char> (cout,"\n"));
istream_iterator <iterator>
Der Iterator ist zum Lesen von Daten aus einem Stream konzipiert. Da er von der
Klasse input_iterator abgeleitet ist, ist er nur für einmalige Durchläufe zu gebrau-
chen.
Die Tatsache, daß es sich um einen Input-Iterator und keinen Forward-Iterator
handelt (letzterer würde mehrfache Durchläufe erlauben), sollte seinen Nutzen
nicht einschränken, da die eingelesenen Daten üblicherweise im Arbeitsspeicher
gepuffert werden, wo entsprechende Operationen wesentlich schneller ausgeführt
werden können.
ostream_iterator <iterator>
Der Iterator ist zur Ausgabe von Daten in einen Stream konzipiert. Da er von der
Klasse output_iterator abgeleitet ist, ist er nur für einmalige Durchläufe zu gebrau-
chen.
Die Tatsache, daß es sich um einen Output-Iterator und keinen Forward-Iterator
handelt (letzterer würde mehrfache Durchläufe erlauben), sollte seinen Nutzen
388
Stream-Iteratoren
istreambuf_iterator <iterator>
Der Iterator ist zum Lesen von Zeichen aus einem basic_streambuf-Objekt konzi-
piert. Der Iterator ist nur für einmalige Durchläufe zu gebrauchen.
template<class charT, class traits = char_traits<charT> >
class istreambuf_iterator
: public iterator<input_iterator_tag, charT,
typename traits::off_type, charT*, charT&> {
public:
typedef charT char_type;
typedef traits traits_type;
typedef typename traits::int_type int_type;
typedef basic_streambuf<charT,traits> streambuf_type;
typedef basic_istream<charT,traits> istream_type;
istreambuf_iterator() throw();
istreambuf_iterator(istream_type& s) throw();
istreambuf_iterator(streambuf_type* s) throw();
istreambuf_iterator(const proxy& p) throw();
charT operator*() const;
istreambuf_iterator<charT,traits>& operator++();
proxy operator++(int);
bool equal(istreambuf_iterator& b);
};
389
Die C++-Standardbibliothek
ostreambuf_iterator <iterator>
Der Iterator ist zum Schreiben von Zeichen in ein basic_streambuf-Objekt konzi-
piert. Der Iterator ist nur für einmalige Durchläufe zu gebrauchen.
Der Dereferenzierungsoperator darf nur auf der linken Seite von Zuweisungen ste-
hen.
template <class charT, class traits = char_traits<charT> >
class ostreambuf_iterator :
iterator<output_iterator_tag,void,void,void,void>{
public:
typedef charT char_type;
typedef traits traits_type;
typedef basic_streambuf<charT,traits> streambuf_type;
typedef basic_ostream<charT,traits> ostream_type;
public:
ostreambuf_iterator(ostream_type& s) throw();
ostreambuf_iterator(streambuf_type* s) throw();
ostreambuf_iterator& operator=(charT c);
ostreambuf_iterator& operator*();
ostreambuf_iterator& operator++();
ostreambuf_iterator& operator++(int);
bool failed() const throw();
};
390
Unterstützung eigener Implementierungen
Iterator-Tags <iterator>
struct input_iterator_tag {};
struct output_iterator_tag {};
struct forward_iterator_tag: public input_iterator_tag {};
struct bidirectional_iterator_tag: public forward_iterator_tag {};
struct random_access_iterator_tag: public bidirectional_iterator_tag {};
Diese Strukturen dienen dazu, als Funktions- oder Template-Parameter die Anpas-
sung an die verschiedenen Iterator-Kategorien zu ermöglichen.
Beispiel
Das folgende Beispiel enthält zwei Funktionen für bidirektionale und Random
Access-Iteratoren und eine Kapselfunktion, die je nach übergebenem Iterator-Typ
die am besten passende Implementierung aufruft:
template <class mindestensBDIter>
inline void tu_was(mindestensBDIter first, mindestensBDIter last) {
tu_was(first, last,
iterator_traits<mindestensBDIter>::iterator_category());
}
391
Die C++-Standardbibliothek
advance() <iterator>
template <class InIter, class Distance>
void advance(InIter& i, Distance n);
Verschiebt den Iterator um n Positionen (mittels +/- oder ++/--)
distance() <iterator>
template <class InIter>
iterator_traits<InIter>::difference_type distance(InIter& i,InIter& j);
Liefert die Distanz (Anzahl Inkrement/Dekrementoperationen) zwischen i und j.
Die Algorithmen
Beschreibung
Die Algorithmen sind eine Sammlung von Funktionentemplates, die für beliebige Datentypen
spezialisiert und per Iteratoren auf die Objekte von Containern angewendet werden können.
Anwendung
Da die Algorithmen nicht als Methoden der Container-Templates, sondern als
eigenständige Templates implementiert sind, erfolgt die Verbindung zu den Elemen-
ten im Container über Iteratoren. Dies hat beispielsweise den Vorteil, daß die Algo-
rithmen nicht für jeden Container einzeln implementiert werden müssen und auch
auf selbst definierte Container (inklusive Arrays und dynamische Felder) angewen-
det werden können.
Voraussetzung ist allerdings, daß die Schnittstelle zwischen Algorithmus und Con-
tainer stimmt. Die Schnittstelle sind die Iteratoren. In der folgenden Aufzählung
können Sie daher an den Namen der Iterator-Template-Parameter ablesen, welchen
Anforderungen der Iterator, der dem Algorithmus übergeben wird, genügen muß.
Wenn die Schnittstelle stimmt, ist die Anwendung der Algorithmen auf Container-
Elemente ganz einfach:
deque<int> container(5);
...
fill([Link](), [Link](), 4);
oder
int feld[30];
...
fill(&feld[0], &feld[30], 3);
392
Unterstützung eigener Implementierungen
Etliche der Algorithmen benötigen zur Ausführung ihrer Operation noch ein weite-
res Argument, üblicherweise:
● einen Wert (beispielsweise fill(), das den Elementen den übergebenen Wert
zuweist)
● oder ein Funktionsobjekt, das meist eine Bedingung spezifiziert, die erfüllt sein
muß, damit die Operation des Algorithmus auf ein Element angewendet wird
(z. B. make_heap() wandelt einen Bereich in einen Heap um. Durch Übergabe ei-
nes Funktionsobjekts kann man eine Vergleichsfunktion übergeben, die die
Sortierung des Heaps festlegt.)
Funktionsobjekte, die Vergleiche durchführen, werden in der nachfolgenden
Auflistung der Algorithmen als Compare bezeichnet, Funktionsobjekte, die auf
einen oder zwei dereferenzierte Iteratoren angewendet und dann einen bool-
Wert zurückliefern, werden als Predicate oder BinaryPredicate bezeichnet.
Oft sind die Templates der Algorithmen überladen, so daß ein und derselbe Algo-
rithmus mit verschiedenen Argumenten aufgerufen werden kann. So kann der
Algorithmus find() nach einem Element suchen, das entweder einen bestimmten
Wert enthält oder eine bestimmte Bedingung erfüllt.
Aus numeric:
template <class InputIter, class T>
accumulate(InputIter first, InputIter last, T init);
template <class InputIter, class T, class BinaryOperation>
accumulate(InputIter first, InputIter last, T init,
BinaryOperation binary_op);
template <class InputIter, class OutputIter>
OutputIter adjacent_difference(InputIter first, InputIter last,
OutputIter result);
template <class InputIter, class OutputIter, class BinaryOperation>
OutputIter adjacent_difference(InputIter first, InputIter last,
OutputIter result,
BinaryOperation binary_op);
template <class InputIter1, class InputIter2, class T>
T inner_product(InputIter1 first1, InputIter1 last1,
InputIter2 first2, T init);
template <class InputIter1, class InputIter2, class T,
class BinaryOperation1, class BinaryOperation2>
T inner_product(InputIter1 first1, InputIter1 last1,
InputIter2 first2, T init,
BinaryOperation1 binary_op1, BinaryOperation2 binary_op2);
template <class InputIter, class OutputIter>
OutputIter partial_sum(InputIter first, InputIter last,
OutputIter result);
template <class InputIter, class OutputIter, class BinaryOperation>
OutputIter partial_sum(InputIter first, InputIter last,
OutputIter result, BinaryOperation binary_op);
Aus algorithm:
393
Die C++-Standardbibliothek
template<class ForwardIter>
ForwardIter adjacent_find(ForwardIter first, ForwardIter last);
template<class ForwardIter, class BinaryPredicate>
ForwardIter adjacent_find(ForwardIter first, ForwardIter last,
BinaryPredicate pred);
template<class ForwardIter, class T>
bool binary_search(ForwardIter first,ForwardIter last,const T& value);
template<class ForwardIter, class T, class Compare>
bool binary_search(ForwardIter first, ForwardIter last,
const T& value, Compare comp);
template<class InputIter, class T>
Iter_traits<InputIter>::difference_type
count(InputIter first, InputIter last, const T& value);
template<class InputIter, class Predicate>
Iter_traits<InputIter>::difference_type
count_if(InputIter first, InputIter last, Predicate pred);
template<class InputIter, class OutputIter>
OutputIter copy(InputIter first, InputIter last, OutputIter result);
template<class BidirectionalIter1, class BidirectionalIter2>
BidirectionalIter2 copy_backward(BidirectionalIter1 first,
BidirectionalIter1 last,
BidirectionalIter2 result);
template<class InputIter1, class InputIter2>
bool equal(InputIter1 first1, InputIter1 last1, InputIter2 first2);
template<class InputIter1, class InputIter2, class BinaryPredicate>
bool equal(InputIter1 first1, InputIter1 last1,
InputIter2 first2, BinaryPredicate pred);
template<class ForwardIter, class T>
pair<ForwardIter, ForwardIter>
equal_range(ForwardIter first, ForwardIter last, const T& value);
template<class ForwardIter, class T, class Compare>
pair<ForwardIter, ForwardIter>
equal_range(ForwardIter first, ForwardIter last, const T& value,
Compare comp);
template<class ForwardIter, class T>
void fill(ForwardIter first, ForwardIter last, const T& value);
template<class OutputIter, class Size, class T>
void fill_n(OutputIter first, Size n, const T& value);
template<class InputIter, class T>
InputIter find(InputIter first, InputIter last, const T& value);
template<class ForwardIter1, class ForwardIter2>
ForwardIter1 find_end(ForwardIter1 first1, ForwardIter1 last1,
ForwardIter2 first2, ForwardIter2 last2);
template<class ForwardIter1, class ForwardIter2, class BinaryPredicate>
ForwardIter1 find_end(ForwardIter1 first1, ForwardIter1 last1,
ForwardIter2 first2, ForwardIter2 last2,
BinaryPredicate pred);
template<class ForwardIter1, class ForwardIter2>
ForwardIter1 find_first_of(ForwardIter1 first1, ForwardIter1 last1,
ForwardIter2 first2, ForwardIter2 last2);
394
Unterstützung eigener Implementierungen
395
Die C++-Standardbibliothek
396
Unterstützung eigener Implementierungen
RandomAccessIter
partial_sort_copy(InputIter first, InputIter last,
RandomAccessIter result_first,
RandomAccessIter result_last,
Compare comp);
template<class BidirectionalIter, class Predicate>
BidirectionalIter partition(BidirectionalIter first,
BidirectionalIter last, Predicate pred);
template<class RandomAccessIter>
void pop_heap(RandomAccessIter first, RandomAccessIter last);
template<class RandomAccessIter, class Compare>
void pop_heap(RandomAccessIter first, RandomAccessIter last,
Compare comp);
template<class BidirectionalIter>
bool prev_permutation(BidirectionalIter first,
BidirectionalIter last);
template<class BidirectionalIter, class Compare>
bool prev_permutation(BidirectionalIter first,
BidirectionalIter last, Compare comp);
template<class RandomAccessIter>
void push_heap(RandomAccessIter first, RandomAccessIter last);
template<class RandomAccessIter, class Compare>
void push_heap(RandomAccessIter first, RandomAccessIter last,
Compare comp);
template<class RandomAccessIter>
void random_shuffle(RandomAccessIter first, RandomAccessIter last);
template<class RandomAccessIter, class RandomNumberGenerator>
void random_shuffle(RandomAccessIter first, RandomAccessIter last,
RandomNumberGenerator& rand);
template<class ForwardIter, class T>
ForwardIter remove(ForwardIter first, ForwardIter last,const T& value);
template<class InputIter, class OutputIter, class T>
OutputIter remove_copy(InputIter first, InputIter last,
OutputIter result, const T& value);
template<class InputIter, class OutputIter, class Predicate>
OutputIter remove_copy_if(InputIter first, InputIter last,
OutputIter result, Predicate pred);
template<class ForwardIter, class Predicate>
ForwardIter remove_if(ForwardIter first, ForwardIter last,
Predicate pred);
template<class ForwardIter, class T>
void replace(ForwardIter first, ForwardIter last,
const T& old_value, const T& new_value);
template<class InputIter, class OutputIter, class T>
OutputIter replace_copy(InputIter first, InputIter last,
OutputIter result,
const T& old_value, const T& new_value);
template<class Iter, class OutputIter, class Predicate, class T>
OutputIter replace_copy_if(Iter first, Iter last,
OutputIter result,
Predicate pred, const T& new_value);
397
Die C++-Standardbibliothek
398
Unterstützung eigener Implementierungen
399
Die C++-Standardbibliothek
Die Stream-Klassen
Übersicht
Beschreibung
Die Stream-Klassen stellen die objektorientierte Alternative zu den ANSI C-Funktionen aus
stdio.h dar. Einen Stream kann man sich dabei als Datenfluß zwischen einer Quelle und einem
Ziel vorstellen, wobei je nach verwendeter Stream-Klasse die Instanz der Stream-Klasse entwe-
der die Quelle oder das Ziel ist. Für eine Instanz der Klasse ifstream ist die mit der Instanz ver-
bundene Datei die Quelle, für eine Instanz der Klasse ofstream wäre sie das Ziel.
Das Grundgerüst der C++-Stream-Klassen sieht nach dem neuen ANSI-Standard wie folgt aus:
ios_base
basic_ios
<class char T, class traits>
basic_istream
basic_ostream basic_ostream
<class char T, class traits> <class char T, class traits>
400
Übersicht
Eigenschaft Beschreibung
ios_base Die Klasse ios_base enthält Informationen sowie Typ- und Konstan-
tendefinitionen, die von allen Stream-Klassen verwendet werden und
nicht von einem speziellen Zeichentyp abhängen – beispielsweise die
Format-Flags, die Status-Bits, die Öffnungsmodi für Dateien.
(Viele Elemente, die mittlerweile in ios_base definiert sind, standen
früher in ios.)
basic_ios Die grundlegende Basisklasse. Sie ist als Template definiert, um
zeichentypspezifische Spezialisierungen zu erlauben. Als Template-
Argumente erwartet sie den Namen des Zeichentyps und eine
char_traits<charT>-Spezialisierung, die den Zeichentyp charakteri-
siert.
basic_ios stellt durch die Definition entsprechender Methoden und
Konstruktoren die Verbindung zu einem Pufferobjekt (für die
Zwischenspeicherung von Ein- und Ausgaben) und einem Locale-
Objekt (zur Anpassung an nationale Formate) her.
basic_istream und Abgeleitete Klassentemplates, die basic_ios als virtuelle Basis erben.
basic_ostream Die Klassen istream und ostream, die man zur Einrichtung von Ein-
und Ausgabe-Streams instanziieren kann, sind Spezialisierungen
dieser Klassentemplates für den Datentyp char. Die im vorangehen-
den Abschnitt vorgestellten Stream-Objekte cin, cout, cerr, clog
sind beispielsweise Instanzen der Klassen istream und ostream.
Die Klassentemplates istream und ostream dienen selbst wieder
anderen Stream-Klassen-Templates als Basisklassen.
Anwendung
Um mit Streams arbeiten zu können, braucht man Stream-Objekte. Stream-Objekte
erzeugt man, indem man
401
Die C++-Standardbibliothek
Verweise
Siehe Kategorie Ein- und Ausgabe
ios_base
aus <ios>
Beschreibung
Die Klasse ios_base ist die Basisklasse zu basic_ios. Sie enthält keine Routinen zur Ein- und
Ausgabe, sondern umfaßt eine Reihe von Datentypen, Konstanten und Methoden zur Excep-
tion-Behandlung, zur Abfrage des Stream-Status und zur Formatierung der Ein- und Ausgabe.
402
ios_base
Referenz
class ios_base {
public:
class failure;
typedef T1 fmtflags;
static const fmtflags boolalpha;
static const fmtflags dec;
static const fmtflags fixed;
static const fmtflags hex;
static const fmtflags internal;
static const fmtflags left;
static const fmtflags oct;
static const fmtflags right;
static const fmtflags scientific;
static const fmtflags showbase;
static const fmtflags showpoint;
static const fmtflags showpos;
static const fmtflags skipws;
static const fmtflags unitbuf;
static const fmtflags uppercase;
static const fmtflags adjustfield;
static const fmtflags basefield;
static const fmtflags floatfield;
typedef T2 iostate;
static const iostate badbit;
static const iostate eofbit;
static const iostate failbit;
static const iostate goodbit;
typedef T3 openmode;
static const openmode app;
static const openmode ate;
static const openmode binary;
static const openmode in;
static const openmode out;
static const openmode trunc;
typedef T4 seekdir;
static const seekdir beg;
static const seekdir cur;
static const seekdir end;
class Init;
// Formatierungflags:
fmtflags flags() const;
fmtflags flags(fmtflags fmtfl);
fmtflags setf(fmtflags fmtfl);
fmtflags setf(fmtflags fmtfl, fmtflags mask);
void unsetf(fmtflags mask);
streamsize precision() const;
streamsize precision(streamsize prec);
streamsize width() const;
403
Die C++-Standardbibliothek
Verweise
Siehe Kategorie Ein- und Ausgabe, Streams in C++
basic_ios
aus <ios>
Beschreibung
Basisklassentemplate für die Stream-Klassen. Enthält allgemeine Routinen zur Kontrolle des
Streams und seines beigeordneten Pufferobjekts (des Klassentemplates basic_streambuf).
Das Klassentemplate basic_ios definiert
einige höhere Funktionen zum Abfragen der wichtigsten Statusinformationen (good(),
eof(), fail(), bad(), bool(), rdstate() und den Operator !).
die Funktionen für den Zugriff und den Austausch des Pufferobjekts (rdbuf()) und verknüpf-
ter Ausgabe-Streams (tie()).
Referenz
template <class charT, class traits = char_traits<charT> >
class basic_ios : public ios_base {
public:
typedef charT char_type;
typedef typename traits::int_type int_type;
typedef typename traits::pos_type pos_type;
typedef typename traits::off_type off_type;
typedef traits traits_type;
operator void*() const
bool operator!() const
404
basic_streambuf
basic_streambuf
aus <streambuf>
Beschreibung
Das Klassentemplate basic_streambuf ist das Basistemplate für alle Streampuffer
(basic_filebuf, basic_stringbuf). Das Klassentemplate basic_streambuf und die abgeleite-
ten Streampuffer dienen dazu, Zeichensequenzen im Arbeitsspeicher zu kontrollieren. Jede
Instanz verfügt dabei nach Bedarf über Speicherbereiche zur Zeicheneingabe wie zur Zeichen-
ausgabe. Auf jede dieser Zeichensequenzen weisen drei Zeiger:
Ein Zeiger auf das erste Element der Sequenz.
Ein Zeiger auf die nächste Adresse, von der gelesen oder in die geschrieben wird.
Ein Zeiger auf die nächste Elementadresse hinter dem Ende der Sequenz.
405
Die C++-Standardbibliothek
Durch die Verbindung mit einem Stream wird der Puffer mit einer Ausgabe- oder Eingabeein-
heit verknüpft. Zum Zugriff auf die Zeichen im Puffer benutzen die High-level-Funktionen der
Stream-Klasse die Low-level-Funktionen des assoziierten Pufferobjekts.
Die Zwischenschaltung von Pufferobjekten ermöglicht eine gepufferte Ein- und Ausgabe. Dies
bedeutet, daß beispielsweise beim Lesen aus einer Datei nicht jeder Leseaufruf des Pro-
gramms mit einem Festplattenzugriff verbunden ist. Statt dessen werden größere Teile der
Datei in den Puffer im Arbeitsspeicher geladen, und die Leseoperationen des Programms wer-
den auf diesem Puffer ausgeführt, bis er vollständig ausgelesen wurde und erneut von der Fest-
platte her aufgefüllt wird. Die verringerte Zahl der Festplattenzugriffe verbessert die Laufzeit
wesentlich, bedeutet aber auch, daß Daten verloren gehen können, wenn bei unerwartetem
Programmabbruch der Puffer nicht geleert ist. Der Abgleich von Puffer und Ein- oder Ausgabe-
einheit kann durch einen Aufruf von pubsync() erreicht werden.
Anwendung
Die Klassen des Templates können nicht direkt instanziiert werden, da sie keinen
public Konstruktor enthalten.
Die Pufferklassen kontrollieren den internen Puffer und bilden somit die Schnitt-
stelle zwischen Stream und Puffer. Dies funktioniert auch, wenn die Streams, die
Größe des internen Puffer des Pufferobjekts auf 0 setzen (siehe Methode pubset-
buf()) – in diesem Fall erhält man eine ungepufferte Ein- oder Ausgabe (die aber
weiterhin über die Instanz der Pufferklasse erfolgt)).
Referenz
template <class charT, class traits = char_traits<charT> >
class basic_streambuf {
public:
typedef charT char_type;
typedef typename traits::int_type int_type;
typedef typename traits::pos_type pos_type;
typedef typename traits::off_type off_type;
typedef traits traits_type;
virtual ~basic_streambuf();
// Lokale:
locale pubimbue(const locale &loc);
locale getloc() const;
// Puffer:
basic_streambuf<char_type,traits>* pubsetbuf(char_type* s,
streamsize n);
pos_type pubseekoff(off_type off, ios_base::seekdir way,
ios_base::openmode which=ios_base::in|ios_base::out);
pos_type pubseekpos(pos_type sp,
ios_base::openmode which=ios_base::in| os_base::out);
int pubsync();
streamsize in_avail();
int_type snextc();
406
basic_istream
int_type sbumpc();
int_type sgetc();
streamsize sgetn(char_type* s, streamsize n);
int_type sputbackc(char_type c);
int_type sungetc();
int_type sputc(char_type c);
streamsize sputn(const char_type* s, streamsize n);
protected:
basic_streambuf();
char_type* eback() const;
char_type* gptr() const;
char_type* egptr() const;
void gbump(int n);
void setg(char_type* gbeg, char_type* gnext, char_type* gend);
char_type* pbase() const;
char_type* pptr() const;
char_type* epptr() const;
void pbump(int n);
void setp(char_type* pbeg, char_type* pend);
// Virtuelle Funktionen:
virtual void imbue(const locale &loc);
// Pufferverwaltung:
virtual basic_streambuf<char_type,traits>*
setbuf(char_type* s, streamsize n);
virtual pos_type seekoff(off_type off, ios_base::seekdir way,
ios_base::openmode which = ios_base::in | ios_base::out);
virtual pos_type seekpos(pos_type sp,
ios_base::openmode which = ios_base::in | ios_base::out);
virtual int sync();
virtual int showmanyc();
virtual streamsize xsgetn(char_type* s, streamsize n);
virtual int_type underflow();
virtual int_type uflow();
virtual int_type pbackfail(int_type c = traits::eof());
virtual streamsize xsputn(const char_type* s, streamsize n);
virtual int_type overflow (int_type c = traits::eof());
};
basic_istream
aus <istream>
Beschreibung
Das Klassentemplate basic_istream stellt die höheren Funktionen und Operatoren zum Einle-
sen aus einem Pufferobjekt zur Verfügung. Das Pufferobjekt selbst wird mit der eigentlichen
Eingabeeinheit (der Quelle des Datenflusses) assoziiert. Für cin ist dies standardmäßig die
Tastatur (stdin).
407
Die C++-Standardbibliothek
basic_istream ist die Basisklasse von basic_ifstream (Einlesen aus Datei) und
basic_istringstream (Einlesen von basic_string-Objekten), und sie kann selbst instanziiert
werden, um Stream-Objekte zum komfortablen, formatierten oder unformatierten Einlesen ein-
zurichten. In diesem Sinne sind die Instanzen cin und win zum Einlesen von char- bzw.
wchar_t-Zeichen von der Tastatur in iostream vordefiniert.
Anwendung
Der erste Schritt zur Erzeugung eines Eingabe-Streams ist, das Template
basic_istream für einen Zeichentyp zu spezialisieren. Für die Zeichentypen char und
wchar_t ist dies bereits geschehen. Die Typdefinitionen stehen in iostream:
typedef basic_istream<char> istream;
typedef basic_istream<wchar_t> wistream;
Der zweite Schritt ist, durch Instanziierung der Stream-Klasse ein Eingabe-Stream-
Objekt zu erzeugen. Dabei muß dem Konstruktor ein Pufferobjekt übergeben wer-
den:
filebuf datei;
[Link]("[Link]", ios_base::in | ios_base::out);
istream dat_ein(&datei);
Für die Instanziierung des Eingabe-Streams cin, der mit der Standardeingabe zu
verbinden ist, sorgt die Implementierung durch den Compilerbauer.
Referenz
template <class charT, class traits = char_traits<charT> >
class basic_istream : virtual public basic_ios<charT,traits> {
public:
// Konstruktoren:
explicit basic_istream(basic_streambuf<charT,traits>* sb);
virtual ~basic_istream();
class sentry;
// Formatierte Eingabe:
basic_istream<charT,traits>& operator>>
(basic_istream<charT,traits>& (*pf)(basic_istream<charT,traits>&))
basic_istream<charT,traits>& operator>>
(basic_ios<charT,traits>& (*pf)(basic_ios<charT,traits>&))
basic_istream<charT,traits>& operator>> (ios_base& (*pf)(ios_base&))
basic_istream<charT,traits>& operator>>(bool& n);
basic_istream<charT,traits>& operator>>(short& n);
basic_istream<charT,traits>& operator>>(unsigned short& n);
basic_istream<charT,traits>& operator>>(int& n);
basic_istream<charT,traits>& operator>>(unsigned int& n);
basic_istream<charT,traits>& operator>>(long& n);
basic_istream<charT,traits>& operator>>(unsigned long& n);
basic_istream<charT,traits>& operator>>(float& f);
basic_istream<charT,traits>& operator>>(double& f);
basic_istream<charT,traits>& operator>>(long double& f);
408
basic_ostream
basic_ostream
aus <ostream>
Beschreibung
Das Klassentemplate basic_ostream stellt die höheren Funktionen und Operatoren zum Schrei-
ben in ein Pufferobjekt zur Verfügung. Das Pufferobjekt selbst wird mit der eigentlichen Ausga-
beeinheit (dem Ziel des Datenflusses) assoziiert. Für cout ist dies standardmäßig der
Konsolenbildschirm (stdout).
basic_ostream ist die Basisklasse von basic_ofstream (Schreiben in Datei) und
basic_ostringstream (Schreiben in basic_string-Objekte), und sie kann selbst instanziiert
werden, um Stream-Objekte zur komfortablen, formatierten oder unformatierten Ausgabe ein-
zurichten. In diesem Sinne sind die Instanzen cout, cerr, clog und wout, werr, wlog zur Ausgabe
von char- bzw. wchar_t-Zeichen auf den Bildschirm in iostream vordefiniert.
409
Die C++-Standardbibliothek
Anwendung
Der erste Schritt zur Erzeugung eines Ausgabe-Streams ist, das Template
basic_ostream für einen Zeichentyp zu spezialisieren. Für die Zeichentypen char und
wchar_t ist dies bereits geschehen. Die Typdefinitionen stehen in iostream:
typedef basic_ostream<char> ostream;
typedef basic_ostream<wchar_t> wostream;
Der zweite Schritt ist, durch Instanziierung der Stream-Klasse ein Ausgabe-Stream-
Objekt zu erzeugen. Dabei muß dem Konstruktor ein Pufferobjekt übergeben wer-
den:
filebuf datei;
[Link]("[Link]", ios_base::in | ios_base::out);
ostream dat_aus(&datei);
Für die Instanziierung des Ausgabe-Streams cout, der mit der Standardausgabe zu
verbinden ist, sorgt die Implementierung durch den Compilerbauer.
Referenz
template <class charT, class traits = char_traits<charT> >
class basic_ostream : virtual public basic_ios<charT,traits> {
public:
// Konstruktoren:
explicit basic_ostream(basic_streambuf<char_type,traits>* sb);
virtual ~basic_ostream();
class sentry;
// Formatierte Ausgabe:
basic_ostream<charT,traits>& operator<<
(basic_ostream<charT,traits>& (*pf)(basic_ostream<charT,traits>&));
basic_ostream<charT,traits>& operator<<
(basic_ios<charT,traits>& (*pf)(basic_ios<charT,traits>&));
basic_ostream<charT,traits>& operator<<
(ios_base& (*pf)(ios_base&));
basic_ostream<charT,traits>& operator<<(bool n);
basic_ostream<charT,traits>& operator<<(short n);
basic_ostream<charT,traits>& operator<<(unsigned short n);
basic_ostream<charT,traits>& operator<<(int n);
basic_ostream<charT,traits>& operator<<(unsigned int n);
basic_ostream<charT,traits>& operator<<(long n);
basic_ostream<charT,traits>& operator<<(unsigned long n);
basic_ostream<charT,traits>& operator<<(float f);
basic_ostream<charT,traits>& operator<<(double f);
basic_ostream<charT,traits>& operator<<(long double f);
basic_ostream<charT,traits>& operator<<(void* p);
basic_ostream<charT,traits>& operator<<
(basic_streambuf<char_type,traits>* sb);
// Unformatierte Ausgabe:
basic_ostream<charT,traits>& put(char_type c);
basic_ostream<charT,traits>& write(const char_type* s, streamsize n);
410
basic_iostream
basic_ostream<charT,traits>& flush();
// Suchen:
pos_type tellp();
basic_ostream<charT,traits>& seekp(pos_type);
basic_ostream<charT,traits>& seekp(off_type, ios_base::seekdir);
};
basic_iostream
aus <istream>
Beschreibung
Das Template ist von basic_istream und basic_ostream abgeleitet und definiert außer Kon-
struktor und Destruktor keine eigenen Elemente.
Anwendung
Das Klassentemplate wird zur Ein- und Ausgabe in einen zugrundeliegenden Puffer
verwendet.
Referenz
template <class charT, class traits = char_traits<charT> >
class basic_iostream :
public basic_istream<charT,traits>,
public basic_ostream<charT,traits> {
public:
explicit basic_iostream(basic_streambuf<charT,traits>* sb);
virtual ~basic_iostream();
};
basic_stringbuf
aus <sstream>
Beschreibung
Das Klassentemplate basic_stringbuf ist von basic_streambuf abgeleitet, um die Eingabe-
oder Ausgabesequenz des Pufferobjekts mit einem basic_string-Objekt zu verbinden.
basic_stringbuf stellt die Pufferobjekte für Stringstreams (basic_istringstream,
basic_ostringstream und basic_stringstream).
411
Die C++-Standardbibliothek
Anwendung
Unter den public-Methoden der Klasse basic_stringbuf finden sich die Methoden,
die die Verbindung zwischen String und Puffer herstellen:
● Die Konstruktoren dienen dazu, das Pufferobjekt einzurichten und eventuell
die Zeiger der Eingabe- oder Ausgabesequenz nach Maßgabe eines übergebe-
nen basic_string-Objekts zu initialisieren.
● str() dient dazu, aus der Eingabe- oder Ausgabesequenz ein basic_string-Ob-
jekt zu erzeugen.
● str(const basic_string<char_type>&) dient dazu, den Puffer mit einem
basic_string-Objekt zu initialisieren.
Referenz
template <class charT, class traits = char_traits<charT>,
class Allocator = allocator<charT> >
class basic_stringbuf : public basic_streambuf<charT,traits> {
public:
typedef charT char_type;
typedef typename traits::int_type int_type;
typedef typename traits::pos_type pos_type;
typedef typename traits::off_type off_type;
// Konstruktoren:
explicit basic_stringbuf(ios_base::openmode which
= ios_base::in | ios_base::out);
explicit basic_stringbuf(
const basic_string<charT,traits,Allocator>& str,
ios_base::openmode which = ios_base::in | ios_base::out);
// Zugriff auf String:
basic_string<charT,traits,Allocator> str() const;
void str(const basic_string<charT,traits,Allocator>& s);
protected:
virtual int_type underflow();
virtual int_type pbackfail(int_type c = traits::eof());
virtual int_type overflow (int_type c = traits::eof());
virtual basic_streambuf<charT,traits>* setbuf(charT*, streamsize);
virtual pos_type seekoff(off_type off, ios_base::seekdir way,
ios_base::openmode which
= ios_base::in | ios_base::out);
virtual pos_type seekpos(pos_type sp,
ios_base::openmode which
= ios_base::in | ios_base::out);
};
412
basic_istringstream
basic_istringstream
aus <sstream>
Stream-Klasse zum Einlesen aus basic_string-Objekten. Benutzt als Pufferobjekt
eine Instanz der Klasse basic_stringbuf.
Anwendung
Der erste Schritt zur Erzeugung eines Stringstreams ist, das Template
basic_istringstream für einen Zeichentyp zu spezialisieren. Für die Zeichentypen
char und wchar_t ist dies bereits geschehen. Die Typdefinitionen stehen in iosfwd:
typedef basic_istringstream<char> istringstream;
typedef basic_istringstream<wchar_t> wistringstream;
Der zweite Schritt ist aus der Stream-Klasse ein Stringstream-Objekt zu erzeugen:
istringstream str("Hallo");
char s[10];
str >> s;
Mit den beiden str()-Methoden kann man das zugrundeliegende basic_string-
Objekt setzen oder zurückliefern. Ansonsten verwendet man zum Einlesen den >>-
Operator und die anderen von basic_istream geerbten Methoden.
Referenz
template <class charT, class traits = char_traits<charT>,
class Allocator = allocator<charT> >
class basic_istringstream : public basic_istream<charT,traits> {
public:
typedef charT char_type;
typedef typename traits::int_type int_type;
typedef typename traits::pos_type pos_type;
typedef typename traits::off_type off_type;
explicit basic_istringstream(ios_base::openmode which =ios_base::in);
explicit basic_istringstream(
const basic_string<charT,traits,Allocator>& str,
ios_base::openmode which = ios_base::in);
basic_stringbuf<charT,traits,Allocator>* rdbuf() const;
basic_string<charT,traits,Allocator> str() const;
void str(const basic_string<charT,traits,Allocator>& s);
};
413
Die C++-Standardbibliothek
basic_ostringstream
aus <sstream>
Stream-Klasse zur Ausgabe in basic_string-Objekte. Benutzt als Pufferobjekt eine
Instanz der Klasse basic_stringbuf.
Anwendung
Der erste Schritt zur Erzeugung eines Stringstreams ist, das Template
basic_ostringstream für einen Zeichentyp zu spezialisieren. Für die Zeichentypen
char und wchar_t ist dies bereits geschehen. Die Typdefinitionen stehen in iosfwd:
typedef basic_ostringstream<char> ostringstream;
typedef basic_ostringstream<wchar_t> wostringstream;
Der zweite Schritt ist aus der Stream-Klasse ein Stringstream-Objekt zu erzeugen:
ostringstream str;
str << "Hallo";
Mit den beiden str()-Methoden kann man das zugrundeliegene basic_string-
Objekt setzen oder zurückliefern. Ansonsten verwendet man zum Schreiben den
<<-Operator und die anderen von basic_ostream geerbten Methoden.
Referenz
template <class charT, class traits = char_traits<charT>,
class Allocator = allocator<charT> >
class basic_ostringstream : public basic_ostream<charT,traits> {
public:
typedef charT char_type;
typedef typename traits::int_type int_type;
typedef typename traits::pos_type pos_type;
typedef typename traits::off_type off_type;
explicit basic_ostringstream(ios_base::openmode which=ios_base::out);
explicit basic_ostringstream(
const basic_string<charT,traits,Allocator>& str,
ios_base::openmode which = ios_base::out);
virtual ~basic_ostringstream();
basic_stringbuf<charT,traits,Allocator>* rdbuf() const;
basic_string<charT,traits,Allocator> str() const;
void str(const basic_string<charT,traits,Allocator>& s);
};
414
basic_stringstream
basic_stringstream
aus <sstream>
Beschreibung
Stream-Klasse zur Ein- und Ausgabe in basic_string-Objekte. Benutzt als Pufferobjekt eine
Instanz der Klasse basic_stringbuf.
Anwendung
Mit den beiden überladenen Methoden str() kann man das zugrundeliegende
basic_string-Objekt setzen oder zurückliefern.
Ansonsten verwendet man die Streamoperatoren und die anderen von
basic_iostream geerbten Methoden.
Referenz
template <class charT, class traits = char_traits<charT>,
class Allocator = allocator<charT> >
class basic_stringstream : public basic_iostream<charT,traits> {
public:
typedef charT char_type;
typedef typename traits::int_type int_type;
typedef typename traits::pos_type pos_type;
typedef typename traits::off_type off_type;
// Konstruktoren
explicit basic_stringstream(
ios_base::openmode which = ios_base::out|ios_base::in);
explicit basic_stringstream(
const basic_string<charT,traits,Allocator>& str,
ios_base::openmode which = ios_base::out|ios_base::in);
// Zugriff auf Puffer und String:
basic_stringbuf<charT,traits,Allocator>* rdbuf() const;
basic_string<charT,traits,Allocator> str() const;
void str(const basic_string<charT,traits,Allocator>& str);
};
basic_filebuf
aus <fstream>
Beschreibung
Das Klassentemplate basic_filebuf ist von basic_streambuf abgeleitet, um die Eingabe- oder
Ausgabesequenz des Pufferobjekts mit einer Datei zu verbinden.
415
Die C++-Standardbibliothek
Sie spezialisiert die Klasse basic_streambuf für die Erzeugung von Pufferobjekten, die mit
Dateien verbunden werden, und stellt die Pufferobjekte für Objekte der Klassentemplates
basic_ifstream, basic_ofstream und basic_fstream.
Anwendung
Unter den public-Methoden der Klasse basic_filebuf finden sich die Methoden, die
die Verbindung zwischen Datei und Puffer herstellen:
● open() zum Öffnen einer Datei.
● close() zum Schließen einer Datei.
filebuf datei; // filebuf ist gleich basic_filebuf<char>
[Link]("[Link]", ios_base::in | ios_base::out);
[Link]();
Referenz
template <class charT, class traits = char_traits<charT> >
class basic_filebuf : public basic_streambuf<charT,traits> {
public:
basic_filebuf();
virtual ~basic_filebuf();
bool is_open() const;
basic_filebuf<charT,traits>* open(const char* s,
ios_base::openmode mode);
basic_filebuf<charT,traits>* close();
protected:
virtual int showmanyc();
virtual int_type underflow();
virtual int_type uflow();
virtual int_type pbackfail(int_type c = traits::eof());
virtual int_type overflow (int_type c = traits::eof());
virtual basic_streambuf<charT,traits>* setbuf(char_type* s,
streamsize n);
virtual pos_type seekoff(off_type off, ios_base::seekdir way,
ios_base::openmode which
= ios_base::in | ios_base::out);
virtual pos_type seekpos(pos_type sp, ios_base::openmode which
= ios_base::in | ios_base::out);
virtual int sync();
virtual void imbue(const locale& loc);
};
416
basic_ifstream
basic_ifstream
aus <fstream>
Beschreibung
Das Klassentemplate basic_ifstream stellt die Funktionen zum Öffnen und Schließen von
Dateien zur Verfügung.
Anwendung
Der erste Schritt zur Erzeugung eines Eingabe-Streams für eine Datei ist, das Tem-
plate basic_ifstream für einen Zeichentyp zu spezialisieren. Für die Zeichentypen
char und wchar_t ist dies bereits geschehen. Die Typdefinitionen stehen in iostream:
typedef basic_ifstream<char> ifstream;
typedef basic_ifstream<wchar_t> wifstream;
Der zweite Schritt ist durch Instanziierung der Stream-Klasse ein Eingabe-Stream-
Objekt zu erzeugen. Dabei muß dem Konstruktor ein Pufferobjekt übergeben wer-
den:
ifstream dat_ein;
dat_ein.open("dateiname", ios_base::in);
Die eigentlichen Lesemethoden werden von basic_istream geerbt.
Referenz
template <class charT, class traits = char_traits<charT> >
class basic_ifstream : public basic_istream<charT,traits> {
public:
typedef charT char_type;
typedef typename traits::int_type int_type;
typedef typename traits::pos_type pos_type;
typedef typename traits::off_type off_type;
basic_ifstream();
explicit basic_ifstream(const char* s,
ios_base::openmode mode = ios_base::in);
basic_filebuf<charT,traits>* rdbuf() const;
bool is_open();
void open(const char* s, openmode mode = in);
void close();
};
417
Die C++-Standardbibliothek
basic_ofstream
aus <fstream>
Beschreibung
Das Klassentemplate basic_ofstream stellt die Funktionen zum Öffnen und Schließen von
Dateien zur Verfügung.
Anwendung
Der erste Schritt zur Erzeugung eines Ausgabe-Streams für eine Datei ist, das Tem-
plate basic_ofstream für einen Zeichentyp zu spezialisieren. Für die Zeichentypen
char und wchar_t ist dies bereits geschehen. Die Typdefinitionen stehen in iostream:
typedef basic_ofstream<char> ofstream;
typedef basic_ofstream<wchar_t> wofstream;
Der zweite Schritt ist durch Instanziierung der Stream-Klasse ein Ausgabe-Stream-
Objekt zu erzeugen. Dabei muß dem Konstruktor ein Pufferobjekt übergeben wer-
den:
ofstream dat_aus;
dat_aus.open("dateiname", ios_base::out);
Die eigentlichen Schreibmethoden werden von basic_ostream geerbt.
Referenz
template <class charT, class traits = char_traits<charT> >
class basic_ofstream : public basic_ostream<charT,traits> {
public:
typedef charT char_type;
typedef typename traits::int_type int_type;
typedef typename traits::pos_type pos_type;
typedef typename traits::off_type off_type;
basic_ofstream();
explicit basic_ofstream(const char* s,
ios_base::openmode mode = ios_base::out|ios_base::trunc);
basic_filebuf<charT,traits>* rdbuf() const;
bool is_open();
void open(const char* s, ios_base::openmode mode = out | trunc);
void close();
};
418
basic_fstream
basic_fstream
aus <fstream>
Beschreibung
Stream-Klasse zur Ein- und Ausgabe in Dateien. Benutzt als Pufferobjekt eine Instanz der
Klasse basic_filebuf.
Anwendung
Mit den Methoden open() und close() kann man Dateien öffnen und schließen.
Für die Ein- und Ausgabe verwendet man die Stream-Operatoren und die anderen
von basic_iostream geerbten Methoden.
Referenz
template <class charT, class traits=char_traits<charT> >
class basic_fstream : public basic_iostream<charT,traits> {
public:
typedef charT char_type;
typedef typename traits::int_type ins_type;
typedef typename traits::pos_type pos_type;
typedef typename traits::off_type off_type;
// Konstruktoren
basic_fstream();
explicit basic_fstream(const char* s,
ios_base::openmode mode = ios_base::in|ios_base::out);
// Zugriff auf Puffer und Dateien:
basic_filebuf<charT,traits>* rdbuf() const;
bool is_open();
void open(const char* s,
ios_base::openmode mode = ios_base::in|ios_base::out);
void close();
};
419
Die C++-Standardbibliothek
Die String-Klassen
Übersicht
Beschreibung
Das Klassentemplate basic_string stellt die objektorientierte Alternative zu den ANSI C-Funk-
tionen aus string.h dar. Die Implementierung als Template erlaubt es, Strings für jedweden
Zeichentyp zu erzeugen.
Um die Klasse typenunabhängig implementieren zu können, wurden wie bei den iostream-
Klassen die grundlegenden, vom verwendeten Zeichentyp abhängigen Routinen in eine
traits-Klasse ausgelagert. Der Zeichentyp und seine traits-Klasse werden dann den Template-
Instanzen von basic_string als Template-Parameter übergeben.
Anwendung
Für die Zeichentypen char und wchar_t sind in der Laufzeitbibliothek bereits Spezia-
lisierungen des traits-Templates sowie Typdefinitionen von basic_string-Spezialisie-
rungen definiert. Letztere heißen string und wstring.
Die wichtigsten Stringmanipulationen sind in basic_string als Methoden und/oder
Operatoren implementiert.
Durch die globale Überladung der Operatoren + (Konkatenation), == , !=, <, <=, >,
>= (für Vergleiche), sowie >> und << (Ein- und Ausgabe), wird der Umgang mit
Zeichenketten noch weiter vereinfacht.
Verweise
Siehe Kategorie Zeichenketten, Die Klasse String
char_traits
aus <string>
Beschreibung
Eine Template-Struktur, die Methoden und Typdefinitionen enthält, deren Definition vom über-
gebenen Zeichentyp charT abhängt und die für die Implementierung des basic_string-Tem-
plates notwendig sind. Auf diese Weise kann die Implementierung des Templates basic_string
unabhängig von den zu manipulierenden Zeichen gehalten werden.
Spezialisierungen des Templates werden als Template-Argument für basic_string und die
Stream-Klassen verwendet.
420
basic_string
Referenz
template<> struct char_traits<char> {
typedef char char_type;
typedef int int_type;
typedef streamoff off_type;
typedef streampos pos_type;
typedef mbstate_t state_type;
basic_string
aus <string>
Beschreibung
Die Klasse unterstützt die Programmierung mit Zeichenketten und bietet eine Fülle an Funktio-
nen zu deren Erzeugung und Manipulation.
Im einzelnen sind das Template-Funktionen
● zur Erzeugung von Strings,
● zum Zuweisen, Anhängen und Einfügen,
● zum Löschen, Entfernen und Ersetzen,
● zur Ermittlung der Größe der Zeichenketten,
● zum indizierten Zugriff auf einzelne Zeichen im String,
● zum Vergleich von Zeichenketten,
● zum Suchen von Zeichen und Teil-Strings.
421
Die C++-Standardbibliothek
Wo dies sinnvoll ist, sind die Funktionen überladen, meist um neben Zeichenketten
auch einzelne Zeichen oder basic_string-Objekte als Argument zu akzeptieren,
oder um mit Iteratoren arbeiten zu können.
Anwendung
Der Gebrauch der Klasse erfolgt einfach durch Spezialisierung des Klassentempla-
tes für den zu verwendenden Zeichentyp. Für char und wchar_t ist dies bereits
geschehen, die entsprechenden String-Typen lauten
string und
wstring
Für diese Klassen können Objekte erzeugt werden, die dann über ihre Methoden
und Operatoren manipuliert werden können.
Referenz
template<class charT, class traits = char_traits<charT>,
class Allocator = allocator<charT> >
class basic_string {
public:
typedef traits traits_type;
typedef typename traits::char_type value_type;
typedef Allocator allocator_type;
typedef typename Allocator::size_type size_type;
typedef typename Allocator::difference_type difference_type;
typedef typename Allocator::reference reference;
typedef typename Allocator::const_reference const_reference;
typedef typename Allocator::pointer pointer;
typedef typename Allocator::const_pointer const_pointer;
typedef implementation defined iterator;
typedef implementation defined const_iterator
typedef std::reverse_iterator<iterator> reverse_iterator;
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
static const size_type npos = -1;
// Konstruktoren, Kopieren:
explicit basic_string(const Allocator& a = Allocator());
basic_string(const basic_string& str, size_type pos = 0,
size_type n = npos, const Allocator& a = Allocator());
basic_string(const charT* s, size_type n, const Allocator& a =
Allocator());
basic_string(const charT* s, const Allocator& a = Allocator());
basic_string(size_type n, charT c, const Allocator& a = Allocator());
template<class InputIterator>
basic_string(InputIterator begin, InputIterator end,
const Allocator& a = Allocator());
~basic_string();
basic_string& operator=(const basic_string& str);
basic_string& operator=(const charT* s);
422
basic_string
// Iteratoren:
iterator begin();
const_iterator begin() const;
iterator end();
const_iterator end() const;
reverse_iterator rbegin();
const_reverse_iterator rbegin() const;
reverse_iterator rend();
const_reverse_iterator rend() const;
// Größe:
size_type size() const;
size_type length() const;
size_type max_size() const;
void resize(size_type n, charT c);
void resize(size_type n);
size_type capacity() const;
void reserve(size_type res_arg = 0);
void clear();
bool empty() const;
// Zugriff auf Zeichen:
const_reference operator[](size_type pos) const;
reference operator[](size_type pos);
const_reference at(size_type n) const;
reference at(size_type n);
// Verändernde Operationen:
basic_string& operator+=(const basic_string& str);
basic_string& operator+=(const charT* s);
basic_string& operator+=(charT c);
basic_string& append(const basic_string& str);
basic_string& append(const basic_string& str, size_type pos,
size_type n);
basic_string& append(const charT* s, size_type n);
basic_string& append(const charT* s);
basic_string& append(size_type n, charT c);
template<class InputIterator>
basic_string& append(InputIterator first, InputIterator last);
basic_string& assign(const basic_string&);
basic_string& assign(const basic_string& str, size_type pos,
size_type n);
basic_string& assign(const charT* s, size_type n);
basic_string& assign(const charT* s);
basic_string& assign(size_type n, charT c);
template<class InputIterator>
basic_string& assign(InputIterator first, InputIterator last);
423
Die C++-Standardbibliothek
424
Übersicht
Verweise
Siehe Kategorie Zeichenketten, Die Klasse String
Übersicht
Beschreibung
Datumsangaben, die Zeichen für nationale Währungseinheiten oder beispielsweise die Zei-
chensetzung in Gleitkommazahlen, sind von Land zu Land verschieden. Auf welche Weise soll
also ein C++-Programm, das sich international verkaufen soll, eine Datumsangabe formatieren?
Die Antwort liegt in der lokalen Einstellung. In ihr sind, nach Kategorien geordnet, die nötigen
Informationen zur länderspezifischen Behandlung abgelegt. Jede Kategorie bündelt wiederum
mehrere Facetten:
425
Die C++-Standardbibliothek
Kategorie Facetten
Anwendung
In C++ sind die lokale Einstellung und die einzelnen Facetten durch Klassen reprä-
sentiert. Sie können diese Klassen nutzen, um eigene Facetten zu implementieren,
eigene lokale Einstellungen aus vorhandenen Einstellungen und Facetten zu erstel-
len, zwischen lokalen Einstellungen oder Facetten hin- und herzuschalten.
Sinnvoll ist der Rückgriff auf die lokalen Einstellungen etwa bei der Ein- und Aus-
gabe von Daten. Die Stream-Klassen verfügen daher schon über eigene Methoden
(imbue()) zur Auswahl einer lokalen Einstellung.
Durch entsprechende Implementierungen der Operatoren << und >> können Sie
Programme schreiben, die sich entweder an die lokalen Gegebenheiten (werden
vom Betriebssystem übernommen) anpassen oder deren Formatierung unabhängig
von nationalen Eigenheiten erfolgt.
426
locale
locale
aus <locale>
Beschreibung
Klasse zur Repräsentation und Verwaltung einer locale-Einstellung.
Die Klasse locale definiert:
● Konstruktoren zum Erzeugen neuer locale-Einstellungen, basierend auf ande-
ren locale-Einstellungen.
● Funktionen und Operatoren zum Abfragen von Informationen über die locale-
Einstellung (name(), ==(), !=() sowie die globalen Funktionentemplates
use_facet() und has_facet()).
● Funktionen für globale locale-Einstellungen (global(), classic()).
● Vergleichsfunktion operator() für Zeichenketten.
Anwendung
Mit Hilfe der Klasse locale können Sie eigene locale-Einstellungen kreieren, die Sie
dann beispielsweise mit der Stream-Methode imbue() einem Stream zuweisen kön-
nen, um formatierte Ein- und Ausgaben nach Maßgabe Ihrer locale-Einstellung
vorzunehmen.
Referenz
class locale {
public:
class facet;
class id;
typedef int category;
static const category;
/* none, collate, ctype,
monetary, numeric,
time, messages,
all = collate | ctype | monetary | numeric | time | messages;
*/
// Konstruktoren:
locale() throw();
locale(const locale& other) throw();,
explicit locale(const char* std_name);
locale(const locale& other, const char* std_name, category);
template <class Facet> locale(const locale& other, Facet* f);
template <class Facet> locale(const locale& other,
const locale& one);
locale(const locale& other, const locale& one, category);
~locale() throw(); // non-virtual
const locale& operator=(const locale& other) throw();
427
Die C++-Standardbibliothek
Beispiel
class de_Num : public numpunct_byname<char> {
public:
de_Num(const char* name) : numpunct_byname<char>(name) {}
protected:
virtual char_type do_decimal_point() const {
return ',';
}
};
ctype_base <locale>
Basisklasse zum Klassentemplate ctype, die einen Aufzählungstyp definiert, der als
Maske bei der Zeichenklassifizierung benutzt wird.
class ctype_base {
public:
enum mask {
space, // Nicht-darstellendes Zeichen
print, // Darstellbares Zeichen
cntrl, // Steuerzeichen
upper, // Großbuchstabe
lower, // Kleinbuchstabe
alpha, // Buchstabe
digit, // Ziffer
428
Die Hilfsklassen für die einzelnen Kategorien
punct, // Interpunktionszeichen
xdigit, // Hexadezimalzahl
alnum, // alpha | digit
graph // alnum | punct
};
};
ctype <locale>
Klassentemplate zur Erzeugung von Facetten der Kategorie ctype, zur Zeichenklas-
sifizierung und -konvertierung.
Enthält einen Satz von public-Methoden zur Zeichenklassifizierung und -konvertie-
rung. Jeder Funktion entspricht eine virtuelle protected Version, die sie aufruft und
die in abgeleiteten Klassen überschrieben werden kann.
template <class charT>
class ctype : public locale::facet, public ctype_base {
public:
typedef charT char_type;
explicit ctype(size_t refs = 0);
bool is(mask m, charT c) const;
const charT* is(const charT* low, const charT* high, mask* vec) const;
const charT* scan_is(mask m,const charT* low,const charT* high) const;
const charT* scan_not(mask m,const charT* low,const charT* high) const;
charT toupper(charT) const;
const charT* toupper(charT* low, const charT* high) const;
charT tolower(charT c) const;
const charT* tolower(charT* low, const charT* high) const;
charT widen(char c) const;
const char* widen(const char* low, const char* high, charT* to) const;
char narrow(charT c, char dfault) const;
const charT* narrow(const charT* low, const charT*, char dfault,
char* to) const;
static locale::id id;
protected:
~ctype(); // virtual
virtual bool do_is(mask m, charT c) const;
virtual const charT* do_is(const charT* low, const charT* high,
mask* vec) const;
virtual const charT* do_scan_is(mask m,
const charT* low, const charT* high) const;
virtual const charT* do_scan_not(mask m,
const charT* low, const charT* high) const;
virtual charT do_toupper(charT) const;
virtual const charT* do_toupper(charT* low, const charT* high) const;
virtual charT do_tolower(charT) const;
virtual const charT* do_tolower(charT* low, const charT* high) const;
virtual charT do_widen(char) const;
virtual const char* do_widen(const char* low, const char* high,
charT* dest) const;
429
Die C++-Standardbibliothek
ctype_byname <locale>
Bietet die Möglichkeit, eine Facette, passend zu einer durch ihren Namen spezifi-
zierten locale-Einstellung, zu erzeugen. Dem Konstruktor wird dazu der Name der
locale-Einstellung übergeben.
template <class charT>
class ctype_byname : public ctype<charT> {
public:
explicit ctype_byname(const char*, size_t refs = 0);
protected:
~ctype_byname(); // virtual
virtual bool do_is(mask m, charT c) const;
virtual const charT* do_is(const charT* low, const charT* high,
mask* vec) const;
virtual const char* do_scan_is(mask m,
const charT* low, const charT* high) const;
virtual const char* do_scan_not(mask m,
const charT* low, const charT* high) const;
virtual charT do_toupper(charT) const;
virtual const charT* do_toupper(charT* low, const charT* high) const;
virtual charT do_tolower(charT) const;
virtual const charT* do_tolower(charT* low, const charT* high) const;
virtual charT do_widen(char) const;
virtual const char* do_widen(const char* low, const char* high,
charT* dest) const;
virtual char do_narrow(charT, char dfault) const;
virtual const charT* do_narrow(const charT* low, const charT* high,
char dfault, char* dest) const;
};
codecvt_base <locale>
Basisklasse zum Klassentemplate codecvt, die einen Aufzählungstyp definiert, der
die verschiedenen Ergebniswerte der Konvertierungsfunktion codecvt::convert()
definiert.
class codecvt_base {
public:
enum result {
ok, // vollständige Konvertierung
partial // nicht genügend Speicher
error // keine Konvertierung möglich
noconv // keine Konvertierung erforderlich
};
};
430
Die Hilfsklassen für die einzelnen Kategorien
codecvt <locale>
Klassentemplate zur Erzeugung von Facetten der Kategorie codecvt, zur Konvertie-
rung von Zeichensätzen.
Die Klasse enthält public-Methoden zur Konvertierung von einem Zeichensatz in
einen anderen. Jeder Funktion entspricht eine virtuelle protected Version, die sie
aufruft und die in abgeleiteten Klassen überschrieben werden kann.
template <class internT, class externT, class stateT>
class codecvt : public locale::facet, public codecvt_base {
public:
typedef internT intern_type;
typedef externT extern_type;
typedef stateT state_type;
explicit codecvt(size_t refs = 0);
result out(stateT& state, const internT* from, const internT* from_end,
const internT*& from_next, externT* to,
externT* to_limit, externT*& to_next) const;
result unshift(stateT& state, externT* to,
externT* to_limit, externT*& to_next) const;
result in(stateT& state, const externT* from, const externT* from_end,
const externT*& from_next, internT* to,
internT* to_limit, internT*& to_next) const;
int encoding() const throw();
bool always_noconv() const throw();
int length(const stateT&, const externT* from, const externT* end,
size_t max) const;
int max_length() const throw();
static locale::id id;
protected:
~codecvt(); // virtual
virtual result do_out(stateT& state, const internT* from,
const internT* from_end, const internT*& from_next,
externT* to, externT* to_limit, externT*& to_next) const;
virtual result do_unshift(stateT& state, externT* to,
externT* to_limit, externT*& to_next) const;
virtual result do_in(stateT& state, const externT* from,
const externT* from_end, const externT*& from_next,
internT* to, internT* to_limit,
internT*& to_next) const;
virtual int do_encoding() const throw();
virtual bool do_always_noconv() const throw();
virtual int do_length(const stateT&, const externT* from,
const externT* end, size_t max) const;
virtual int do_max_length() const throw();
};
431
Die C++-Standardbibliothek
codecvt_byname <locale>
Bietet die Möglichkeit, eine Facette, passend zu einer durch ihren Namen spezifi-
zierten locale-Einstellung, zu erzeugen. Dem Konstruktor wird dazu der Name der
locale-Einstellung übergeben.
template <class internT, class externT, class stateT>
class codecvt_byname : public codecvt<internT, externT, stateT> {
public:
explicit codecvt_byname(const char*, size_t refs = 0);
protected:
~codecvt_byname(); // virtual
virtual result do_out(stateT& state, const internT* from,
const internT* from_end, const internT*& from_next,
externT* to, externT* to_limit,
externT*& to_next) const;
virtual result do_in(stateT& state, const externT* from,
const externT* from_end, const externT*& from_next,
internT* to, internT* to_limit,
internT*& to_next) const;
virtual int do_encoding() const throw();
virtual bool do_always_noconv() const throw();
virtual int do_length(const stateT&, const externT* from,
const externT* end,size_t max) const;
virtual int do_max_length() const throw();
};
collate <locale>
Klassentemplate zur Erzeugung von Facetten der Kategorie collate, zum Vergleich
von Zeichenketten.
Enthält einen Satz von public-Methoden zum Vergleich von Zeichenketten. Jeder
Methode entspricht eine virtuelle protected Version, die sie aufruft und die in abge-
leiteten Klassen überschrieben werden kann.
template <class charT>
class collate : public locale::facet {
public:
typedef charT char_type;
typedef basic_string<charT> string_type;
explicit collate(size_t refs = 0);
int compare(const charT* low1, const charT* high1,
const charT* low2, const charT* high2) const;
string_type transform(const charT* low, const charT* high) const;
long hash(const charT* low, const charT* high) const;
static locale::id id;
protected:
~collate(); // virtual
virtual int do_compare(const charT* low1, const charT* high1,
const charT* low2, const charT* high2) const;
virtual string_type do_transform(const charT* low,
432
Die Hilfsklassen für die einzelnen Kategorien
collate_byname <locale>
Bietet die Möglichkeit, eine Facette, passend zu einer durch ihren Namen spezifi-
zierten locale-Einstellung, zu erzeugen. Dem Konstruktor wird dazu der Name der
locale-Einstellung übergeben.
template <class charT>
class collate_byname : public collate<charT> {
public:
explicit collate_byname(const char*, size_t refs = 0);
protected:
~collate_byname(); // virtual
virtual int do_compare(const charT* low1, const charT* high1,
const charT* low2, const charT* high2) const;
virtual string_type do_transform(const charT* low,
const charT* high) const;
virtual long do_hash( const charT* low, const charT* high) const;
};
messages_base <locale>
Basisklasse zum Klassentemplate messages, die eine Abkürzung für den Typ der Bot-
schaftskataloge definiert.
class messages_base {
public:
typedef int catalog;
};
messages <locale>
Klassentemplate zur Erzeugung von Facetten der Kategorie messages, zur Auswahl
von Meldungen aus Katalogen.
Enthält einen Satz von public-Methoden zur Auswahl von Meldungen aus Katalo-
gen. Jeder Funktion entspricht eine virtuelle protected Version, die sie aufruft und
die in abgeleiteten Klassen überschrieben werden kann.
template <class charT>
class messages : public locale::facet, public messages_base {
public:
typedef charT char_type;
typedef basic_string<charT> string_type;
explicit messages(size_t refs = 0);
catalog open(const basic_string<char>& fn, const locale&) const;
string_type get(catalog c, int set, int msgid,
const string_type& dfault) const;
433
Die C++-Standardbibliothek
messages_byname <locale>
Bietet die Möglichkeit, eine Facette, passend zu einer durch ihren Namen spezifi-
zierten locale-Einstellung, zu erzeugen. Dem Konstruktor wird dazu der Name der
locale-Einstellung übergeben.
template <class charT>
class messages_byname : public messages<charT> {
public:
explicit messages_byname(const char*, size_t refs = 0);
protected:
~messages_byname(); // virtual
money_get <locale>
Klassentemplate zur Erzeugung von Facetten der Kategorie monetary, zum Einlesen
von Währungsangaben.
Enthält public-Methoden zum Einlesen von Währungsangaben. Jeder Methode ent-
spricht eine virtuelle protected Version, die sie aufruft und die in abgeleiteten Klas-
sen überschrieben werden kann.
template <class charT, class InputIterator = istreambuf_iterator<charT> >
class money_get : public locale::facet {
public:
typedef charT char_type;
typedef InputIterator iter_type;
typedef basic_string<charT> string_type;
explicit money_get(size_t refs = 0);
iter_type get(iter_type s, iter_type end, bool intl,
ios_base& f, ios_base::iostate& err,
long double& units) const;
iter_type get(iter_type s, iter_type end, bool intl,
434
Die Hilfsklassen für die einzelnen Kategorien
money_put <locale>
Klassentemplate zur Erzeugung von Facetten der Kategorie monetary, zum Ausgeben
von Währungsangaben.
Enthält public-Methoden zum Ausgeben von Währungsangaben. Jeder Funktion
entspricht eine virtuelle protected Version, die sie aufruft und die in abgeleiteten
Klassen überschrieben werden kann.
template <class charT, bool Intl = false,
class OutputIterator = ostreambuf_iterator<charT> >
class money_put : public locale::facet {
public:
typedef charT char_type;
typedef OutputIterator iter_type;
typedef basic_string<charT> string_type;
explicit money_put(size_t refs = 0);
iter_type put(iter_type s, bool intl, ios_base& f,
char_type fill, long double units) const;
iter_type put(iter_type s, bool intl, ios_base& f,
char_type fill, const string_type& digits) const;
static locale::id id;
protected:
~money_put(); // virtual
virtual iter_type do_put(iter_type, bool, ios_base&, char_type fill,
long double units) const;
virtual iter_type do_put(iter_type, bool, ios_base&, char_type fill,
const string_type& digits) const;
};
money_base <locale>
Basisklasse zum Klassentemplate moneypunct, die einen Aufzählungstyp und einen
zugehörigen Strukturtyp definiert, die zur Festlegung der Abfolge von Elementen in
Währungsangaben dienen.
class money_base {
public:
435
Die C++-Standardbibliothek
enum part {
none, // keine Angaben
space, // Nicht darstellendes Zeichen
symbol, // Währungssymbol
sign, // Vorzeichen
value // Wert };
struct pattern { char field[4]; };
};
moneypunct <locale>
Klassentemplate zur Erzeugung von Facetten der Kategorie monetary, zur Zeichen-
setzung in Währungsangaben.
Enthält einen Satz von public-Methoden zur Zeichensetzung in Währungsangaben.
Jeder Methode entspricht eine virtuelle protected Version, die sie aufruft und die in
abgeleiteten Klassen überschrieben werden kann.
template <class charT, bool International = false>
class moneypunct : public locale::facet, public money_base {
public:
typedef charT char_type;
typedef basic_string<charT> string_type;
explicit moneypunct(size_t refs = 0);
charT decimal_point() const;
charT thousands_sep() const;
string grouping() const;
string_type curr_symbol() const;
string_type positive_sign() const;
string_type negative_sign() const;
int frac_digits() const;
pattern pos_format() const;
pattern neg_format() const;
static locale::id id;
static const bool intl = International;
protected:
~moneypunct(); // virtual
virtual charT do_decimal_point() const;
virtual charT do_thousands_sep() const;
virtual string do_grouping() const;
virtual string_type do_curr_symbol() const;
virtual string_type do_positive_sign() const;
virtual string_type do_negative_sign() const;
virtual int do_frac_digits() const;
virtual pattern do_pos_format() const;
virtual pattern do_neg_format() const;
};
436
Die Hilfsklassen für die einzelnen Kategorien
moneypunct_byname <locale>
Bietet die Möglichkeit, eine Facette, passend zu einer durch ihren Namen spezifi-
zierten locale-Einstellung, zu erzeugen. Dem Konstruktor wird dazu der Name der
locale-Einstellung übergeben.
template <class charT, bool Intl = false>
class moneypunct_byname : public moneypunct<charT, Intl> {
public:
explicit moneypunct_byname(const char*, size_t refs = 0);
protected:
~moneypunct_byname(); // virtual
virtual charT do_decimal_point() const;
virtual charT do_thousands_sep() const;
virtual string do_grouping() const;
virtual string_type do_curr_symbol() const;
virtual string_type do_positive_sign() const;
virtual string_type do_negative_sign() const;
virtual int do_frac_digits() const;
virtual pattern do_pos_format() const;
virtual pattern do_neg_format() const;
};
num_get <locale>
Klassentemplate zur Erzeugung von Facetten der Kategorie numeric, zum Einlesen
von numerischen Werten.
Enthält einen Satz von public-Methoden zum Einlesen von numerischen Werten.
Jeder Methode entspricht eine virtuelle protected Version, die sie aufruft und die in
abgeleiteten Klassen überschrieben werden kann.
template <class charT, class InputIterator = istreambuf_iterator<charT> >
class num_get : public locale::facet {
public:
typedef charT char_type;
typedef InputIterator iter_type;
explicit num_get(size_t refs = 0);
iter_type get(iter_type in, iter_type end, ios_base&,
ios_base::iostate& err, bool& v) const;
iter_type get(iter_type in, iter_type end, ios_base& ,
ios_base::iostate& err, long& v) const;
iter_type get(iter_type in, iter_type end, ios_base&,
ios_base::iostate& err, unsigned short& v) const;
iter_type get(iter_type in, iter_type end, ios_base&,
ios_base::iostate& err, unsigned int& v) const;
iter_type get(iter_type in, iter_type end, ios_base&,
ios_base::iostate& err, unsigned long& v) const;
iter_type get(iter_type in, iter_type end, ios_base&,
ios_base::iostate& err, float& v) const;
iter_type get(iter_type in, iter_type end, ios_base&,
ios_base::iostate& err, double& v) const;
437
Die C++-Standardbibliothek
num_put <locale>
Klassentemplate zur Erzeugung von Facetten der Kategorie numeric, zum Ausgeben
von numerischen Werten.
Enthält einen Satz von public-Methoden zum Ausgeben von numerischen Werten.
Jeder Methode entspricht eine virtuelle protected Version, die sie aufruft und die in
abgeleiteten Klassen überschrieben werden kann.
template <class charT, class OutputIterator =ostreambuf_iterator<charT> >
class num_put : public locale::facet {
public:
typedef charT char_type;
typedef OutputIterator iter_type;
explicit num_put(size_t refs = 0);
iter_type put(iter_type s, ios_base& f, char_type fill, bool v) const;
iter_type put(iter_type s, ios_base& f, char_type fill, long v) const;
iter_type put(iter_type s, ios_base& f, char_type fill,
unsigned long v) const;
iter_type put(iter_type s, ios_base& f, char_type fill,
double v) const;
iter_type put(iter_type s, ios_base& f, char_type fill,
long double v) const;
iter_type put(iter_type s, ios_base& f, char_type fill,
438
Die Hilfsklassen für die einzelnen Kategorien
void* v) const;
static locale::id id;
protected:
~num_put(); // virtual
virtual iter_type do_put(iter_type, ios_base&, char_type fill,
bool v) const;
virtual iter_type do_put(iter_type, ios_base&, char_type fill,
long v) const;
virtual iter_type do_put(iter_type, ios_base&, char_type fill,
unsigned long) const;
virtual iter_type do_put(iter_type, ios_base&, char_type fill,
double v) const;
virtual iter_type do_put(iter_type, ios_base&, char_type fill,
long double v) const;
virtual iter_type do_put(iter_type, ios_base&, char_type fill,
void* v) const;
};
numpunct <locale>
Klassentemplate zur Erzeugung von Facetten der Kategorie numeric, zur Zeichenset-
zung in numerischen Werten.
Enthält einen Satz von public-Methoden zur Zeichensetzung. Jeder Funktion ent-
spricht eine virtuelle protected Version, die sie aufruft und die in abgeleiteten Klas-
sen überschrieben werden kann.
439
Die C++-Standardbibliothek
numpunct_byname <locale>
Bietet die Möglichkeit, eine Facette, passend zu einer durch ihren Namen spezifi-
zierten locale-Einstellung, zu erzeugen. Dem Konstruktor wird dazu der Name der
locale-Einstellung übergeben.
template <class charT>
class numpunct_byname : public numpunct<charT> {
public:
explicit numpunct_byname(const char*, size_t refs = 0);
protected:
~numpunct_byname(); // virtual
virtual char_type do_decimal_point() const;
virtual char_type do_thousands_sep() const;
virtual string do_grouping() const;
virtual string_type do_truename() const; // for bool
virtual string_type do_falsename() const; // for bool
};
time_base <locale>
Basisklasse zum Klassentemplate time_get, die einen Aufzählungstyp definiert, der
die wichtigsten Abfolgen von Datumsangaben spezifiziert.
class time_base {
public:
enum dateorder { no_order, // keine bevorzugte Reihenfolge
dmy, // Tag – Monat – Jahr
mdy, // Monat – Tag – Jahr
ymd, // Jahr – Monat – Tag
ydm // Jahr – Tag – Monat };
};
time_get <locale>
Klassentemplate zur Erzeugung von Facetten der Kategorie time, zum Einlesen von
Zeitangaben.
Enthält einen Satz von public-Methoden zum Einlesen von Zeitangaben. Jeder
Funktion entspricht eine virtuelle protected Version, die sie aufruft und die in abge-
leiteten Klassen überschrieben werden kann.
template <class charT, class InputIterator = istreambuf_iterator<charT> >
class time_get : public locale::facet, public time_base {
public:
typedef charT char_type;
typedef InputIterator iter_type;
explicit time_get(size_t refs = 0);
dateorder date_order() const { return do_date_order(); }
iter_type get_time(iter_type s, iter_type end, ios_base& f,
ios_base::iostate& err, tm* t) const;
iter_type get_date(iter_type s, iter_type end, ios_base& f,
ios_base::iostate& err, tm* t) const;
440
Die Hilfsklassen für die einzelnen Kategorien
time_get_byname <locale>
Bietet die Möglichkeit, eine Facette, passend zu einer durch ihren Namen spezifi-
zierten locale-Einstellung, zu erzeugen. Dem Konstruktor wird dazu der Name der
locale-Einstellung übergeben.
template <class charT, class InputIterator = istreambuf_iterator<charT> >
class time_get_byname : public time_get<charT, InputIterator> {
public:
explicit time_get_byname(const char*, size_t refs = 0);
protected:
~time_get_byname(); // virtual
virtual dateorder do_date_order() const;
virtual iter_type do_get_time(iter_type s, iter_type end, ios_base&,
ios_base::iostate& err, tm* t) const;
virtual iter_type do_get_date(iter_type s, iter_type end, ios_base&,
ios_base::iostate& err, tm* t) const;
virtual iter_type do_get_weekday(iter_type s, iter_type end, ios_base&,
ios_base::iostate& err, tm* t) const;
virtual iter_type do_get_monthname(iter_type s,iter_type end,ios_base&,
ios_base::iostate& err, tm* t) const;
virtual iter_type do_get_year(iter_type s, iter_type end, ios_base&,
ios_base::iostate& err, tm* t) const;
};
441
Die C++-Standardbibliothek
time_put <locale>
Klassentemplate zur Erzeugung von Facetten der Kategorie time, zur Ausgabe von
Zeitangaben.
Enthält einen Satz von public-Methoden zur Ausgabe von Zeitangaben. Jeder
Funktion entspricht eine virtuelle protected Version, die sie aufruft und die in abge-
leiteten Klassen überschrieben werden kann.
template <class charT, class OutputIterator =ostreambuf_iterator<charT> >
class time_put : public locale::facet {
public:
typedef charT char_type;
typedef OutputIterator iter_type;
explicit time_put(size_t refs = 0);
iter_type put(iter_type s, ios_base& f, char_type fill, const tm* tmb,
const charT* pattern, const charT* pat_end) const;
iter_type put(iter_type s, ios_base& f, char_type fill,
const tm* tmb, char format, char modifier = 0) const;
static locale::id id;
protected:
~time_put(); // virtual
virtual iter_type do_put(iter_type s,ios_base&,char_type,const tm* t,
char format, char modifier) const;
};
time_put_byname <locale>
Bietet die Möglichkeit, eine Facette, passend zu einer durch ihren Namen spezifi-
zierten locale-Einstellung, zu erzeugen. Dem Konstruktor wird dazu der Name der
locale-Einstellung übergeben.
template <class charT, class OutputIterator =ostreambuf_iterator<charT> >
class time_put_byname : public time_put<charT, OutputIterator> {
public:
explicit time_put_byname(const char*, size_t refs = 0);
protected:
~time_put_byname(); // virtual
virtual iter_type do_put(iter_type s,ios_base&,char_type,const tm* t,
char format, char modifier) const;
};
442
complex
complex
aus <complex>
Beschreibung
Das Template complex implementiert eine Repräsentation der komplexen Zahlen sowie die auf
ihnen definierten Operationen.
Anwendung
Die Klasse complex selbst definiert lediglich die Konstruktoren zum Erzeugen von
komplexen Objekten und überladene Versionen der arithmetischen Operatoren.
complex<float> c(12.3, 0.5);
Die Klasse selbst definiert zwar nur die arithmetischen Operatoren, aber global
sind weitere Funktionen zur Arbeit mit complex-Objekten definiert:
● Überladene Formen der mathematischen C-Funktionen.
● Überladene Formen der Vergleichsoperatoren.
● Überladene Formen der Operatoren zur Ein- und Ausgabe.
● Spezielle Funktionen für komplexe Zahlen (real(), imag(), abs(), arg(),
norm(), conj() und polar()).
Ganzzahlen oder Gleitkommawerte können als komplexe Zahlen dargestellt wer-
den, deren Realteil der Ganzzahl/Gleitkommazahl entspricht und deren Imaginär-
teil gleich Null ist.
Für die Datentypen float, double und long double sind bereits entsprechende Tem-
plate-Instanzen spezialisiert.
Referenz
template<class T>
class complex {
public:
typedef T value_type;
443
Die C++-Standardbibliothek
T real() const;
T imag() const;
valarray
aus <valarray>
Beschreibung
Das Template valarray dient dazu, geordnete Mengen zu repräsentieren. Durch die verschiede-
nen Möglichkeiten der Indizierung, die die Klasse zur Verfügung stellt, ist es möglich, die
Menge als Arrays oder Matrizen zu behandeln (bzw. entsprechende Klassen abzuleiten).
Ergänzt wird die Klasse valarray durch die global überladenen mathematischen
Funktionen und die Hilfsklassen zur Erzeugung von Teilmengen (slice,
slice_array, gslice, gslice_array, mask_array und indirect_array).
Anwendung
Zur Erzeugung eines valarray-Objekts spezialisiert man das Template für den
Datentyp der Mengenelemente und definiert ein Objekt der Klasse:
valarray<int> va(20);
Die Klasse valarray definiert – mit Ausnahme des Index-Operators [ ] – eine Reihe
von Funktionen zur Manipulation von Mengen, die stets alle Elemente der Klasse
betreffen.
Zusätzlich sind die wichtigsten Operatoren sowie die mathematischen Funktionen
für valarray<T> überladen, wobei die Operationen auf allen Elementen im valarray-
Objekt ausgeführt werden.
Der Index-Operator ist überladen, um entweder auf einzelne Elemente oder Teil-
mengen zuzugreifen.
444
valarray
teil = va[gslice(2,size,stride)];
cout << "\nTeilarray\n";
for(int i = 0; i < size[0]*size[1]; i++) {
cout << teil[i] << endl;
}
Wird der Operand auf ein konstantes valarray-Objekt angewendet, liefert er eine
Kopie der Teilmenge als neues valarray-Objekt zurück. Wird der Operand auf ein
nicht-konstantes valarray-Objekt angewendet, liefert er eine Referenz auf die Teil-
menge als Objekt des Typs slice_array, gslice_array, mask_array oder
indirect_array zurück. Alle Zugriffe auf diese Referenzen sind Zugriffe auf das Ori-
ginal-valarray.
Referenz
template<class T> class valarray {
public:
typedef T value_type;
// Konstruktoren:
valarray();
explicit valarray(size_t);
valarray(const T&, size_t);
valarray(const T*, size_t);
valarray(const valarray&);
valarray(const slice_array<T>&);
valarray(const gslice_array<T>&);
valarray(const mask_array<T>&);
valarray(const indirect_array<T>&);
~valarray();
// Zuweisung:
valarray<T>& operator=(const valarray<T>&);
valarray<T>& operator=(const T&);
valarray<T>& operator=(const slice_array<T>&);
valarray<T>& operator=(const gslice_array<T>&);
445
Die C++-Standardbibliothek
446
Teilmengen von valarray-Objekten
Verweise
Siehe Beispiel zu Header-Datei valarray
slice <valarray>
Eine Instanz der Klasse definiert jeweils eine Anzahl von Indizes, die einer Teil-
menge eines valarray-Objekts entsprechen. Die Indizes werden spezifiziert als
● Erster Index
● Anzahl der Indizes
● Abstand zwischen den Indizes
Beispiel
slice(3,5,2)
wählt aus einem Array die Elemente mit den Indizes
3, 5, 7, 9, 11
aus.
Um auf die Teilmenge zugreifen zu können, wird der Indexoperator [ ] der Klasse
valarray benutzt, beispielsweise:
valarr[slice(3,5,2)]
Referenz
class slice {
public:
slice();
slice(size_t, size_t, size_t);
447
Die C++-Standardbibliothek
Verweise
Siehe Beispiel zu Header-Datei valarray
gslice <valarray>
Eine Instanz der Klasse definiert jeweils eine Anzahl von Indizes, die einer Teil-
menge eines valarray-Objekts entsprechen. Die Indizes werden spezifiziert als
● Erster Index (start)
● Anzahl der Indizes pro Dimension (size)
● Abstand zwischen den Indizes für jede Dimension (stride)
Die Dimension wird gegeben durch Anzahl der Elemente für size und stride.
Beispiel
Eine Instanz mit
start = 2;
size = {3,4};
stride = {5,1};
wählt beispielsweise aus einem valarray-Objekt die folgende 3x4-Matrix aus:
2, 3, 4, 5
7, 8, 9, 10
12, 13, 14, 15
Die Berechnung der Indizes k der ausgewählten Elemente im valarray-Objekt stellt
sich dar als
for(i=0;i<size[0];i++}
for(j=0;j<size[1];j++}
k = start + i*stride[i] + j*stride[j];
Um auf die Teilmenge zugreifen zu können, wird der Indexoperator [ ] der Klasse
valarray benutzt, beispielsweise:
valarray<size_t> size(2);
size[0] = 3; size[1] = 4;
valarray<size_t> stride(2);
stride[0] = 5; stride[1] = 1;
teil = va[gslice(2,size,stride)];
Referenz
class gslice {
public:
gslice();
gslice(size_t s, const valarray<size_t>& l, const valarray<size_t>& d);
448
Teilmengen von valarray-Objekten
slice_array <vallarray>
Die Klasse dient dazu, eine – durch eine slice-Instanz definierte – Teilmenge eines
valarray-Objekts auszuwählen (Indexoperator [ ] der Klasse valarray), auf ihr zu
operieren oder sie in ein eigenständiges valarray-Objekt umzuwandeln (letzteres
mit Hilfe des entsprechenden Konstruktors der Klasse valarray).
Beispiel
valarr[slice(3,8,2)].fill(3);
Referenz
template <class T> class slice_array {
public:
typedef T value_type;
449
Die C++-Standardbibliothek
~slice_array();
private:
slice_array();
slice_array(const slice_array&);
slice_array& operator=(const slice_array&);
};
gslice_array <valarray>
Die Klasse dient dazu, eine – durch eine gslice-Instanz definierte – Teilmenge eines
valarray-Objekts auszuwählen (Indexoperator [ ] der Klasse valarray), auf ihr zu
operieren oder sie in ein eigenständiges valarray-Objekt umzuwandeln (letzteres
mit Hilfe des entsprechenden Konstruktors der Klasse valarray).
template <class T> class gslice_array {
public:
typedef T value_type;
mask_array <valarray>
Die Klasse dient dazu, eine – durch eine valarray<bool>-Instanz definierte – Teil-
menge eines valarray-Objekts auszuwählen (Indexoperator [ ] der Klasse valarray),
auf ihr zu operieren oder sie in ein eigenständiges valarray-Objekt umzuwandeln
(letzteres mit Hilfe des entsprechenden Konstruktors der Klasse valarray).
template <class T> class mask_array {
public:
typedef T value_type;
450
Teilmengen von valarray-Objekten
indirect_array <valarray>
Die Klasse dient dazu, eine – durch eine valarray<size_t>-Instanz definierte – Teil-
menge eines valarray-Objekts auszuwählen (Indexoperator [ ] der Klasse valarray),
auf ihr zu operieren oder sie in ein eigenständiges valarray-Objekt umzuwandeln
(letzteres mit Hilfe des entsprechenden Konstruktors der Klasse valarray).
template <class T> class indirect_array {
public:
typedef T value_type;
451
Die C++-Standardbibliothek
numeric_limits
aus <limits>
Beschreibung
Die Klasse numeric_limits kapselt die Informationen über die implementierungsspezifische
Repräsentation der numerischen Datentypen. Verschiedene Elemente der Klasse sind nur für
bestimmte Datentypen sinnvoll zu definieren. Datenelemente, die nicht zur Charakterisierung
eines Datentyps beitragen, werden auf Null oder false gesetzt. Außer des Templates sind in der
Laufzeitbibliothek auch Spezialisierungen für die elementaren Datentypen definiert.
Referenz
template<class T> class numeric_limits {
public:
static const bool is_specialized = false;
static T min() throw();
static T max() throw();
static const int digits = 0;
static const int digits10 = 0;
static const bool is_signed = false;
static const bool is_integer = false;
static const bool is_exact = false;
static const int radix = 0;
static T epsilon() throw();
static T round_error() throw();
452
exception
exception
aus <exception>
Beschreibung
Basisklasse für die Exception-Objekte, die von der Sprache und den Komponenten der C++-
Standardbibliotheken ausgelöst werden (oder zur Bequemlichkeit des Programmierers vordefi-
niert sind). Direkt von ihr abgeleitet sind die von der Sprache verwendeten Exceptions (bad_...)
sowie die Klassen logic_error (logische Fehler) und runtime_error (Laufzeitfehler), von
denen wiederum die restlichen Exception-Klassen abgeleitet sind.
Anwendung
Enthält neben Konstruktor, Destruktor noch einen Kopierkonstruktor und entspre-
chend eine eigene Version des Zuweisungsoperators, sowie eine Methode zum Aus-
geben eines Meldungsstrings.
Da alle Elemente der Klasse mit throw() deklariert sind, kann die Klasse selbst keine
Exceptions auslösen.
Von der Klasse exception selbst werden üblicherweise keine Exception-Objekte
gebildet, sie dient lediglich als Basisklasse.
Referenz
class exception {
public:
exception() throw();
exception(const exception&) throw();
exception& operator=(const exception&) throw();
virtual ~exception() throw();
virtual const char* what() const throw();
};
453
Die C++-Standardbibliothek
Abgeleitete Exception-Klassen
aus <exception>, <stdexcept> und <typeinfo>
Klassentyp für Exceptions, die von den Methoden der Laufzeitbibliothek im Falle
eines Fehlers bei der Speicherreservierung ausgelöst werden.
class bad_alloc : public exception {
public:
bad_alloc() throw();
bad_alloc(const bad_alloc&) throw();
bad_alloc& operator=(const bad_alloc&) throw();
virtual ~bad_alloc() throw();
virtual const char* what() const throw();
};
Klassentyp für Exceptions, die im Falle einer gescheiterten Typumwandlung mittels
dynamic_cast ausgelöst werden.
class bad_cast : public exception {
public:
bad_cast() throw();
bad_cast(const bad_cast&) throw();
bad_cast& operator=(const bad_cast&) throw();
virtual ~bad_cast() throw();
virtual const char* what() const throw();
};
Klassentyp für Exceptions, die bei Fehlern in der Exception-Behandlung (Auslö-
sung einer Exception in einer Klasse, für die die Exception nicht deklariert ist, Auf-
treten einer nicht behandelten Exception, etc.) ausgelöst werden.
class bad_exception : public exception {
public:
bad_exception() throw();
bad_exception(const bad_exception&) throw();
bad_exception& operator=(const bad_exception&) throw();
virtual ~bad_exception() throw();
virtual const char* what() const throw();
};
Klassentyp für Exceptions, die bei Auftreten eines Null-Zeigers in einem typeid-
Ausdruck ausgelöst werden.
class bad_typeid : public exception {
public:
bad_typeid() throw();
bad_typeid(const bad_typeid&) throw();
bad_typeid& operator=(const bad_typeid&) throw();
virtual ~bad_typeid() throw();
virtual const char* what() const throw();
};
454
Abgeleitete Exception-Klassen
Klassentyp für Exceptions, die bei Auftreten von unzulässigen Werten ausgelöst
werden.
class domain_error : public logic_error {
public:
domain_error(const string& what_arg);
};
Klassentyp für Exceptions, die bei Übergabe unzulässiger Argumente ausgelöst wer-
den.
class invalid_argument : public logic_error {
public:
invalid_argument(const string& what_arg);
};
Klassentyp für Exceptions, die ausgelöst werden, wenn die zulässige Größe von
Datenstrukturen überschritten wird.
class length_error : public logic_error {
public:
length_error(const string& what_arg);
};
Klassentyp für Exceptions, die bei Auftreten logischer Fehler – also Fehlern, die
möglicherweise noch vor der Programmausführung aufgespürt werden können –
ausgelöst werden.
class logic_error : public exception {
public:
logic_error(const string& what_arg);
};
Klassentyp für Exceptions, die ausgelöst werden, wenn ein übergebenes Argument
nicht im vorgesehenen Wertebereich liegt.
class out_of_range : public logic_error {
public:
out_of_range(const string& what_arg);
};
Klassentyp für Exceptions, die bei Überlauf arithmetischer Variablen ausgelöst
werden.
class overflow_error : public runtime_error {
public:
overflow_error(const string& what_arg);
};
Klassentyp für Exceptions, die bei Verletzung von Gültigkeitsbereichen ausgelöst
werden.
class range_error : public runtime_error {
public:
range_error(const string& what_arg);
};
455
Die C++-Standardbibliothek
Klassentyp für Exceptions, die bei Auftreten von Laufzeitfehlern – also Fehlern, die
meist erst während der Programmausführung aufgespürt werden können – ausge-
löst werden.
class runtime_error : public exception {
public:
runtime_error(const string& what_arg);
};
Klassentyp für Exceptions, die bei Unterlauf arithmetischer Variablen ausgelöst
werden.
class underflow_error : public runtime_error {
public:
underflow_error(const string& what_arg);
};
set_terminate() <exception>
Richtet die Funktion ein, die bei vorzeitigen Programmabbrüchen, z. B. infolge
unbehandelter Exceptions aufgerufen wird. Dazu wird ein Zeiger auf die Pro-
grammabbruchfunktion, der vom Typ
terminate_handler (typedef void (*terminate_handler)() )
sein muß, übergeben.
terminate_handler set_terminate(terminate_handler t_func) throw();
● Rückgabe: Zeiger auf die alte Programmabbruchfunktion.
set_unexpected() <exception>
Richtet die Funktion ein, die aufgerufen wird, wenn innerhalb einer Funktion eine
Exception ausgelöst wird, für die die Funktion nicht deklariert ist. Die eingerichtete
Funktion muß entweder
456
Funktionen zur Exception-Behandlung
terminate() <exception>
Die Funktion terminate() wird bei Auftreten eines Fehlers zum vorzeitigen Pro-
grammabbruch aufgerufen, beispielsweise wenn keine Behandlungsfunktion zu
einer ausgelösten Exception gefunden wird (meist also von unexpected() ). Die
Funktion terminate() ruft ihrerseits die von set_terminate() eingerichtete Funktion
zum Programmabbruch auf.
void terminate();
uncaught_exception() <exception>
Zeigt an, daß eine Exception ausgelöst wurde, zu der bislang kein Handler gefun-
den wurde. Kann beispielsweise in Destruktoren verwendet werden.
bool uncaught_exception();
● Rückgabe: true, wenn eine bisher unbehandelte Exception vorliegt.
unexpected() <exception>
Die Funktion unexpected() wird aufgerufen, wenn in einer Funktion eine Exception
ausgelöst wird, für die die Funktion nicht deklariert ist. Die Funktion unexpected()
ruft ihrerseits die von set_unexpected() eingerichtete Funktion zur Behandlung auf.
void unexpected();
457
Die C++-Standardbibliothek
Laufzeittypidentifizierung
type_info
aus <typeinfo>
Beschreibung
Die Tatsache, daß jede Instanz einer abgeleiteten Klasse in C++ auch als Instanz ihrer Basis-
klassen aufgefaßt werden kann, erweitert einerseits die Möglichkeiten der dynamischen
Typumwandlung, erschwert allerdings auch die Übersicht über die aktuellen Datentypen von
Zeigern und Referenzen auf Klasseninstanzen. Die Klasse type_info bietet die Möglichkeit, zur
Laufzeit des Programms Informationen zum Datentyp eines Objekts abzufragen.
Anwendung
Die Klasse type_info definiert nur private Konstruktoren. Sie kann daher nicht
explizit initialisiert werden. Statt dessen wird die Klasse in Zusammenhang mit
dem typeid-Operator benutzt, der Referenzen der Klasse erzeugt.
Referenz
class type_info {
public:
virtual ~type_info();
bool operator==(const type_info& rhs) const;
bool operator!=(const type_info& rhs) const;
bool before(const type_info& rhs) const;
const char* name() const;
private:
type_info(const type_info& rhs);
type_info& operator=(const type_info& rhs);
};
}
458
Die Struktur pair
Utilities
T1 first;
T2 second;
pair();
pair(const T1& x, const T2& y);
template<class U, class V> pair(const pair<U, V> &p);
};
template <class T1, class T2>
pair<T1, T2> make_pair(const T1& x, const T2& y);
Funktionsobjekte
aus <functional>
Beschreibung
Die Implementierung generischer Funktionen beruht oftmals auf der Übergabe von Funktionen
als Parameter (vergleiche qsort() ). Die STL erweitert dieses Konzept, indem sie Funktionen in
Klassen kapselt. Allen diesen Klassen gemeinsam ist, daß der ()-Operator für sie überladen
wurde, damit die Instanzen der Klasse (die Funktionsobjekte) wie Funktionen aufgerufen wer-
den können.
Funktionsobjekte sind mächtiger als Funktionen, da sie auf die internen Daten und
Methoden ihrer Klasse zurückgreifen können. Zudem sind alle Funktionsobjekte
der STL als Templates implementiert, um mit beliebigen Datentypen arbeiten zu
können.
Die STL unterscheidet
● Arithmetische Funktionsobjekte, die eine arithmetische Operation durchfüh-
ren (divides, etc.), und
459
Die C++-Standardbibliothek
● Prädikate, die einen Vergleich durchführen (equal_to, etc.), bool als Ergebnis-
typ haben und in den Algorithmen der STL häufig verwendet werden, um eine
Bedingung zu definieren, die die Elemente, auf denen die Algorithmenfunktion
operiert, erfüllen müssen.
● Negatoren, die ein Prädikat negieren.
● Binder, die es erlauben ein binäres Funktionsobjekt (zwei Argumente) wie ein
Funktionsobjekt mit einem Argument einzusetzen.
● Adapter, die es ermöglichen Methoden oder Zeiger auf Funktionen als Argu-
mente an Algorithmen zu übergeben.
Basisstrukturen
Abgeleitet sind die Funktionsobjekte von den Strukturen unary_function und
binary_function, je nachdem, ob ihr ()-Operator ein oder zwei Argumente erwartet.
template <class Arg, class Result>
struct unary_function {
typedef Arg argument_type;
typedef Result result_type;
};
template <class Arg1, class Arg2, class Result>
struct binary_function {
typedef Arg1 first_argument_type;
typedef Arg2 second_argument_type;
typedef Result result_type;
};
Arithmetische Funktionsobjekte
Alle Funktionsobjekte definieren den ()-Operator um wie Funktionen aufgerufen
werden zu können.
template <class T> struct divides : public binary_function<T,T,T>
T operator()(const T& x, const T& y) const;
template <class T> struct minus : public binary_function<T,T,T>
T operator()(const T& x, const T& y) const;
template <class T> struct modulus : public binary_function<T,T,T>
T operator()(const T& x, const T& y) const;
template <class T> struct multiplies : public binary_function<T,T,T>
T operator()(const T& x, const T& y) const;
template <class T> struct negate : public unary_function<T,T>
T operator()(const T& x) const;
template <class T> struct plus : public binary_function<T,T,T>
T operator()(const T& x, const T& y) const;
460
Funktionsobjekte
Prädikate
Auch die vordefinierten Prädikate definieren nur den ()-Operator.
template <class T> struct equal_to : public binary_function<T,T,bool>
bool operator()(const T& x, const T& y) const;
template <class T> struct greater : public binary_function<T,T,bool>
bool operator()(const T& x, const T& y) const;
template <class T> struct greater_equal:public binary_function<T,T,bool>
bool operator()(const T& x, const T& y) const;
template <class T> struct less : public binary_function<T,T,bool>
bool operator()(const T& x, const T& y) const;
template <class T> struct less_equal : public binary_function<T,T,bool>
bool operator()(const T& x, const T& y) const;
template <class T> struct logical_and : public binary_function<T,T,bool>
bool operator()(const T& x, const T& y) const;
template <class T> struct logical_or: public binary_function<T,T,bool>
bool operator()(const T& x, const T& y) const;
template <class T> struct logical_not: public unary_function<T,bool>
bool operator()(const T& x) const;
template <class T> struct not_equal_to: public binary_function<T,T,bool>
bool operator()(const T& x, const T& y) const;
Negatoren
template <class Predicate>
class unary_negate
: public unary_function<Predicate::argument_type,bool> {
public:
explicit unary_negate(const Predicate& pred);
bool operator()(const argument_type& x) const;
};
Funktionsklasse zur Negation eines Aussageobjekts. Der Template-Parameter Pre-
dicate bezeichnet ein unäres Funktionsobjekt, dessen Aussage negiert werden soll.
Üblicherweise verwendet man das globale Funktionentemplate not1() zur Bildung
eines unary_negate-Objekts.
template <class Predicate>
class binary_negate
: public binary_function<Predicate::first_argument_type,
Predicate::second_argument_type, bool> {
public:
explicit binary_negate(const Predicate& pred);
bool operator()(const first_argument_type& x,
const second_argument_type& y) const;
};
Funktionsklasse zur Negation eines Aussageobjekts. Der Template-Parameter
bezeichnet ein binäres Funktionsobjekt, dessen Aussage negiert werden soll. Übli-
cherweise verwendet man das globale Funktionentemplate not2() zur Bildung eines
binary_negate-Objekts.
461
Die C++-Standardbibliothek
Binder
template <class Operation>
class binder1st
: public unary_function<Operation::second_argument_type,
Operation::result_type> {
protected:
Operation op;
Operation::first_argument_type value;
public:
binder1st(const Operation& x,const Operation::first_argument_type& y);
result_type operator()(const argument_type& x) const;
};
Wandelt ein binäres Funktionsobjekt in ein unäres Funktionsobjekt, indem dem
ersten Argument ein fester Wert zugewiesen wird. Üblicherweise verwendet man
das globale Funktionentemplate bind1st() zur Bildung eines binder1st-Objekts.
template <class Operation>
class binder2nd
: public unary_function<Operation::first_argument_type,
Operation::result_type> {
protected:
Operation op;
Operation::second_argument_type value;
public:
binder2nd(const Operation& x,const Operation::second_argument_type& y);
result_type operator()(const argument_type& x) const;
};
Wandelt ein binäres Funktionsobjekt in ein unäres Funktionsobjekt, indem dem
zweiten Argument ein fester Wert zugewiesen wird. Üblicherweise verwendet man
das globale Funktionentemplate bind2nd() zur Bildung eines binder2nd-Objekts.
template <class Operation, class T>
binder1st<Operation> bind1st(const Operation& op, const T& x);
template <class Operation, class T>
binder2nd<Operation> bind2nd(const Operation& op, const T& x);
Beide Funktionen dienen dazu, aus einem Funktionsobjekt mit zwei Argumenten
ein Funktionsobjekt mit einem Objekt zu machen. Dazu wird ein Argument an
einen konstanten Wert »gebunden«. bind1st() bindet das 1. Argument, bind2nd()
das zweite.
462
Funktionsobjekte
Adapter
Um Funktionszeiger an Binder übergeben zu können, stellt die C++-Bibliothek die
Adapterklassen pointer_to_unary_function und pointer_to_binary_function zur Ver-
fügung:
template <class Arg, class Result>
class pointer_to_unary_function
: public unary_function<Arg,Result>
{
public:
explicit pointer_to_unary_function(Result (*f)(Arg));
Result operator()(Arg x) const;
};
template <class Arg1, class Arg2, class Result>
class pointer_to_binary_function
: public binary_function<Arg1,Arg2,Result>
{
public:
explicit pointer_to_binary_function(Result (*f)(Arg1,Arg2));
Result operator()(Arg1 x, Arg2 y) const;
};
sowie die überladene globale Funktion ptr_fun():
template <class Arg, class Result>
pointer_to_unary_function<Arg, Result>
ptr_fun(Result (*f)(Arg));
template <class Arg1, class Arg2, class Result>
pointer_to_binary_function<Arg1,Arg2,Result>
ptr_fun(Result (*f)(Arg1, Arg2));
Um auch Methoden als Argumente an Funktionsobjekt-Parameter von Algorithmen
übergeben zu können (Methode muß über Instanz aufgerufen werden), sind die
Klassen mem_fun_t, mem_fun1_t, mem_fun_ref_t und mem_fun1_ref_t für Methoden ohne
und mit einem Argument definiert
template <class S, class T> class mem_fun_t
: public unary_function<T*, S> {
public:
explicit mem_fun_t(S (T::*p)());
S operator()(T* p);
};
template <class S, class T, class A> class mem_fun1_t
: public binary_function<T*, A, S> {
public:
explicit mem_fun1_t(S (T::*p)(A));
S operator()(T* p, A x);
};
template <class S, class T> class mem_fun_ref_t
: public unary_function<T, S> {
public:
463
Die C++-Standardbibliothek
Speicherallokation
allocator
aus <memory>
Beschreibung
Die Klasse allocator definiert Methoden zur Anforderung und Verwaltung physikalischen
Speichers. Eine Instanz der Klasse übernimmt damit die Aufgabe eines Speichermanager. Die
von ANSI vorgesehene Implementierung beruht auf der üblichen Verwendung der Operatoren
new und delete.
Die STL-Container verwenden Allokatoren für die Speicheranforderung, d. h., die Methoden der
Container greifen intern zur Speicheranforderung und -verwaltung auf die Methoden des Allo-
katorobjekts zurück. Standardmäßig verwenden die Container eine Instanz der Klasse alloca-
tor, die als Vorgabeargument für den entsprechenden Template-Parameter vorgesehen ist.
Durch Implementierung und Übergabe eigener Allokatoren mit gleicher Schnittstelle kann ein
Programmierer die Speicherverwaltung eines Containers an verschiedene Speichermodelle
(DOS, 16-Bit-Windows) anpassen.
464
auto_ptr
Referenz
template <class T> class allocator {
public:
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef T* pointer;
typedef const T* const_pointer;
typedef T& reference;
typedef const T& const_reference;
typedef T value_type;
template <class U> struct rebind { typedef allocator<U> other; };
allocator() throw();
allocator(const allocator&) throw();
template <class U> allocator(const allocator<U>&) throw();
~allocator() throw();
pointer address(reference x) const;
const_pointer address(const_reference x) const;
pointer allocate(
size_type, typename allocator<void>::const_pointer hint = 0);
void deallocate(pointer p, size_type n);
size_type max_size() const throw();
void construct(pointer p, const T& val);
void destroy(pointer p);
};
auto_ptr
aus <memory>
Dient dazu, den Speicherbereich eines mit new eingerichteten Objekts automatisch
freizugeben, wenn der Zeiger auf den Speicherbereich gelöscht wird (zum Beispiel
durch Verlassen seines Gültigkeitsbereichs).
template<class X> class auto_ptr {
public:
typedef X element_type;
explicit auto_ptr(X* p =0) throw();
auto_ptr(const auto_ptr&) throw();
template<class Y> auto_ptr(const auto_ptr<Y>&) throw();
auto_ptr& operator=(const auto_ptr&) throw();
template<class Y> auto_ptr& operator=(const auto_ptr<Y>&) throw();
~auto_ptr();
X& operator*() const throw();
X* operator->() const throw();
X* get() const throw();
X* release() const throw();
};
465
Die C++-Standardbibliothek
get_temporary_buffer() <memory>
Liefert die Pufferadresse und die Kapazität des Puffers in Einheiten von T als
Instanz der Klasse pair zurück.
template <class T> pair<T*, ptrdiff_t> get_temporary_buffer(ptrdiff_t n);
return_temporary_buffer() <memory>
Gibt den Puffer zurück, auf den ptr verweist und der mit get_temporary_buffer()
allokiert wurde.
template <class T> void return_temporary_buffer(T* ptr);
uninitialized_... <memory>
Die Funktion uninitialized_copy() ruft new in einer Schleife auf, um den Bereich
von result bis result + last mit den Werten aus [first, last) zu initialisieren.
Die Funktion uninitialized_fill() ruft new in einer Schleife auf, um den Bereich
von first bis last mit wert zu initialisieren.
Die Funktion uninitialized_fill_n() ruft new in einer Schleife auf, um den Bereich
von first bis first+n mit wert zu initialisieren.
template <class InIter, class FWIter>
FWIter uninitialized_copy(InIter first, InIter last, FWIter result);
template <class FWIter, class T>
void uninitialized_fill(FWIter first,FWIter last, const T& wert);
template <class FWIter, class Size, class T>
void uninitialized_fill_n(FWIter first, Size n, const T& wert);
466
Index
Index
- (Vorzeichen) 101
!
! 107
- 102
-- 103
!= 106
# 224
## 224
#define 96, 220
#elif 222
#else 223
#endif 223
#error 225
#if 222
#ifdef 223
#ifndef 223
#include 219
#line 225
#pragma 226
% 102
& 113
& (Adresse) 126
& (Referenzen) 87
&& 107
( ) (Parameterliste) 145
() (Typumwandlung) 120
* 102
* (Zeiger-Deklaration) 81
* (Zeiger-Dereferenzierung) 83, 109
+ 102
+ (Vorzeichen) 101
++ 103
, 127
. 110
.* 111
... 157
/ 102
: 112
::* (Zeiger auf Klassenelemente) 86
< 106
<< 115
<< (Streamoperator) 116
<= 106
468
Index
469
Index
bad_cast 454
bad_typeid 454
basic_filebuf 415
basic_fstream 419
basic_ifstream 417
basic_ios 404
basic_iostream 411
basic_istream 407
basic_istringstream 413
basic_ofstream 418
basic_ostream 409
basic_ostringstream 414
basic_streambuf 405
basic_string 237, 421
basic_stringbuf 411
basic_stringstream 415
Basisklassen 165
– direkte 196
– indirekte 197
– polymorphe 121
– virtuelle 205
– Zugriff auf verdeckte Elemente 63
Basisklassenobjekte
– einrichten 195
– Zuweisung abgeleiteter Objekte 105
Basisklassenzeiger 86, 202
– in Zeiger auf abgeleitete Objekte umwandeln 121
Bedingte Kompilierung 222
Bedingungsoperator 126
Bezeichner 17, 46
Bibliotheken
– Standardbibliotheken 29
binary_function 460
binary_negate 461
bind1st() 462
bind2nd() 462
Binder für Funktionsobjekte 462
binder1st 462
binder2nd 462
Bindung, späte 199
Bitfelder
– als bitset-Container 332, 360
– als Strukturen 77
470
Index
471
Index
const (Zeiger) 85
const_cast 121
Container 357
– allgemeine Eigenschaften 358
– assoziative Container 359
– bitset 360
– deque 362
– list 365
– map 367
– multimap 367
– multiset 375
– priority_queue 372
– queue 373
– sequentielle Container 358
– set 375
– stack 378
– vector 379
continue 142
cout 242
ctype 429
ctype_base 428
ctype_byname 430
D
Dateibereich 58
Datentypen 48
– arithmetische 49
– Arrays 67
– Aufzählungstypen 66
– Codierung 48
– elementare 50
– integrale 49
– Klassen 164
– Konvertierungen durch Compiler 90
– Literale 94
– skalare 49
– Speicherbelegung 49
– Strukturen 74
– Templates 207
– Unions 79
– Wertebereich 49
– zusammengesetzte 65
default 136
defined 223
472
Index
Definition 47
Deklaration 47
Dekrement 103
delete 117
deque 362
Dereferenzierung 83
Destruktor 186
– bei Vererbung 201
Diagnoseklassen 453
Diagnosemeldungen 225
difftime() 261
distance() 392
divides 460
do 141
domain_error 455
double 51
dynamic_cast 121, 204
E
Ein- und Ausgabe 31, 239
– cerr 242
– cin 242
– clog 242
– cout 242
– Fehlerbehandlung in C++ 245
– FILE 240
– formatiert in C 239
– formatiert in C++ 239
– Formatierung in C++ 242
– Funktionen in C 240
– Manipulatoren in C++ 244
– Pufferung 246
– stderr 240
– stdin 240
– stdout 240
– Streams in C 240
– Streams in C++ 242
– unformatiert in C 239
– unformatiert in C++ 239
Einbettung
– Initialisierung eingebetteter Objekte 171
– versus Vererbung 191
Elemente in Programme einführen 46
else 133
473
Index
endl 338
enum 66
equal_to 461
errno 249
Escape-Sequenzen 42
exception 453
Exceptions 226
– abfangen 232
– auslösen 230
– eigene Exceptionklassen definieren 229
– Funktionsdeklaration mit throw 231
– Handlerbereich festlegen 233
– Schema der Exception-Behandlung 228
– verwandte Funktionen 233
– Vor- und Nachteile 226
exit() 142, 254
explicit 184
export 208
extern 57, 146, 159
F
false 50
FILE 240
Flags 77, 360
Fließkommazahlen 52
float 51
for 138
friend 180
Friends 180
– in Templates 210
front_insert_iterator 386
Function Overhead 156
Funktionen 143
– call by reference 151
– call by value 151
– const-Parameter 152
– der C-Laufzeitbibliotheken 264
– Exceptions auslösen 147, 231
– Function Overhead 156
– globale Variablen 149
– inline-Funktionen 147, 158
– main() 147
– mit beliebig vielen Argumenten 157
– ohne Rückgabewert 146
474
Index
475
Index
iterator_traits 390
Iteratoren 382
– Einfüge-Iteratoren 385
– Kategorien 382
– Stream-Iteratoren 387
K
Kapselung 167
Kernighan, Brian 14
Klassen 164
– Abgeschlossenheit 167
– abstrakte Klassen 201
– abstrakte Methoden 201
– Arrays von Objekten 188
– Basisklassenzeiger 202
– const-Datenelemente 170
– const-Methoden 175
– Datenelemente 168
– Deklaration in übergeordneter Klasse 172
– der C++-Laufzeitbibliotheken 357
– Destruktor 186
– eingebettete Objekte 170
– Einrichtung geerbter Elemente 183, 195
– Information hiding 167
– Instanzbildung 188
– Kapselung 167
– konstante Instanzen 188
– Konstruktor 183
– Konstruktorliste 171
– Kopierkonstruktor 184
– Methoden 173
– Objekte als Datenelemente 170
– objektorientierte Programmierung 166
– Standardkonstruktor 183
– Standardmethoden 187
– static-Datenelemente 169
– static-Methoden 174
– this-Zeiger 187
– verschachtelte Klassen 172
– Zugriff auf Basisklassenelemente 181
– Zugriff auf Elemente 178, 179
– Zugriffsspezifizierer 176
Klassenbereich 58
476
Index
Klassentemplates 210
– Methoden in Klassentemplates 211
Kommandozeilenargumente 148
Komma-Operator 127
Kommentare 25
Konsolenprogramme 19
Konstanten 94
– #define 96
– const-Variablen 98
– Literale 94
Konstruktoren 183
– bei Vererbung 194
– explicit-Deklaration 184
– Konstruktorliste 171, 195, 207
– Konvertierung in Klassentyp 184
– Kopierkonstruktor 184
– Mehrfachvererbung 196
– Standardkonstruktor 183
Konstruktorliste 171, 195, 207
Kopieren
– Klasseninstanzen 184
– Strings 73
Kopierkonstruktor 184
L
Laufzeitbibliotheken
– Algorithmen 392
– C 247
– C++ 329
– C++-Headerdateien 330
– C++-Klassen 357
– C-Funktionen 264
– C-Headerdateien 247
– Container 357
– Diagnoseklassen 453
– Iteratoren 382
– Lokale Klassen 425
– Numerische Klassen 443
– Stream-Klassen 400
– String-Klassen 420
– Typidentifizierung 458
– Utility-Klassen 459
Laufzeittypidentifizierung 203
– mit dynamic_cast 204
477
Index
478
Index
mem_fun1_ref_t 464
mem_fun1_t 463
messages 433
messages_base 433
messages_byname 434
Methoden 173
– abstrakte Methoden 201
– in Klassentemplates 211
– konstante 175
– nicht vererbbare Methoden 197
– statische 174
– Überladung 163
– Überschreibung 199
– virtuelle Methoden 199
minus 460
Modularisierung 26
modulus 460
money_base 435
money_get 434
money_put 435
moneypunct 436
moneypunct_byname 437
Multibyte-Zeichen 238
multimap 367
multiplies 460
multiset 375
mutable 160, 175
N
Namensbereiche 59
– deklarieren 60
– Elemente aus Namensbereich verwenden 60, 61
– erweitern 61
Namensgebung 17
namespace 60
negate 460
Negatoren für Funktionsobjekte 461
new 117
not_equal_to 461
not1() 462
not2() 462
num_get 437
num_put 438
numeric_limits 452
479
Index
480
Index
plus 460
pointer_to_binary_function 463
pointer_to_unary_function 463
Polymorphie 197
pow() 253
Präprozessor 217
– Arbeitsweise 217
– Bedingte Kompilierung 222
– Diagnosemeldungen 225
– Grundsymbolverbindung 224
– Makros 220
– Pragma-Direktiven 226
– Quellcode einfügen 219
– Zeichenkettenbildung 224
Pragma-Direktiven 226
Priorität 128
priority_queue 372
private 177, 193
Programme
– Aufbau 17
– aus mehreren Quelldateien 26
– erstellen 34
– Kommandozeilenargumente 148
– Konsolenprogramme 19
– modularisieren 26
– typische Komponenten 20
Programmerstellung 34
Programmfluß 33
Programmsteuerung 132
– Schleifen 137
– Verzweigungen 132
protected 177, 193
ptr_fun() 463
public 177, 193
Pufferung 246
putchar() 248
Q
queue 373
R
range_error 455
raw_storage_iterator 466
Referenzen 87
– const-Deklaration 89
481
Index
register 56
reinterpret_cast 123
return 139, 142, 150
return_temporary_buffer() 466
reverse_iterator 384
Ritchie, Dennis 14
RTTI 203
– mit dynamic_cast 204
– mit typeid 204
– mit virtuellen Methoden 203
Rückgabewert 149, 150
runtime_error 456
S
Schleifen 137
– Abbruchbefehle 142
– do-while 141
– Endlosschleifen 139
– for 138
– while 139
Schlüsselwörter 44
set 375
set_new_handler() 456
set_terminate() 234, 456
set_unexpected() 234, 456
setjmp() 253
setlocale() 252
setw() 338
short 51
Sichtbarkeit 63
signal() 254
Signatur 146
signed 50, 53
sin() 253
sizeof 125
slice 447
slice_array 449
Speicherbelegung
– Aufzählungstypen 67
– für Gleitkommatypen 52
– für Integer-Typen 51
Speicherverwaltung
– Zeiger 81
482
Index
483
Index
484
Index
– static_cast 122
Typunabhängigkeit 207
U
Überladung
– von Funktionen 160
– von Methoden 163
– von Operatoren 129
Überschreibung 199
unary_function 460
unary_negate 461
uncaught_exception() 457
underflow_error 456
unexpected() 234, 457
UNICODE 235
uninitialized_copy() 466
uninitialized_fill() 466
uninitialized_fill_n() 466
union 79
Unions 79
unsigned 51, 53
using 60
Utility-Klassen 459
V
valarray 355, 444
Variablen 22, 48, 54
– globale 63
– Initialisierung 55
– Lebensdauer 64
– Sichtbarkeit 63
– Spezifizierer 55
– Verdeckung 63
vector 379
Verdeckung 63
Vererbung 189
– Bindung, späte 199
– Destruktoren 201
– Konstruktoren 194
– Mehrfachvererbung 204
– nicht vererbbare Methoden 197
– Polymorphie 197
– Überschreibung 199
– versus Einbettung 191
– Zugriffsrechte auflockern 194
485
Index
– Zugriffsspezifizierer 192
Vergleichen
– Operatoren 106
– Strings 74
Verzweigungen
– if 132
– if-else 133
– switch 135
virtual (Basisklassen) 190, 205
virtual (Methoden) 160, 199, 201
void 84, 146
volatile 55, 160
Vorzeichen 101
W
wchar_t 51, 238
Wertebereiche
– von Gleitkommazahlen 50
– von Integer-Datentypen 50
while 139
Wide Characters 238
width() 339
WinMain() 19
wstring 237
Z
Zeichenketten 235
– als Arrays 72
– initialisieren 73
– kopieren 73
– Multibyte-Zeichen 238
– String-Klassen 420
– vergleichen 74
– Wide Characters 238
– Zugriff auf einzelne Zeichen 74
Zeichensatz 41
Zeiger 81
– auf Datenelemente 85
– auf Funktionen 85
– auf Methoden 86
– auf statische Klassenelemente 86
– auf void 84
– auf Zeichenketten 84
– Basisklassenzeiger 86, 202
– Dereferenzierung 83
486
Index
– Einsatzgebiete 81
– Initialisierung 82
– konstante Zeiger 85
– NULL-Zeiger 82
– this 87
Zugriffsspezifizierer
– bei Vererbung 192
– in Klassendeklaration 176
Zuweisungen 104
487