QT输出汉语乱码深刻深入分析

总结:

1. qt输出粤语乱码原因剖判

qt的编程情状默许是utf-8编码格式(至于编码见下文知识要点豆蔻梢头);

cout << "中文" << endl;

程序运营,程序并不认得ANSI,UTF-8以至任何别的编码.系统只精晓管理你给它的字符的**二进制表示.**

 

关于  "中""文" 的3种编码二进制内容:

 

ANSI(GBK): 0xd6d0  0xcec4

 

UTF-8: 0xe4b8ad 0xe69687

 

Unicode: 0x4e2d 0x6587

1卡塔尔国在简体中文Windows下的调节台显示情形是ANSI编码(代码页936, GBK卡塔尔(قطر‎,先明了那点.

第黄金年代差别,MinGW见到的是"0xe4b8ad"和"0xe69687"(gcc暗中认可UTF-8卡塔尔(英语:State of Qatar).注意,用MinGW编译的源文件中有中文宽字符必需保留为UTF-8编码.

2卡塔尔国测量试验代码:

#include <iostream>
using namespace std;

int main()
{
    char a[] = "中文";
    cout << a << endl;
    return 0;
}

3卡塔尔(英语:State of Qatar)经在qt5.第88中学测验乱码;

浅析:参见(下文知识要点生机勃勃,知识要点二)轻巧开掘UTF-8只是大器晚成种编码举行方案,并非实际编码;再参见(知识要点五),程序运转是能过最终编写翻译完结的二进制码输出

在vs2017中,用unicode编码方式,编写翻译运营输出平常;原因笔者想很好领悟了,当程序编写翻译后保存的是“汉语”unicode二进制编码,而决定台出口时CodePage (GBK 936)那一个CodePage就能根据映射表去各种对应GBK中的中文字,再开展输出;

而在qt5.8(MinGW卡塔尔中,输出则是乱码;因为qt5.8暗许的编码方式是UTF-8;当程序编写翻译后保存的是“中文”UTF-8二进制编码,而决定台出口时CodePage (GBK 936卡塔尔国那几个CodePage就能够基于映射表去各类对应GBK中的汉语字,好像哪里不对,好了,难点就出在那时了,CodePage是多个国家与unicode的映射表,并非与UTF-8的(知识要点二CodePage),在qt5.8(MinGW卡塔尔(قطر‎中,原程被编写翻译二进制文件,保存下来的“汉语”地址是,UTF-8编码,而映射表是在unicode中找内容,再进行输出,自然就是乱码;

网络消除方法1.修正注册表CodePage 65001  经测量检验依旧乱码

辩驳深入分析:CodePage(GBK 936卡塔尔国找不到映射,那么把调控台换到UTF-8;那么然先保存的,UTF-8中文,再通过UTF-8对应的汉字码,不就会出口汉字;理论好像可行,但在本人的win7 陆14位中国语言法学系统上,qt5.8,vs2017均未果;

或然原因:作者系统中cmd调节台并不支持UTF-8编码格局(有时机在win10中测验后再做补偿)

削株掘根办法2:通过(知识点生机勃勃,二, 五),计算,当要在支配台进行汉语输出时,编码方式应该保留为unicode,或ACSI(GBK卡塔尔(英语:State of Qatar);

4卡塔尔国关于宽字节出口乱码的难点;

输出宽字傅延年语(详见知识要点四):例

#include <iostream>
using namespace std;

int main()
{
    wcout << L"中文" << endl;
    return 0;
}

输出则要用wcout而不可能是cout;关于宽字符详见;文化要点二后续,**文化要点三**

在vs2017中,输出普通话,为空;

1、cout和wcout

 在C 下,cout能够一贯出口粤语,但对于wcout却极度。对于wcout,需求将其locale设为本地语言技能出口中文:

 wcout.imbue(locale(locale(),"",LC_CTYPE));

 也许有人用如下语句的,但那会转移wcout的有所locale设置,比方数字“1234”会输出为“1,234”。

 wcout.imbue(locale(""));

 在C语言下,locale设置为本地语言(C语言中独有全局locale)就能够健康输出了:

 setlocale(LC_CTYPE, "");

 在qt5.8(MinGW卡塔尔国碰到中,以上并不实用,近期还未有找到出口普通话的艺术,未完待续;

 

文化要点生机勃勃:编码**

ASCII: 前期的字符集,7位,1二十六个字符,包罗大小写a-z字母,0-9数字以至一些决定字符.

  扩展ASCII: 1个字节8位,只用7位不合理.于是第8位用于扩展ASCII字符集,那样就又多了1二十九个字符.于是用着后1三十个字符来扩张表示如拉丁字母,希腊(Ελλάδα卡塔尔国字母等特殊符号.但难点是欧洲那黄金时代票国家相当多互相都具备不平等的分歧平日字母,一同塞进后1贰二十一个分明非常不够,于是代码页现身了.

**  Code Page(代码页)**: 1个字节前126个字符大家集结和ASCII同样,而后1二十六个字符,根据不一样系统所谓代码页来分别各类语言不均等的假名和符号.

**  DBCS(双字节字符集)**: 对于澳国国家,后1二十七个字符仍然不只怕包涵大批量的象形文字,DBCS就是为此的一个缓慢解决方案.DBCS由二个或多少个字节表示叁个字符,那注脚DBCS并不一定是八个字节,对于如印度语印尼语字母,是向ASCII宽容的,如故由1个字节表示,而对于如中文则用2个字节表示.葡萄牙共和国语和国语能够统生龙活虎地拍卖,而区分是或不是为普通话编码的不二诀要是2个字节中的高字节的第三位为1,就必需检查后边紧跟着的不胜字节,2个字节一齐解释为1个字符.GB2312,GBK到GB18030都归属DBCS.此外,简体汉语Windows下的ANSI编码平日是指GBK(代码页936卡塔尔(英语:State of Qatar).

DBCS非常的大难点在于字符串的字符数无法经过字节数来支配,如"中文abc",字符数是5,而字节数是7.对此用 或--运算符来遍历字符串的技师来说,那大概正是恶梦!

  Unicode: 学名为"Universal Multiple-Octet Coded Character Set",简称"UCS".UCS能够看作是"Unicode Character Set"的缩写.

也是大器晚成种字符集/字符编码方法,它统风流罗曼蒂克用唯豆蔻梢头的字符集来含有那几个星球上比相当多语言的书写系统.UCS向ASCII宽容(即前1三十个字符是平等的卡塔尔国,但并不相配DBCS,因为任何字符在UCS中被重新编码(重新布置地点卡塔尔(قطر‎.

UCS有三种格式:UCS-2和UCS-4.前面四个用2个字节(拾叁人卡塔尔(英语:State of Qatar)编码,前面一个用4个字节(实际上只用叁14位卡塔尔(英语:State of Qatar)编码.USC-4前2个字节都为0的一些称得上BMP(基本多语言平面卡塔尔国,就是说BMP去掉前2个零字节便是UCS-2.近期的UCS-4规范中还不曾其余字符被分配在BMP之外.(说白了,USC-4就是为当拾伍人的USC-2都被分配完时候做再做扩张用的,以后还未用到卡塔尔(英语:State of Qatar)

  UTF-8,UTF-16,UTF-32: "Unicode transformation format"(UTF) ,即Unicode的传导格式.Unicode规定了怎么编码字符,而UTF规定怎么将二个Unicode字符单元映射到字节序来传输或保存.

UTF-16UTF-32独家表示以16人和叁九个人为三个Unicode单元进行编码,其实UTF-16对应正是UCS-2,UTF-32对应就是UCS-4(UCS-2和UCS-4是陈旧的布道,应丢掉卡塔尔. 其它,平日说的Unicode正是指UTF-16.

UTF-8是关键!借使统生机勃勃Unicode都用2字节表示,波兰语字母感觉本身就备受损(高字节始终是0字节卡塔尔(قطر‎.UTF-8提供了黄金时代种灵活的消除办法:以单字节(8bit卡塔尔(英语:State of Qatar)作为编码单元,变长多字节编码格局.如ASCII字母继续应用1字节囤积,汉语汉字用3字节囤积,其余最多可直6字节.

UTF-16和UTF-32必要有字节序标记BOM(FEFF卡塔尔(قطر‎解除大端小端难点.UTF-8未有字节序的主题素材(因为以1个字节为单元卡塔尔.

 

===============================================================================

其余注意点:

DBCS准确说,应该是MBCS(Multi-Byte Chactacter System, 多字节字符系统卡塔尔国.

字符集(Charset卡塔尔国和编码(Encoding卡塔尔注意区别.如GBK,GB2312以致Unicode都既是字符集,也是编码格局,而UTF-8只是编码格局,并不是字符集.

Linux下The GUN C Library(从glibc 2.2伊始卡塔尔国中宽字符wchar_t是以叁玖人的Unicode(USC-4卡塔尔国表示.如宽字符"中"字为 "0x00004e2d".而Windows下的CRT使用宽字符仍然是十四人的.

 

文化要点二:关于Unicode的心得(加深对编码的通晓)

析Unicode和UTF-8 

少年老成、首先说澳优下现行反革命常用的有的编码方案:
1. 在中国,大陆最常用的就是GBK18030编码,除了那一个之外还只怕有GBK,GB2312,那一个编码的涉嫌是那般的。
最初制订的汉字编码是GB2312,满含6762个汉字和6八十五个其余符号
95年重新修正了编码,命名GBK1.0,共收音和录音了218玖拾个暗记。
之后又推出了GBK18030编码,共收音和录音了274八十四个汉字,同一时候还收音和录音了藏文、蒙文、维吾尔文等要害的少数民族文字,今后WINDOWS平台应当要扶助GBK18030编码。
信守GBK18030、GBK、GB2312的相继,3种编码是向下宽容,同二个汉字在五个编码方案中是风度翩翩致的编码。
2.  新疆,香港(Hong Kong卡塔尔国等地使用的是BIG5编码
3.  日本:SJIS编码
二、Unicode
  假如把各类文字编码形容为各省的方言,那么Unicode正是社会风气多个国家营商业和供应和发售合营社作开采的风流倜傥种语言。
  在这里种语言情形下,不会再有语言的编码冲突,在同屏下,能够显示此外语言的从头到尾的经过,那正是Unicode的最大好处。
  那么Unicode是如何编码的吗?其实非常轻巧。
  正是将世界上享有的文字用2个字节统生龙活虎开展编码。大概你会问,2个字节最多能够代表655四11个编码,够用啊?
  高丽国和日本的大多数中华夏族民共和国字都以从当中华夏儿女民共和国流传过去的,字型是截然生龙活虎致的。
  举个例子:“文”字,GBK和SJIS中都以同一个中中原人民共和国字,只是编码分歧而已。
  那样,像那样统一编码,2个字节就曾经足足容纳世界上存有的言语的大部文字了。
UCS-2 与UCS-4
  Unicode的学名是"Universal Multiple-Octet Coded Character Set",简单的称呼为UCS。
  今后用的是UCS-2,即2个字节编码,而UCS-4是为着抗御以后2个字节远远不够用才开辟的。UCS-2也称为基本多文少禽平面。
  UCS-2转变来UCS-4只是轻易的在前头加2个字节0。
  UCS-4则根本用来保存支持平面,举个例子Unicode 4.0中的第二扶植平面
  20000-20FFF - 21000-21FFF - 22000-22FFF - 23000-23FFF - 24000-24FFF

  • 25000-25FFF -   26000-26FFF   - 27000-27FFF - 28000-28FFF - 29000-29FFF - 2A000-2AFFF - 2F000-2FFFF
      总共扩充了15个帮扶平面,由原先的655四13个编码扩大至周边100万编码。
    三、 兼容codepage
      那么既然统一了编码,如何同盟原先多个国家的文字编码呢?
      那时候就供给codepage了。
      什么是codepage?codepage正是多个国家的文字编码和Unicode之间的映射表。
      比方简体中文和Unicode的映射表正是CP936,点这里查看法定的映射表。
      以下是多少个常用的codepage,相应的改过上面的地点的数字就能够。
      codepage=936 简体汉语GBK
      codepage=950 繁体汉语BIG5
      codepage=437 美利坚合众国/加拿大阿尔巴尼亚语
      codepage=932 日文
      codepage=949 韩文
      codepage=866 俄文
      codepage=65001 unicode UFT-8
    提起底三个65001,据个人精晓,应该只是叁个杜撰的映射表,实际只是一个算法而已。
    从936中自由取黄金年代行,举个例子:
    0x9993 0x6ABD #CJK UNIFIED IDEOGRAPH
    前面的编码是GBK的编码,前边的是Unicode。
    透过查那张表,就会大致的落到实处GBK和Unicode之间的转移。
    四、UTF-8
      今后知道了Unicode,那么UTF-8又是怎么啊?又干什么会现出UTF-8呢?
      ASCII转变来UCS-2,只是在编码前插入两个0x0。用这个编码,会席卷一些调控符,举例'' 或 '/',那在UNIX和一些C函数中,将会时有产生严重错误。由此能够一定,UCS-2不合乎充作Unicode的外界编码。
      因而,才一败涂地了UTF-8。那么UTF-8是哪些编码的?又是哪些化解UCS-2的难点啊?
    例:
    E4 BD A0        11100100 10111101 10100000
    这是“你”字的UTF-8编码
    4F 60          01001111 01100000
    这是“你”的Unicode编码
    有关汉字根据UTF-8的编码准则,分解如下:xxxx0100 xx111101 xx100000
    把除了x之外的数字拼接在一起,就改成“你”的Unicode编码了。
    静心UTF-8的最前头3个1,表示整个UTF-8串是由3个字节构成的。
    透过UTF-8编码之后,再也不会现身敏感字符了,因为最高位始终为1。
    以下是Unicode和UTF-8之间的转变关系表:
    U-00000000 - U-0000007F: 0xxxxxxx
    U-00000080 - U-000007FF: 110xxxxx 10xxxxxx
    U-00000800 - U-0000FFFF: 1110xxxx 10xxxxxx 10xxxxxx
    U-00010000 - U-001FFFFF: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
    U-00200000 - U-03FFFFFF: 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
    U-04000000 - U-7FFFFFFF: 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx、
    Unicode编码转换成UTF-8,针对汉语,简单的把Unicode字节流套到x中就改为UTF-8了。

续篇:

unicode在windows api中的应用
    实际上,常提到的Win32 API的名号而不是它们的安分守己名称。这几个名称仅仅是后生可畏对宏,你能够在PSDK的头文件中找到这几个宏对用的函数名称。所以,假若PSDK的文书档案提到一个函数,如CreateFile,开垦人士应该开掘到它仅仅是三个宏。它的诚笃名称是CreateFileA和CreateFileW。是的,它意味着了“多少个”函数名,实际不是叁个,是同三个函数在分化Win32函数的三个例外的版本。以'A'结尾的函数选拔ANSI字符串(char *),即Unicode字符串(wchar_t *卡塔尔(قطر‎而在vs中得以用WCHA逍客宏替代,即wchar_ts型字符串。二种版本的函数都在模块kernel32.dll中落到实处,假设您的编制程序情况是Unicode则,则宏CreateFile在编写翻译是会被CreateFileW取代,否则用CreateFileA取代。

PSDK的字符串施工方案:TCHALANDs
    为了制止为分裂的windows操作系统开垦分歧版本的PSDK,微软拟订了三个统生机勃勃的字符串类型TCHA大切诺基s。TCHAPAJERO以致其余的对应的宏在头文件WinNT.h中有定义。程序员在前后相继中不须要为使用char依旧wchar_t而纠缠,只需求接受宏TCHA奇骏就足以了。依照Unicode蒙受是还是不是存在,编写翻译器会活动进行对应的转换。相像道理,技师无需为运用'A'还是'W'型Win32 API函数纠结。

对于较中期的类别均选用ACSI编码,而在风行系统中则都合併为unicode编码(如:手机系统)

 

文化要点三: L"......", _T(), _TEXT ,TEXT()

L"......": L是意味着字符串能源转为宽字符的保留(平日转为unicode卡塔尔(英语:State of Qatar),却未必是unicode字符,那与编写翻译器完成相关。

_T(" ……"卡塔尔 是一个适配的宏     #ifdef _UNICODE(当系统景况是unicod下卡塔尔(قطر‎ _T正是L   而当系统情状是ACSI  _T就是ANSI的。(有低价开始时代windows系编制程序文件的移植,到达新旧种类互相)

_T、_TEXT、TEXT 三者效果等同

tchar.h是运作时的头文件,_T、_TEXT 根据_UNICODE来显明宏
winnt.h是Win的头文件依据,TEXT 依据UNICODE 来明确宏

朝气蓬勃旦必要同一时间接收那3个宏,则需同一时间定义 UNICODE 和 _UNICODE
VS二零零六过后的本子中 ,设置:项目–属性–配置属性–常规–字符集–使用Unicode字符集, 那么编写翻译器命令选项中确确实实同不平日候到场了_UNICODE和UNICODE。

知识要点四: c 的cout 与 wcout**

cout << "hello world!" << endl; //ACSI 编码输出

cout << L“hello world!” <<endl;// unicode 输出

当输出双字节编码到调整台时,cout输出的将是地点而并非内容当时就要用到wcout;

改为:

cout << "hello world!" << endl; //ACSI 编码输出

wcout << L“hello world!” <<endl;// unicode 输出

** 


文化要点五:编写翻译连接进度

1.预处理 生成.i文件

C 的预管理是指在C 程序源代码被编写翻译早先,由预微电脑对C 程序源代码进行的拍卖。那个进度并不对前后相继的源代码进行分析。

此间的预微电脑(preprocessor)是指真的的编写翻译伊始此前由编写翻译器调用的一个独立程序。

预微电脑首要承当以下的几处

1.宏的更替

2.去除注释

3.甩卖预管理指令,如#include,#ifdef

 2.编写翻译和优化 生成汇编.s原文件

词法深入分析 -- 识别单词,确认词类;举个例子int i;知道int是多个类型,i是贰个首要字以至剖断i的名字是或不是合法
语法分析 -- 识别短语和句型的语法属性;

语义深入分析 -- 确认单词、短语和句型的语义特征;

代码优化 -- 修辞、文本编辑;

代码生成 -- 生成译文。

3.生成**.o**目的文件


汇编进程实际上指把汇编语言代码翻译成目的机器指令的长河。

在最终的靶子文件中

除了那几个之外拥有协调的数额和二进制代码之外,还要起码提供2个表:未减轻符号表和导出符号表,分别报告链接器自个儿索要哪些和力所能致提供哪些。

编写翻译器把叁个cpp编写翻译为对象文件的时候,除了要在目的文件里写入cpp里带有的数据和代码,还要最少提供3个表:未缓和符号表,导出符号表和地址重定向表。
未缓慢解决符号表提供了拥有在该编写翻译单元里引用可是定义并不在本编译单元里的号子及其现身的地点。
导出符号表提供了本编写翻译单元具备定义,何况愿意提必要其余编写翻译单元使用的标志及其地址。
地址重定向表提供了本编写翻译单元全体对本身地址的援用的笔录。

4.链接

由汇编制程序序生成的靶子文件并无法立刻就被实践,在这之中恐怕还应该有许多未曾减轻的题目。举个例子,有些源文件中的函数恐怕引用了另一个源文件中定义的某部符号(如变量恐怕函数调用等);在程序中或然调用了某些库文件中的函数,等等。全部的那些主题材料,都急需经链接程序的管理方能得以化解。

 

本文由亚洲必赢娱乐游戏发布于亚洲必赢娱乐,转载请注明出处:QT输出汉语乱码深刻深入分析

TAG标签:
Ctrl+D 将本页面保存为书签,全面了解最新资讯,方便快捷。