Viele Zeichensätze erfordern den Einsatz von "breiten Zeichen" (wide characters), um die für das jeweilige Zeichen notwendigen Informationen zu speichern, da der Zeichensatz durchaus aus mehr als 256 Zeichen bestehen kann. Wide Character sind zu groß (zu "breit") für den char Datentyp. Daher wurde der wchar_t-Datentyp zur Speicherung solcher Zeichen eingeführt.
Eine Zeichenkette, der ein L vorangestellt wurde, ist immer eine Wide Character Constant. Intern wird zur Ablage von WC-Konstanten ein Integer-Typ verwendet, der entweder in
Die Definition von Wide Character Constants unterscheidet sich nicht von der schmaler Zeichen:
wchar_t wc = L'Z'; wchar_t wmc = L'XYZ'; wchar_t *wstring = L"Hello World!"; wchar_t *x = L"Hello World"; wchar_t z[] = L"Hello World";
Im Gegensatz zur NUL-Terminierung schmaler Zeichenketten ist die Terminierung hier 32 Bit lang.
Zwar lassen sich WC-Konstanten ebenso einfach deklarieren, wie ihre schmalen Pendants, allerdings müssen wir bei der Arbeit mit breiten Zeichen auf Besonderheiten einstellen.
Nicht mallocieren
Viele Programmierer gehen bei der Arbeit mit Wide Characters vor, wie Sie es mit schmalen Zeichen gewohnt sind. Folgender Code ist in der schmalen Zeichenbreite durchaus üblich:
char* wc = (char *)malloc(4); strcpy(wc, "abc");
Übertragen auf die breite Zeichenwelt ergeben die beiden obigen Ausdrücke nur wenig Sinn:
wchar_t* wc = (wchar_t *)malloc(4); wcscpy(wc, "abc");
Während der erste Ausdrück zwar syntaktisch richtig ist, wird nur Speicherplatz für 1 breites Zeichen reserviert (da wchar_t als unsigned int repräsentiert wird), weil malloc nur n Bytes reserviert, in diesem Fall also 4. Desweiteren beschwehrt sich der Compiler über den Versuch eine schmale Zeichenkonstante in einen breiten Datentyp zu kopieren. Besser wäre wcscpy(wc, L"abc")
Die libc-Bibliothek sieht für die Konvertierung von schmalen Zeichenkonstanten in ihr breites Pendant die Funktion mbstowcs vor:
wchar_t* wc = (wchar_t *)malloc(8 * (sizeof(wchar_t))); mbstowcs(wc, "abc", 4);
Breite Zeichen lesen und schreiben
Um breite Zeichen von einem Stream zu lesen, bietet sich die Bibliotheksfunktion fgetwc(3) an, die genauso verwendet wird, wir wir es von fgetwc(3) kennen:
#include <stdio.h> #include <locale.h> #include <stdlib.h> int main(int argc, char **argv) { wint_t retval; FILE *fp; wchar_t *pwcs; setlocale(LC_ALL, ""); if ((fp = fopen("file", "r")) == NULL) { /* Error handling */ } else { /* pwcs points to a wide character buffer of BUFSIZ. */ while ((retval = fgetwc(fp)) != WEOF){ *pwcs++ = (wchar_t)retval; /* break when buffer is full */ } } /* Process the wide characters in the buffer */ return (0); }
Das gleiche läßt sich auch über getwchar(3) sagen:
#include <stdio.h> #include <locale.h> #include <stdlib.h> int main(int argc, char **argv) { wint_t retval; FILE *fp; wchar_t *pwcs; setlocale(LC_ALL, ""); while((retval = getwchar()) != WEOF){ /* pwcs points to a wide character buffer of BUFSIZ. */ *pwcs++ = (wchar_t)retval; /* break on buffer full */ } /* Process the wide characters in the buffer */ return (0); }
Zum zeilenweisen Einlesen von Dateien verwenden wir fgetws(3):
#include <stdio.h> #include <locale.h> #include <stdlib.h> int main(int argc, char **argv) { FILE *fp; wchar_t *pwcs; setlocale(LC_ALL, ""); /* Error Handling if fopen was not successful. */ if((fp = fopen("file", "r")) == NULL) { /* Error handling */ } else { /* pwcs points to wide character buffer of BUFSIZ. */ while(fgetws(pwcs, BUFSIZ, fp) != (wchar_t *)NULL){ /* * pwcs contains wide characters with null * termination. */ } } }
Schließlich sehen wir uns noch an, wie fputwc(3) und fputws(3) arbeiten:
#include <stdio.h> #include <locale.h> #include <stdlib.h> int main(int argc, char **argv) { int index, len; wint_t retval; FILE *fp; wchar_t *pwcs; setlocale(LC_ALL, ""); /* Error Handling if fopen was not successful. */ if((fp = fopen("file", "w")) == NULL){ /* Error handling */ } else { /* * Let len indicate number of wide chars to output. * pwcs points to a wide character buffer of BUFSIZ. */ for (index = 0; index < len; index++){ if ((retval = fputwc(*pwcs++, fp)) == WEOF) /* write error occurred */ break; /* errno is set to indicate the error. */ } } }
#include <stdio.h> #include <locale.h> #include <stdlib.h> int main(int argc, char **argv) { int retval; FILE *fp; wchar_t *pwcs; setlocale(LC_ALL, ""); /* Error Handling if fopen was not successful. */ if((fp = fopen("file", "w")) == NULL){ /* Error handler */ } else { if ((retval = fputws(pwcs, fp)) == -1) { /* Write error occurred */ /* errno is set to indicate the error */ } } }
Manipulation breiter Zeichen
Folgende Bibliotheksfunktionen sind für die Verarbeitung von Wide Character Strings vorgesehen:
wcrtomb()– Konvertiert eine WC-Konstante in ein Zeichen (wcrtomb.c)wcscat()– Verbindet zwei WC-Konstanten(wcscat.c)wcschr()– Lokalisiert ein Zeichen in einer WC-Konstante(wcschr.c)wcscmp()– Vergleicht zwei WC-Konstanten(wcscmp.c)wcscoll()– Vergleicht zwei WC-Konstanten unter Berücksichtigung der Werte in LC_COLLATE (wcscoll.c)wcscpy()– Kopiert eine WC-Konstante in einen breiten Speicherbereich (wcscpy.c)wcscspn()– Bestimmt die Länge eines komplementären Substrings (wcscspn.c)wcsftime()– Konvertiert Datum und Zeit in eine breite Zeichenkonstantewcslen()– Bestimmt die Länge einer WC-Konstantewcsncat()– Verbindet einen Teil einer WC-Konstante mit einer anderenwcsncmp()– Vergleicht einen Teil einer WC-Konstante mit einer anderenwcsncpy()– Kopiert einen Teil einer WC-Konstante in einen breiten Speicherbereichwcspbrk()– Lokalisiert eine Zeichenkette in einer WC-Konstante (wcspbrk.c)wcsrchr()– Lokalisiert die letzte Position eines Zeichens in einer WC-Konstante (wcsrchr.c)wcsrtombs()– Konvertiert eine WC-Konstante in ihr schmales Pendantwcsspn()– Gibt die Länge eines Substrings in einer WC-Konstante aus (wcsspn.c)wcsstr()– Lokalisiert eine Zeichenkette in einer WC-Konstante (exkl. NUL-Terminierung) (wcsstr.c)wcstod()– Konvertiert eine WC-Konstante in einen Wert mit doppelter Präzision (wcstod.c)wcstof()– Konvertiert eine WC-Konstante in einen Wert mit doppelter Präzisionwcstoimax()– Konvertiert eine WC-Konstante in einen Integerwertwcstok()– Teilt eine WC-Konstante in Einzelteile (wcstok.c)wcstol()– Konvertiert eine WC-Konstante in einen long int (wcstol.c)wcstold()– Konvertiert eine WC-Konstante in einen Wert mit doppelter Präzisionwcstoll()– Konvertiert eine WC-Konstante in einen long intwcstombs()– Konvertiert eine WC-Konstante in eine Zeichenkonstante (wcstombs.c)wcstoul()– Konvertiert eine WC-Konstante in einen unsigned long (wcstoul.c)wcstoull()– Konvertiert eine WC-Konstante in einen unsigned longwcstoumax()– Konvertiert eine WC-Konstante in einen Integerwcswcs()– Findet eine WC-Konstante (obsolet) (wcswcs.c)wcswidth()– Anzahl der Spaltenpositionen einer WC-Konstante (wcswidth.c)wcsxfrm()– Transformiert eine WC-Konstante (wcsxfrm.c)wctob()– Konvertiert eine WC-Konstante in ein Einzelbytezeichenwctomb()– Konvertiert eine WC-Konstante in eine schmale Zeichenkette (wctomb.c)wctrans()– Definiert das Mapping von Zeichenwctype()– Definiert eine Zeichenklassewcwidth()– Anzahl der Spaltenpositionen eines WC-Codes (wcwidth.c)
graegerts