printf("%s"),printf("%ls"),wprintf("%s")和wprintf(>)之间的区别是什么? "%2!&#34)?

时间:2014-11-08 11:21:03

标签: 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;
}

这个输出是:

1 narrow 
2 wide 

我想知道:

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

3 个答案:

答案 0 :(得分:9)

你需要这样做:

wprintf(L"3 %hs \n", narrowstr.c_str());
wprintf(L"4 %s \n", widestr.c_str());

为什么呢?因为对于printf%s 表示narrow-char-string。对于wprintf%ls 表示广泛。

但是,对于wprintf%s 意味着广泛,%ls 意味着广泛。 %hs 意味着缩小(两者都有)。对于printf%s ,以这种方式只是意味着%hs

在VC ++ / Windows上,%S(大写S)会扭转效果。因为printf("%S")它意味着宽,wprintf("%S")意味着狭窄。这对_tprintf非常有用。

答案 1 :(得分:5)

请注意,您正在使用C流。 C流具有非常特殊的质量,称为“定向”。流是未定向的,宽的或窄的。方向取决于对任何特定流的第一个输出(有关C I / 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_t s,然后将wchar_t s发送到宽流,然后wctomb将它们转换为字节或多字节序列,然后使用write

将其推送到标准中

最后,如果widestr在utf16中,你必须使用Windows,所有的赌注都关闭;在该平台上,除了ASCII以外的任何东西都很少支持。您也可以放弃并使用WinAPI(您可以使用标准C ++ 11获取某些Unicode内容,甚至使用魔术字_setmode(_fileno(stdout), _O_U16TEXT);执行此C输出,已经讨论了足够多次)

答案 2 :(得分:0)

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

对于3,语言标准没有为字符串或wchar_t的任何特定大小指定任何特定编码。您需要查阅实现的文档,而不是正确的语言(尽管很少编写依赖于实现的代码)。