日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

c++ unicode转换中文_彻底弄懂UTF-8、Unicode、宽字符、locale

發布時間:2024/9/19 c/c++ 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 c++ unicode转换中文_彻底弄懂UTF-8、Unicode、宽字符、locale 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

結論

寬字符類型wchar_t

locale

為什么需要寬字符類型

多字節字符串和寬字符串相互轉換

最近使用到了wchar_t類型,所以準備詳細探究下,沒想到水還挺深,網上的資料大多都是復制粘貼,只有個結論,也沒個驗證過程。本文記錄探究的過程及結論,如有不對請指正。

Unicode、UCS

UCS(Universal Character Set)本質上就是一個字符集。

Unicode的開發結合了國際標準化組織所制定的 ISO/IEC 10646,即通用字符集(

Universal Character Set, UCS)。Unicode 與 ISO/IEC 10646 在編碼的運作原理相同,但 The Unicode Standard 包含了更詳盡的實現信息、涵蓋了更細節的主題,諸如比特編碼(bitwise encoding)、校對以及呈現等。摘自(Unicode)

所以也可以簡單的理解為,Unicode和UCS等價,都是字符集。

UCS編碼的長度是31位,可用4個字節表示,可以表示2的31次方個字符。如果兩個字符的高位相同,只有低16位不同,則它們屬于同一平面,所以一個平面由2的16次方個字符組成。目前大部分字符都位于第一個平面稱為BMP。BMP的編碼通常以U+xxxx這種形式表示,其中x是16進制數。

比如中文“你”對應的UCS編碼為U+4f60,“好”對應的UCS編碼為U+597d。更多中文編碼可以在Unicode編碼表中查詢。

有了UCS編碼,任何一個字符在計算機中都最多可以用四個字節來表示,稱為碼點。

UTF8

現在有了UCS字符集,那么一個字符在計算機中真的要按四個字節(UTF-32)來存儲嗎?

答案是否定的,一方面每個字符都按四字節來存儲非常浪費空間,因為大部分字符都在BMP,只有后16位有效,前16位都是0。另一方面這與c語言不兼容,在c語言中0字節表示字符串的結尾,庫函數strlen等函數依賴這一點,如果按UTF-32存儲,其中有很多0字節并不表示字符串結尾。

Ken Thompson發明了UTF-8編碼,可以很好的解決以上問題。Unicode 和 UTF-8 之間的轉換關系表如下:

碼點起 值碼點 終值字節序列 Byte1 Byte2 Byte3 Byte4 Byte5 Byte6

U+0000 U+007F 1 0xxxxxxx

U+0080 U+07FF 2 110xxxxx 10xxxxxx

U+0800 U+FFFF 3 1110xxxx 10xxxxxx 10xxxxxx

U+10000 U+1FFFFF 4 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

U+200000 U+3FFFFFF 5 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx

U+4000000 U+7FFFFFFF 6 111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx


第一個字節要么最高位是0(ASCII碼),要么最高位都是1,最高位之后的1的個數決定了后面的有多少個字節也屬于當前字符編碼,例如111110xx,最高位之后還有4個1,表示后面的4個字節屬于當前編碼。后面的每個字節的最高位都是10,可以和第一個字節區分開來。后面字節的x表示的就是UCS編碼。所以UTF-8就像一列火車,第一個字節是車頭,包含了后面的哪幾個字節也屬于當前這列火車的信息,后面的字節是車廂,其中承載著UCS編碼。

以中文字符“你”為例,對應的Unicode為"U+4f60",二進制表示為0100 1111 0110 0000。按照表中的規則編碼成UTF-8就是11100100 10111101 10100000(0xe4 0xbd 0xa0)。

結論

Unicode本質是字符集,在這個集合中的任意一個字符都可以用一個四字節來表示。

UTF-8是編碼規則,可以通過這個規則將Unicode字符集中任一字符對應的字節轉換為另一個字節序列。UTF-8只是編碼規則中的一種,其它的編碼規則還有UTF-16,UTF-32等。

寬字符類型wchar_t

在介紹寬字符前先了解下locale。因為多字節字符串和寬字符串的轉換和locale相關。

locale

什么是locale

區域設置(locale),也稱作“本地化策略集”、“本地環境”,是表達程序用戶地區方面的軟件設定。在linux執行locale可以查看當前locale設置:

ubuntu@VM-0-16-ubuntu:~$ localeLANG=zh_CN.UTF-8LANGUAGE=LC_CTYPE="zh_CN.UTF-8"LC_NUMERIC="zh_CN.UTF-8"LC_TIME="zh_CN.UTF-8"LC_COLLATE="zh_CN.UTF-8"LC_MONETARY="zh_CN.UTF-8"LC_MESSAGES="zh_CN.UTF-8"LC_PAPER="zh_CN.UTF-8"LC_NAME="zh_CN.UTF-8"LC_ADDRESS="zh_CN.UTF-8"LC_TELEPHONE="zh_CN.UTF-8"LC_MEASUREMENT="zh_CN.UTF-8"LC_IDENTIFICATION="zh_CN.UTF-8"LC_ALL=

可以將locale理解為一系列環境變量。locale環境變量值的格式為language_area.charset。languag表示語言,例如英語或中文;area表示使用該語言的地區,例如美國或者中國大陸;charset表示字符集編碼,例如UTF-8或者GBK。

這些環境變量會對日期格式,數字格式,貨幣格式,字符處理等多個方面產生影響。

參考資料:

locale wiki

Environment Variables

如何設置系統默認的locale

修改配置文件/etc/default/locale,比如要將locale設為zh_CN.UTF-8,添加如下語句LANG=zh_CN.UTF-8

locale環境變量有何作用

以LC_TIME為例,該變量會影響strftime()等函數。size_t strftime(char *str, size_t maxsize, const char *format, const struct tm *timeptr)

strftime根據format中定義的格式化規則,格式化結構timeptr表示的時間,并把它存儲在str中。

#include<locale.h>#include<stdio.h>#include<time.h>intmain(){time_tcurrtime;structtm*timer;charbuffer[80]; time( &currtime ); timer = localtime( &currtime );printf("Locale is: %sn", setlocale(LC_TIME,"en_US.iso88591")); strftime(buffer,80,"%c", timer );printf("Date is: %sn", buffer);printf("Locale is: %sn", setlocale(LC_TIME,"zh_CN.UTF-8")); strftime(buffer,80,"%c", timer );printf("Date is: %sn", buffer);printf("Locale is: %sn", setlocale(LC_TIME,"")); strftime(buffer,80,"%c", timer );printf("Date is: %sn", buffer);return(0);}

編譯后運行結果如下:

Localeis: en_US.iso88591Dateis: Sun07Jul201904:08:39PM CSTLocaleis: zh_CN.UTF-8Dateis:2019年07月07日 星期日16時08分39秒Localeis: zh_CN.UTF-8Dateis:2019年07月07日 星期日16時08分39秒

可以看到對LC_TIME設置不同的值后,調用strftime()會產生不同的結果。

char* setlocale (int category, const char* locale);可以用來對當前程序進行地域設置。

category:用于指定設置影響的范圍,LC_CTYPE影響字符分類和字符轉換,LC_TIME影響日期和時間的格式,LC_ALL影響所有內容。

locale:用于指定變量的值,上例中分別使用了"en_US.iso88591","zh_CN.UTF-8"和空字符串"",""表示使用當前操作系統默認的區域設置。

參考資料:

setlocale()

為什么需要寬字符類型

“你好”對應的Unicode分別為"U+4f60"和"U+597d”,對應的UTF-8編碼分別為“0xe4 0xbd 0xa0”和“0xe5 0xa5 0xbd”

多字節字符串在編譯后的可執行文件以UTF-8編碼保存

#include<stdio.h>#include<string.h>intmain(void){chars[] ="你好";size_tlen =strlen(s);printf("len = %dn", (int)len);printf("%sn", s);return0;}

編譯后執行,輸出如下:

len = 6

你好

od編譯后的可執行文件,可以發現"你好"以UFT-8編碼保存,也就是“0xe4 0xbd 0xa0”和“0xe5 0xa5 0xbd”6個字節。

strlen()函數只管結尾的0字節而不管字符串里存的是什么,所以len是6,也就是“你好”的UFT-8編碼的字節數。

printf("%sn", s);相當于將“0xe4 0xbd 0xa0”和“0xe5 0xa5 0xbd”6個字節write到當前終端的設備文件,如果當前終端的驅動程序能識別UTF-8編碼就能打印漢字,如果當前字符終端的驅動程序不能識別UTF-8就打印不出漢字。

寬字符串在編譯后可執行文件中以Unicode保存

#include<wchar.h>#include<stdio.h>#include<locale.h>intmain(void){ setlocale(LC_ALL,"zh_CN.UTF-8");//設置localewchar_ts[] =L"你好";size_tlen = wcslen(s);printf("len = %dn", (int)len);printf("%lsn", s);return0;}

編譯后執行,輸出如下:

len = 2

你好

對編譯后的可執行文件執行od命令,可以找到如下這些字節:

193 000302000100020` O 00} Y 00n 0001940002000100004f600000597d0000000a

00004f60正是“你”對應的Unicode,0000597d是“好”對應的Unicode。所以對于寬字符串是按Unicode保存在可執行文件中的。

wchar_t是寬字符類型。在字符常量或者字符串前加L就表示寬字符常量或者寬字符串。所以len是2。

wcslen()和strlen()不同,不是見到0字節就結束而是要遇到UCS編碼為0的字符才結束。

目前寬字符在內存中以Unicode進行保存,但是要write到終端仍然需要以多字節編碼輸出,這樣終端驅動程序才能識別,所以printf在內部把寬字符串轉換成多字節字符串,然后write出去。這個轉換過程受locale影響,setlocale(LC_ALL, "zh_CN.UTF-8");設置當前進程的LC_ALL為zh_CN.UTF-8,所以printf將Unicode轉成多字節的UTF-8編碼,然后write到終端設備。如果將setlocale(LC_ALL, "zh_CN.UTF-8");改為setlocale(LC_ALL, en_US.iso88591):打印結果中將不會輸出"你好"。

一般來說程序在內存計算時通常以寬字符編碼,存盤或者網絡發送則用多字節編碼。

多字節字符串和寬字符串相互轉換

c語言中提供了多字節字符串和寬字符串相互轉換的函數。

#include<stdlib.h>size_tmbstowcs(wchar_t*dest,constchar*src,size_tn);size_twcstombs(char*dest,constwchar_t*src,size_tn);

mbstowcs()將多字節字符串轉換為寬字符串。

wcstombs()將寬字符串轉換為多字節字符串。

考慮下面的例子:

#include<locale.h>#include<stdio.h>#include<time.h>#include<stdlib.h>#include<wchar.h>#include<string.h>wchar_t* str2wstr(constcharconst* s) {constsize_tbuffer_size =strlen(s) +1;wchar_t* dst_wstr = (wchar_t*)malloc(buffer_size *sizeof(wchar_t)); wmemset(dst_wstr,0, buffer_size); mbstowcs(dst_wstr, s, buffer_size);returndst_wstr;}voidprintBytes(constunsignedcharconst* s,intlen){for(inti =0; i < len; i++) {printf("0x%02x ", *(s + i)); }printf("n");}intmain(){chars[10] ="你好";//內存中對應0xe4 0xbd 0xa0 0xe5 0xa5 0xbd 0x00 wchar_tws[10] =L"你好";//內存中對應0x60 0x4f 0x00 0x00 0x7d 0x59 0x00 0x00 0x00 0x00 0x00 0x00 printf("Locale is: %sn", setlocale(LC_ALL,"zh_CN.UTF-8"));//Locale is: zh_CN.UTF-8printBytes(s,7);//0xe4 0xbd 0xa0 0xe5 0xa5 0xbd 0x00 printBytes((char*)ws,12);//0x60 0x4f 0x00 0x00 0x7d 0x59 0x00 0x00 0x00 0x00 0x00 0x00 printBytes((char*)str2wstr(s),12);//0x60 0x4f 0x00 0x00 0x7d 0x59 0x00 0x00 0x00 0x00 0x00 0x00 return(0);}

編譯后,執行結果如下:

Locale is: zh_CN.UTF-80xe40xbd0xa00xe50xa50xbd0x000x600x4f0x000x000x7d0x590x000x000x000x000x000x000x600x4f0x000x000x7d0x590x000x000x000x000x000x00

第二行輸出也印證了我們之前說的多字節字符串在內存中以UTF-8存儲,"0xe4 0xbd 0xa0 0xe5 0xa5 0xbd"正是"你好"的UTF-8編碼。

第三行輸出印證了之前說的寬字符串在內存中以Unicode存儲,"0x60 0x4f 0x00 0x00 0x7d 0x59 0x00 0x00"正好是寬字符串L"你好"對應的Unicode。

setlocale(LC_ALL, "zh_CN.UTF-8")設置locale,程序將以UTF-8解碼寬字符串。調用mbstowcs()后,可以看到“你好”的UTF-8編碼 "0xe4 0xbd 0xa0 0xe5 0xa5 0xbd 0x00"確實被轉換成了“你好”對應的Unicode "0x60 0x4f 0x00 0x00 0x7d 0x59 0x00 0x00 0x00 0x00 0x00 0x00"。

如果將setlocale(LC_ALL, "zh_CN.UTF-8")換成setlocale(LC_ALL, "en_US.iso88591 ");那么最后一行的輸出也就會不一樣。

需要更多點擊這里

總結

以上是生活随笔為你收集整理的c++ unicode转换中文_彻底弄懂UTF-8、Unicode、宽字符、locale的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 韩国精品视频在线观看 | 亚洲特级黄色片 | 国产一区二区三区三州 | 欧美 亚洲 视频 | 午夜日韩精品 | 欧美色图亚洲自拍 | 黄色h视频| 天天天天干 | 国产成人三级 | 亚洲一区二区蜜桃 | 一级性生活黄色片 | 天天操天天干天天 | 欧美日韩在线免费视频 | 免费在线看污 | 久久精品婷婷 | 26uuu精品一区二区在线观看 | 丝袜一区二区三区 | 男生操女生网站 | 亚洲熟女少妇一区 | 国产一级特黄a高潮片 | 一级片在线免费观看视频 | 亚洲欧美日韩在线看 | 精品视频一区二区三区 | 成熟妇人a片免费看网站 | 99热只有这里有精品 | 国产a黄| 欧洲精品视频在线 | 成人黄色大全 | 欧美黄色一级大片 | 久久阁| 51国产偷自视频区视频 | 在线观看日韩视频 | 国产精品麻豆一区二区三区 | 国产精品熟妇人妻g奶一区 a少妇 | 性猛交xxxx乱大交3 | 亚洲色婷婷一区二区三区 | 国产片网址 | 青草视频在线 | 特黄特色特刺激免费播放 | 亚洲人在线观看视频 | 亚洲精品 欧美 | 日本色片网站 | 欧美亚洲综合视频 | 91麻豆精品国产理伦片在线观看 | 欧美精品自拍偷拍 | 一区二区三区 日韩 | 香蕉视频性 | 在线观看www视频 | 一区二区三区四区视频在线观看 | 国精无码欧精品亚洲一区蜜桃 | 国产白丝在线观看 | 黄色污污视频网站 | 4438亚洲最大 | 国产妇女视频 | 亚洲色图欧美视频 | 国产人妖一区 | 色图自拍| 古装做爰无遮挡三级 | 久草精品视频 | 超碰97在线播放 | 成人在线免费av | 精品看片| 亚洲午夜毛片 | 五月天黄色小说 | 精产国品一区二区三区 | 亚洲精品欧美日韩 | 亚洲黄色在线 | 男生操女生动漫 | 精品电影在线观看 | 久久22 | 黄色小网站入口 | 在线观看国产小视频 | 九九久久免费视频 | 拔擦8x成人一区二区三区 | 少妇厨房愉情理伦bd在线观看 | 日本大尺度吃奶做爰久久久绯色 | 国产乱淫av一区二区三区 | 日韩国产三级 | 九九99久久 | 黄色91免费观看 | 久久av影院 | 日韩人妻一区二区三区蜜桃视频 | 国产九色在线 | 波多野吉衣一区二区 | 高清av不卡 | 日本视频h | 亚洲视频一区二区 | 成人免费高清视频 | 国产特级淫片免费看 | 国产美女性生活 | 欧美a√在线 | 黄色一级生活片 | 美痴女~美人上司北岛玲 | 国产免费一级视频 | 阿v视频在线免费观看 | 久久久久久91亚洲精品中文字幕 | 俄罗斯黄色录像 | 欧美另类视频在线观看 | 成人99|