为什么 std::codecvt<wchar_t, char, mbstate_t> 不能按定义工作?

xml*_*lmx 1 c++ windows unicode iostream character-encoding

#include <iostream>\n\nusing namespace std;\n\nvoid f1()\n{\n    wcout.imbue(locale("chs"));\n    wcout << L"\xe6\x82\xa8" << endl;\n}\n\nvoid f2()\n{\n    locale loc(wcout.getloc(), new codecvt<wchar_t, char, mbstate_t>());\n\n    wcout.imbue(loc);\n    wcout << L"\xe5\xa5\xbd" << endl;\n}\n\nint main()\n{\n    f1(); // OK\n    f2(); // Error. There is no output as expected.\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

根据cplusplus.com的在线文档:

\n\n
codecvt<wchar_t,char,mbstate_t>: \n\n    converts between native wide and narrow character sets.\n
Run Code Online (Sandbox Code Playgroud)\n\n

该程序用VC++编译,在Windows上运行。

\n\n

本程序中,内部字符集为UCS-2,由VC++编译器定义;外部字符集,即窄字符集,在控制台环境下为GBK(中文字符集)。如果文档属实,则wcout可以将 unicode 字符串从 UCS-2 转换为 GBK f1();然而,事实并非如此。为什么?

\n

Cub*_*bbi 5

您已经默认构造了一个std::codecvt,没有特定的转换规则。它无法知道您需要 GBK 而不是 GB18030 或 UTF-8。

获取将wchar_t转换为GBK的codecvt的方法:

  • 构建一个std::localeGBK 只需将其与您的流一起使用,无需拉出一个方面

    wcout.imbue(std::locale("")); // this uses the current user settings,
    wcout.imbue(std::locale("zn_CN.gbk")); // or name the locale explicitly,
                                           // by whatever name Windows calls it
    
    Run Code Online (Sandbox Code Playgroud)
  • 直接构造facetstd::codecvt_byname

    wcout.imbue(std::locale(wcout.getloc(),
                new std::codecvt_byname("zh_CN.gbk")); // explict name
    
    Run Code Online (Sandbox Code Playgroud)
  • 编写您自己的转换例程并从 派生std::codecvt,因此您可以将其与

    wcout.imbue(std::locale(wcout.getloc(), new yourcodecvt);
    
    Run Code Online (Sandbox Code Playgroud)

Windows 对 C++ 语言环境的支持很差,但 WinAPI 可能有更合适的转换函数。