最早的是ASCII字符集,它用一个字节的后7位来表示字母、数字、标点和其他常用字符,所以共有0-127个字符;后来又把第一位用上用来表示其他特殊的字符,这样就可以表示0-255个字符,这称为扩展ASCII(又称IOS-8859-1latin1),latin1向下兼容ASCII。

后来由于其他国家使用的的文字个数远超过使用英语国家的这些256个字符,所以为了支持本国语言在计算机上显示,不同国家开发出了不同的字符集,比如中国大陆一开始使用GB2312,后来扩展成了GBK(完全兼容GB2312),后来又扩展成了GB18030(支持少数民族语言)。而香港、台湾地区使用BIG5,日本使用Shift_JIS字符集。 

GBK编码使用1或2个字节来表示一个字符,比如使用1个字节来表示英文等ASCII字符,使用2个字节来表示一个汉字。对于双字节来说其第一个字节的取值范围是81–FE(129–254),因此如果用一个signed来保存其第一个字节的话,它会是一个负数。

ANSI表示各语言使用的标准化的字符集,比如英文的ANSI字符集是指ASCII,简体中文的ANSI字符集指GBK、日文是Shift_JIS。

MBCS(multi-byte character set)是多字节字符集的意思,他也不是指某个具体的字符集,而是符合这种编码方式的字符集的统称。上面说过,许多非英文国家和地区发明并使用了不同的编码方式(GBK, BIG5, Shift_JIS等),这些本地字符编码就统称为MBCS。常见的有用一个字符来表示一个英文字符,用两个字节来表示一个本地字符的,如GBK,所以又延伸出了DBCS(double byte character set)也就是是双字节字符集这个统称。在VS中工程设置中可以看到有“使用多字节字符集”这个设置,对于我们来说这个就是使用GBK了。

由于不同国家使用不同的本地字符集,其互不兼容,所以后来就出现了UNICODE,它包含了全球不同国家都可以统一使用的字符集。UNICODE其实是一种统称,其具体实现方式又可以分为UTF-8、UTF-16、UTF-32等,而且一般情况下我们说unicode字符集的话默认指的是utf16。

UTF-8是一种变长字符编码,它使用1-6个字节来存储一个字符,比如使用1个字节来存储英文字符,使用2个字符来存储拉丁文,使用3个字符来存储大部分汉字。互联网上基本上都使用UTF-8字符集。

UTF-16使用2或4个字节来存储一个字符,其大部分字符使用2个字节存储就可以了,所以其也是一种变长字符编码。在windows API中,UTF-16被仅以2个字节来存储,因为这两个字节可以表示大部分的字符,比如sizeof(wchar_t)的大小为2,而在linux上的UTF-16是以4个字节存储的,一个wchar_t占4个字节。不同系统对于UTF-16的字节存储顺序会有所不同,Mac会使用大端序(Big-Endian)而Windows和Linux使用小端序(Little-Endian),比如说在Windows下以UTF-16编码保存一个字符“乙”,在Mac OS环境下打开会显示成“奎”。

如果没有特别指出的话,我们说使用UNICODE字符集就是指使用UTF-16字符集,如VS设置中使用UNICODE字符集的话即表示使用UTF-16字符编码版本的方法,使用多字节字符集的话对于我们就是使用GBK。

在字符串中的"\u十六进制数"表示对应的UNICODE编码的字符,如汉字"一"的UNICODE编码是0x4E00,"\u4E00个人"就相当于是"一个人"。

计算机是怎么区分ASCII码和汉字的?如果使用的是UNICODE编码即UTF16编码的话因为所有字符都占用两个字节(Linux下为4个字节),所以通过字符的编码值即可分辨。如果是UTF-8编码的话,汉字字符的每个字节的第一位都是1,即为负数。

字符集:由一些指定的字符的所组成集合,如ASCII字符集由128个字符组成,其它的字符集还有GBK、UNICODE等。

字符编码:字符集中字符的编码,如ASCII字符集中,a的字符编码是97。对于相同的字符,不同的字符集使用的字符编码不尽相同。

经测试,对于VS下代码中的字符串常量,使用“文件-高级文件保存选项”将代码文件修改成UTF-8或GBK的话,字符串常量都是GBK编码的,而如果在字符串常量前添加u8的话字符串才是UTF-8编码的(不论设置了文件编码为GBK或UTF-8)。而对于Qt Creator下,使用"工具-选项-文件编码"改变文件编码为UTF8的话字符串常量就是UTF-8格式的,代码文件编码为GBK的话则字符串常量是GBK编码,如果在文件编码为GBK的情况下给字符串常量添加了u8前缀,这个字符串也是GBK编码的。

1、C中字符串、C++的string

  下面为在VS下的命令行程序中的测试代码,由于std::string内部直接使用传入的字符串而不会进行任何编码转换,而中文操作系统默认使用的是GBK编码,所以对于GBK格式的字符串或string可以正常显示,对于UTF-8格式的字符串或string中文显示乱码。UNICODE格式的字符串需要使用对应的宽字符版本输出方法wprintf()或wstring、wcout来进行输出(我猜其也也是将unicode转换为GBK后再进行显示的):

int main()
{
    //给printf()传入与系统字符编码相同的字符串,则中文可以正常显示
    char* p = "abc测试"; //vs下代码文件使用的是gbk编码(与系统字符编码相同),其与项目属性设置的字符集无关, 所以这里的字符串是GBK格式
    printf(p); //显示正常

               //给printf()传入与系统字符编码不同的字符串,则中文不能正常显示
    //char ary[] = { 97, 98, 99, -26, -75, -117, -24, -81, -107, 0 }; //utf-8编码格式的"abc测试"
    char* ary = u8"abc测试";
    printf(ary); //中文会乱码

    setlocale(LC_ALL, ""); //输出宽字符需要设置区域
    wchar_t* wp = L"abc中文\n"; //使用UNICODE格式字符串
    wprintf(wp); //显示正常


                 //给string传入与系统字符编码相同的字符串,则中文可以正常显示
    string str("abc测试");
    cout << str << endl; //正常显示

                         //给string传入与系统字符编码不同的字符串,则中文不能正常显示
    //char ary2[] = { 97, 98, 99, -26, -75, -117, -24, -81, -107, 0 }; //utf-8编码格式的"abc测试"
    char* ary2 = u8"abc测试";
    string str2(ary2);
    cout << str2 << endl; //中文显示乱码

    wcout.imbue(std::locale("chs"));
    wstring wstr(L"abc中文"); //使用UNICODE格式字符串
    wcout << wstr << endl; //正常显示

    return 0;
}
View Code

相关文章:

  • 2021-12-04
  • 2022-02-02
  • 2021-09-19
  • 2022-12-23
  • 2022-01-29
  • 2021-11-20
  • 2021-12-26
猜你喜欢
  • 2021-07-16
  • 2022-12-23
  • 2021-07-17
  • 2022-12-23
  • 2021-12-19
相关资源
相似解决方案