当前位置:C++技术网 > 资讯 > ASCII和Unicode编码内部是什么样的

ASCII和Unicode编码内部是什么样的

更新时间:2015-06-25 12:55:56浏览次数:1+次

    ASCII编码字符串赋值:

    使用如下语句给字符数组初始化赋值,即可得到ASCII编码的字符串。
    语句:

unsigned char str[] = "0这0是0含0有0中0文0的0字0符0串0";

    注意:对于字符,最好使用unsigned char存储,因为字符编码是没有正负的。虽然说,ASCII编码是0-127,不会出现负数。但是,如果用在判断编码来确定字符串中的汉字时,要统计汉字的个数或者判断有没有汉字,就会出现正负问题。因为汉字的编码很大的,这样得到的数值就超过了128,就称为负数了,此时判断ASCII编码是否大于127来确定是否含有汉字,就会永远小于127,结果出错。这一点,非常需要注意,因为往往就会在这里陷入困境。

    下图是ASCII内部的字节存储方式:

   
    图中框住的部分,除了红线擦除的地方,其他的字节都是"0这0是0含0有0中0文0的0字0符0串0"的内部字节内容。因为是ASCII存储方式,因此,一个字节表示一个字符,如果是宽字符,则用两个字节表示。图中蓝色箭头指向的都是ASCII字符能表示的0,编码为0x30。这里面显示的都是十六进制值。红色箭头指向的都是中文的两个字节。这也就是通常大家理解的,一个汉字占两个字节的原因。最后一个0x00,就是字符的结尾空字符。
    而这种编码想要正确的读取字符,就要判断字符的类型。而判断的依据则是对ASCII编码进行判断。所以此时编码特别要注意的一点就是上面提到的无符号的char类型。因为中文字符是超过127的,有符号的char就变成了负数。为了正确比较,就需要用无符号的表示。这样,非ASCII字符,整型是就大于127,就表示不是英文字符。如果只有英文和中文,就可以简单的认为,字符串中含有中文了。如果要进一步判断是中文还是日文等,则要对字符数值按照Unicode编码进行判断,在哪个编码范围之内属于中文,哪个范围属于日文来判断。
    让我一直疑惑的就是,通过遇到的字节值进行判断,如果大于十进制的127就表示不是英文了。这里不管高低字节。通过求证,中文中的低字节的编码值不可能小于127,所以就可以放心的判断这个编码值。如果是中文,则跳过后一个字节,因为后一个字节与当前字节是组成一个汉字的。
    这里说明一点:在用几个字节表示一个字符时,字节的先后是有讲究的。在Intel平台中,是小端序列的。也就是说,低字节在左边,高字节在右边。所以图中0xd5 0xe2中,0xd5为低字节,我们只需要对低字节的编码值判断就可以知道是中文字符还是英文字符了。具体的代码演示和代码详解,请查看本站其他文章。


    Unicode编码字符串赋值:
    使用如下语句可以得到Unicode编码的字符串:
    语句:

wchar_t str[] = L"0这0是0含0有0中0文0的0字0符0串0";

    注意:Unicode编码是以两个字节来存储字符的,任何字符都是两个字节表示。比如,中文字符、韩文字符,英文字符等等,都是两个字节。因为char是一个字节表示一个字符的,因此不适合存储Unicode编码字符。所有这里用了wchar_t宽字符类型,用两个字节表示一个字符,程序会自动按两个字节组合解释成一个字符。
    还需要注意的就是:wchar_t的原始类型时unsigned short 类型,被包装成基本类型了。所以,本身就是无符号类型的了,就不要想上面ASCII里说的,加unsigned修饰了。这里必须加一个大写字母L表示初始化的字符串以Unicode宽字符方式赋值。如果不加,则编译不通过。

    下图是Unicode内部的字节存储方式:

   
    Unicode简化了字符处理。所有的字符都用两个字节存放。而英文字符因为只需要一个字节就可以存放,所以为了兼容ASCII编码,Unicode编码中的前128个编码就留给了ASCII。英文字符的高字节使用0填充。如图中所示,字符0表示为0x30 0x00两个字节,低字节为0x30就可以表示了。为了整体的设计,就在高字节填零。而汉字或者日文都是用两个字节存放。所以,使用Unicode编码的文本文件,直接每次读取两个字节,然后判断第二个字节的值是否大于零,大于就可以初步判断为中文,为了严谨,可以参考Unicode编码文档,了解中文的编码值范围,进一步确定。如果只有中文和英文,就不必进一步判断了。
    注意:Unicode编码字符串的结尾会使用两个0结尾。
    特别提醒:系统记事本存储的txt文件的Unicode编码文件,开头两个字节是0xFF 0xFE,用来区别ASCII编码和Unicode编码。这个不是数据,只是记事本自己加上去识别的。如果只是提取数据,注意要去掉这两个字节的标志。当然你也可以利用这个来判断文本的编码模式。