ASCII是基本的文字編碼方式,它的方式是用一個字節Byte來表示一個符號,好比說0x30表明'0',而0x41表明'A',這個連接有詳細的ASCII每一個數字對應的字符。
如下的C代碼打印出你所須要的ASCII符號 'A':linux
printf("ASCII: %c\r\n", 0x41); // 或者 printf("ASCII: %c\r\n", 'A');
但你們可能會有疑問,一個字節一共有256個值,明明可使用256個字符,爲何ASCII只有128個?若是是printf("Code Page: %c\r\n", 0xA0);
會打印出什麼結果?
答案是另外128個字符預留給了不一樣的Code Page(碼頁)。爲了打印出各個國家的符號,咱們定義了多個碼頁,通常來講每一個碼頁第0-127 是同樣的,即拉丁數字和26個英文字母等經常使用符號,而第128-255是根據每一個碼頁而不一樣的。好比說Visual Studio的系統預設(default)的碼頁是Code Page 437。所以上面的代碼會打印出:windows
printf("Code Page: %c\r\n", 0xA0); //結果 Code Page: á
咱們能夠切換不一樣的碼頁,好比說Code Page 864 有阿拉伯文字所需的符號。Code Page 932 有日文符號。數組
// Code Page 932 Japanese SetConsoleOutputCP(932); // Set to Code Page 932 printf("Code Page: %c\r\n", 0xC0); // 結果 Code Page: タ
這個連接 是目前windows 支持的碼頁ID(SetConsoleOutputCP
支持的參數)。網絡
接下來你們可能會想到這個問題,咱們的中文一共可不止128個字符,常常使用的中文字符大約有5000個,是沒法使用碼錶來表示的。
所以咱們用Unicode來包含更多的字符,咱們只須要使用Unicode就能夠表示不一樣國家的文字,無需在不一樣文字系統之間系統切換。Unicode的想法很是直接,就是用多個字節Byte來表示文字符號。
在Unicode中,經常使用的編碼方式用兩種,一個是UTF-8,一個是UTF-16。ide
UTF-8是最爲經常使用的編碼方式,這種方式最大的優勢是它和ASCII碼錶是通用的。這種編碼方式中,咱們用1-4的字節來表示一個文字符號。網上有很多查詢UTF-8/16的工具,連接。若是咱們想知道「你們好」的UTF-8的值,一次查詢每個文字字符,咱們獲得:工具
大:0xE5 0xA4 0xA7 家:0xE5 0xAE 0xB6 好:0xE5 0xA5 0xBD
咱們能夠在Windows系統中用gcc編譯下面的UTF-8測試文件並運行測試
#include <stdio.h> #include <Windows.h> int main( int argc, char **argv ) { char PrintData[] = { 0xE5, 0xA4, 0xA7, 0xE5, 0xAE, 0xB6, 0xE5, 0xA5, 0xBD, 0x00}; //0x00 is for NUL termination SetConsoleOutputCP(65001); printf( "%s\n", PrintData); return 0; } // 輸出 你們好
這種編碼方式中,咱們固定用兩個字節來表示一個文字符號。這種編碼的優點在於由於長度是固定的,因此利於存儲。咱們能夠方便地創建一個uint16_t的數組來存儲UTF-16。若是咱們想知道「你們好」的UTF-16的值,一次查詢每個文字字符,咱們獲得:ui
大:0x5927 家:0x5BB6 好:0x597D
咱們也能夠在Visual Studio中打印出UTF-16編碼的「你們好」(參考連接1, 參考連接2):編碼
// Windows System #include <stdio.h> #include <windows.h> #include <fcntl.h> #include <io.h> int main () { wchar_t SampleData[] = {0x5927, 0x5BB6, 0x597D, 0x0}; _setmode(_fileno(stdout), _O_U16TEXT); wprintf(L"%s\n", SampleData); return 0; } // Linux System #include <stdio.h> #include <wchar.h> #include <stdlib.h> #include <locale.h> int main() { setlocale(LC_ALL,""); wchar_t SampleData[] = {0x5927, 0x5BB6, 0x597D, 0x0}; wprintf(L"%ls\n", SampleData); }
int8_t Utf8To16Converter(const uint8_t * Utf8Val, uint16_t * Utf16Result, uint16_t NumOfUtf8Byte) { int8_t Status = 0; // -1 for process fail uint16_t Utf16Val = 0; uint8_t TrailingNumOfBytes = 0; // The number of bytes of UTF8 is 1 - 4 uint16_t i = 0; const uint8_t * InputTraveler; InputTraveler = Utf8Val; while (i < NumOfUtf8Byte) { if (*InputTraveler <= 0x7F) { Utf16Val = *InputTraveler; TrailingNumOfBytes = 0; } else if (*InputTraveler <= 0xBF) { Status = -1; } else if (*InputTraveler <= 0xDF) { Utf16Val = (*InputTraveler) & 0x1F; TrailingNumOfBytes = 1; } else if (*InputTraveler <= 0xEF) { Utf16Val = (*InputTraveler) & 0x0F; TrailingNumOfBytes = 2; } else if (*InputTraveler <= 0xF7) { Utf16Val = (*InputTraveler) & 0x07; TrailingNumOfBytes = 3; } else { Status = -1; } if (-1 == Status) { break; } else { uint8_t j; for (j = 0; j < TrailingNumOfBytes; j++) { InputTraveler ++; if (*InputTraveler == 0x0) { Status = -1; break; } else { Utf16Val <<= 6; Utf16Val += (*InputTraveler) & 0x3F; } i ++; } if (-1 == Status) { break; } else { *Utf16Result = Utf16Val; Utf16Result ++; InputTraveler ++; i ++; Utf16Val = 0; TrailingNumOfBytes = 0; } } } return Status; } int8_t Utf16ToUtf8Converter(const uint16_t * Utf16Val, uint8_t * Utf8Result, uint16_t NumOfUtf16Vals) { int Status = 0; uint8_t Utf8Val; uint16_t i = 0; for (i = 0; i < NumOfUtf16Vals; i++) { uint16_t Utf16TempVal = Utf16Val[i]; if (Utf16TempVal <= 0x7F) { *(Utf8Result) = (uint8_t)Utf16TempVal; Utf8Result ++; } else if (Utf16TempVal <= 0x7FF) { *(Utf8Result) = 0xC0 | (Utf16TempVal >> 6); /* 110xxxxx */ Utf8Result ++; *(Utf8Result) = 0x80 | (Utf16TempVal & 0x3F); /* 10xxxxxx */ Utf8Result ++; } else if (Utf16TempVal <= 0xFFFF) { *(Utf8Result) = 0xE0 | (Utf16TempVal>> 12); /* 1110xxxx */ Utf8Result ++; *(Utf8Result) = 0x80 | ((Utf16TempVal >> 6) & 0x3F); /* 10xxxxxx */ Utf8Result ++; *(Utf8Result) = 0x80 | (Utf16TempVal & 0x3F); /* 10xxxxxx */ Utf8Result ++; } else if (Utf16TempVal <= 0x10FFFF) { *(Utf8Result) = 0xF0 | (Utf16TempVal >> 18); /* 11110xxx */ Utf8Result ++; *(Utf8Result) = 0x80 | ((Utf16TempVal >> 12) & 0x3F); /* 10xxxxxx */ Utf8Result ++; *(Utf8Result) = 0x80 | ((Utf16TempVal >> 6) & 0x3F); /* 10xxxxxx */ Utf8Result ++; *(Utf8Result) = 0x80 | (Utf16TempVal & 0x3F); /* 10xxxxxx */ Utf8Result ++; } else { Status = -1; } if (-1 == Status) { break; } } return Status; }