欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C++中的字符串編碼處理方法

 更新時間:2023年05月15日 08:32:52   作者:assassinx  
這篇文章主要介紹了C++中的字符串編碼處理,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下

今天由于在項目中用到一些與C++混合開發(fā)的東西 ,需要通過socket與C++那邊交換數(shù)據(jù),沒啥特別的,字節(jié)碼而已,兩邊確定一種編碼規(guī)則就行了。我們確定的UTF-8。關(guān)于C++的 這種又是寬字節(jié) 又是MessageBoxW 又是MessageBoxA 的 ,說實話相比C#而言 搞的確實非常的和稀泥 搞的非常的糊,別說新手 有些不是新手的都搞不明白。

字符串字面量怎么被編碼成字節(jié)的

什么是字符串?C#里的 string?C++里的char* ? 字符串的本質(zhì)是什么?字符串不過是一個特殊的數(shù)據(jù)字節(jié)包裝 帶有編碼信息,特別是C++的 更原始 更便于我們想清楚這個底層,其實其他的已經(jīng)迎刃而解了。首先我們無論如何確定一個東西 那就是交換的東西是字節(jié)碼 ,說白了 也就是C++ 里的char [ ] 也就是char *,在我不管你編碼的情況下 我新建VC++項目 在代碼里這樣寫:

char str1[] = "中a";
 printf("%s\r\n", str1);

能不能輸出東西?能不能輸出中文 當(dāng)然能,那這個str1 字節(jié)碼到底是什么字節(jié)碼, 只要我們把這個搞明白就可以了。一切未知的恐懼源于不明白。我們先調(diào)試C++代碼 取到字節(jié)碼,然后編寫下面這兩句C#代碼:

 byte[] bts2 = new byte[] { 0xd6, 0xd0, 0x61 };
 Console.WriteLine(Encoding.GetEncoding("gb2312").GetString(bts2));

正常輸出了C++代碼里的中文 由此可見C++里默認(rèn)代碼到字節(jié) 的字面量轉(zhuǎn)換 就是gb2312 ,就這樣而已。就這樣而已 ,真的就這么點東西 ,不要探究是什么機(jī)制驅(qū)使VC++默認(rèn)把字符串轉(zhuǎn)換到了gb2312編碼,事情不要歪呀歪的想想復(fù)雜了,人的精力是有限的 要放在有作用的地方。你看C++里是char [ ] 還不像C#的string經(jīng)過包裝的 更便于你想明白這個過程。不是說C++有std庫么 不是有string 么 還沒講呢 ,C++這門語言呢又好又不好 設(shè)計特點是暴露的細(xì)節(jié)多 各個細(xì)節(jié)你都可以自己控制 讓會用的人知道自己在做什么 ,但是也有些坑,其實string 就是char[] 的變種而已。你看C++里 在你琢磨不透的情況下悄然在你不知情編碼的情況下轉(zhuǎn)換成了字節(jié)碼,C#的string 封裝的 不會給你這個機(jī)會 有明確的Encoding庫調(diào)用指定編碼。

窄字符和寬字符 ,怎么個寬法

C++里字符串的字面量分為兩種 一種是普通的窄字符 ,也就是普通的char [ ] 一個元素占1字節(jié), 另一種是寬字符 wchar_t [ ] 一個元素占2字節(jié),_T("中a") 或者L"中a" 這種就是強(qiáng)行表示Unicode寬字符字面量。 寬字符 怎么個寬法呢,我們說他是Unicode 也就是utf-16,我們用C#進(jìn)行驗證:

 byte[] bts3 = new byte[] {  0x2d,0x4e, 0x61,0x00, };
 Console.WriteLine(Encoding.Unicode.GetString(bts3));

好了,這就明朗了,C++這玩意兒 由于歷史遺留原因,直接在代碼書寫字符串字面量搞了兩套標(biāo)準(zhǔn) 窄字符和寬字符 ,你看上面的同字符里面的字節(jié)碼整的兩套標(biāo)準(zhǔn) 這就很扯,整的被迫大多數(shù)C++的函數(shù) 或者接口都要按照這個套路玩。就有了看到的MessageBoxA ()接受char[]窄字符參數(shù),MessageBoxW()接受寬字符參數(shù) ,不要有誤區(qū)哈 覺得char[ ] 就不能輸出中文 ,能不能是由對應(yīng)的地方能不能解析這個字節(jié)碼決定的 而不是其他。

關(guān)于UTF-8

utf-8的現(xiàn)實意義更大于編程的字面量意義 ,為什么這么說,現(xiàn)在網(wǎng)絡(luò) 數(shù)據(jù)交換都是UTF-8 編碼,C++編程 字面量 沒有所謂UTF-8這個說法 ,UTF-8是一種落地編碼,落地編碼 懂嗎?就像圖像編程 保存最終格式有.jpg .png,utf-8 他是變長的 對于字符串處理會出現(xiàn)很多問題 不利于程序處理,圖像編程中不管你jpg png格式也好載入到內(nèi)存中最后都是易于處理的BMP內(nèi)存映像。編程中都是Unicode因為2字節(jié)代表一個字符 標(biāo)標(biāo)準(zhǔn)準(zhǔn)的 是對齊的,利于編程處理。還有 utf-8 一個中文3字節(jié) 其實比utf-16 一個中文2字節(jié) 多, 但是如果是英文的話 就是1字節(jié) 可以實現(xiàn)Unicode到ASCII的無縫轉(zhuǎn)換 可以處理一些老舊系統(tǒng)的兼容問題。 C++里Unicode可以通過手段轉(zhuǎn)換為UTF-8:

void UnicodeToUtf8(const wchar_t* unicode,char  utf82[],int * lenout)
{
    int len;
    len = WideCharToMultiByte(CP_UTF8, 0, unicode, -1, NULL, 0, NULL, NULL);
    char szUtf82[50] = { 0 };
    *lenout = len;
    WideCharToMultiByte(CP_UTF8, 0, unicode, -1, utf82, len, NULL, NULL);
}

關(guān)于VC++項目屬性里的設(shè)置字符集

什么意思呢:

當(dāng)選擇“使用Unicode字符集”時,編譯器會增加宏定義——UNICODE;而選擇“使用多字節(jié)字符集”時,編譯器則不會增加宏定義——UNICODE。https://blog.csdn.net/huashuolin001/article/details/95620424
當(dāng)選用“使用Unicode字符集”時,調(diào)用函數(shù)MessageBox,實際使用的是MessageBoxW,MessageBoxW關(guān)于字符串的入?yún)㈩愋褪荓PCWSTR,使用MessageBox時,字符串前需加L::MessageBox(NULL, L"這是一個測試程序!", L"Title", MB_OK);

多字節(jié),默認(rèn)的窄字符char[]帶中文 就是典型的多字節(jié),接上面章節(jié)說明 多字節(jié)+中文 對于字符串處理分割 會帶來很多問題,所以帶中文請盡量使用寬字符。然后另一個 基于gb2312和Unicode編碼我就不細(xì)說了哈,如果你想你的程序能夠賣到國外在世界范圍內(nèi)使用,那么請使用Unicode,也就是 L" " 寬字符。C++里這些概念搞的比較糊 ,我描述的這些也是個意會 ,也許某些細(xì)節(jié)部分說錯了 像原來文章里那些評論里那樣 尖銳的指出來 不怕批評。

最后 ,一些測試的大雜燴代碼:

// ConsoleApplication1.cpp : 定義控制臺應(yīng)用程序的入口點。
//
#include "stdafx.h"
#include <iostream>
#include "h1.h"
#include "FqTabData.h"
#include "test1.h"
#include <windows.h>
#include <string>
#include <iomanip>
#include <type_traits>
using namespace std;
//引用的使用方式
void test1(int &r){
    r = r+1;
}
void UnicodeToUtf8(const wchar_t* unicode,char  utf82[],int * lenout)
{
    int len;
    len = WideCharToMultiByte(CP_UTF8, 0, unicode, -1, NULL, 0, NULL, NULL);
    char szUtf82[50] = { 0 };
    *lenout = len;
    WideCharToMultiByte(CP_UTF8, 0, unicode, -1, utf82, len, NULL, NULL);
}
int _tmain(int argc, _TCHAR* argv[])
{
    setlocale(LC_ALL, "");//注意控制臺輸出要先加上這句哈要不然無法輸出中文
    wchar_t wstr2[] = L"中a";
    wprintf(L"%ls\r\n", wstr2);
    char str1[] = "中ab";
    printf("%s\r\n", str1);
    return 0;
    //關(guān)于c++里的編碼問題
    //    并非 不在在項目屬性里設(shè)置編碼字符集 為Unicode 就不能顯示中文
    //char str11[] = "中a";         printf("%s", str11);
    //這段代碼照樣顯示中文,中a被編譯器編成3個元素存在str11 里+\0結(jié)尾
    //當(dāng)選擇“使用Unicode字符集”時,編譯器會增加宏定義——UNICODE;而選擇“使用多字節(jié)字符集”時,編譯器則不會增加宏定義——UNICODE。
    //https://blog.csdn.net/huashuolin001/article/details/95620424
    //當(dāng)選用“使用Unicode字符集”時,調(diào)用函數(shù)MessageBox,實際使用的是MessageBoxW,MessageBoxW關(guān)于字符串的入?yún)㈩愋褪荓PCWSTR,
    //使用MessageBox時,字符串前需加L
    //::MessageBox(NULL, L"這是一個測試程序!", L"Title", MB_OK);
    //關(guān)于這個L ,等同于_T("")  Tchar 這些玩意兒他們都有同等意義
    //可以傻瓜的理解 L 本身就是搞一個寬字符型 字符串 ,每個字符占2字節(jié)
    //wchar_t ws[] = L"國家";
    //設(shè)置為Unicode 就意味著寬字符 就意味著字符串 要加L
    //就像前面的 好多函數(shù)接口有兩種版本 MessageBoxA MessageBoxW ,
    //MessageBoxW就意味著你要傳一個寬字符數(shù)組進(jìn)去 也就是 wchar_t 或者L"dd"
    //注意多字節(jié)字符集是一個很容易讓人費解的玩意兒,
    //我們說  utf-8是 一種Unicode的落地編碼
    //編程里都是用 Unicode 不管項目設(shè)沒設(shè)置Unicode字符集 wchar_t ws[] = L"國家"; 得到的都是寬字符串
    //但是編程代碼里 沒有utf-8 這一說法 utf-8是變長的 也就是多字節(jié)   他是一種編碼落地
    //你想想你整個變長 別人接口怎么寫 ,怎么達(dá)到在讓你用變長省內(nèi)存的同時 識別你的有效字符
    //如果數(shù)組里存utf-8 你想想 別人要以字節(jié)數(shù)讀字符 半個的時候怎么搞
    //這跟gdi圖像處理是同一個道理 jpg png 各種是落地格式都可以讀進(jìn)來 但是到內(nèi)存都是bmp
    //還有不論哪種printf 或者其他接口 都不支持所謂的utf-8的參數(shù) 也沒這種接口可言
    //https://zhuanlan.zhihu.com/p/23190549
    //前幾天在微博上受到了@Belleve給我的啟發(fā),于是簡單地實現(xiàn)了幾個在 Windows
    //下接受 UTF - 8 參數(shù)的 printf 系列函數(shù)。大致思路是判斷當(dāng)前 stdout / stderr
    //是否為控制臺,如果是控制臺則將參數(shù)轉(zhuǎn)為 UTF - 16 后調(diào)用 wprintf 輸出,否則不轉(zhuǎn)換直接調(diào)用 printf。
    //L 是一個很微妙的 ,稱之為轉(zhuǎn)換為寬字符的字面量  什么叫字面量 根據(jù)你當(dāng)前編程環(huán)境 以及源代碼編碼 轉(zhuǎn)換成對應(yīng)的字節(jié)
    //L"發(fā)" 字面量 你細(xì)品
    setlocale(LC_ALL, "");
    printf("--------------------");
    //wchar_t wc = L'破';
    std::wstring wstr = L"破a的";
    std::cout << wstr.size() << std::endl;
    //utf-8 只是流行 ,事實上utf-8 一個漢字要占3字節(jié)  而utf-16一個漢字一字節(jié)
    /*wchar_t wstr2[] = L"破曉S";
    wprintf(L"%ls", wstr2);*/
    printf("--------------------//");
    char utf82[50] = { 0 };
    int len = 0;
    UnicodeToUtf8(wstr2, utf82, &len);
    //char* str222 = UnicodeToUtf8(wstr2);
    //printf("%S", str222);
    //printf("aaa");
    return 0;
    //
    //c++ 中指針的變種  引用的使用方式
    printf("aaa\r\n");
    int a = 123;
    int& b = a;
    a = 456;
    printf("%d \r\n", b);
    test1(b);
    printf("%d \r\n", b);
    int c = 345;
    test1(c);
    printf("%d \r\n", c);
    return 0;
}

到此這篇關(guān)于C++中的字符串編碼處理的文章就介紹到這了,更多相關(guān)C++字符串編碼內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C語言線性表的鏈?zhǔn)奖硎炯皩崿F(xiàn)詳解

    C語言線性表的鏈?zhǔn)奖硎炯皩崿F(xiàn)詳解

    線性表的鏈?zhǔn)酱鎯μ攸c則是用一組任意的存儲單元存儲線性表的數(shù)據(jù)元素。這組存儲單元既可以是連續(xù)的,也可以是不連續(xù)的。本文將詳解一下C語言線性表的鏈?zhǔn)奖硎炯皩崿F(xiàn),感興趣的可以了解一下
    2022-07-07
  • 一步步從底層入手搞定C++引用與內(nèi)聯(lián)函數(shù)

    一步步從底層入手搞定C++引用與內(nèi)聯(lián)函數(shù)

    內(nèi)聯(lián)函數(shù)是代碼插入到調(diào)用者代碼處的函數(shù),內(nèi)聯(lián)函數(shù)通過避免被調(diào)用的開銷來提高執(zhí)行效率,下面這篇文章主要給大家介紹了關(guān)于如何從底層入手搞定C++引用與內(nèi)聯(lián)函數(shù)的相關(guān)資料,需要的朋友可以參考下
    2023-03-03
  • C語言strtod()函數(shù)案例詳解

    C語言strtod()函數(shù)案例詳解

    這篇文章主要介紹了C語言strtod()函數(shù)案例詳解,本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-07-07
  • c++中cin/cout與scanf/printf的區(qū)別比較

    c++中cin/cout與scanf/printf的區(qū)別比較

    這篇文章主要介紹了c++中cin/cout與scanf/printf的區(qū)別比較,需要的朋友可以參考下
    2017-06-06
  • C語言實現(xiàn)簡單版三子棋

    C語言實現(xiàn)簡單版三子棋

    這篇文章主要為大家詳細(xì)介紹了C語言實現(xiàn)簡單版三子棋,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-10-10
  • Microsoft Visual C++ 程序的部署方法

    Microsoft Visual C++ 程序的部署方法

    由Microsoft Visual C++編譯的程序動態(tài)鏈接到C運(yùn)行時(/MD 或 /MDd),它必須捆綁C運(yùn)行DLL的一份拷貝(通常被叫作MSVCRT.DLL 或 MSVCRxx.DLL,其中xx代表Visual C++的版本)
    2013-04-04
  • C++11異步與通信之std::async的使用

    C++11異步與通信之std::async的使用

    std::async 異步運(yùn)行一個函數(shù),將返回值保存在std::future中,本文主要介紹了C++11異步與通信之std::async的使用,具有一定的參考價值,感興趣的可以了解一下
    2023-08-08
  • Opencv開發(fā)實現(xiàn)拼圖游戲

    Opencv開發(fā)實現(xiàn)拼圖游戲

    這篇文章主要為大家詳細(xì)介紹了Opencv開發(fā)實現(xiàn)拼圖游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-07-07
  • C語言模式實現(xiàn)C++繼承和多態(tài)的實例代碼

    C語言模式實現(xiàn)C++繼承和多態(tài)的實例代碼

    本篇文章主要介紹了C語言模式實現(xiàn)C++繼承和多態(tài)的實例代碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-07-07
  • C++實現(xiàn)MyString的示例代碼

    C++實現(xiàn)MyString的示例代碼

    本文主要介紹了C++實現(xiàn)MyString的示例代碼,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-02-02

最新評論