printf("%s"),printf("%ls"),wprintf("%s")和wprintf("%ls")之间有什么区别?

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)

我在想:

  1. 为什么3和4没有打印
  2. 1和3,2和4之间的区别是什么.
  3. 如果narrowstr在utf8中并且widestr在utf16中会有什么不同吗?

Aja*_*jay 9

你需要这样做:

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.


Cub*_*bbi 5

请注意,您正在使用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);已经讨论了足够多次)


n. *_* m. 0

问题 1 和 2 的答案在文档中。任何好的文档集都可以。他们说cppreference非常好。

至于 3,语言标准没有指定任何特定的字符串编码,也没有指定任何特定的wchar_t. 您需要查阅有关实现的文档,而不是特定语言的文档(尽管很少建议编写依赖于实现的代码)。