unicode编码表(ascii编码与unicode编码)
- 知识
- 2021-06-03
- 366热度
- 0评论
unicode编码表
ascii编码与unicode编码
01
ascii编码
定义字符数组 szHello ,初值为 "Hello"。编写程序1:
#include<stdio.h>#include<string.h>#include<stdlib.h>
int main(int argc, char* argv[]){ char szHello[] = "Hello"; printf("%srn", szHello); system("pause"); return 0;}
按 F10 进行单步调试,发现 Hello 字符串的每个字符在内存中各占一个字节,这就是 ascii码 。由美国人发明,所以只出现大小写英文字母、数字和一些符号。因此,最早只有127个字符被编码到计算机里,也就是 7位 2进制数字,最高位(第八位)为 0 。
这个编码表被称为 ascii编码,比如大写字母 H 的编码是 72(16进制48),小写字母 o 的编码是 111(16进制6F)。
02
unicode编码
定义字符数组 szHello ,初值为 "Hello同学们"。编写程序2:
#include<stdio.h>#include<string.h>#include<stdlib.h>
int main(int argc, char* argv[]){ char szHello[] = "Hello同学们"; printf("%srn", szHello); system("pause"); return 0;}
按 F10 进行单步调试,发现字符串 "Hello" 的每个字符在内存中仍各占一个字节,但是字符串 "同学们",每一个汉子在内存中却占两个字节。
这是因为,在中国1990年出版的《辞海》就高达14872个汉字,上面提到的 ascii编码,每个字只用一个字节表示,最多可表示 256 个字,显然是远远不够的,至少需要两个字节,而且还不能和ASCII编码冲突,所以,中国制定了GB2312编码,用来把中文编进去。
可以想得到的是,全世界有上百种语言,日本,韩国等,并且各国有各国的标准,就会不可避免地出现冲突,结果就是,在多语言混合的文本中,显示出来会有乱码。
因此,unicode编码应运而生。unicode编码在内存中占两个字节,最多可表示 65535 个字,可以把所有语言都统一到一套编码里,这样就解决了乱码问题。
通过调试结果也可以看出,字节值为正数,用 ascii 编码表示英文;字节值负数,用 unicode 编码表示中文。
编译执行,并不会出现乱码输出。
03
程序使用unicode编码
但是如果在英文中文混用的情况下,编译器判断一个字节出错时,会连续判断错误,造成大面积的乱码。例如将 6F 改为 8F,如下图所示,导致"同学们"字符串均发生乱码。
因为中英文混用时,内存中一会占一个字节,一会占两个字节,编译器处理的难度会提升很多,容易造成乱码现象。利用空间换时间的思维,不论英文还是中文,都利用 unicode编码方式,全部在内存空间中占两个字节。
将内存空间占一个字节的变量类型 char ,改为内存空间占两个字节的变量类型 unsigned short int 。编写程序3:
#include<stdio.h>#include<string.h>#include<stdlib.h>
int main(int argc, char* argv[]){ unsigned short int szHello[] = "Hello同学们"; printf("%srn", szHello); system("pause"); return 0;}
因为字符串 "Hello同学们" 仍是 ascii编码方式,所以编译未通过,提示无法从 char [12] 转换为 unsigned short [],没有可以进行这种转换的环境。
在字符串前加 L ,如 L"我的字符串" 表示将 ascii编码字符串转换成 unicode编码的字符串。在字符串 "Hello同学们" 前加 L,编写程序4:
#include<stdio.h>#include<string.h>#include<stdlib.h>
int main(int argc, char* argv[]){ unsigned short int szHello[] = L"Hello同学们"; printf("%srn", szHello); system("pause"); return 0;}
编译通过。按 F10 进行单步调试,字符串中的每个字符和汉字都各占两个字节的内存空间。
printf 函数是按 ascii编码方式打印,默认字符串 结尾,因为字符串 "Hello同学们" 是 unicode编码,所以在 H 字符后是 00 ,printf 看见 00 结束打印,只输出 H 。
查看 MSDN 可知,打印 unicode编码字符串,必须要用 wprintf 函数。因为 wprintf函数是 printf函数的宽字节版本,但两函数的行为相同。
将 printf 函数改为 wprintf 函数。编写程序5:
#include<stdio.h>#include<string.h>#include<stdlib.h>
int main(int argc, char* argv[]){ unsigned short int szHello[] = L"Hello同学们"; wprintf(L"%s", szHello); system("pause"); return 0;}
编译执行,只输出了 Hello,而中文部分字符串"同学们"却没有输出。
只有利用 setlocale 函数,设置当前位置,才能显示中文部分的字符串。查看 MSDN,输出简体中文用 "chs" 。
根据 MSDN 获取到的修改方式,编写程序6:
#include<stdio.h>#include<string.h>#include<stdlib.h>#include <locale.h>
int main(int argc, char* argv[]){ setlocale(LC_ALL, "chs"); unsigned short int szHello[] = L"Hello同学们"; wprintf(L"%srn", szHello); system("pause"); return 0;}
编译执行,输出 "Hello同学们" 成功。
04
可选择使用ascii编码或unicode编码
利用编译选项宏实现 ascii编码方式和unicode编码方式的随时切换,思路为如果定义宏 MYUNICODE ,代码全部为 unicode编码模式,否则代码全部为 ascii编码模式。编写程序7:
#include<stdio.h>#include<string.h>#include<stdlib.h>#include <locale.h>
#define MYUNICODE
#ifdef MYUNICODE#define TCHAR unsigned short int#define _tprintf wprintf#define _tmain wmain#define _tsetlocale _wsetlocale#define _tsystem _wsystem#define _T(x) L ## x
#else #define TCHAR char #define _tprintf printf#define _tmain main#define _tsetlocale setlocale#define _tsystem system#define _T(x) x
#endif
int main(int argc, char* argv[]){ _tsetlocale(LC_ALL, _T("chs")); TCHAR szHello[] = _T("Hello同学们"); _tprintf(_T("%srn"), szHello); _tsystem(_T("pause")); return 0;}
按 F10 进行单步调试,字符串以 unicode编码方式在内存中存储。
注释掉宏 MYUNICODE 。编写程序8:
#include<stdio.h>#include<string.h>#include<stdlib.h>#include <locale.h>
// #define MYUNICODE
#ifdef MYUNICODE#define TCHAR unsigned short int#define _tprintf wprintf#define _tmain wmain#define _tsetlocale _wsetlocale#define _tsystem _wsystem#define _T(x) L ## x
#else #define TCHAR char #define _tprintf printf#define _tmain main#define _tsetlocale setlocale#define _tsystem system#define _T(x) x
#endif
int main(int argc, char* argv[]){ _tsetlocale(LC_ALL, _T("chs")); TCHAR szHello[] = _T("Hello同学们"); _tprintf(_T("%srn"), szHello); _tsystem(_T("pause")); return 0;}
按 F10 进行单步调试,字符串以 ascii编码方式在内存中存储。
更多精彩
扫码关注