C++:宽字符输出错误?

9

我的代码基本上是这样的:

wstring japan = L"日本";
wstring message = L"Welcome! Japan is ";

message += japan;

wprintf(message.c_str());

我希望使用宽字符串,但我不知道它们如何输出,所以我使用了wprintf。当我运行类似以下代码的内容时:

./widestr | hexdump

十六进制代码点生成了这个:
65 57 63 6c 6d 6f 21 65 4a 20 70 61 6e 61 69 20 20 73 3f 3f
e  W  c  l  m  o  !  e  J     p  a  n  a  i        s  ?  ?

为什么它们都按顺序跳跃?我的意思是,如果wprintf是错误的,我仍然不明白为什么它会以如此特定的混乱顺序输出!编辑:字节序或其他原因吗?它们似乎每两个字符旋转一次。嗯。编辑2:我尝试使用wcout,但它输出完全相同的十六进制代码点。奇怪!

也许你应该尝试使用 cout << message << endl - phimuemue
@phimuemue,它不起作用,它给我发送了大约30个错误,第一个是widestr.cpp:18: error: no match for ‘operator<<’ in ‘std::cout << message‘,还包括许多关于ostream字符特性或其他内容的错误,它无法输出宽字符串! - John D.
1
你使用的是哪个平台和编译器? - hlovdal
我正在使用GCC / Linux 2.6(x86)。 - John D.
1个回答

15

您需要定义locale。

    #include <stdio.h>
    #include <string>
    #include <locale>
    #include <iostream>

    using namespace std;

    int main()
    {

            std::locale::global(std::locale(""));
            wstring japan = L"日本";
            wstring message = L"Welcome! Japan is ";

            message += japan;

            wprintf(message.c_str());
            wcout << message << endl;
    }

正常工作(即将宽字符串转换为窄的UTF-8并打印)。

当您将全局区域设置为“”时,您设置了系统区域设置(如果它是UTF-8,则会以UTF-8打印 - 即wstring将被转换)。

编辑:忘记我所说的sync_with_stdio - 这是不正确的,默认情况下它们是同步的。不需要。


1
你让sync_with_stdiowcout听起来像是替代品,但它们实际上是做完全不同的事情。如果你想要在C++流使用(如wcout)中插入C流函数(如wprintf),那么就需要使用sync_with_stdio;如果你想要改变wcout使用的语言环境,则需要使用imbue - CB Bailey
1
我无法测试它,但是在Windows上wcout应该可以在没有代码页设置的情况下工作,因为在Windows上wchar_t是UTF-16代码单元,而UTF-16是Windows唯一的本地编码。因此,std::wcout应该使用WriteConsoleW而不需要进行任何区域设置转换。如果没有这样做,那么这就是一个库错误。 - Philipp
2
@Philipp,这不是标准定义的方式。标准规定,宽字符应根据区域设置的代码页转换为窄编码。这就是所做的。Windows的问题在于它不支持UTF-8。因此,在Windows上,您可能需要使用locale :: globale(locale(“Japan”)),它将在输出中使用Shift-JIS编码。否则,它将无法转换字符。 - Artyom
"wprintf"的输出符合预期,但"wcout"没有显示任何输出(全为空白)。为什么? - parasrish
那么对于像L"{"type":"string","value":"\u9CE5"},\n"这样的日语字符呢?它似乎不能像您上面展示的那样使用wprintf或wcout。 - Michele
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接