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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/26816547/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 20:40:14  来源:igfitidea点击:

What's the difference between printf("%s"), printf("%ls"), wprintf("%s"), and wprintf("%ls")?

c++unicodeprintfwidechar

提问by Display Name

Consider this sample program:

考虑这个示例程序:

#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;
}

The output of this is:

这个的输出是:

1 narrow 
2 wide 

I'm wondering:

我很好奇:

  1. why 3 & 4 didn't print
  2. what the differences are between 1&3, and 2&4.
  3. does it make any difference if narrowstr is in utf8 and widestr is in utf16?
  1. 为什么 3 & 4 没有打印
  2. 1&3 和 2&4 之间有什么区别。
  3. 如果narrowstr 在utf8 中而widestr 在utf16 中,这有什么区别吗?

回答by Ajay

You need to do:

你需要做:

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

Why? Because for printf, %ssays narrow-char-string. For wprintf, %lssays wide.

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

But, for wprintf, %simplies wide, %lswould mean wide itself. %hswould mean narrow (for both). For printf, %s, in this manner would simply mean %hs

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

On VC++/Windows, %S(capital S), would reverse the effect. Therfore for printf("%S")it would mean wide, and wprintf("%S")would mean narrow. This is useful for _tprintf.

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

回答by Cubbi

Note that you're using C streams. C streams have a very special quality called "orientation". A stream is either unoriented, wide, or narrow. Orientation is decided by the first output made to any particular stream (see http://en.cppreference.com/w/cpp/io/cfor a summary of C I/O streams)

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

In your case, stdoutstarts out unoriented, and by executing the first printf, you're setting it narrow. Once narrow, it's stuck narrow, and wprintffails (check its return code!). The only way to change a C stream is to freopenit, which doesn't quite work with stdout. That's why 3 and 4 didn't print.

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

The differences between 1 and 3 is that 1 is a narrow output function which is using narrow string conversion specifier %s: it reads bytes from the char array and sends bytes into a byte stream. 3 is a wide output function with a narrow string conversion specifier %s: it first reads bytes from the char array and mbtowcs them into wchar_ts, then sends wchar_ts into a wide stream, which then wctombs them into bytes or multibyte sequences that are then pushed into the standard out with a write

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

Finally, if widestr is in utf16, you must be using Windows, and all bets are off; there is very little support for anything beyond ASCII on that platform. You may as well give in and use WinAPI (you can get by with standard C++11 for some Unicode things, and even do this C output, with magic words _setmode(_fileno(stdout), _O_U16TEXT);, that's been discussed enough times)

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

回答by n. 'pronouns' m.

The answers to 1 and 2 are in the question are in the documentation. Any good set of documentation will do. They say cppreferenceis very good.

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

As for 3, the language standard does not specify any particular encoding for strings, or any particular size of wchar_t. You need to consult the documentation for your implementation, rather than for the language proper (though writing implementation-dependent code is rarely advisable).

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