Warum transliteriert wprintf russischen Text in Unicode unter Linux in Latein?

Lesezeit: 3 Minuten

Benutzeravatar von vitaut
vitaut

Warum funktioniert das folgende Programm

#include <stdio.h>
#include <wchar.h>

int main() {
  wprintf(L"Привет, мир!");
}

print “Liguster, mir!” unter Linux? Warum transkribiert es russischen Text in Unicode ins Lateinische, anstatt ihn in UTF-8 zu transkodieren oder Ersatzzeichen zu verwenden?

Demonstration dieses Verhaltens auf Godbolt: https://godbolt.org/z/36zEcG

Die nicht breite Version printf("Привет, мир!") gibt diesen Text wie erwartet aus (“Привет, мир!”).

  • Aus Neugier, warum überhaupt verwenden wchar unter Linux?

    – Mccarton

    30. Dezember 2020 um 15:51 Uhr

  • Es gibt keinen Grund zu verwenden wchar_t da es nicht tragbar ist. Ich bin gerade auf dieses “interessante” Verhalten gestoßen, als ich eine andere SO-Frage beantwortet habe: stackoverflow.com/a/65480111/471164,

    – vitaut

    30. Dezember 2020 um 16:05 Uhr

  • In meinem System druckt es nur ??????, ???!. Könntest du prüfen /usr/share/i18n/locales/C und sehen Sie, ob es irgendwelche Regeln gibt, die mit beginnen translit da drin?

    – Heinzi

    31. Dezember 2020 um 11:55 Uhr

  • @Heinzi, bei Interesse können Sie die Gebietsschemas auf Godbolt überprüfen – die Frage enthält einen Link.

    – vitaut

    31. Dezember 2020 um 15:47 Uhr

Benutzeravatar von StaceyGirl
StaceyGirl

Weil die Konvertierung von Breitzeichen gemäß dem aktuell eingestellten Gebietsschema erfolgt. Standardmäßig beginnt ein C-Programm immer mit einem „C“-Locale, das nur ASCII-Zeichen unterstützt.

Sie müssen zuerst zu einem beliebigen russischen oder UTF-8-Gebietsschema wechseln:

setlocale(LC_ALL, "ru_RU.utf8"); // Russian Unicode
setlocale(LC_ALL, "en_US.utf8"); // English US Unicode

Oder zu einem aktuellen Systemgebietsschema (was wahrscheinlich das ist, was Sie brauchen):

setlocale(LC_ALL, "");

Das volle Programm wird sein:

#include <stdio.h>
#include <wchar.h>
#include <locale.h>

int main() {
  setlocale(LC_ALL, "ru_RU.utf8");
  wprintf(L"Привет, мир!\n");
}

Was Ihren Code betrifft, der auf anderen Computern unverändert funktioniert, liegt dies daran, wie libc dort funktioniert. Einige Implementierungen (wie musl) unterstützen keine Nicht-Unicode-Locales und können daher breite Zeichen bedingungslos in eine UTF-8-Sequenz übersetzen.

  • Es druckt Drucke wörtlich Privet, mir! wenn ich es auf Godbolt mit oder ohne laufen lasse setlocale(LC_ALL, "ru_RU.utf8") oder setlocale(LC_ALL, "").

    – Jabberwocky

    29. Dezember 2020 um 15:27 Uhr


  • Aber warum transliterieren? Ist das irgendwo dokumentiert?

    – vitaut

    29. Dezember 2020 um 15:27 Uhr

  • @Jabberwocky Haben Sie das Gebietsschema “ru_RU.utf8” auf Ihrem Computer installiert? Wenn nicht, schlägt die Einstellung fehl. Verwenden "" (Standardgebietsschema), das wahrscheinlich ein UTF-8 ist. Jedes Unicode-Gebietsschema reicht aus.

    – StaceyGirl

    29. Dezember 2020 um 15:27 Uhr


  • @vitaut Ich bin mir nicht sicher, aber ich denke, es ist einfach illegal, diese Zeichen ohne Gebietsschema auszugeben, und libc kann wahrscheinlich tun, was es will. Die Transliteration ist eine gute Möglichkeit, gültige und dennoch lesbare Ausgaben zu erzeugen.

    – StaceyGirl

    29. Dezember 2020 um 15:28 Uhr


  • @Jabberwocky welches Gebietsschema verwendest du dann? Versuchen Sie “en_US.utf8”, wenn Sie sich in den USA befinden.

    – StaceyGirl

    29. Dezember 2020 um 15:29 Uhr


Benutzeravatar von KamilCuk
KamilCuk

Warum wird russischer Text in Unicode in Latein transkribiert, anstatt ihn in UTF-8 zu transkodieren oder Ersatzzeichen zu verwenden?

Da das Startgebietsschema Ihres Programms das Standardgebietsschema ist, wird die C Gebietsschema. Es übersetzt also eine breite Zeichenfolge in C Gebietsschema. C locale verarbeitet weder UTF-8 noch Unicode, daher ist es in Ihrer Standardbibliothek am besten, breite Zeichen in einen grundlegenden Zeichensatz zu übersetzen, der in verwendet wird C Gebietsschema.

Sie können das Gebietsschema auf ändern irgendein UTF-8-Gebietsschema und das Programm sollte eine UTF-8-Zeichenfolge ausgeben.

Hinweis: (in Umsetzung ist mir bekannt) die Kodierung der FILE Strom bestimmt und damals gespeichert die Stream-Ausrichtung (breit vs. normal) wird gewählt. Denken Sie daran, das Gebietsschema festzulegen Vor irgendwas damit machen stdout (dh. Dies vs Dies).

1390870cookie-checkWarum transliteriert wprintf russischen Text in Unicode unter Linux in Latein?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy