22

考虑这个示例程序:

#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 和 4?
  2. 1 & 3 和 2 & 4 有什么区别?
  3. 如果narrowstr是 UTF8 和widestrUTF16 有什么区别吗?
4

3 回答 3

16

你需要做:

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

为什么?因为对于printf%s表示窄字符字符串。对于wprintf, %ls表示宽。

但是,对于wprintf%s意味着宽,%ls将意味着宽本身。%hs意味着窄(对于两者)。对于printf, %s,以这种方式仅表示%hs

在 VC++/Windows 上,%S(大写的 S)会反转效果。因此,printf("%S")它意味着宽,wprintf("%S")也意味着窄。这对_tprintf.

于 2014-11-08T12:50:58.213 回答
7

请注意,您使用的是 C 流。C 流有一个非常特殊的特性,称为“方向”。流要么是无方向的,要么是宽的,要么是窄的。方向由对任何特定流的第一个输出决定(有关 CI/O 流的摘要,请参见http://en.cppreference.com/w/cpp/io/c )

在您的情况下,stdout开始时是无方向的,通过执行 first printf,您将其设置为窄。一旦变窄,它就会变窄并wprintf失败(检查它的返回码!)。更改 C 流的唯一方法是使用freopen它,它不适用于标准输出。这就是为什么 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);这已经讨论了足够多的时间了)

于 2014-11-13T03:26:49.123 回答
0

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

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

于 2014-11-08T11:37:52.283 回答