UTF-8, toupper() und die Umlaute
-
Hi Zusammen!
Ich bin gerade dabei ein SDK, welches ich intern benutze, zu programmieren, und dabei auf einen interessanten Effekt gestoßen, den ich nicht ganz nachvollziehen kann.
Und zwar betrifft das die Funktion toupper(), weil ich gerne einen String in Großbuchstaben konvertieren möchte. Bekanntlich gibt es da Probleme mit Umlauten und Sonderzeichen. Was ich gerne hätte wäre eine völlig universelle Funktion, die einfach jedes Zeichen richtig in Großbuchstaben konvertiert, sofern es dazu ein Pendant gibt. Diese Funktion habe ich auch gegunden, es scheint wohl towupper() für wchar_t zu sein.
In den manpages steht zu toupper() allerdings:
The details of what constitutes an uppercase or lowercase letter depend
on the current locale. For example, the default "C" locale does not
know about umlauts, so no conversion is done for them.In some non-English locales, there are lowercase letters with no corre‐
sponding uppercase equivalent; the German sharp s is one example.Das sagt mir, dass wenn mein locale auf de_DE.UTF-8 steht sollten doch deutche Umlaute entsprechend umgesetzt werden. Das tut mein Testprogramm, welches dem folgendem entspricht, nicht.
unsigned char out [ 4 + 1 ]; unsigned char* in = "ä"; wchar_t ch; int i_ch; printf( "%s\n", setlocale( LC_ALL, "" ) ); printf( "in = >%s<\n", in ); ch = u8_char( in ); i_ch = u8_char( in ); printf( "wchar_t = %d %d\n", ch, towupper( ch ) ); printf( "int = %d %d\n", i_ch, toupper( i_ch ) ); ch = towupper( ch ); memset( out, 0, sizeof( out ) ); u8_toutf8( out, sizeof( out ), &ch, 1 ); printf( "out(1) = >%s<\n", out ); i_ch = toupper( i_ch ); memset( out, 0, sizeof( out ) ); u8_toutf8( out, sizeof( out ), &i_ch, 1 ); printf( "out(2) = >%s<\n", out );
(die Funktionen u8_char() und u8_toutf8() basieren dabei aus einer UTF-8 Library, die ich etwas erweitert habe, die man unter http://www.cprogramming.com/tutorial/unicode.html finden kann; Diese Funktionen haben keine Relevanz auf den Programmablauf in diesm Fall)
Was bei einem Lauf dieses Programms rauskommt:
de_DE.UTF-8 in = >ä< wchar_t = 228 196 int = 228 228 out(1) = >Ä< out(2) = >ä<
Das interessante ist nun die Ausgabe. Denn towupper(), die wchar_t-Variante gibt mir egal bei welchem locale immer den richtigen Wert zurück. toupper() kümmert das aber anscheinend nicht. Ob ich nun de_DE.UTF-8 oder en_US.UTF-8 als LC_ALL setze, es kommt immer dasselbe Ergebnis raus.
Habt ihr 'ne Idee dazu?
Grüße
~code_pilot