A simple problem: I'm writing a chatroom program in C++ (but it's primarily C-style) for a class, and I'm trying to print, “#help — display a list of commands...” to the output window. While I could use two hyphens (--) to achieve roughly the same effect, I'd rather use an em-dash (—). printf(), however, doesn't seem to support printing em-dashes. Instead, the console just prints out the character, ù, in its place, despite the fact that entering em-dashes directly into the prompt works fine.
How do I get this simple Unicode character to show up?
Looking at Windows alt key codes, I find it interesting how alt+0151 is "—" and alt+151 is "ù". Is this related to my problem, or a simple coincidence?
the windows is unicode (UTF-16) system. console unicode as well. if you want print unicode text - you need (and this is most effective) use
WriteConsoleWin this case in your binary file will be wide character
—(2 bytes0x2014) and console print it as is.if ansi (multi-byte) function is called for output console - like
WriteConsoleAorWriteFile- console first translate multi-byte string to unicode viaMultiByteToWideCharand in place CodePage will be used value returned byGetConsoleOutputCP. and here (translation) can be problem if you use characters > 0x80first of all compiler can give you warning: The file contains a character that cannot be represented in the current code page (number). Save the file in Unicode format to prevent data loss. (C4819). but even after you save source file in Unicode format, can be next:
because
L"ù"saved as wide char string (as is) in binary file - here all ok and no any problems and warning. but"ù"is saved as char string (single byte string). compiler need convert wide string "ù" from source file to multi-byte string in binary (.obj file, from which linker create pe than). and compiler use for thisWideCharToMultiBytewith CP_ACP (The current system default Windows ANSI code page.)so what happens if you say call
printf("ù");?WideCharToMultiByte(CP_ACP, )and this will be at compile time. resulting multi-byte string will be saved in binary fileMultiByteToWideChar(GetConsoleOutputCP(), ..)and print this stringso you got 2 conversions:
unicode -> CP_ACP -> multi-byte -> GetConsoleOutputCP() -> unicodeby default
GetConsoleOutputCP() == CP_OEMCP != CP_ACPeven if you run program on computer where you compile it. (on another computer with anotherCP_OEMCPespecially)problem in incompatible conversions - different code pages used. but even if you change console code page to your
CP_ACP- convertion anyway can wrong translate some characters.and about CRT api
wprintf- here situation is next:the
wprintffirst convert given string from unicode to multi-byte by using it internal current locale (and note that crt locale independent and different from console locale). and then callWriteFilewith multi-byte string. console convert back this multi-bytes string to unicodeunicode -> current_crt_locale -> multi-byte -> GetConsoleOutputCP() -> unicodeso for use
wprintfwe need first set current crt locale toGetConsoleOutputCP()but anyway here i view (on my comp)
-on screen instead—. so will be-—if callPrintString(L"—");(which usedWriteConsoleW) just after this.so only reliable way print any unicode characters (supported by windows) - use WriteConsoleW api.