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; }