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
What's the difference between printf("%s"), printf("%ls"), wprintf("%s"), and wprintf("%ls")?
提问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:
我很好奇:
- why 3 & 4 didn't print
- what the differences are between 1&3, and 2&4.
- does it make any difference if narrowstr is in utf8 and widestr is in utf16?
- 为什么 3 & 4 没有打印
- 1&3 和 2&4 之间有什么区别。
- 如果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, stdout
starts out unoriented, and by executing the first printf
, you're setting it narrow. Once narrow, it's stuck narrow, and wprintf
fails (check its return code!). The only way to change a C stream is to freopen
it, 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 mbtowc
s them into wchar_t
s, then sends wchar_t
s into a wide stream, which then wctomb
s 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_t
s放入s,然后将wchar_t
s发送到宽流中,然后将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
. 您需要查阅实现的文档,而不是正确的语言(尽管编写依赖于实现的代码很少是可取的)。