請教C++是如何識別雙位元組字符的?比如漢字。謝謝
比如:
有文本檔案TEST.TXT,只有一行,總共3個位元組,內容如下:
A好
如何把第2和第3個位元組識別成漢字"好"?
特別是在記憶體中指標移動位元組時。
謝謝
uj5u.com熱心網友回復:
按照編碼,有ansi(多位元組字符集) utf8 unicode
uj5u.com熱心網友回復:
ascii碼只用到了7位,最高位不為1,如果是1,則按雙位元組處理。uj5u.com熱心網友回復:
控制臺里面認的漢字編碼只有GBK或者GB2312這種情況下,漢字是雙位元組, 而且每個位元組的ascii值都大于127
從頭開始,兩個連續的ascii值都大于127的位元組就是一個漢字
( str[I]&0x80 && str[I+1]&0x80 ) 滿足這個條件的 str[I]和str[I+1]共同構成了一個漢字
uj5u.com熱心網友回復:
String可以存盤漢字啊?
uj5u.com熱心網友回復:
兩虛的兩個位元組,且必須每個位元組的最高位都是1,就是漢字,或者是雙位元組字符?
還是高位的最高位是1,低位的最高位是0?
謝謝
uj5u.com熱心網友回復:
謝謝大神
兩虛的兩個位元組,且必須每個位元組的最高位都是1,就是漢字,或者是雙位元組字符?
還是高位的最高位是1,低位的最高位是0?
uj5u.com熱心網友回復:
這個就是多位元組漢字“A好”的具體表示,漢字的兩個位元組高位都為1
pszMultiByte[0] 0x41 'A' char
pszMultiByte[1] 0xba '?' char
pszMultiByte[2] 0xc3 '?' char
uj5u.com熱心網友回復:
(1)Unicode檔案的判斷——IsTextUnicode(lpBuffer,cb, lpi)iFileLength = GetFileSize(hFile, NULL);
pBuffer = malloc(iFileLength + 2);//多出兩個位元組存放兩個\0
//讀檔案到緩沖區,并在檔案末尾放\0結束符
ReadFile(hFile, pBuffer, iFileLength, &dwBytesRead, NULL);
CloseHandle(hFile);
pBuffer[iFileLength] = '\0';
pBuffer[iFileLength + 1] = '\0';
//測驗文本是否是Unicode編碼,前兩個位元組為0xFEFF或0xFFFE
//IS_TEXT_UNICODE_SIGNATURE——0xFEFF(小端:高高低低)
//IS_TEXT_UNICODE_REVERSE_SIGNATURE——0xFFFE(大端)
iUniTest = IS_TEXT_UNICODE_SIGNATURE | IS_TEXT_UNICODE_REVERSE_SIGNATURE;
if (IsTextUnicode(pBuffer, iFileLength, &iUniTest)) //最3個引數是個in/out引數。會滿足的那個條件傳給iUniTest
{
pText = pBuffer + 2; //跳過前兩個位元組,指向正文部分
iFileLength -= 2;
if (iUniTest & IS_TEXT_UNICODE_REVERSE_SIGNATURE) //大端存盤,調換位元組順序
{
for (int i = 0; i < iFileLength / 2; i++)
{
bySwap = pText[2 * i];
pText[2 * i] = pText[2 * i + 1];
pText[2 * i + 1] = bySwap;
}
}
//為可能的字串轉換分配記憶體
pConv = malloc(iFileLength + 2);
#ifndef UNICODE //Edit控制元件使用非Unicode,則顯示之前將Unicode文本轉化為多位元組文本
WideCharToMultiByte(CP_ACP, 0, (PTSTR)pText, -1, pConv, iFileLength + 2, NULL, NULL); //共iFileLength+2位元組,含2個\0
#else //Edit控制元件是Unicode,則直接拷貝文本
lstrcpy((PTSTR)pConv, (PTSTR)pText);
#endif
} else //非Unicode檔案
{
pText = pBuffer;
pConv = malloc(2 * iFileLength + 2); //ASCII轉Unicode,需2倍的空間。額外加兩個\0。
//為可能字串轉換分配記憶體
#ifdef UNICODE //Edit控制元件使用Unicode,則顯示之前,將多位元組文本轉化為Unicode文本
MultiByteToWideChar(CP_ACP, 0, pText, -1, (PTSTR)pConv, iFileLength + 1); //找到\0時,總共iFileLength+1個字符(含\0)
#else //Edit控制元件是使用ASCII,則直接拷貝文本
lstrcpy((PTSTR)pConv, (PTSTR)pText);
#endif
}
SetWindowText(hwndEdit, (PTSTR)pConv);
https://www.cnblogs.com/5iedu/p/4695106.html
uj5u.com熱心網友回復:
不做“識別”,只是當做二進制處理uj5u.com熱心網友回復:
https://baike.baidu.com/item/GBK字庫/3910360?fr=aladdin#4_1https://baike.baidu.com/item/字符編碼/8446880?fr=aladdin#4
看看GBK,GB2312的編碼范圍, 其中有明確的說明
uj5u.com熱心網友回復:
體編碼范圍為 8140-FEFE,首位元組在 81-FE 之間,尾位元組在 40-FE 之間,剔除 xx7F 一條線。總計 23940 個碼位,共收入 21886 個漢字和圖形符號,其中漢字(包括部首和構件)21003 個,圖形符號 883 個。
全部編碼分為三大部分:
1. 漢字區。包括:
a. GB 2312 漢字區。即 GBK/2: B0A1-F7FE。收錄 GB 2312 漢字 6763 個,按原順序排列。
b. GB 13000.1 擴充漢字區。包括:
(1) GBK/3: 8140-A0FE。收錄 GB 13000.1 中的 CJK 漢字 6080 個。
(2) GBK/4: AA40-FEA0。收錄 CJK 漢字和增補的漢字 8160 個。CJK 漢字在前,按 UCS 代碼大小排列;增補的漢字(包括部首和構件)在后,按《康熙字典》的頁碼/字位排列。
2. 圖形符號區。包括:
a. GB 2312 非漢字符號區。即 GBK/1: A1A1-A9FE。其中除 GB 2312 的符號外,還有 10 個小寫羅馬數字和 GB 12345 增補的符號。計符號 717 個。
b. GB 13000.1 擴充非漢字區。即 GBK/5: A840-A9A0。BIG-5 非漢字符號、結構符和“○”排列在此區。計符號 166 個。
3. 用戶自定義區:分為(1)(2)(3)三個小區。
(1) AAA1-AFFE,碼位 564 個。
(2) F8A1-FEFE,碼位 658 個。
(3) A140-A7A0,碼位 672 個。
第(3)區盡管對用戶開放,但限制使用,因為不排除未來在此區域增補新字符的可能性。
uj5u.com熱心網友回復:
前面說的是GBK擴展的編碼GB2312則如下:
在使用GB2312的程式中,通常采用EUC儲存方法,以便兼容于ASCII。瀏覽器編碼表上的“GB2312”,通常都是指“EUC-CN”表示法。
每個漢字及符號以兩個位元組來表示。第一個位元組稱為“高位位元組”(也稱“區位元組)”,第二個位元組稱為“低位位元組”(也稱“位位元組”)。
“高位位元組”使用了0xA1-0xF7(把01-87區的區號加上0xA0),“低位位元組”使用了0xA1-0xFE(把01-94加上 0xA0)。 由于一級漢字從16區起始,漢字區的“高位位元組”的范圍是0xB0-0xF7,“低位位元組”的范圍是0xA1-0xFE,占用的碼位是 72*94=6768。其中有5個空位是D7FA-D7FE。
uj5u.com熱心網友回復:
好像是這么回事的uj5u.com熱心網友回復:
如果只是中英文混合,ASCII碼在 0-255 之間。而中文是雙位元組編碼所以可以這樣寫。//=======================================================
// 從start開始 截取中英混合字符 遵循GBK編碼規則
//
//=======================================================
std::string substr(const char * data, int start, int length){
std::string temp = data;
std::string res;
//=======================================================
// 從start開始 截取中英混合字符 遵循GBK編碼規則
//
//=======================================================
for (int i = start; i < temp.length() && i < length; i++){
//==========================================
// 獲取第一位在記憶體中的數值
//==========================================
unsigned short first_char = temp.at(i);
//==========================================
// 初始化第二位在記憶體中的數值
//==========================================
unsigned short sencond_char = 0;
//==========================================
// 如果第2位不越界,初始化第二位在記憶體中的數值
//==========================================
if (i + 1 != length && i + 1 != temp.length()){
sencond_char = temp.at(i + 1);
}
//=================================================
// 如果第一位的字符中包含在0xff81 至 0xffff (GBK編碼)
//=================================================
if (first_char >= 0xff81 && first_char <= 0xffff){
// 如果第二位有值
if (sencond_char >= 0x40 && sencond_char <= 0xffff){
res += first_char;
res += sencond_char;
// 向右多偏移一位
i++;
}
// 如果第二位已越界
else{
break;
}
}
//==================================================
// 如果第一位不在GBK編碼中
//==================================================
else{
res += first_char;
}
}
return res;
}
uj5u.com熱心網友回復:
不難的。多想想就好了。uj5u.com熱心網友回復:
不能用string的話,你的char型陣列 或者 鏈表肯定有操作手段,代碼都貼了應該不難解決了。uj5u.com熱心網友回復:
謝謝各位大神想請教下
對于GBK字符集,是不是雙位元組字符的高位位元組的第一個bit一定是1? 不限于漢字
uj5u.com熱心網友回復:
文本檔案中都存有編碼資訊,以Windows txt為例,你存一個空內容的txt檔案,但編碼方式選不一樣檔案大小就不一樣,anis是0位元組,Unicode是4位元組,這4位元組就表示用Unicode-le編碼,Unicode又分大端還是小端。在C++中,你用char默認就是ansi字符集,具體編碼方式和作業系統的設定有關,在控制面板里面有設定,當然通過代碼也能改,wchar_t就是小端unicode編碼。另外Unicode和utf-8嚴格來說是不一樣的,Unix上文本檔案默認是utf-8但是沒有標記,windwos 文本的utf-8是帶標記的,所以夸系統的文本檔案非ascii編碼的字符很容易亂碼uj5u.com熱心網友回復:
謝謝各位大神
想請教下
對于GBK字符集,是不是雙位元組字符的高位位元組的第一個bit一定是1? 不限于漢字
編碼范圍為 8140-FEFE,首位元組在 81-FE 之間,尾位元組在 40-FE 之間,剔除 xx7F 一條線
這就告訴你啦。 第一個位元組的高位是1, 第二個不一定了
GB2312雙位元組,都是高位是1
GBK是GB2312的擴展,擴展多出來的不僅僅是漢字還包括其他的一些符號在內
常規來說,你只要判斷第一個位元組高位是1,直接兩個字符放一起當做一個漢字, 大概率不會出錯
uj5u.com熱心網友回復:
IsDBCSLeadByte方法判斷是否漢子的首位元組uj5u.com熱心網友回復:
有沒有Lol專案作者啊uj5u.com熱心網友回復:
???????uj5u.com熱心網友回復:
文本檔案中都存有編碼資訊,以Windows txt為例,你存一個空內容的txt檔案,但編碼方式選不一樣檔案大小就不一樣,anis是0位元組,Unicode是4位元組,這4位元組就表示用Unicode-le編碼,Unicode又分大端還是小端。在C++中,你用char默認就是ansi字符集,具體編碼方式和作業系統的設定有關,在控制面板里面有設定,當然通過代碼也能改,wchar_t就是小端unicode編碼。另外Unicode和utf-8嚴格來說是不一樣的,Unix上文本檔案默認是utf-8但是沒有標記,windwos 文本的utf-8是帶標記的,所以夸系統的文本檔案非ascii編碼的字符很容易亂碼
謝謝
針對GBK
問題1:其實我要區分的是雙位元組字符和單位元組字符
雙位元組字符肯定是高位第一個bit是1,單位元組字符肯定是最高位bit是0?
這樣對嗎?
問題2:對于CPU的大小端, 一個漢字,或者說一個雙位元組字符,其高位和低位位元組位置不一樣的吧?
uj5u.com熱心網友回復:
謝謝各位大神對于比如 漢字“好”
小端CPU的編碼是 BAC3
打斷CPU的編碼會是C3BA碼?
uj5u.com熱心網友回復:
如果只是中英文混合,ASCII碼在 0-255 之間。而中文是雙位元組編碼所以可以這樣寫。
//=======================================================
// 從start開始 截取中英混合字符 遵循GBK編碼規則
//
//=======================================================
std::string substr(const char * data, int start, int length){
std::string temp = data;
std::string res;
//=======================================================
// 從start開始 截取中英混合字符 遵循GBK編碼規則
//
//=======================================================
for (int i = start; i < temp.length() && i < length; i++){
//==========================================
// 獲取第一位在記憶體中的數值
//==========================================
unsigned short first_char = temp.at(i);
//==========================================
// 初始化第二位在記憶體中的數值
//==========================================
unsigned short sencond_char = 0;
//==========================================
// 如果第2位不越界,初始化第二位在記憶體中的數值
//==========================================
if (i + 1 != length && i + 1 != temp.length()){
sencond_char = temp.at(i + 1);
}
//=================================================
// 如果第一位的字符中包含在0xff81 至 0xffff (GBK編碼)
//=================================================
if (first_char >= 0xff81 && first_char <= 0xffff){
// 如果第二位有值
if (sencond_char >= 0x40 && sencond_char <= 0xffff){
res += first_char;
res += sencond_char;
// 向右多偏移一位
i++;
}
// 如果第二位已越界
else{
break;
}
}
//==================================================
// 如果第一位不在GBK編碼中
//==================================================
else{
res += first_char;
}
}
return res;
}
沒看懂,謝謝
uj5u.com熱心網友回復:
文本檔案中都存有編碼資訊,以Windows txt為例,你存一個空內容的txt檔案,但編碼方式選不一樣檔案大小就不一樣,anis是0位元組,Unicode是4位元組,這4位元組就表示用Unicode-le編碼,Unicode又分大端還是小端。在C++中,你用char默認就是ansi字符集,具體編碼方式和作業系統的設定有關,在控制面板里面有設定,當然通過代碼也能改,wchar_t就是小端unicode編碼。另外Unicode和utf-8嚴格來說是不一樣的,Unix上文本檔案默認是utf-8但是沒有標記,windwos 文本的utf-8是帶標記的,所以夸系統的文本檔案非ascii編碼的字符很容易亂碼
謝謝
針對GBK
問題1:其實我要區分的是雙位元組字符和單位元組字符
雙位元組字符肯定是高位第一個bit是1,單位元組字符肯定是最高位bit是0?
這樣對嗎?
問題2:對于CPU的大小端, 一個漢字,或者說一個雙位元組字符,其高位和低位位元組位置不一樣的吧?
問題1:GBK具體編碼還真沒研究過,所以我也不知道,不好意思
問題2:是的,雙位元組的字符大小端不一樣存盤位置就不一樣
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/97370.html
標籤:C++ 語言
下一篇:運行程式時NTL報語法錯誤
