[已解決]在微軟 UCRT 的實作中,_setmode(_fileno(stdout), _O_U8TEXT);
對於文字終端機的串流會開啟 Unicode 模式,直接使用 WriteConsoleW
送出,因此只要 Unicdoe 字元都可以正常顯示。但 SetConsoleOutputCP(CP_UTF8);
是透過檔案輸出給終端機後,才由終端機依據指定的 codepage 解譯文字,在從串流輸出到終端機的過程中,就會經過幾道轉碼程序,導致 '🍌' 這種在 Unicode 輔助平面的字元,在轉碼過程中被丟棄,無法顯示出來。以上處理都是針對輸出到文字模式終端機的串流才會發生。
請教在 Windows 上使用
SetConsoleOutputCP(CP_UTF8);
與
_setmode(_fileno(stdout), _O_U8TEXT);
讓程式可以在終端機輸出 Unicode 字元的差異是什麼?我的測試中,例如:
#include <locale.h>
#include <stdio.h>
#include <wchar.h>
#include <windows.h>
#include <io.h>
#include <fcntl.h>
int main(void)
{
// _setmode(_fileno(stdout), _O_U8TEXT);
SetConsoleOutputCP(CP_UTF8);
setlocale(LC_ALL, "en_US.utf8");
wchar_t* const str_ch = L"\r🍌金黃色的曙光\n";
wchar_t* const str_ja = L"\r🍌金色の暁\n";
wprintf(str_ch);
wprintf(str_ja);
}
使用 SetConsoleOutputCP()
的方式 '🍌' 會消失:
金黃色的曙光
金色の暁
但若是使用 _setmode()
,則可以完整顯示:
🍌金黃色的曙光
🍌金色の暁
請請教為什麼會有這樣的差別?
至於為什麼要在寬字元字串開頭加 '\r',那又是另外一個問題。
要不試試
SetConsoleOutputCP(65001);