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

Documentos relacionados