本文使用代碼參考於https://www.cnblogs.com/leemang/p/3215499.html
一、全角字符
全角字符(Full-width characters)指一個字符占用兩個標准字符位置,漢字字符和規定了全角的英文字符及國標GB2312-80中的圖形符號和特殊字符都是全角字符。
二、半角字符
半角字符(Half-width characters)占用1個字節位置,可以由ASCII碼表示
三、半角字符(標准字符)出現的原因
在計算機系統中,所有的數據在存儲和運算時都要使用二進制數表示(因為計算機用高電平和低電平分別表示1和0);我們可以用我們的語言中的唯一符號映射唯一一個二進制數,這樣我們就能在計算機中表達自己的意思了,比如用數字0來表示二進制數0011 0000 ,每個人都可以按照自己的想法設計一條映射規則(編碼)。不過如果這樣的話不同編碼規則之間的交流就有很大的障礙了,不同的編碼類似於各地的方言,沒有經過學習就無法理解對方編碼的意思。為了統一規范 ASCII(American Standard Code for Information Interchange, 美國信息交換標准代碼)出現了。
ASCII是基於拉丁字母的一套電腦編碼系統,主要用於顯示現代英語和其他西歐語言。它是最通用的信息交換標准,並等同於國際標准ISO/IEC 646。ASCII第一次以規范標准的類型發表是在1967年,最后一次更新則是在1986年,到目前為止共定義了128個字符。
四、ASCII碼
ASCII 碼使用指定的7 位或8 位二進制組合來表示128 或256 種可能的字符。標准ASCII 碼也叫基礎ASCII碼,使用7 位二進制數(剩下的1位二進制為0)來表示所有的大寫和小寫字母,數字0 到9、標點符號,以及在美式英語中使用的特殊控制字符。其中0~31及127(共33個)是控制字符或通信專用字符(其余為可顯示字符)。
在標准ASCII中,其最高位(b7)用作奇偶校驗。所謂奇偶校驗,是指在代碼傳送過程中用來檢驗是否出現錯誤的一種方法,分為奇校驗和偶校驗兩種。奇校驗規定:正確的代碼一個字節中1的個數必須是奇數,若非奇數,則在最高位b7添1;偶校驗規定:正確的代碼一個字節中1的個數必須是偶數,若非偶數,則在最高位b7添1。
后128個稱為擴展ASCII碼。許多基於x86的系統都支持使用擴展(或“高”)ASCII。擴展ASCII 碼允許將每個字符的第8 位用於確定附加的128 個特殊符號字符、外來語字母和圖形符號。
五、計算機中的漢字的表示方法
我們可以發現使用128中組合就已經能夠表示出全部的英文內容了,但是這個世界的語言不止英語一種,我們中國的漢字常用的就有幾千個,區區256種是遠遠不夠的,所以想要在計算機中表示漢字,我們需要尋找別的方式。
為了與ASCII碼具有某種兼容性,同時解決中國等國家象形符號數量的問題,出現了雙字節字符集。使用兩個字節表示一個漢字,理論上最多可以表示 256 x 256 = 65536 個符號。當然肯定不是看起來這么簡單的,我們漢字編碼從1980年制定的GB2312-80(采用擴展 ASCII 碼的編碼空間進行編碼,一個漢字占用兩個字節,每個字節的最高位為 1) 標准到1995年制定的《漢字內碼擴展規范》(GBK)(使用雙字節編碼,編碼空間為 0x8140~0xFEFE,共有 23940 個碼位,其中 GBK1 區和 GBK2 區也是 GB2312 的編碼范圍)到最后出現的GB18030編碼標准《信息交換用漢字編碼字符集基本集的補充》,編碼容量不斷擴大,直到能夠完整包括所有的中國漢字。
現在我們知道漢字是由兩個字節表示的,形象來說如果一次只能刪除一字節內容的話要刪兩次才能刪掉,一次只能刪一半
六、全角字符與半角字符舉例
七、在C語言中如何轉換全角字符與半角字符
要解決全角轉半角的問題,我們首先要知道,全角字符和半角字符是如何區分的。
通過查詢規則我們知道全角字符的第一個字節總是等於163,第二個字節是相同半角字節加上128(空格除外)而中文的第一個字節是大於163的。
驗證全角符號
#include <stdio.h> int main(void) { char strBuff[2 + 1] = "A"; char firstch = strBuff[0]; char secondch = strBuff[1]; printf("字符A的第一個字節為[%0x]\n", firstch); printf("字符A的第二個字節為[%0x]\n", secondch); return 0; }
結果如下:
我們通過將字符&0xff的方式將低八位的數據取出來
進行一下進制轉換
16進制的A3 = 十進制的163
16進制的C1 = 十進制的193
193 - 128 = 65
查詢ASCII碼表發現65就是大寫字母A的ASCII值
驗證全角空格的特殊性
通過結果可以發現全角空格的兩個字節都是十六進制的A1也就是十進制的161,而半角空格只有一個字節有值,值是十六進制的20也就是十進制的32
驗證漢字
十六進制CD等於十進制203 大於163
由此,我們知道了全角字符與半角字符的轉換規則可以開始設計我們的代碼了
八、代碼實現
全角字符轉半角字符
關鍵點一、漢字
因為漢字就是雙字節編碼,所以沒有轉換的必要,要真砍了一字節看到的就都是亂碼了
實現邏輯如下
關鍵點二、空格
半角空格ASCII值32,十六進制值20,全角空格十六進制值A1A1
實現邏輯如下圖
關鍵點三、其他可見字符
按照關系依次轉換就好了
完整代碼
void FullToHalf(char *strBuff, char *strResult) { for(; *strBuff; ++strBuff) { if((*strBuff & 0xff) == 0xA1 && (*(strBuff + 1) & 0xff) == 0xA1) //全角空格 { *strResult++ = 0x20; ++strBuff; } else if((*strBuff & 0xff) == 0xA3 && (*(strBuff + 1) & 0xff) >= 0xA1 && (*(strBuff + 1) & 0xff) <= 0xFE)//ASCII碼中可見字符 { *strResult++ = *++strBuff - 0x80; } else { if(*strBuff < 0) //如果是中文字符,則拷貝兩個字節 { *strResult++ = *strBuff++; } *strResult++ = *strBuff; } } *strResult = 0; }
同理是可實現半角轉全角
半角字符轉全角字符
void HalfToFull(char *strBuff, char *strResult) { for(; *strBuff; ++strBuff) { if((*strBuff & 0xff) == 0x20) //半角空格 { *strResult++ = 0xA1; *strResult++ = 0xA1; } else if((*strBuff & 0xff) >= 0x21 && (*strBuff & 0xff) <= 0x7E) { *strResult++ = 0xA3; *strResult++ = *strBuff + 0x80; } else { if(*strBuff < 0) //如果是中文字符,則拷貝兩個字節 { *strResult++ = *strBuff++; } *strResult++ = *strBuff; } } *strResult = 0; }