Systemnahe Programmierung in C/C++
Transcrição
Systemnahe Programmierung in C/C++
Systemnahe Programmierung in C/C++ Peter Piehler [email protected] Lehrstuhl für Datenbanken und Informationssysteme Fakultät für Mathematik und Informatik 2006–10–25 Peter Piehler (DBIS) C/C++ Programmierung 2006–10–25 1 / 46 Agenda 1 typedef 2 Kommandozeilenargumente 3 Rückblick 4 Ellipsenfunktionen 5 Ein- Ausgabe 6 Environment 7 i18n in C 8 Aufgaben Peter Piehler (DBIS) C/C++ Programmierung 2006–10–25 2 / 46 Outline 1 typedef 2 Kommandozeilenargumente 3 Rückblick 4 Ellipsenfunktionen 5 Ein- Ausgabe 6 Environment 7 i18n in C 8 Aufgaben Peter Piehler (DBIS) C/C++ Programmierung 2006–10–25 3 / 46 Verwendung Die typedef-Anweisung deklariert einen Alias zu einem Datentyp. Die Syntax lautet: typedef TYP Alias; Es handelt sich dabei um keinen neuen Datentyp! int minim ( int m , int n ); ... typedef int GANZE_ZAHL ; // falsche Redeklaration / Ueberladung double minim ( GANZE_ZAHL m , GANZE_ZAHL n ); In ANSI-C wird typedef verwendet um Struktur-Definitionen einen Bezeichner zuzuordnen: typedef struct { double x ; double y ; } point ; Der Geltungsbereich eines Typ-Alias ist von der Blockstruktur abhängig. Peter Piehler (DBIS) C/C++ Programmierung 2006–10–25 4 / 46 Portabilität Auch im Zusammenhang mit der Portierung von Programmen auf eine andere Plattform wird die typedef-Anweisung eingesetzt. Zu den plattformabhängige Datentypen werden konzeptionelle Datentypen deklariert und somit die Plattform abstrahiert. Eine solche Abstraktion übernimmt stdint.h (C99 Standard) für ganzzahlige Datentypen. // intN_t v o r z e i c h e n b e h a f t e t e r G a n z z a h l d a t e n t y p mit exakt N Bit int8_t , int16_t , int32_t , int64_t // uintN_t v o rz e i c h en l o s e r G a n z z a h l d a t e n t y p mit exakt N Bit uint8_t , ... // int_leastN_t , uint_leastN_t // int_fastN_t , uint_fastN_t // intptr_t , uintptr_t // intmax_t , uintmax_t siehe man stdint.h typedef wird verwendet um Typen für Funktionszeiger zu deklarieren (Funktionszeiger werden in einer späteren Vorlesung behandelt). Peter Piehler (DBIS) C/C++ Programmierung 2006–10–25 5 / 46 Outline 1 typedef 2 Kommandozeilenargumente 3 Rückblick 4 Ellipsenfunktionen 5 Ein- Ausgabe 6 Environment 7 i18n in C 8 Aufgaben Peter Piehler (DBIS) C/C++ Programmierung 2006–10–25 6 / 46 Argumentvektor int main (int argc, char *argv[]){ ... } argc (argument count) ist ein Parameter vom Datentyp int, der die Anzahl der beim Programmaufruf übergebenen Zeichenketten enthält, einschließlich des Programmnamens. argv (argument vector) ist ein Vektor von Zeigern auf die im Programmaufruf angegebenen Zeichenketten; argv[0] zeigt dabei auf den Programmnamen selbst, argv[1] auf das erste Argument,..., argv[n] auf das n-te Argument. Peter Piehler (DBIS) C/C++ Programmierung 2006–10–25 7 / 46 Outline 1 typedef 2 Kommandozeilenargumente 3 Rückblick 4 Ellipsenfunktionen 5 Ein- Ausgabe 6 Environment 7 i18n in C 8 Aufgaben Peter Piehler (DBIS) C/C++ Programmierung 2006–10–25 8 / 46 Stack / Heap Funktionsparameter, Variablen und Konstanten liegen immer auf dem Stack. Das Freigeben solcher Speicherbereiche mittels free führt zu undefiniertem Programmverhalten. denn die C-Bibliotheken führen eine Buchhaltung über den dynamischen Speicher malloc trägt vergebene Speicherbereiche ein deshalb bedarf free keines Parameters über die Größe des Speicherbereiches malloc und free arbeiten immer im Duo! Peter Piehler (DBIS) C/C++ Programmierung 2006–10–25 9 / 46 1 1 Quelle: www.wachtler.de/ck/9 Speichermodell Prozesses.html Peter Piehler (DBIS) C/C++ Programmierung 2006–10–25 10 / 46 Outline 1 typedef 2 Kommandozeilenargumente 3 Rückblick 4 Ellipsenfunktionen 5 Ein- Ausgabe 6 Environment 7 i18n in C 8 Aufgaben Peter Piehler (DBIS) C/C++ Programmierung 2006–10–25 11 / 46 Stack und Funktionsargumente In C können Funktionen mit beliebig vielen Argumenten aufgerufen werden. Grundlage dafür ist, wie Paramter an eine Funktion auf dem Stack übergeben werden: 1 2 3 Die aufrufende Funktion präperiert den Stack. Dann wird die Funktion gerufen. Wenn die gerufen Funktion beendet ist (return), dann erhält die aufrufende Funktion die Kontrolle und entfernt die Argumente vom Stack. Würde die zu rufende Funktion für die Bereinigung des Stacks zuständig sein, würde sie immer eine feste Anzahl von Argumenten behandeln. Der ANSI-Standard legt fest, dass die Argumente von rechts nach links auf den Stack abgelegt werden. Der Aufruf von myFunc(10, 20); /*void myFunc(int, int)*/ bewirkt: 1 2 3 lege 20 auf den Stack ab (sizeof(int)) lege 10 auf den Stack ab (sizeof(int)) Funktionssprung Peter Piehler (DBIS) C/C++ Programmierung 2006–10–25 12 / 46 variable Argumentliste Eine variable Anzahl von Parametern wird mit Parameter deklariert. Beispiel: myFunc(uint_fast8_t argCount, ...); ... als letzter Diese Funktion kann mit mindestens einem und beliebig vielen Argument verwendet werden: myFunc ( 0 ); myFunc ( 1 , 10 ); myFunc ( 2 , 10 , 20 ); Für den Zugriff auf die Ellipsen-Parameter stehen Makros aus stdarg.h zur Verfügung. Peter Piehler (DBIS) C/C++ Programmierung 2006–10–25 13 / 46 Beispiel - variable Argumentliste Beispiel: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 void myFunc ( uint_fast8_t argCount , ...) /* Die Ellipse */ { va_list ap ; /* Eine Variable vom Typ va_list */ int arg ; if ( argCount ) { /* va_start : va_list - Zeiger in it ial is ier en . */ va_start ( ap , argCount ); while ( argCount --) { /* va_arg - Schleife holt naechstes Argument vom Stack */ arg = va_arg ( ap , int ); printf ( " % d " , arg ); } printf ( " \ n " ); /* A u f r a e u m u n g s a r b e i t e n : va_end ausfuehren */ va_end ( ap ); } } Peter Piehler (DBIS) C/C++ Programmierung 2006–10–25 14 / 46 Outline 1 typedef 2 Kommandozeilenargumente 3 Rückblick 4 Ellipsenfunktionen 5 Ein- Ausgabe 6 Environment 7 i18n in C 8 Aufgaben Peter Piehler (DBIS) C/C++ Programmierung 2006–10–25 15 / 46 stdin, stdout, stderr Bei Programmstart werden standardmäßig drei FILE-Ziegerkonstanten initialisiert (stdio.h). 1 2 3 stdin (Standardeingabe) stdout (Standardausgabe) stderr (Standardfehlerausgabe) FILE ist eine Struktur, die alle Informationen enthält, die die Standard-E/A-Routinen benötigen. Im Normalfall hat der Programmierer nichts mit den Interna der FILE-Struktur zu tun. Ein FILE-Zeiger wird beim Öffnen von Dateien mit fopen zurückgeliefert. Die Ausführung von myprog > out.txt 2>/dev/null bewirkt: 1 2 3 stdin liest vom Terminal stdout schreibt in out.txt stderr schreibt auf das pseudo-Device /dev/null (wird verworfen) Peter Piehler (DBIS) C/C++ Programmierung 2006–10–25 16 / 46 Dateideskriptoren Wenn eine Datei geöffnet wird, dann wird dieser Datei eine nichtnegative Zahl (0,1,2...), der sogenannte Dateideskriptor zugewiesen. Auf Systemebene werden offene Dateien nicht durch Zeiger auf eine Struktur FILE, sondern durch Dateideskriptoren vertreten. Ein Dateideskriptor (vom Typ int) ist ein Index in die Deskriptortabelle des Prozesses. Unter Angabe des Dateideskriptors kann mit den entsprechenden Systemroutinen in die geöffnete Datei geschrieben werden (write, read, getc, putc ...) Unter Unix-oiden Systemen ist ’alles eine Datei’ Dateideskriptoren sind das Kernstück der Ein- und Ausgabe. Auch Netzwerkverbindungen (sockets) sind auf Anwendungsebene Dateideskriptoren. Peter Piehler (DBIS) C/C++ Programmierung 2006–10–25 17 / 46 Dateideskriptoren Für die Standardein- und Standardausgabe sind in unistd.h folgende drei Konstanten definiert: 1 2 3 STDIN FILENO (üblicherweise 0) STDOUT FILENO (üblicherweise 1) STDERR FILENO (üblicherweise 2) Zu einem gültigen FILE-Zeiger kann ein Dateideskriptor ermittelt werden. int fileno(FILE *stream); Das Gegenstück zu fileno ist fdopen FILE *fdopen(int fildes, const char *mode); fdopen assoziiert einen stream zu einem Dateideskriptor. mode ("r", "r+", "w", "w+","a", "a+") muss dabei kompatibel mit den Eigenschaften des Dateideskritpor sein Peter Piehler (DBIS) C/C++ Programmierung 2006–10–25 18 / 46 EA über FILE* Für die Ein- und Ausgabe mit FILE-Zeigern steht die printf/scanf-Familie zur verfügung. Dabei handelt es sich um Ellipsenfunktionen. printf-Familie: 1 2 3 4 5 6 7 8 9 10 11 12 13 # include < stdio .h > int int int int printf ( const char * format , ...); fprintf ( FILE * stream , const char * format , ...); sprintf ( char * str , const char * format , ...); snprintf ( char * str , size_t size , const char * format , ...); # include < stdarg .h > int int int int vprintf ( const char * format , va_list ap ); vfprintf ( FILE * stream , const char * format , va_list ap ); vsprintf ( char * str , const char * format , va_list ap ); vsnprintf ( char * str , size_t size , const char * format , va_list ap ); Peter Piehler (DBIS) C/C++ Programmierung 2006–10–25 19 / 46 EA über FILE* Formatanweisungen sind: Steuerzeichen Argumenttyp i,d int o int x,X int u unsigned int c int s char* f double e,E double p void* %% Peter Piehler (DBIS) Erläuterung dezimale Zahl oktale Zahl hexadezimale Zahl ohne Vorzeichen dezimale Zahl ohne Vorzeichen einzelnes Zeichen Zeichenkette (0-Terminator) Gleitkommazahl Gleitkommazahl (E-Darstellung) Zeiger, Darstellung als Adresse Ausgabe des ’%’ Zeichens C/C++ Programmierung 2006–10–25 20 / 46 inttypes.h Um ganz portable Programme zu schreiben, müsste man bei Ein- und Ausgabe statt der fixed Formatdefinitionen abstrakte Typdefinitionen angeben. Also, zum abstrakten Typ int32 t die konkrete Formatdefinition ermitteln. In inttypes.h sind Makros definiert die das übernehmen. Beispiel: 1 2 3 4 5 6 7 8 9 10 11 int32_t i32 ; printf ( " int32_t - Wert : " ); scanf ( " % " SCNd32 , i32 ); printf ( " int32_t - Wert : % " PRId32 " \ n " , i32 ); // SCNd32 = " d " // PRId32 = " d " uint32_t ui32 ; printf ( " uint32_t - Wert : " ); scanf ( " % " SCNu32 , ui32 ); printf ( " uint32_t - Wert : % " PRIu32 " \ n " , ui32 ); // SCNu32 = " u " // PRIu32 = " u " wirkt umständlich Peter Piehler (DBIS) C/C++ Programmierung 2006–10–25 21 / 46 printf-Format Syntax einer Formatdefinition: [-] [m] [.g] k Ausrichtung nach Links m Mindestanzahl der Stellen (Feldbreite) g Genauigkeit (Nachkommastellen) k key (i, d, x, o, ...) float f = 12.34; printf("\%15.10f",f) ⇒ 12.3400000000 Sonderzeichen: \n \r \b \t \¨ \\ \ddd Peter Piehler (DBIS) new line (ASCII 10) carriage return (ASCII 13) backspace (ASCII 8) tabulator (ASCII 9) doublequote backsplash ddd: oktaler ASCII-Code C/C++ Programmierung 2006–10–25 22 / 46 printf Anpassen printf parst den format-Parameter und verarbeitet dementsprechend die Ellipsenparameter Typsicherheit ist somit nicht garantiert. Fehlerhafte Parameter führen zu umbestimmten Programmverhalten. printf("%s\n",10) ⇒ Programmabsturtz? Die GNU-C Library erlaubt es das Verhalten der printf-Familie anzupassen. Dazu lassen sich eigene Formatanweisungen definieren. Mit Hilfe der Funktion register printf function wird eine eigene Funktion registriert, mit der die Ausgabe gesteuert werden kann. r e g i s t e r _ p r i n t f _ f u n c t i o n ( int spec , pr i n t f _f u n c t io n handler - function , p r i n t f _ a r g i n f o _ f u n c t i o n arginfo - function ) Dies bietet sich besonders an, um Strukturen auszugeben. Dokumentation und ein Beispiel befindet sich unter: http://www.gnu.org/software/libc/manual/html_node/Customizing-Printf.html Peter Piehler (DBIS) C/C++ Programmierung 2006–10–25 23 / 46 scanf scanf-Familie: 1 2 3 4 5 6 7 8 9 # include < stdio .h > int scanf ( const char * format , ...); int fscanf ( FILE * stream , const char * format , ...); int sscanf ( const char * str , const char * format , ...); # include < stdarg .h > int vscanf ( const char * format , va_list ap ); int vsscanf ( const char * str , const char * format , va_list ap ); int vfscanf ( FILE * stream , const char * format , va_list ap ); Argumente in der Ellipse müssen Zeiger sein. Rückgabewert ist die Anzahl der erfolgreich einlgelesenen Argumente. Peter Piehler (DBIS) C/C++ Programmierung 2006–10–25 24 / 46 scanf - Pufferüberläufe scanf ist anfällig für Pufferüberläufe 1 2 3 4 5 char name [20]; printf ( " Name : " ); scanf ( " % s " , name ); printf ( " Ihr Name ist % s \ n " , name ); Nie "%s" ohne Feldbreitenangabe verwenden! korrekte Benutzung von scanf: 1 2 3 4 5 char name [20]; printf ( " Name : " ); scanf ( " %19 s " , name ); printf ( " Ihr Name ist % s \ n " , name ); Peter Piehler (DBIS) C/C++ Programmierung 2006–10–25 25 / 46 EA über FILE* fopen FILE *fopen(const char *path, const char *mode); öffnet eine Datei mit dem Namen path. Für mode sind folgende Argumente möglich: modus-Argument r oder rb w oder wb a oder ab r+,r+b oder rb+ w+,w+b oder wb+ a+,a+b oder ab+ Bedeutung zum Lesen öffnen zum Schreiben öffnen (neu anlegen eine exitierenden Datei überschreiben) zum Schreiben am Dateiende öffnen (nicht existierende Datei wird angelegt) zum Lesen und Schreiben öffnen zum Lesen und Schreiben öffnen (Inhalt einer existierenden Datei wird gelöscht) zum Lesen und Schreiben ab Dateiende öffnen Der Buchstabe b bei der modus-Angabe wird benötigt, um zwischen Textund Binärdaten zu unterscheiden. Peter Piehler (DBIS) C/C++ Programmierung 2006–10–25 26 / 46 EA über FILE* fclose schließt eine geöffnete Datei. Bevor fclose die Verbindung zwischen einer Datei und dem FILE-Zeiger fp auflöst, überträgt diese Funktion alle Inhalte von noch nicht geleerten Ausgabepuffern in die entsprechende Datei (siehe fflush). Inhalte von Eingabepuffern gehen verloren. int fclose(FILE *fp); Tritt beim Lesen oder Schreiben in eine Datei (Stream) ein Fehler auf, so wird das Fehler-Flag gesetzt. Wird beim Lesen das Dateiende erreicht, so wird das EOF-Flag gesetzt. feof ferror int feof(FILE *stream); gibt zurück: nicht 0 wenn EOF-Flag, sonst 0. int ferror(FILE *stream); gibt zurück: nicht 0 wenn Fehler-Flag, sonst 0. Peter Piehler (DBIS) C/C++ Programmierung 2006–10–25 27 / 46 EA über FILE* fclearerr void clearerr(FILE *stream); setzt Fehler- und EOF-Flag zurück. Um ganze Blöcke von binären Daten zu lesen oder zu schreiben, stehen die Funktionen fread und fwrite zur Verfügung. fread fwrite liest bis zu nmemb Blöcke, wobei jeder Block die Größe von size besitzt, und schreibt diese in den Speicherbereich auf den ptr zeigt. size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream); schreibt bis zu nmemb Blöcke, wobei jeder Block size groß ist, von ptr nach stream. size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream); Peter Piehler (DBIS) C/C++ Programmierung 2006–10–25 28 / 46 EA über FILE* Zum Lesen einer ganzen Zeile von der Standareingabe steht die Funktion gets und zum Lesen einer ganzen Zeile aus einer Datei steht die Funktion fgets zur Verfügung. Mit puts kann eine ganze Zeile auf die Standardausgabe und mit der Funktion fputs in eine Datei geschrieben werden. Diese Funktionen interpretieren im Gegensatz zu fread, fwrite die Zeichen \0 und \n. gets fgets char *gets(char *s); char *fgets(char *s, int size, FILE *stream); beide geben zurück: Adresse s bei Erfolg, sonst NULL puts fputs int puts(const char *s); int fputs(const char *s, FILE *stream); beide geben zurück: nichtnegativen Wert bei Erfolg, sonst EOF Peter Piehler (DBIS) C/C++ Programmierung 2006–10–25 29 / 46 Outline 1 typedef 2 Kommandozeilenargumente 3 Rückblick 4 Ellipsenfunktionen 5 Ein- Ausgabe 6 Environment 7 i18n in C 8 Aufgaben Peter Piehler (DBIS) C/C++ Programmierung 2006–10–25 30 / 46 Environment-Liste Jeder Unix-Prozeß besitzt eine eigene Umgebung (environment). Diese Environment liegt in Form einer Liste vor, die ihm von der Startup-Routine übergeben wird. Daher: Die Environment wird vom Elternprozeß and den Kindprozeß vererbt. Die Environment-Liste ist - wie die Argumenten-Liste argv - ein Array von Zeigern auf Strings. Die Strings sind - wie bei argv - mit ’\0’ abgeschlossen. Die Adresse der Environment-Liste ist immen in der globalen Variablen environ enthalten. extern char** environ; Das letzte Element der Environment-Liste besitzt den Wert NULL (wie argv). Befehl um das aktuelle Environment anzuzeigen: env Peter Piehler (DBIS) C/C++ Programmierung 2006–10–25 31 / 46 Environment verändern putenv setenv unsetenv int putenv(char *entry); übernimmt einen den String entry in der Form name=value und trägt ihn in die Environment-Liste ein. Falls name schon existiert, wird dessen bisherige Definition entfernt. trägt das name-value Paar in die Environment-Liste ein. Falls name bereits existiert, wird dessen alte Definition nur dann aus der Environment-List entfernt, wenn overwrite einen Wert verschieden von 0 besitzt. int setenv(const char *name, const char *value, int overwrite); int unsetenv(const char *name); löscht aus der Environment-Liste den zum name gehörenden Eintrag. Peter Piehler (DBIS) C/C++ Programmierung 2006–10–25 32 / 46 Environment auslesen getenv char *getenv(const char *name); gibt einenen Zeiger auf den zu name gehörenden Wert zurück. Falls kein Eintrag für name vorhanden ist wird NULL zurückgeliefert. Es ist empfehlenswert den von getenv zurückgegebenen String zu kopieren. Wieso? Peter Piehler (DBIS) C/C++ Programmierung 2006–10–25 33 / 46 Outline 1 typedef 2 Kommandozeilenargumente 3 Rückblick 4 Ellipsenfunktionen 5 Ein- Ausgabe 6 Environment 7 i18n in C 8 Aufgaben Peter Piehler (DBIS) C/C++ Programmierung 2006–10–25 34 / 46 Exkurs warum/was ist Lokalisierung? was ist ein encoding/encoding point? 2 2 Quelle: http://de.wikipedia.org/wiki/Utf8 Peter Piehler (DBIS) C/C++ Programmierung 2006–10–25 35 / 46 LOCALE LOCALE ist ein Basiskonzept in ISO C. Das Verhalten mancher C-Funktionen ist abhängig von LOCALE-Environment. Der Vorteil der locale-Technologie liegt darin, dass: die Software unabhängig von dem konkreten encoding entwickelt werden kann, die Software kann alle encoding unterstützen die das Betriebssystem unterstützt (eingeschlossen 7bit, 8bit, multibyte, stateful and stateless encodings wie ASCII, ISO 8859-*, EUC-*, ISO 2022-*, Big5, VISCII, TIS 620, UTF-* und so weiter) es eine übergreifende Konfiguration für das System gibt, man encodings/Lokalisierungen nachinstallieren kann ohne die Software abändern oder neu zu übersetzten zu müssen. Peter Piehler (DBIS) C/C++ Programmierung 2006–10–25 36 / 46 Locale Kategorien Das LOCALE-Environment ist unterteilt in sechs Kategorien, welche unabhängig voneinender durch setlocale gesetzt werden können: LC TYPE Legt das encoding fest. Abhängige Funktionen sind unter anderem islower, mblen LC COLLATE Beeinflusst die Sortierung (strcoll). LC MESSAGES Legt die Sprache fest in der Ausgaben erfolgen (gettext) LC MONETARY Legt fest wie Währungsbeträge darzustellen (Währungszeichen) sind (localeconv) LC NUMERIC Legt fest wie Zahlen darzustellen (Dezimalpunkt) sind (printf, atof). LC TIME Formatdefinition wie Zeit- und Datumsangaben formatiert werden (strftime). Peter Piehler (DBIS) C/C++ Programmierung 2006–10–25 37 / 46 setlocale legt für eine Kategorie ein neues locale fest. Die Angabe von LC ALL als setzt für alle Kategorien das locale (export LC_ALL=C maskiert alle weitern LC * Einstellungen mit dem C-locale). C ist der kleinste gemeinsame Nenner der von allen C-Compilern angeboten wird. Die installierten Lokalisierungen können mit locale -a abgefragt werden. Wobei jede Lokalisierungseintrag in der Syntax language[ terrritory][.codeset][@modifier] erfolgt. language Zwei kleine Buchstaben nach ISO639 (en-Englsich, eo-Esperanto ...) territory Zwei Großbuchstaben nach ISO3166 (GB-Großbritatien, KR-Südkorea ...) codeset Nicht standardisiert. Typische Werte sind ISO-8859-15, UTF8 und so weiter. modifier Nicht standardisiert. Typischer Wert ist euro. char *setlocale(int category, const char *locale); Peter Piehler (DBIS) C/C++ Programmierung 2006–10–25 38 / 46 nl langinfo wird verwendet, um auf ein bestimmtes Element der locale-Angaben zuzugreifen. char *nl_langinfo(nl_item item); Im Gegensatz zu localeconv(), die alle Elemente zurück gibt, erlaubt nl langinfo(), ein bestimmtes Element auszuwählen. nl_langinfo(CODESET) liefert das aktuelle encoding Befehl um das aktuell benutzte encoding anzuzeigen: locale charmap Peter Piehler (DBIS) C/C++ Programmierung 2006–10–25 39 / 46 iconv Die Funktionen iconv open(), iconv(), iconv close() ermöglichen es zwischen allen installierten encodings zu konvertieren. iconv open iconv_t iconv_open(const char *tocode, const char *fromcode); legt einen conversion-descriptor an, um Bytesequenzen von fromcode nach tocode zu konvertieren. Hinweis: hier kann das der Returnwert von nl langinfo(CODESET) verwendet werden. Hinweis: iconv -l liefert die installierten encodings. iconv size_t iconv ( iconv_t cd , char ** inbuf , size_t * inbytesleft , char ** outbuf , size_t * outbytesleft ); Konvertiert Zeichen zwischen verschiedenen encodings. Dabei wird aus inbuf gelesen und nach outbuf geschrieben. inbytesleft wird um die Anzahl Bytes verringert die das decodieren benötigt hat. Die Anzahl der Bytes die benötigt werden um das Zeichen im Ziel-encoding darzustellen wird outbytesleft Peter Piehler (DBIS) C/C++ Programmierung 2006–10–25 40 / 46 iconv iconv close int iconv_close(iconv_t cd); Peter Piehler (DBIS) gibt die Struktur hinter cd wieder frei. C/C++ Programmierung 2006–10–25 41 / 46 wchar t In ANSI-C wurde ein Datentyp wchar t aufgenommen, um Vielbyte-Zeichen aufzunehmen. Meist umfasst wchar t 4 Byte. Meist existiert ein abstraktes encoding WCHAR T für die iconv-Bibliothek. Für die Ein- und Ausgabe sowie den string-Funktionen existieren Versionen für den Umgang mit wchar t-Zeichenketten (wchar.h): int fwprintf(FILE *stream, const wchar_t *format, ...); int fwscanf(FILE *stream, const wchar_t *format, ...); wprinf(const wchar_t *format, ... ); wchar_t *wcscpy(wchar_t *s1, const wchar_t *s2) ; u.s.w Peter Piehler (DBIS) C/C++ Programmierung 2006–10–25 42 / 46 Outline 1 typedef 2 Kommandozeilenargumente 3 Rückblick 4 Ellipsenfunktionen 5 Ein- Ausgabe 6 Environment 7 i18n in C 8 Aufgaben Peter Piehler (DBIS) C/C++ Programmierung 2006–10–25 43 / 46 Aufgabe 1 Schreiben Sie eine Ellipsenfunktion err printf die: 1 2 3 einen Formatstring und beliebig viele Parameter übernimmt, die Parameter auf stderr ausgibt, der Ausgabe <programname>: voranstellt. Geben Sie das gesamte Environment und den gesamten Argumentvektor per err printf aus. Hinweis: programname ist der Name, unter dem das Programm gestartet wurde. Peter Piehler (DBIS) C/C++ Programmierung 2006–10–25 44 / 46 Aufgabe 2 Schreiben Sie eine Programm, welches testet ob setenv eine Kopie des zweiten Parameters (value) anlegt. Fassen Sie stichpunktartig zusammen was bei der Verwendung von putenv, setenv und unsetenv zu beachten ist, wenn keine Kopie von value angelegt wird. Peter Piehler (DBIS) C/C++ Programmierung 2006–10–25 45 / 46 Aufgabe 3 Schreiben Sie eine Programm, welches 1 2 als Argumente einen Dateinamen und das encoding der Datei erhält, die Datei einliest und zählt 1 2 wieviel Bytes verarbeitet werden, wievielen Schriftzeichen das entspricht, Geben Sie die Werte aus. Schreiben Sie die eingelesen Daten im UTF32-encoding nach stderr. Hinweis: Wenn Sie eine UTF8-codierte Datei anlegen und mit Umlauten füllen, muß sich eine Differenz zwischen der Anzahl der Bytes und der Schriftzeichen ergeben. Peter Piehler (DBIS) C/C++ Programmierung 2006–10–25 46 / 46