【问题标题】:What's the difference between printf("%s"), printf("%ls"), wprintf("%s"), and wprintf("%ls")?printf("%s")、printf("%ls")、wprintf("%s") 和 wprintf("%ls") 有什么区别?
【发布时间】:2015-01-05 03:33:18
【问题描述】:

考虑这个示例程序:

#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 和 widestr 是 UTF16 有什么区别吗?

【问题讨论】:

  • "widestr is in utf16" 表示您使用的是 Windows(更多 Unicode 友好的系统使用 UTF-32 作为宽字符串的默认值)。如果您想在使用标准 C++ 或 C 的 WIndows 系统上执行 ASCII 以外的任何操作,则有许多神秘的箍要跳。您不妨放弃并使用 WinAPI。
  • 不要屈服于微软的愚蠢行为。省去自己的痛苦,编写自己的字符串库。看在上帝的份上,不要使用 windows 宏转换和其他疯狂的东西,相信我,这太可怕了,而且在混乱中会出现各种错误。
  • #4 可能没有打印,因为您的程序在 #3 上崩溃了。 %ls 是最便携的打印wchar_t 字符串的方法,可以同时使用printfwprintf。您应该避免使用 %S,因为它的 Visual C++ 解释与 C99/C++11 标准完全相反。

标签: c++ unicode printf widechar


【解决方案1】:

你需要做的:

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很有用。

【讨论】:

  • 等一下!为什么它甚至不打印数字?你检查 wprintf 工作了吗?
【解决方案2】:

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

在您的情况下,stdout 开始时是无方向的,通过执行第一个 printf,您将其设置为窄。一旦变窄,它就会变窄,wprintf 会失败(检查它的返回码!)。更改 C 流的唯一方法是 freopen 它,它不适用于标准输出。这就是 3 和 4 没有打印出来的原因。

1 和 3 的区别在于 1 是一个窄输出函数,它使用窄字符串转换说明符 %s:它从 char 数组中读取字节并将字节发送到字节流中。 3 是具有窄字符串转换说明符 %s 的宽输出函数:它首先从 char 数组中读取字节并将 mbtowcs 读取到 wchar_ts 中,然后将 wchar_ts 发送到宽流中,然后 @987654329将它们@s 成字节或多字节序列,然后用write 推入标准输出

最后,如果widestr是utf16,那你一定是在用Windows,而且所有的赌注都关闭了;在该平台上几乎不支持 ASCII 以外的任何内容。你也可以放弃并使用 WinAPI(你可以使用标准 C++11 来处理一些 Unicode 的事情,甚至可以用魔法词 _setmode(_fileno(stdout), _O_U16TEXT); 来做这个 C 输出,这已经讨论了足够多的时间了)

【讨论】:

    【解决方案3】:

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

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

    【讨论】:

      猜你喜欢
      • 2013-07-16
      • 2016-10-01
      • 2017-01-17
      • 2017-07-26
      • 2012-01-30
      • 2019-12-12
      • 2019-07-01
      • 1970-01-01
      相关资源
      最近更新 更多