中文字幕日韩精品一区二区免费_精品一区二区三区国产精品无卡在_国精品无码专区一区二区三区_国产αv三级中文在线

QString亂談(2)&QT5中文亂碼問題

QString亂談(2)

  • 長期以來,很多人都清楚,一旦C++源碼中直接使用了中文,這樣的源碼想要跨平臺(tái)(I18N)會(huì)非常困難。

    創(chuàng)新互聯(lián)從2013年成立,先為尖草坪等服務(wù)建站,尖草坪等地企業(yè),進(jìn)行企業(yè)商務(wù)咨詢服務(wù)。為尖草坪企業(yè)網(wǎng)站制作PC+手機(jī)+微官網(wǎng)三網(wǎng)同步一站式服務(wù)解決您的所有建站問題。

隨著:

  • Windows下:MSVC2010成為主流

  • Linux下:GCC升級(jí)到4.6

C++中的中文問題 才算有了一個(gè)比較優(yōu)雅的、跨平臺(tái)的Workaround。

(本文討論編譯器范圍:GCC4.6+, MSVC2010sp1+ 。本文屬于QString系列,但暫不涉及QString)

C++ 中文問題

要在C++中正確使用中文,必須要了解下面兩個(gè)概念:

源碼字符集(the source character set)

源碼文件是使用何種編碼保存的

執(zhí)行字符集(the execution character set)

可執(zhí)行程序內(nèi)保存的是何種編碼(程序執(zhí)行時(shí)內(nèi)存中字符串編碼)

C++98的問題: 既沒有規(guī)定源碼字符集,也沒有規(guī)定執(zhí)行字符集

這個(gè)... 如何理解?不妨看個(gè)例子

例子

這個(gè)要求高么?

  • 一個(gè)簡單的C++程序,只是希望它能在簡體中文Windows、正體中文Windows、英文版Windows、Linux、MAC OS...下的結(jié)果一致。

//main.cppint main(){    char mystr[] = "老老實(shí)實(shí)的學(xué)問,來不得半點(diǎn)馬虎";    return sizeof mystr;}

可以試著反問自己兩個(gè)問題

  • 這個(gè)源碼文件是何種編碼保存的?(有確定答案么?)

  • mystr中是什么內(nèi)容?(有確定答案么?)

對(duì)C++來說,這兩個(gè)都不確定。

  • 固定平臺(tái)的話,還能忍忍

  • 要跨平臺(tái)的話,這種東西...

GCC

在GCC下,這兩個(gè)都可以使用你自己喜好的編碼(如果不指定,默認(rèn)都是UTF8)

-finput-charset=charset-fexec-charset=charset

除了前兩個(gè)選項(xiàng)外,還有一個(gè):

-fwide-exec-charset=charset

wide? 不妨先猜一下它是干嘛的

MSVC

MSVC沒有類似前面的選項(xiàng)。

源碼字符集如何解決?

有BOM么,有則按BOM解釋,無則使用本地Locale字符集(隨系統(tǒng)設(shè)置而變)

執(zhí)行字符集如何解決?

使用本地Locale字符集(隨系統(tǒng)設(shè)置而變)

挺霸道哈(當(dāng)然,源碼中可以使用#pragma setlocale("..."),但功能很有限,比如Windows沒有utf8的locale,所以...)。

另外,和GCC對(duì)應(yīng)的wide-exec-charset呢?

寬執(zhí)行字符集如何解決?

不妨先考慮一下

怎么辦?

這才兩個(gè)編譯器,看起來就這么復(fù)雜了。而C++編譯器的數(shù)目遠(yuǎn)大于2.

要想跨平臺(tái),必須確保這兩個(gè)字符集都是“確定”的,而能勝任該任務(wù)的字符集,似乎理想的也只能是...

UTF-8方案

  • 如果我們將源碼保存成utf8,執(zhí)行字符集也選為utf8,那么天下將太平了。使用非ASCII字符的源碼文件也就可以在不同國家的用戶間無障礙流通了 ;-).

源碼保存成UTF-8沒有什么困難,但是,執(zhí)行字符集需要是UTF-8。沒那么簡單

對(duì)GCC來說,這個(gè)問題很簡單(默認(rèn)的編碼選項(xiàng)足夠了):

  • 只要源碼文件保存成utf8即可(帶或不帶BOM均可)

  • 早期的gcc不接收帶BOM的utf8源碼文件,現(xiàn)在,至少在GCC4.6中,這一限制不再存在。

對(duì)MSVC來說,這個(gè)問題異常復(fù)雜:

  • 對(duì)MSVC2003來說,只要源碼保存成不帶BOM的utf8即可

  • 對(duì)MSVC2005、(沒在SP1基礎(chǔ)上裝熱補(bǔ)丁的)MSVC2008來說。完全沒辦法

  • 直到MSVC2010sp1,才算提供了一個(gè)解決方案。源碼保存成帶BOM的utf8,utf16,...,然后添加

#pragma execution_character_set("utf-8")

要想跨GCC4.6+和MSVC2010sp1+,我們需要取它們的交集:也就是

  • 源碼保存成帶BOM的utf8

  • 為MSVC添加#pragma

//main.cpp#if _MSC_VER >= 1600#pragma execution_character_set("utf-8")#endifint main(){    char mystr[] = "老老實(shí)實(shí)的學(xué)問,來不得半點(diǎn)馬虎";    return sizeof mystr;}

C++11

等到MSVC支持C++11的String Literals之時(shí),我們就沒必要用那個(gè)蹩腳的pragma了,直接

    char mystr[] = u8"老老實(shí)實(shí)的學(xué)問,來不得半點(diǎn)馬虎";

即可(盡管現(xiàn)在在GCC下沒問題,但要跨平臺(tái),估計(jì)要等到Visual C++ 12了)。

有個(gè)問題?

C++98中不是有個(gè)wchar_t么,它不是用來表示unicode字符的么?

Unicode 4.0標(biāo)準(zhǔn)的5.2節(jié)是如何說的:

The width of wchar_t is compiler-specific and can be as small as 8 bits. Consequently, programs that need to be portable across any C or C++ compilershould not use wchar_t for storing Unicode text. The wchar_t type is intended forstoring compiler-defined wide characters, which may be Unicode characters in some compilers.

在回頭看看GCC的選項(xiàng)

-fwide-exec-charset=charset

盡管GCC為其提供的默認(rèn)編碼是UTF16或UTF32(取決于wchar_t的寬度),但該編碼是可以隨意設(shè)置的。

盡管這個(gè)東西不保證跨平臺(tái),也很不好玩, 但是,由于在windows下面wchar_t用來表示utf16字符,而且直接對(duì)應(yīng)系統(tǒng)API接口,所以在類型char16_t普及之前,還是很重要的。

C++11執(zhí)行字符集

前面提到的u8就是C++11為“執(zhí)行字符集”所做的努力之一。

新明確規(guī)定了utf8、utf16和utf32這3種執(zhí)行字符集。

char*

u8"中文"

char16_t*

u"中文"

char32_t*

U"中文"

可是C++11并沒有規(guī)定源碼字符集

const char* mystr=u8"中文";

C++標(biāo)準(zhǔn)對(duì)編譯器說,我不管這個(gè)文件的具體編碼是什么,但你必須給我生成對(duì)應(yīng)utf8編碼的字節(jié)流。

編譯器似乎有點(diǎn)傻了吧?不知道源文件的編碼,我如何轉(zhuǎn)換

于是:

MSVC說:源碼文件必須有BOM,不然我就認(rèn)為你是本地locale的編碼

GCC說:我認(rèn)為你就是utf8編碼,除非通過命令行通知我其他編碼

在C++11標(biāo)準(zhǔn)下,對(duì)源碼編碼 簡單的處理辦法還是,使用帶BOM的UTF8保存。

第二篇

今天,隨著Change QString's default codec to be UTF-8 進(jìn)入Qt5的master分支,我們總算可以重新審視一下Qt的中文支持問題。

20120516更新:建議閱讀QtCore模塊維護(hù)者Thiago Macieira 的文章 Source code must be UTF-8 and QString wants it 

沒有了setCodecXXX的Qt5

  • Qt5假定的執(zhí)行字符集是UTF8,不再允許用戶擅自改動(dòng)。這樣一來,Qt4中setCodecXXX的各種副作用不再存在,而且中文問題更為簡單。

QString s1 = "漢語";QString s2("漢語");QString s3 = tr("中文")QString s4 = QStringLiteral("中文");//只要字符串不需要翻譯,請(qǐng)關(guān)注這個(gè)QString s5 = QString::fromWCharArray(L"中文");QString s6 = u8"中文";//C++11QString s7 = tr(u8"中文")...

所有這些在Qt5默認(rèn)都會(huì)正常工作,唯一要求就是:確保你的C++的執(zhí)行字符集(the execution character set)是UTF-8

各種寫法PK?

簡單不一定好

最簡單直接的用法,當(dāng)屬:

QString s1 = "漢語";QString s2("漢語");QString s6 = u8"中文";//C++11...

這有什么問題呢?

  • 定義宏QT_NO_CAST_FROM_ASCII之后,上述代碼無法將通過編譯(對(duì)了,這個(gè)宏似乎應(yīng)該改個(gè)名字才對(duì),叫QT_NO_CAST_FROM_CSTRING會(huì)名副其實(shí)一些)

被誤用最多的

在Qt4中,QObject::tr()是被濫用(誤用)的函數(shù)之一:

QString s3 = tr("中文")...

原因:

  • 在Qt4,不少用戶被鋪天蓋地的setCodecForTr()所影響,進(jìn)而靠它來解決中文問題。

它的用途是用來進(jìn)行翻譯(I18N和L10N)的,如果你沒有這方面的需求,真的沒必要用它。(在Qt4中,我只注意到有2個(gè)大陸網(wǎng)友和1個(gè)日本網(wǎng)友有需求并真正進(jìn)行過這方面的嘗試,那么其他應(yīng)該算誤用吧?)

讓人困惑的wchar_t

剛開始接觸Qt和QString時(shí),曾多次想過,為什么不用wchar_t,為什么,...

QString s5 = QString::fromWCharArray(L"中文");

這個(gè)東西在Windows下真的很有用:首先它是Windows系統(tǒng)API所用字符串,其次它和QString內(nèi)部表示相同。但是由于MSVC處于種種考慮,鼓勵(lì)大家使用TEXT/_T,反倒使大家對(duì)它比較陌生。

但是從C++標(biāo)準(zhǔn)來說,wchar_t畢竟不是char16_t,所以跨平臺(tái)性不好。在linux下,這行代碼需要utf32到utf16的轉(zhuǎn)換。

QStringLiteral

這是一個(gè)宏,一個(gè)蠻復(fù)雜的宏:

QString s4 = QStringLiteral("中文");

之前?

在介紹這個(gè)宏之前,我們先看看下面寫法有什么劣勢(shì):

QString s1 = "漢語";QString s2("漢語");QString s3 = tr("中文")QString s6 = u8"中文";//C++11...

首先,2個(gè)漢字的字符串以UTF-8編碼的形式被編譯器放到了常量區(qū)。(至少占7個(gè)字節(jié)吧?)

然后,程序運(yùn)行時(shí),構(gòu)造QString實(shí)例,需要在堆上申請(qǐng)空間,存放utf16格式的相應(yīng)字符串。

有沒有存在浪費(fèi)?

方案

QString 內(nèi)部是UTF16,如果C++編譯器在編譯期直接提供了UTF16的字符串,那么我們?cè)赒String內(nèi)部直接保存也就夠了。這樣

  • 省掉存在兩份不同的拷貝(即相應(yīng)的轉(zhuǎn)換,malloc的成本)

  • 對(duì)漢字來說,UTF16本身就是UTF8省空間

現(xiàn)實(shí)

目前,我們還沒有可靠的方式在C++使用UTF16的執(zhí)行字符集(the execution character set)。

  • 盡管 L"..."(wchar_t*) 在Windows下是UTF16,但是不具備跨平臺(tái)性。

  • C++11可以保證這一點(diǎn),u"..."(char16_t),但主流編譯器尚未提供完美支持。

這兩點(diǎn),導(dǎo)致了QStringLiteral的復(fù)雜性

實(shí)現(xiàn)

源碼見 qtbase/src/corelib/tools/qstring.h

(代碼中使用宏、模板、lambda表達(dá)式,還是相當(dāng)復(fù)雜的,此處只摘片段)

  • 如果編譯器支持char16_t,則直接使用

#define QT_UNICODE_LITERAL_II(str) u"" strtypedef char16_t qunicodechar;...

  • 否則。如果在Windows平臺(tái)下,或者在其他的wchar_t寬度為2的環(huán)境下,使用wchar_t

#if defined(Q_CC_MSVC)#    define QT_UNICODE_LITERAL_II(str) L##str#else#    define QT_UNICODE_LITERAL_II(str) L"" str#endiftypedef wchar_t qunicodechar;...

  • 否則。編譯器不支持,Qt作為一個(gè)庫,肯定也沒有辦法

# define QStringLiteral(str) QString::fromUtf8(str, sizeof(str) - 1)

本文標(biāo)題:QString亂談(2)&QT5中文亂碼問題
文章來源:http://www.rwnh.cn/article24/gcgece.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供關(guān)鍵詞優(yōu)化、做網(wǎng)站、電子商務(wù)網(wǎng)站收錄、建站公司

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

小程序開發(fā)
兴化市| 阳春市| 开江县| 永靖县| 大荔县| 筠连县| 修武县| 广丰县| 综艺| 宾阳县| 方正县| 沙湾县| 从江县| 孙吴县| 武平县| 时尚| 武邑县| 浠水县| 如东县| 肇东市| 西盟| 彭阳县| 柳河县| 韩城市| 马尔康县| 西华县| 永春县| 广宁县| 伊宁市| 万年县| 新竹市| 潼南县| 新乐市| 商都县| 河津市| 清水县| 大足县| 新源县| 新乐市| 临澧县| 平阳县|