91在线观看视频-91在线观看视频-91在线观看免费视频-91在线观看免费-欧美第二页-欧美第1页

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

C++中字符編碼的轉換

工程師 ? 來源:CSDN ? 作者:FlushHip ? 2020-10-15 10:21 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

作者:FlushHip

在處理東方語言(中日韓)時,經常會遇到各種編碼問題,而且被這類問題搞的暈頭轉向。到網上查資料,看的也是一頭霧水,最后往往是誤打誤撞的把問題解決了,自己仍然稀里糊涂。

這篇文章介紹了如何在最常見的編碼方式(Unicode, UTF-8, ANSI)之間進行轉換,結合代碼實例,清晰明了,方便讀者理解,例子也可以直接拿來使用。本文推薦給經常對文字字符串進行處理的程序員閱讀,使其掌握字符轉換的一些基本方法。

正文

C++的項目,字符編碼是一個大坑,不同平臺之間的編碼往往不一樣,如果不同編碼格式用一套字符讀取格式讀取就會出現亂碼。因此,一般都是轉化成UTF-8這種平臺通用,且支持性很好的編碼格式。

Unicode、UTF-8的概念不做過多解釋,這里說一下ANSI,我第一次看到這個名詞,我看成了ASCII。被Mentor狠批一頓。

ANSI是一種字符代碼,為使計算機支持更多語言,通常使用 0x00 ~ 0x7F范圍的1 個字節來表示 1 個英文字符。超出此范圍使用0x80~0xFFFF來編碼,即擴展的ASCII編碼。

不同的國家和地區制定了不同標準,由此產生了 GB2312、GBK、GB18030、Big5、Shift_JIS 等各自的編碼標準。這些使用多個字節來代表一個字符的各種漢字延伸編碼方式,稱為 ANSI 編碼。在簡體中文Windows操作系統,ANSI 編碼代表 GBK 編碼;在繁體中文Windows操作系統,ANSI編碼代表Big5;在日文Windows操作系統,ANSI 編碼代表 Shift_JIS 編碼。

以上內容摘自百度百科,可以看出,ANSI和ASCII還是有關系的。ANSI也叫本地碼。

我們要做到能在Unicode、UTF-8、ANSI這三種編碼格式中自由轉換。如下圖所示:

在C++中,要怎么做呢?當然是用標準庫的東西啦,C++11對國際化標準做得還是可以的,提供了這些接口,正如圖中虛線所示,標準庫沒有提供UTF-8到ANSI的互相轉化接口,但是我們可以自己封轉接口,借用這條路(UTF-8 《=》 Unicode 《=》 ANSI)來實現。

因此,接下來就聊聊UTF8 《=》 Unicode和Unicode 《=》 ANSI。

UTF8 《=》 Unicode

先看代碼:

std::string UnicodeToUTF8(const std::wstring & wstr){ std::string ret; try { std::wstring_convert《 std::codecvt_utf8《wchar_t》 》 wcv; ret = wcv.to_bytes(wstr); } catch (const std::exception & e) { std::cerr 《《 e.what() 《《 std::endl; } return ret;}std::wstring UTF8ToUnicode(const std::string & str){ std::wstring ret; try { std::wstring_convert《 std::codecvt_utf8《wchar_t》 》 wcv; ret = wcv.from_bytes(str); } catch (const std::exception & e) { std::cerr 《《 e.what() 《《 std::endl; } return ret;}

UTF-8是多字節字符串(multibyte string),而Unicode是寬字符字符串(wchar_t string)。

而C++11提供了wstring_convert這個類,這個類可以在wchar_t string和multibyte string之間來回轉換;

而codecvt_utf8可以提供UTF-8的編碼規則。這個類在#include 《codecvt》中。有了wstring_convert提供寬字符字符串到多字節字符串的轉化,而這個轉換規則由codecvt_uft8提供。這樣子就可以實現UTF8和Unicode的互相轉換。

從UTF8到Unicode調用成員函數wstring_convert::from_bytes;

從Unicode到UTF8調用成員函數wstring_convert::to_bytes;

Unicode 《=》 ANSI

std::string UnicodeToANSI(const std::wstring & wstr){ std::string ret; std::mbstate_t state = {}; const wchar_t *src = wstr.data(); size_t len = std::wcsrtombs(nullptr, &src, 0, &state); if (static_cast《size_t》(-1) != len) { std::unique_ptr《 char [] 》 buff(new char[len + 1]); len = std::wcsrtombs(buff.get(), &src, len, &state); if (static_cast《size_t》(-1) != len) { ret.assign(buff.get(), len); } } return ret;}std::wstring ANSIToUnicode(const std::string & str){ std::wstring ret; std::mbstate_t state = {}; const char *src = str.data(); size_t len = std::mbsrtowcs(nullptr, &src, 0, &state); if (static_cast《size_t》(-1) != len) { std::unique_ptr《 wchar_t [] 》 buff(new wchar_t[len + 1]); len = std::mbsrtowcs(buff.get(), &src, len, &state); if (static_cast《size_t》(-1) != len) { ret.assign(buff.get(), len); } } return ret;}

標準庫提供了wcsrtombs和mbsrtowcs這兩個函數,當然C的標準庫也提供了這兩個函數。

講下wcsrtombs,這個函數把寬字符串轉成多字節字符串。編碼規則受地域的LC_CTYPE影響。因此這個函數可以用于本地碼的轉化(和本地的編碼息息相關)。

因此,有關于本地碼的使用,在代碼中要加上下列語句:

setlocale(LC_CTYPE, “”);

目的是讓本地碼生效,這條代碼的作用就是讓C++語言的Locale(地域)和本地的地域相同。在Linux下可以運行locale命令看看:

可以看到,LC_CTYPE = en_US.UTF-8,這表示英文,英國,UTF-8編碼,也就是說本地碼就是這個。

當然,你也可以在setlocale中指定一些編碼規則,把wcsrtombs用于別的編碼轉化,但是,這里不推薦,因為setlocale是全局的,設置了這個就會影響其他地方的編碼。

wcsrtombs的四個參數分別代表什么意思呢?

std::size_t wcsrtombs( char* dst, const wchar_t** src, std::size_t len, std::mbstate_t* ps );

dst,轉化后的結果存入dst指向的內存;

src,待轉化的字符串的指針的指針;

len,dst指向內存的可用字節數;

ps,轉換的狀態,一般默認初始化就好了;

return type,轉化后結果的長度,不包含\0。

注意:如果dst == nullptr,這個時候wcstombs的返回值表示會有這么多字節的結果產生,因此,我們可以拿到這個返回值去新建一個數組來存儲new char[len + 1]。所以,一般調用兩次wcstombs。

mbsrtowcs同理。

UTF-8 《=》 ANSI

以Unicode為中介裝換便是。

std::string UTF8ToANSI(const std::string & str){ return UnicodeToANSI(UTF8ToUnicode(str));}std::string ANSIToUTF8(const std::string & str){ return UnicodeToUTF8(ANSIToUnicode(str));}

總結

C++11的標準庫還是挺強大的,雖然這么強大,但是很多特性還不了解,因此還是要多擴寬自己的視野,不然有好東西都不知道用,那就棒槌了。

對了,在Linux下加上setlocale(LC_CTYPE, “”)后程序在命令行中可以正常顯示,不加有可能不正常顯示,原因是setlocale(LC_CTYPE, “”)也影響了cout,全局的嘛;而在CodeBlocks下不能正常顯示,不知道為什么,但是調試的過程中,觀察到了正常的結果;Visual Studio中沒有做實驗,不過應該沒問題。

責任編輯:haq

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 計算機
    +關注

    關注

    19

    文章

    7663

    瀏覽量

    90827
  • 編程
    +關注

    關注

    88

    文章

    3689

    瀏覽量

    95270
  • C++
    C++
    +關注

    關注

    22

    文章

    2119

    瀏覽量

    75332
  • UTF-8
    +關注

    關注

    0

    文章

    13

    瀏覽量

    7971
收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評論

    相關推薦
    熱點推薦

    為什么無法在運行時C++推理讀取OpenVINO?模型?

    使用模型優化器 2021.1 版OpenVINO?轉換模型 使用 Runtime 2022.3 版本在 C++ 推理實現 ( core.read_model()) 讀取模型OpenVINO?并
    發表于 03-05 06:17

    基于OpenHarmony標準系統的C++公共基礎類庫案例:ThreadPoll

    。每個線程每秒打印1段字符串,10秒后停止。2、基礎知識C++公共基礎類庫為標準系統提供了一些常用的C++開發工具類,包括:文件、路徑、字符串相關操作的能力增強接口
    的頭像 發表于 02-10 18:09 ?375次閱讀
    基于OpenHarmony標準系統的<b class='flag-5'>C++</b>公共基礎類庫案例:ThreadPoll

    Spire.XLS for C++組件說明

    Spire.XLS for C++ 是一款專業的 C++ Excel 組件,可以用在各種 C++ 框架和應用程序。Spire.XLS for C+
    的頭像 發表于 01-14 09:40 ?632次閱讀
    Spire.XLS for <b class='flag-5'>C++</b>組件說明

    字符串在數據庫的存儲方式

    數據庫是現代信息技術存儲和管理數據的核心組件。字符串作為最常見的數據類型之一,在數據庫的存儲方式對其性能和可擴展性有著重要影響。 數據類型 固定長度字符串 :如CHAR類型,它為每
    的頭像 發表于 01-07 15:41 ?827次閱讀

    EE-112:模擬C++的類實現

    電子發燒友網站提供《EE-112:模擬C++的類實現.pdf》資料免費下載
    發表于 01-03 15:15 ?0次下載
    EE-112:模擬<b class='flag-5'>C++</b><b class='flag-5'>中</b>的類實現

    base64字符轉換為二進制文件

    Base64是一種編碼方法,用于將二進制數據轉換為ASCII字符串。這種編碼通常用于在不支持二進制數據的系統傳輸數據,例如電子郵件或網頁。
    的頭像 發表于 11-10 10:55 ?2841次閱讀

    base64編碼和解碼的使用方法

    Base64編碼是一種廣泛使用的編碼方案,用于將二進制數據轉換為純文本格式。這種編碼方式特別適用于在不支持二進制數據的系統之間傳輸數據,例如電子郵件、網頁等。 1. Base64
    的頭像 發表于 11-10 10:48 ?4345次閱讀

    如何使用ASCII碼進行編碼

    知道要編碼字符在ASCII碼表對應的數字代碼。例如: 'A' 的 ASCII 碼是 65 'a' 的 ASCII 碼是 97 '0' 的 ASCII 碼是 48 空格(' ')的 A
    的頭像 發表于 11-10 09:37 ?1709次閱讀

    C語言和C++結構體的區別

    同樣是結構體,看看在C語言和C++中有什么區別?
    的頭像 發表于 10-30 15:11 ?773次閱讀

    C7000優化C/C++編譯器

    電子發燒友網站提供《C7000優化C/C++編譯器.pdf》資料免費下載
    發表于 10-30 09:45 ?0次下載
    <b class='flag-5'>C</b>7000優化<b class='flag-5'>C</b>/<b class='flag-5'>C++</b>編譯器

    使用OpenVINO GenAI API在C++構建AI應用程序

    許多桌面應用程序是使用 C++ 開發的,而將生成式AI(GenAI)功能集成到這些應用程序可能會很具有挑戰性,尤其是因為使用像 Hugging Face 這樣的 Python 庫的復雜性。C++
    的頭像 發表于 10-12 09:36 ?1133次閱讀
    使用OpenVINO GenAI API在<b class='flag-5'>C++</b><b class='flag-5'>中</b>構建AI應用程序

    ostream在c++的用法

    ostream 是 C++ 標準庫中一個非常重要的類,它位于 頭文件(實際上,更常見的是通過包含 頭文件來間接包含 ,因為 包含了 和 )。 ostream 類及其派生類(如 std::cout
    的頭像 發表于 09-20 15:11 ?1947次閱讀

    labview字符串如何轉換為16進制字符

    在LabVIEW,將字符轉換為16進制字符串是一個常見的需求,尤其是在處理數據通信和硬件接口時。LabVIEW提供了多種方法來實現這一轉換
    的頭像 發表于 09-04 15:54 ?5338次閱讀

    c++編譯后鏈接失敗的原因?如何解決?

    /c++項目,將剛才新建的項目轉換c++項目。 完成后點擊編譯,此時也是正常的。 新建一個cpp文件,將原項目的main.c內容全部拷貝
    發表于 07-25 08:13

    ModusToolbox 3.2在c代碼包含c++代碼的正確步驟是什么?

    使用 ModusToolbox 3.2 我有一個用純 C 語言編寫的 XMC4700 項目。 我正在嘗試添加一些 C++ 函數,并將其合并到我的原始代碼。 我可以構建獨立的 .cpp/.hpp
    發表于 07-23 08:21
    主站蜘蛛池模板: 三级黄色一级视频 | 狼色视频在线观免费观看 | 欧美性黑人极品hd网站 | 综合婷婷| 女人精aaaa片一级毛片女女 | 在线免费看视频 | 国产女人视频免费观看 | 欧美人另类zooz | 久99频这里只精品23热 视频 | 狠狠色狠狠干 | 欧亚激情偷乱人伦小说视频 | 久久99爱爱 | 亚洲国产成人久久一区久久 | 性网站在线观看 | 色黄网站 | free性日韩| 三级国产| 日韩黄色网址 | 色天天天天综合男人的天堂 | 美女扒开尿囗给男人玩的动图 | 狠狠操天天 | 日日爽天天干 | 色黄视频网站 | 一区不卡 | 97黄网| 男人j进入女人j在线视频 | 操女人视频网站 | 色综合日韩 | 欧美在线观看视频一区 | 色多多在线观看视频 | 韩国xxxxx视频在线 | 狠狠的操| 色婷婷在线视频观看 | 性性欧美 | 天天操天天射天天色 | 免费在线观看视频 | xxxx日| 久久青青草原精品老司机 | 色婷婷五 | 性欧美另类 | 男人日女人的网站 |