代码之家  ›  专栏  ›  技术社区  ›  xmllmx

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

  •  1
  • xmllmx  · 技术社区  · 12 年前
    #include <iostream>
    
    using namespace std;
    
    void f1()
    {
        wcout.imbue(locale("chs"));
        wcout << L"您" << endl;
    }
    
    void f2()
    {
        locale loc(wcout.getloc(), new codecvt<wchar_t, char, mbstate_t>());
    
        wcout.imbue(loc);
        wcout << L"好" << endl;
    }
    
    int main()
    {
        f1(); // OK
        f2(); // Error. There is no output as expected.
    }
    

    根据 cplusplus.com 的联机文档:

    codecvt<wchar_t,char,mbstate_t>: 
    
        converts between native wide and narrow character sets.
    

    此程序使用VC++编译,并在Windows上运行。

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

    1 回复  |  直到 12 年前
        1
  •  5
  •   Cubbi    12 年前

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

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

    • 构造一个 std::locale 对于GBK,只需将其用于流,无需提取一个方面

      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
      
    • 使用直接构建面 std::codecvt_byname

      wcout.imbue(std::locale(wcout.getloc(),
                  new std::codecvt_byname("zh_CN.gbk")); // explict name
      
    • 编写自己的转换例程并从 标准::编码 ,所以您可以将其与

      wcout.imbue(std::locale(wcout.getloc(), new yourcodecvt);
      

    Windows对C++语言环境的支持非常差,不过WinAPI可能有一个更合适的转换功能。