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:
narrowstr
is in UTF8 and widestr
is in UTF16?%ls is the most portable way to print a wchar_t string and works from both printf and wprintf . You should avoid all use of %S because the Visual C++ interpretation of it is the exact opposite of the C99/C++11 standard.
The wprintf() function is used to print the wide character to the standard output. The wide string format may contain the format specifiers which is starting with % sign, these are replaced by the values of variables which are passed to the wprintf(). int wprintf (const wchar_t* format, ...);
In C programming language, %d and %i are format specifiers as where %d specifies the type of variable as decimal and %i specifies the type as integer. In usage terms, there is no difference in printf() function output while printing a number using %d or %i but using scanf the difference occurs.
You need to do:
wprintf(L"3 %hs \n", narrowstr.c_str());
wprintf(L"4 %s \n", widestr.c_str());
Why? Because for printf
, %s says narrow-char-string. For wprintf
, %ls says wide.
But, for wprintf
, %s implies wide, %ls would mean wide itself. %hs would mean narrow (for both). For printf
, %s, in this manner would simply mean %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
.
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/c for a summary of C I/O streams)
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.
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
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)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With