iT邦幫忙

1

[已解決]請教 Windows 平台上 SetConsoleOutputCP() 和 __setmode() 的差異?

  • 分享至 

  • xImage

[已解決]在微軟 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',那又是另外一個問題。

尼克 iT邦大師 1 級 ‧ 2025-01-21 11:52:40 檢舉
你應該是要貼在技術文章那裡
meebox iT邦新手 3 級 ‧ 2025-01-21 15:29:39 檢舉
這邊不是『問答』嗎?
meebox iT邦新手 3 級 ‧ 2025-01-21 15:30:05 檢舉
我改一下貼文
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 個回答

0
zivzhong
iT邦研究生 2 級 ‧ 2025-01-22 00:29:19

要不試試

SetConsoleOutputCP(65001);
meebox iT邦新手 3 級 ‧ 2025-01-23 09:19:43 檢舉

這其實跟 SetConsoleOutputCP(CP_UTF8); 是一樣的。

我要發表回答

立即登入回答