王忠家 在Qt5中解決VC下的亂碼問題

2021-07-22 08:38:23 字數 2739 閱讀 6823



本文假設你所使用的開發環境為qt5.6+vs2015,為了能夠復現亂碼的問題我們先隨便建立乙個qt的空工程,新增乙個main.cpp檔案(utf8格式),使用qdebug(),和std::count輸出一句漢語「我是中國人」:

#

include

#include

void

main

()

結果如下所示:

std count:

我是中國人

qdebug:

?????й???

使用c++的標準輸出(std::cout)輸出了正確的結果,而使用qt的qdebug()則沒有得到正確的結果,彷彿qt的「相容性」不如c++似的,首先我們要搞懂字串的編譯過程:

(1)程式設計師在文字檔案中書寫字串,事實上原始檔中所有的東西都是字串,需要「傳輸到」到程式中進行處理的是使用雙引號括起來的「我是中國人」。此時「我是中國人」在文字檔案中按照utf-8格式儲存。

(3)編譯器將字串的內容轉換為目標檔案中的全域性變數,「我是中國人」這五個字在原始碼中形象的被稱之為「儲存在全域性資料區的型別為const char *的字串」,直到此時,這五個字才轉變為「const char *」儲存在全域性資料區。這個時段,編譯器(說的就是msvc)想當然地把gbk版本的「我是中國人」依舊儲存為gbk格式。

(4)在執行期間,程式對字串的格式完全處於無知的狀態,顯然 const char *是沒有表露任何格式資訊的。但是為什麼std::cout卻能夠輸出完全正確的結果呢?神探狄仁傑曾經說過,這世界上根本沒有巧合,只有精心策劃的陰謀:微軟當然不會自己編寫程式把自己的編譯器搞出來的const char *輸出亂碼!呵呵!在qt4的時代,使用者可以在需要格式話載入字串的場合之前呼叫以下**來顯式的指定const char *的編碼:

qtextcodec::settextcodcfortr(...)
想想也知道這又多麻煩,萬一有幾處**沒有設定,豈不麻煩。在qt5的時期,qt官方果斷的刪除了這一系列的函式,所有的轉換const char *的動作均按照utf-8處理。

根據以上的論述,要保證輸出不亂碼,總結需要保證四條:

(1)源檔案格式清楚明白(作者自己必須心裡有數)(2)編譯器按照正確格式讀取;(3)編譯器生成全域性const char *的格式要搞明白;(4)全域性const char *的格式和qt的字串載入所需格式對上。

解決(1),(2)的內容,需要設定編輯器檔案編碼,在qtcreator的設定如下圖所示,如果你的原始檔不是utf-8建議批量轉成utf-8:

由於qt已經明確要求全域性資料去的字串必須是utf-8格式了,那麼就必須通過編譯器來設定,在使用vc的情況下,加入這些**就成生效,前提是用的vs是2012以上的版本(相信大家都已經用新的了):

#

if_msc_ver >= 1600

#pragma

execution_character_set(

"utf-8")#

endif

即便不是天才也能看出來這個做法比設定qtextcodec還要麻煩,難道每個檔案都要添家三句**嗎?好在qt的工程管理中已經支援將乙個標頭檔案預編譯,可以通過這種機制讓工程中所有的原始檔全部在編譯時段自動的包含同乙個標頭檔案。

新建乙個檔案,設名稱為utf8.h,將pragma命令語句新增裡面,然後在qt的工程檔案中新增:

#設定編碼統一使用utf8

precompiled_header += $$gtdir/include

/utf8.h

將整個**工程重新qmake,重新編譯,亂碼一去不復返,且對**無汙染。

講了上面那麼多理論,我們用剛才的小工程測試一下,main函式變更為:

#

include

#include#if

_msc_ver >= 1600

#pragma

execution_character_set(

"utf-8")#

endif

void

main

()

輸出結果為下圖所示:

std count:

鎴戞槸涓浗浜

qdebug:

我是中國人

qdebug好了,std::cout確亂了,沒辦法,誰叫他們用的格式不一樣呢,當然在這裡,qt是大局。相信你不會用std::cout再輸出東西的。

如果非要使用stdout輸東西,一定記得轉換為本地格式,不要計較本地格式是啥,qstring的tolocal8bit會幫你做判斷的,因此,將**改為:

#

include

#include#if

_msc_ver >= 1600

#pragma

execution_character_set(

"utf-8")#

endif

void

main

()

我們得到了完全正確的輸出:

std count:

我是中國人

qdebug:

我是中國人

Qt5中setCursor編譯報錯的解決

中因相容性存在setcursor錯誤,錯誤 如下 myitem myitem 產生了錯誤 h qt graphicsview01 graphicsview01 myitem.cpp 8 error no matching function for call to myitem setcursor q...

7 8 VC2010下Qt5的中文亂碼問題

1 vc2010下qt5的中文亂碼問題 qtcreator 中的.pro檔案新增 if msc ver 1600 pragma execution character set utf 8 endif codecfortr utf 8 or gbk defaultcodec utf 8 codec u...

C 11 在 Qt 5 中的應用

c 11 現在已經是 c 標準,也就沒有理由不在新的應用中使用。qt 4.8 是第乙個支援 c 11 特性的 qt 版本,不過這裡,我們首先介紹的是,qt 5 中如何結合使用 c 11。至於 qt 4.8,我們會在後續文章中進行闡述。顯而易見的是,比起 qt 4.8,qt 5 利用了更多的 c 11...