请稍等 ...
×

采纳答案成功!

向帮助你的同学说点啥吧!感谢那些助人为乐的人

MinGW 沒辦法用 setlocale 設定字符集 (出現亂碼) ??

老師在視頻中示範了 MSVC 的寬窄字符亂碼的處理:

(1) 源文件用utf-8來儲存
(2) 在編譯器選項中加入 "/utf-8"
(3) setlocale(LC_ALL, "zh_CN.utf-8")

的確能夠輸出正確的中文字符。如圖:
图片描述

可是我將環境換成 MinGW 後,並在編譯器選項中加入:

(1) -finput-charset=utf-8
(2) -fexec-charset=utf-8
(3) -fwide-exec-charset=utf-16le

結果卻出現亂碼?? 而且我發現 setlocale 回傳的是 NULL,代表裡面的參數設錯了??? 如圖:
图片描述

正在回答

4回答

bennyhuo 2021-01-06 21:21:49

mingw 确实不支持 setlocale ,不用跟他较劲了

1 回复 有任何疑惑可以回复我~
  • 提问者 Haowei Hsu #1
    總之,若要寫在Windows上運行的程序,最好還是用MSVC的標準來寫,對吧?
    回复 有任何疑惑可以回复我~ 2021-01-09 18:43:22
  • bennyhuo 回复 提问者 Haowei Hsu #2
    对的,没错
    回复 有任何疑惑可以回复我~ 2021-01-09 19:29:47
  • 提问者 Haowei Hsu #3
    非常感谢!
    
    # 這裡給這個問題做個總結好了:
    1. MinGW的setlocale的第二個參數:
        (1) 不支持"zh_CN"、"en_US"這種地區寫法。
        (2) 解決亂碼主要是設定字碼頁".936"、".65001"、".950"。
        (3) 但不支持utf-8(".65001")的邊碼(即使Windows有utf-8的字碼頁)。
    2. 如果要寫在Windows上運行的程序,最好用MSVC來編譯。
    回复 有任何疑惑可以回复我~ 2021-01-09 22:55:51
提问者 Haowei Hsu 2021-01-09 16:54:28

老師,我發現:

MinGW的 setlocale 是可以設定第二個參數的。

只不過好像不支持 "zh_CN" 這種地區寫法。

如果寫"cht"、"chinese"...等,setlocale就不會回傳NULL了。

如果要指定終端執行運行時的編碼方式,就輸入".950"、".936"...等等

但是,我輸入了UTF-8的字碼頁".65001"後,卻依然回傳了NULL。

https://img1.sycdn.imooc.com//szimg/5ff96e6d094cd54018100752.jpg

https://img1.sycdn.imooc.com//szimg/5ff96e71090c95b518080755.jpg

後來我在一個英文頁面上看到有人說: 

MinGW的setlocale不支持utf-8的邊碼 (雖然Windows的utf-8字碼頁是存在的)

如果真的是這樣,那估計就真的沒辦法了。

https://img1.sycdn.imooc.com/szimg/5ff96f0e0966db3506910219.jpg

0 回复 有任何疑惑可以回复我~
  • 你说的这种写法其实是windows api的原生写法,msvc下也是支持的,chs是简体中文,cht是正体中文。不过mingw 的utf8的设置,我确实也没有找到合适的解法,遇到一些场合,就只好用一些特别的api来显式指定编码了,例如在16章源码当中fileutils当中的SmartFOpen 当中使用win32 api 做mbs 到 wcs的转换,来规避这个问题,同学可以参考下。
    回复 有任何疑惑可以回复我~ 2021-01-09 19:40:43
  • 研究得很细致,给你按赞
    回复 有任何疑惑可以回复我~ 2021-01-09 19:41:34
bennyhuo 2021-01-07 08:16:55

用 mac 做了下实验,比较符合预期:https://img1.sycdn.imooc.com//szimg/5ff65243095ad47011481360.jpg

https://img1.sycdn.imooc.com//szimg/5ff6524f0951f81804920276.jpg

MinGW 默认的 locale 应该跟系统自己的设置有关系,但目前没有办法直接修改,因此表现出来的比较奇怪。这部分暂时先了解即可。如果遇到需要解决的场景,可以使用 Windows 的 api 做转换,例如:https://docs.microsoft.com/en-us/windows/win32/api/stringapiset/nf-stringapiset-multibytetowidechar

转换时可以指定编码类型,避免与 locale 直接产生依赖:MultiByteToWideChar(CP_UTF8, 0, e.what(), (int)strlen(e.what()), &wideWhat[0], (int)wideWhat.size());

这个函数我们在 16章处理下载文件名的cjk字符时也有用到。

0 回复 有任何疑惑可以回复我~
提问者 Haowei Hsu 2021-01-06 21:33:07

所以 mingw 無法打印寬字符的中文嗎?

0 回复 有任何疑惑可以回复我~
  • 打印宽字符没什么问题,只是在于窄字符转换的过程中,只能用utf8编码。如果你的源码文件是gbk,那窄字符字面量就会解码错误,因此使用mingw时,源码使用utf8编码,或者不要写cjk字符。
    回复 有任何疑惑可以回复我~ 2021-01-06 22:04:38
  • 提问者 Haowei Hsu 回复 bennyhuo #2
    可是,我的源碼文件是用 utf-8 儲存的,轉換的過程中也都用 utf-8。可是從 MinGW 的輸出結果來看: 
    (1) 寬字符中的 "中文(cjk字符)" 根本沒打出來???
    (2) 多字節字符中的 "中文(cjk字符)" 則是亂碼???
    回复 有任何疑惑可以回复我~ 2021-01-06 23:40:42
  • bennyhuo 回复 提问者 Haowei Hsu #3
    MinGW 在这块确实支持的不是很完善,setlocale 不管设置什么都会失败。
    控制台打印的话印象中只要是 utf8 都是可以打印的,不过从同学的运行结果来看,宽字符什么也没有打印出来,可能是控制台支持的问题,你可以试试写入到文件当中,看是否能够正常写入;最后一行的 printf 打印中文字符乱码似乎并不应该发生。要不同学直接在 powershell 或者 cmd 当中运行一下这个程序试试看结果是不是跟 CLion 有关系?我现在在外面休假一周,只带了个 Mac ,暂时没办法跟你一起调试,预计 1.12 就可以回去拿 Windows 跟你一起再试试看了哈。
    回复 有任何疑惑可以回复我~ 2021-01-07 07:50:03
问题已解决,确定采纳
还有疑问,暂不采纳
意见反馈 帮助中心 APP下载
官方微信