Die Anzeige wide chars mit printf
Ich versuche zu verstehen wie funktioniert printf Arbeit mit wide-Zeichen (wchar_t
).
Habe ich den folgenden code-Beispiele :
Beispiel 1 :
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
wchar_t *s;
s = (wchar_t *)malloc(sizeof(wchar_t) * 2);
s[0] = 42;
s[1] = 0;
printf("%ls\n", s);
free(s);
return (0);
}
Ausgabe :
*
Alles ist in Ordnung hier : mein Charakter (*
) wird korrekt angezeigt.
Beispiel 2 :
Wollte ich die Anzeige einer anderen Art von Charakter. Auf meinem system wchar_t
scheinen codiert auf 4 bytes. So habe ich versucht, zeigen die folgenden Charakter :
É
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
wchar_t *s;
s = (wchar_t *)malloc(sizeof(wchar_t) * 2);
s[0] = 0xC389;
s[1] = 0;
printf("%ls\n", s);
free(s);
return (0);
}
Aber es gibt keine Ausgabe in dieser Zeit versuchte ich mit vielen Werten aus dem "encoding" - Abschnitt (cf. vorherigen link) für s[0]
(0xC389, 201, 0xC9)... Aber ich bekomme nie die É
Zeichen angezeigt. Ich habe auch versucht mit %S
statt %ls
.
Wenn ich versuche zu nennen printf wie diese : printf("<%ls>\n", s)
das einzige Zeichen, das gedruckt wird, ist '<'
wird, wird die Anzeige abgeschnitten.
Warum ich dieses problem haben? Wie sollte ich das tun?
- Gibt es einen Grund, die Sie zuordnen, dynamisch statt deklarieren ein array mit zwei Elementen?
- Versuchen Lesung mit
scanf("%1ls")
eine"É"
und berichten, was Wert fürprintf("%lX\n", (unsigned long) s[0])
Sie bekommen. printf("%ld\n", (unsigned long int) L'É');
gibt mir201
.- Schlage vor, das Ergebnis von "Lesen mit
scanf("%1ls")
ein "É". Ihr Kommentar berichtet, was der source-code, der denkt, dass ein 'É' ist. Wir sind daran interessiert, wie der code verarbeitet die I/O, die möglicherweise unterscheiden sich in Zeichen-Kodierung. - Auf meinem system ist, ist der Rückgabewert von
scanf("%1ls", s);
-1 (s[0]
nicht festgelegt) unterstützt, stackoverflow.com/a/40600658/2410359
Du musst angemeldet sein, um einen Kommentar abzugeben.
Warum ich dieses problem haben?
Stellen Sie sicher, dass Sie überprüfen
errno
und der return-Wertprintf
!Finden Sie in der Ausgabe:
Wie zu beheben
Zunächst das Standard-Gebietsschema der C Programm
C
(auch bekannt alsPOSIX
), die ASCII-only. Sie müssen zum hinzufügen eines Anrufs zusetlocale
spezifischsetlocale(LC_ALL,"")
.Wenn Ihr
LC_ALL
,LC_CTYPE
oderLANG
Umgebungsvariablen nicht gesetzt sind, zu UTF-8, wenn leere, Sie müssen explizit ein Gebietsschema auswählen.setlocale(LC_ALL, "C.UTF-8")
funktioniert auf den meisten Systemen -C
ist standard, und dieUTF-8
Teilmenge vonC
ist in der Regel umgesetzt.Finden Sie in der Ausgabe:
Der Grund, warum das falsche Zeichen gedruckt ist, weil
wchar_t
stellt ein breites Zeichen (z.B. UTF-32), nicht ein multibyte-Zeichen (z.B. UTF-8). Beachten Sie, dasswchar_t
ist immer 32 bit breit, in der GNU-C-Bibliothek, aber der C-standard nicht verlangen, dass Sie sein. Wenn Sie initialisieren Sie die Zeichen mithilfe derUTF-32BE
- Codierung (d.h.0x000000C9
), dann druckt es richtig aus:Ausgabe:
Beachten Sie, dass Sie können auch die
LC
(locale) Umgebungsvariablen über die Kommandozeile:Ein problem ist, dass Sie versuchen zu codieren, UTF-8, das ist ein single-byte-Codierung-Schema, wie ein multi-byte-Codierung. Für UTF-8-Sie verwenden nur
char
.Beachten Sie auch, dass, weil Sie versuchen, kombinieren Sie die UTF-8-Sequenz in ein multi-byte-Typ, haben Sie endianness (byte-order) Fragen (in memory
0xC389
gespeichert werden könnten, als0x89
und0xC3
in dieser Reihenfolge). Und, dass der compiler wird sich melden-erweitern Sie Ihre Nummer ebenfalls (wennsizeof(wchar_t) == 4
und schauen Sies[0]
im debugger könnte es sein0xFFFFC389
).Ein weiteres problem ist das terminal oder Konsole, die Sie verwenden, um zu drucken. Vielleicht ist es einfach doesn ' T support UTF-8 oder die anderen Codierungen probiert?