Dis*_*ame 16 c++ unicode printf widechar
考虑这个示例程序:
#include <cstdio>
#include <cwchar>
#include <string>
int main()
{
std::string narrowstr = "narrow";
std::wstring widestr = L"wide";
printf("1 %s \n", narrowstr.c_str());
printf("2 %ls \n", widestr.c_str());
wprintf(L"3 %s \n", narrowstr.c_str());
wprintf(L"4 %ls \n", widestr.c_str());
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这个输出是:
1 narrow
2 wide
Run Code Online (Sandbox Code Playgroud)
我在想:
你需要这样做:
wprintf(L"3 %hs \n", narrowstr.c_str());
wprintf(L"4 %s \n", widestr.c_str());
Run Code Online (Sandbox Code Playgroud)
为什么?因为printf,%s表示窄字符串.因为wprintf,%ls说宽.
但是,对于wprintf,%S暗示宽%LS将意味着广本身.%hs意味着狭窄(两者).对于printf,%S,以这种方式将仅仅意味着%HS
在VC++/Windows上,%S(大写S),会扭转效果.因为printf("%S")它意味着宽,并且wprintf("%S")意味着狭窄.这很有用_tprintf.
请注意,您正在使用C流.C流具有非常特殊的质量,称为"定向".流是未定向的,宽的或窄的.方向取决于对任何特定流的第一个输出(有关CI/O流的摘要,请参阅http://en.cppreference.com/w/cpp/io/c)
在你的情况下,stdout开始是无定向的,通过执行第一个printf,你将它设置得很窄.一旦变窄,它就会变窄,然后wprintf失败(检查它的返回代码!).更改C流的唯一方法是使用freopen它,这与stdout不太一样.这就是为什么3和4没有打印的原因.
1和3之间的差异是1是一个窄输出函数,它使用窄字符串转换说明符%s:它从char数组中读取字节并将字节发送到字节流.3是一个带有窄字符串转换说明符%s的宽输出函数:它首先从char数组读取字节并将mbtowc它们转换为wchar_ts,然后将wchar_ts 发送到宽流中,然后将wctomb它们转换为字节或多字节序列,然后将其推送进入标准出来了write
最后,如果widestr在utf16中,你必须使用Windows,所有的赌注都是关闭的; 在该平台上,除了ASCII以外的任何东西都很少支持.您也可以放弃并使用WinAPI(您可以使用标准C++ 11获取某些Unicode内容,甚至可以使用魔术字进行此C输出,_setmode(_fileno(stdout), _O_U16TEXT);已经讨论了足够多次)
问题 1 和 2 的答案在文档中。任何好的文档集都可以。他们说cppreference非常好。
至于 3,语言标准没有指定任何特定的字符串编码,也没有指定任何特定的wchar_t. 您需要查阅有关实现的文档,而不是特定语言的文档(尽管很少建议编写依赖于实现的代码)。