std::cout.imbue() does not work, but std::locale::global() works



  • Please help me to understand behaviour of this simple program (My config: Windows 7, VS2013, codepage Windows-1251 for string literals encoding, the same is default system-wide, CP 866 codepage for console):

    **std::cout << 1.2 << " Hi! Привет!" << std::endl; //Prints 1.2 Hi! ╧ЁштхЄ!

    std::locale locale("");
    std::cout.imbue(locale);
    std::cout << 1.2 << " Hi! Привет!" << std::endl; //Prints 1,2 Hi! ╧ЁштхЄ!

    std::locale::global(locale);
    std::cout << 1.2 << " Hi! Привет!" << std::endl; //Prints 1,2 Hi! Привет!**

    The «╧ЁштхЄ» is how «Привет!» looks like when wrongly interpreted as CP 866 instead of 1251.

    For unknown reasons std::cout.imbue(locale) changes only decimal separator, but not output encoding, so I get wrong results. std::locale::global(locale) does good job, but I cannot use it, because it changes behaviour of std::stof ( std::stof("1.2") will return 1, which I do not want).

    It is also unfair that «Hi!» is always printed correctly, but «Привет!» is not (even this forum did not allowed me to use cyrillic in [code] tag). I would prefer to have cyrillic letters to be printed correctly worldwide, and latin ones to be printed as gibberish except for rare cases when codepages are correctly set and matched.



  • I think this is more of a Windows-specific problem. You are creating a Windows console application I guess? From experience I know that setting a global C++ locale results in calling the library function std::setlocale which sets the global C locale (used by functions like std::atof) which on Windows also tends to adjust the codepage of the console. Imbueing a stream with a locale does not call setlocale. To get your text to be displayed correctly without interfering with the global C locale you could either manually set a codepage for your console with WinApi (I remember there being a function for setting codepages) and hope that the console will support it or use a good GUI package.

    If you want to keep modifying the global locale, you could still use stringstreams imbued with a "C" locale to parse text instead of atof. That is one of the main advantages of using seperate locale objects for every stream instead of a single big locale for everything, you don't have to depend on the assumption that the current global locale is correct for your work.



  • I think this is more of a Windows-specific problem. You are creating a Windows console application I guess? From experience I know that setting a global C++ locale results in calling the library function std::setlocale which sets the global C locale (used by functions like std::atof) which on Windows also tends to adjust the codepage of the console. Imbueing a stream with a locale does not call setlocale.

    That sounds plausible.

    If you want to keep modifying the global locale, you could still use stringstreams imbued with a "C" locale to parse text instead of atof.

    Thanks, that works for me.



  • @SAn: You can quote someone's post by clicking on "Zitieren" in the right upper corner of a post.


Anmelden zum Antworten