Hier ist alles in Ordnung : mein Charakter (*) wird korrekt angezeigt.
Probe 2:
Ich wollte eine andere Art von Charakter zeigen. Auf meinem System wchar_t scheinen auf 4 Bytes codiert. Also habe ich versucht, das folgende Zeichen anzuzeigen: É
Aber es gibt diesmal keine Ausgabe, ich habe es mit vielen Werten aus dem Abschnitt “Codierung” (vgl. vorherigen Link) versucht s[0] (0xC389, 201, 0xC9) … Aber ich bekomme das nie hin É Zeichen angezeigt. Ich habe es auch mit versucht %S Anstatt von %ls.
Wenn ich versuche, printf so aufzurufen: printf("<%ls>\n", s) das einzige gedruckte Zeichen ist '<'wird die Anzeige abgeschnitten.
Warum habe ich dieses Problem? Wie soll ich es machen?
Gibt es einen Grund, warum Sie dynamisch zuweisen, anstatt ein Array aus zwei Elementen zu deklarieren?
– Irgendein Programmierer-Typ
14. November 2016 um 13:51 Uhr
Versuchen Sie, mit zu lesen scanf("%1ls") a "É" und berichte welchen Wert für printf("%lX\n", (unsigned long) s[0]) du erhältst.
– chux – Wiedereinsetzung von Monica
14. November 2016 um 16:47 Uhr
@chux printf("%ld\n", (unsigned long int) L'É'); gibt mir 201.
– vmonteco
16. November 2016 um 11:49 Uhr
Schlagen Sie vor, das Ergebnis von „Lesen mit scanf("%1ls") ein “É”. Ihr Kommentar gibt an, was der Quellcode für ein ‘É’ hält. Uns interessiert, wie der Code mit der I/O umgeht, die sich in der Zeichenkodierung unterscheiden kann.
– chux – Wiedereinsetzung von Monica
16. November 2016 um 15:02 Uhr
Auf meinem System ist der Rückgabewert von scanf("%1ls", s); ist -1 (s[0] nicht festgelegt), die stackoverflow.com/a/40600658/2410359 unterstützt
– chux – Wiedereinsetzung von Monica
16. November 2016 um 15:09 Uhr
Tim
Warum habe ich dieses Problem?
Stellen Sie sicher, dass Sie dies überprüfen errno und der Rückgabewert von printf!
$ gcc test.c && ./a.out
printf: Invalid or incomplete multibyte or wide character
Wie repariert man
Zunächst einmal ist das Standardgebietsschema eines C-Programms C (auch bekannt als POSIX), die nur ASCII ist. Sie müssen einen Anruf hinzufügen setlocalespeziell setlocale(LC_ALL,"").
Wenn dein LC_ALL, LC_CTYPE oder LANG Umgebungsvariablen sind nicht so eingestellt, dass sie UTF-8 zulassen, wenn sie leer sind, müssen Sie explizit ein Gebietsschema auswählen. setlocale(LC_ALL, "C.UTF-8") funktioniert auf den meisten Systemen – C ist Standard, und die UTF-8 Teilmenge von C wird allgemein umgesetzt.
Der Grund, warum das falsche Zeichen ausgedruckt wird, ist weil wchar_t steht für ein Breitzeichen (z. B. UTF-32), nicht für ein Multibyte-Zeichen (z. B. UTF-8). Beachten Sie, dass wchar_t ist in der GNU-C-Bibliothek immer 32 Bit breit, aber der C-Standard verlangt dies nicht. Wenn Sie das Zeichen mit der initialisieren UTF-32BE codieren (bzw 0x000000C9), dann wird es korrekt ausgedruckt:
Beachten Sie, dass Sie auch die festlegen können LC (lokale) Umgebungsvariablen über die Kommandozeile:
$ LC_ALL=C.UTF-8
$ ./a.out
É
Ein Problem besteht darin, dass Sie versuchen, UTF-8, bei dem es sich um ein Einzelbyte-Codierungsschema handelt, als Multibyte-Codierung zu codieren. Für UTF-8 verwenden Sie plain char.
Beachten Sie auch, dass Sie, weil Sie versuchen, die UTF-8-Sequenz in einen Multi-Byte-Typ zu kombinieren Endianität (Byte-Reihenfolge) Probleme (in memory 0xC389 könnte gespeichert werden als 0x89 und 0xC3in dieser Reihenfolge). Und dass der Compiler auch Ihre Nummer vorzeichenerweitert (falls sizeof(wchar_t) == 4 und du schaust zu s[0] in einem Debugger könnte es sein 0xFFFFC389).
Ein weiteres Problem ist das Terminal oder die Konsole, die Sie zum Drucken verwenden. Vielleicht unterstützt es einfach nicht UTF-8 oder die anderen Codierungen, die Sie ausprobiert haben?
Ich habe einen einfachen Weg gefunden, breite Zeichen zu drucken. Ein wichtiger Punkt ist setlocale()
Gibt es einen Grund, warum Sie dynamisch zuweisen, anstatt ein Array aus zwei Elementen zu deklarieren?
– Irgendein Programmierer-Typ
14. November 2016 um 13:51 Uhr
Versuchen Sie, mit zu lesen
scanf("%1ls")
a"É"
und berichte welchen Wert fürprintf("%lX\n", (unsigned long) s[0])
du erhältst.– chux – Wiedereinsetzung von Monica
14. November 2016 um 16:47 Uhr
@chux
printf("%ld\n", (unsigned long int) L'É');
gibt mir201
.– vmonteco
16. November 2016 um 11:49 Uhr
Schlagen Sie vor, das Ergebnis von „Lesen mit
scanf("%1ls")
ein “É”. Ihr Kommentar gibt an, was der Quellcode für ein ‘É’ hält. Uns interessiert, wie der Code mit der I/O umgeht, die sich in der Zeichenkodierung unterscheiden kann.– chux – Wiedereinsetzung von Monica
16. November 2016 um 15:02 Uhr
Auf meinem System ist der Rückgabewert von
scanf("%1ls", s);
ist -1 (s[0]
nicht festgelegt), die stackoverflow.com/a/40600658/2410359 unterstützt– chux – Wiedereinsetzung von Monica
16. November 2016 um 15:09 Uhr