facet ändern



  • @Meep-Meep sagte in facet ändern:

    ich hab doch geschrieben das ich das locale unter VS2019 mit dem string "de" erzeuge und nicht mit UTF8. solange ich nicht mein eigenes facet mit reinschiebe funktioniert die ausgabe mit den umlauten. aber wenn ich bei der erzeugung mein facet mit angebe, scheint er auf das classic locale zurück zu gehen.

    naja hier erstellst du schon eine utf-8 lokale bzw erfragst diese:

    std::locale ger_loc(std::locale("de_DE.UTF-8"), new umlaut<char>);
    

    Und laut dieser dokumenation von microsoft funktioniert utf-8 nicht unter windows.
    Es bezieht sich hier auf setlocale aber das grundlegende Problem bleibt erhalten dass windows kein utf-8 in der ANSI api (char) kann.

    https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/setlocale-wsetlocale?view=vs-2019:

    The locale argument can take a locale name, a language string, a language string and country/region code, a code page, or a language string, country/region code, and code page.
    The set of available locale names, languages, country/region codes, and code pages includes all those supported by the Windows NLS API except code pages that require more than two bytes per character, such as UTF-7 and UTF-8. If you provide a code page value of UTF-7 or UTF-8, setlocale will fail, returning NULL. The set of locale names supported by setlocale are described in Locale Names, Languages, and Country/Region Strings. The set of language and country/region strings supported by setlocale are listed in Language Strings and Country/Region Strings. We recommend the locale name form for performance and for maintainability of locale strings embedded in code or serialized to storage. The locale name strings are less likely to be changed by an operating system update than the language and country/region name form.

    Anders beispiel: https://github.com/ocornut/imgui/issues/917



  • @Firefly: Du verwirrst hier zuviel. @Meep-Meep hat doch im ersten Beitrag geschrieben, daß die Umlaute korrekt mit "de" ausgegeben werden.

    @Meep-Meep:
    Zum Test probiere mal

    std::locale loc_ger("de");
    const auto &f = std::use_facet<std::ctype<char>>(loc_ger);
    std::locale loc = std::locale(loc_ger, &f);
    std::locale::global(loc);
    std::cout << "üöäÜÖÄ" << std::endl;
    std::cout << "locale: " << loc.name() << std::endl;
    

    Dann sollten auch die Umlaute korrekt ausgegeben werden, ansonsten wäre dieser Konstruktor falsch implementiert.
    Du kannst es sonst auch mal mit anderen Facets (bei use_facet<...>) ausprobieren.



  • hi TH69,

    ausgabe:

    ³÷õ▄Í─
    locale: *
    

    das selbe in gruen.

    nun mit einem anderen facet:

       std::locale loc_ger("de");
       std::locale loc_en("en");
       const auto &f = std::use_facet<std::money_get<char>>(loc_en);
       std::locale loc = std::locale(loc_ger, &f);
       std::locale::global(loc);
       std::cout << "üöäÜÖÄ" << std::endl;
       std::cout << "locale: " << loc.name() << std::endl;
    

    ausgabe:

    ³÷õ▄Í─
    locale: *
    

    nun mit einem nullptr als facet:

       std::locale loc_ger("de");
       std::locale loc_en("en");
       const auto *f = &std::use_facet<std::money_get<char>>(loc_en);
       f = nullptr;
       std::locale loc = std::locale(loc_ger, f);
       std::locale::global(loc);
       std::cout << "üöäÜÖÄ" << std::endl;
       std::cout << "locale: " << loc.name() << std::endl;
    

    ausgabe:

    üöäÜÖÄ
    locale: de
    


  • Dann würde ich ja sagen, daß die Implementierung kaputt ist, denn mindestens die erste Ausgabe sollte ja wie die dritte sein (denn es wird ja das eigene Facet angegeben).

    Evtl. liegt es intern daran, daß dieser locale keinen Namen mehr hat (*) und dann auf classic ("C") umgestellt wird.

    Kommt denn bei "C" und "" die selbe Ausgabe?



  • gestern hatte ich ja auf rextester.com einen test gemacht und da kam:

    üöäÜÖÄ
    locale: *
    

    also das lokal wird umbenannt. das scheint in ordnung zu sein.

    zu locales "C" und "". ich hab deine frage mal folgend interpretiert:

       std::locale loc_ger("");
       std::locale loc_en("C");
       const auto &f = std::use_facet<std::money_get<char>>(loc_en);
       std::locale loc = std::locale(loc_ger, &f);
       std::locale::global(loc);
       std::cout.imbue(loc);
       std::cout << "üöäÜÖÄ" << std::endl;
       std::cout << "locale: " << loc.name() << std::endl;
    

    kommt wieder:

    ³÷õ▄Í─
    locale: *
    


  • Wenn dort also dieselben Zeichen ausgegeben werden, dann bestätigt das meine Vermutung.
    Ein Workaround fällt mir leider auch nicht ein, denn der Facet-Konstruktor ist wohl die einzige Möglichkeit bei einem bestehenden locale-Objekt ein Facet zu ändern.



  • hab mal nen bug report geschrieben. mal schauen ob das was bringt...
    hab vor 2.5 jahren schon mal einen wegen std::ctype<char>::::is(std::blank, ch) geschrieben, weil std::ctype_base::blank gleich wie std::ctype_base::space agiert, ist bis jetzt auch noch nix passiert. steht seit meinem bug report Mai 2017 auf "Under Investigation" 😕



  • Bei dem von dir geposteten Online-Compiler rextester kommen aber bei "VC++ [19.00.23506 for x64]" mit dem Testcode die richtigen Umlaute heraus.



  • @Th69 sagte in facet ändern:

    Bei dem von dir geposteten Online-Compiler rextester kommen aber bei "VC++ [19.00.23506 for x64]" mit dem Testcode die richtigen Umlaute heraus.

    Dann klingt das ganze eventuell nach einem reinem darstellungsproblem.

    Die Frage ist wie kommen wir an die byte (hexadezimal) Darstellung der Ausgabe. Nicht das doch UTF-8 ausgegeben werden soll aber die "Konsole" die zeichen als ANSI oder in einer anderen codepage interpretiert.
    Oder das die Ausgabe kein unicode ist aber die zeichen als unicode interpretiert werden



  • Man könnte die Ausgabe in der Konsole ja per >file.txt in eine Datei umleiten (und dann mit einem Hex-Editor anschauen).



  • @Meep-Meep:

    Gibt es einen unterschied der Darstellung bei folgenden code?

    #include <iostream>
    #include <locale>
    
    int main()
    {
        std::locale loc_ger("de");
    const auto &f = std::use_facet<std::ctype<char>>(loc_ger);
    std::locale loc = std::locale(loc_ger, &f);
    std::locale::global(loc);
    std::cout << "üöäÜÖÄ" << std::endl;
    std::cout << "locale: " << loc.name() << std::endl;
    std::cout << "utf-8 encoded: \303\274\303\266\303\244\303\234\303\226\303\204" << std::endl;
    }
    

    Die utf-8 encoded enthält üöäÜÖÄ utf-8 kodiert in oktaler schreibweise.

    Bei https://rextester.com/l/cpp_online_compiler_visual bekomme ich folgende ausgabe:

    üöäÜÖÄ
    locale: *
    utf-8 encoded: üöäÜÖÄ

    Also identisch



  • @firefly die ausgabe:

    ³÷õ▄Í─
    locale: *
    utf-8 encoded: ├╝├Â├ñ├£├û├ä
    

    wenn es an der codierung liegen wuerde, dann wuerde ich immer das problem haben. aber so lange ich standard locales erstelle passt alles. was rextester da im hintergrund am laufen hat, weiß ich nicht. vielleicht kann ja jemand hier, der VS2019 hat, den source auch mal testen und schreiben, was er fuer eine ausgabe bekommt.



  • Das sieht echt nach einem reinem Darstellungsproblem aus.
    Gut wäre es jetzt zu sehen ob das gleiche Ergebnis kommt, wenn die Ausgabe direkt in eine Datei umgeleitet wurde.

    Dann könnte man sich mit einem Hexeditor anschauen wie die einzelnen Zeichen kodiert sind.



  • @firefly hier die umleitung in eine datei. editor ist auf ansi gestellt

    üöäÜÖÄ
    locale: *
    utf-8 encoded: üöäÜÖÄ
    

    umlaute sind da, passt. es ist einfach das local was nicht stimmt. wenn ich die umlaute mittels std::locale("C") ausgebe bekomme ich auch wieder die selben zeichen:

    ³÷õ▄Í─
    

    das darstellungsproblem, wie du es nennst, kommt vom "C" locale.



  • Welche Codepage ist denn bei deiner Konsole eingestellt (weil es wundert mich jetzt, daß die Konsolenausgabe jetzt anders als die Dateiausgabe ist)?
    Mit chcp kannst du diese abfragen bzw. mit chcp nnn entsprechend setzen.
    Standardmäßig (bei einem deutschen System) ist 850 ("DOS-Latin-1") in der Konsole eingestellt, während unter Windows (also Desktop bzw. Explorer) 1252 (Westeuropäische Sprachen) als ANSI aktiviert ist.

    Setze diese in der Konsole auch mal auf 1252 und teste dann noch mal.
    Daß du jedoch bei "de" die richtige Ausgabe erhältst, bei der Änderung mit use_facet aber nicht, deutet m.E. aber trotzdem auf einen Fehler hin.

    Mit z.B. "Notepad++" kannst du für den Text in einer Datei auch die Codepage umschalten (so daß du die Codepage damit ermitteln kannst).



  • das umschalten der codepage kann ich im viewer vom total commander auch.
    das setzen auf 1252 bringt insofern nichts, da das "C" locale die codepage bei der ausfuehrung wieder aendern wuerde. es ist definitiv ein bug. mein report wurde inzwischen von Stephan T. Lavavej aufgenommen und als Bug gekennzeichnet. trotzdem danke fuer eure anregungen und hilfen.



  • Kannst du den Link auf den Bug-Report hier posten?



  • @Meep-Meep sagte in facet ändern:

    das umschalten der codepage kann ich im viewer vom total commander auch.
    das setzen auf 1252 bringt insofern nichts, da das "C" locale die codepage bei der ausfuehrung wieder aendern wuerde. es ist definitiv ein bug. mein report wurde inzwischen von Stephan T. Lavavej aufgenommen und als Bug gekennzeichnet.

    Es kann allerdings noch einige Zeit ins Land ziehen bis, das gefixt und auch tatsächlich verfügbar ist. Vielleicht hilft es ja die Codepage im Programm selbst zu setzen anstatt mit chcp oder sowas? Eventuell nochmal nach dem locale-Gedöns?

    Vor einiger Zeit gab es hier mal eine Diskussion zur UTF-8-Ausgabe in Windows-Konsolenprogrammen. Dort kannst du sehen, wie man die Konsolen-Codepage im Programm selbst ändert.

    Auch wenn du nicht auf UTF-8 im Speziellen hinaus willst: Meine Erkenntnis war damals auch dass da bei VS (2015 in dem Fall) bezüglich Zeichencodierungen schon noch einiges im argen liegt. Für möglichst intuitive UTF-8-Ausgabe empfahl es sich, die Datei in VS als Unicode (UTF-8 without signature) - Codepage 65001 zu speichern und gewöhnliche String-Literale ohne Präfix zu verweden.

    Ansonsten möchte ich noch erwähnen, dass die native Unicode-Codierung für Windows UTF-16 ist (im gegensatz zu Linux, wo eher UTF-8 angesagt und UTF-16 ein Exot ist). Eventuell verhält sich dein Programm ja so, wie du es erwartest, wenn du damit arbeitest (wcout, wchar_t und Codepage 65001)? Das würde zumindest theoretisch keine Umstellung der Codepage erfordern, wenn man die Locale ändert (falls es daran liegt).




Anmelden zum Antworten