分类: 算法 cpp2012-03-10 16:01 7120人阅读 评论(2) 收藏 举报
null生活c
对于只包含中文和英文的文本中判断编码方式是非常简单的,中文的编码方式最常用的是GBK,字符集更大的如GBK向下兼容GB2312,其中包含的的很多一部分字符是我们在日常生活中用不到的,因此在实际中我们一般只需要区分GB2312和UTF8编码。这里我只是提供一种可行的方法,如果判断GBK也可以采用类似的方式首先分析一下汉字在GB2312中的编码方式,gb2312规则汉字采用双字节编码其中第一字节161~247,第二字节161~254,其中含有边界条件。而utf8的编码方式可以看如下表示:
- <span style="font-family:Arial, Verdana, sans-serif;"><span style="white-space: normal;">
- </span></span>
代码范围 十六进制 | 标量值(scalar value) 二进制 | UTF-8 二进制/十六进制 | 注释 |
---|---|---|---|
000000 - 00007F 128个代码 | 00000000 00000000 0zzzzzzz | 0zzzzzzz(00-7F) | ASCII字符范围,字节由零开始 |
七个z | 七个z | ||
000080 - 0007FF 1920个代码 | 00000000 00000yyy yyzzzzzz | 110yyyyy(C0-DF) 10zzzzzz(80-BF) | 第一个字节由110开始,接着的字节由10开始 |
三个y;二个y;六个z | 五个y;六个z | ||
000800 - 00D7FF 00E000 - 00FFFF 61440个代码 [Note 1] | 00000000 xxxxyyyy yyzzzzzz | 1110xxxx(E0-EF) 10yyyyyy 10zzzzzz | 第一个字节由1110开始,接着的字节由10开始 |
四个x;四个y;二个y;六个z | 四个x;六个y;六个z | ||
010000 - 10FFFF 1048576个代码 | 000wwwxx xxxxyyyy yyzzzzzz | 11110www(F0-F7) 10xxxxxx 10yyyyyy 10zzzzzz | 将由11110开始,接着的字节由10开始 |
- unsigned int countGBK(const char * str)
- {
- assert(str != NULL);
- unsigned int len = (unsigned int)strlen (str);
- unsigned int counter = 0;
- unsigned char head = 0x80;
- unsigned char firstChar, secondChar;
- for (unsigned int i = 0; i < len - 1; ++i)
- {
- firstChar = (unsigned char)str[i];
- if (!(firstChar & head))continue;
- secondChar = (unsigned char)str[i];
- if (firstChar >= 161 && firstChar <= 247 && secondChar>=161 && secondChar <= 254)
- {
- counter+= 2;
- ++i;
- }
- }
- return counter;
- }
- unsigned int countUTF8(const char * str)
- {
- assert(str != NULL);
- unsigned int len = (unsigned int)strlen (str);
- unsigned int counter = 0;
- unsigned char head = 0x80;
- unsigned char firstChar;
- for (unsigned int i = 0; i < len; ++i)
- {
- firstChar = (unsigned char)str[i];
- if (!(firstChar & head))continue;
- unsigned char tmpHead = head;
- unsigned int wordLen = 0 , tPos = 0;
- while (firstChar & tmpHead)
- {
- ++ wordLen;
- tmpHead >>= 1;
- }
- if (wordLen <= 1)continue; //utf8最小长度为2
- wordLen --;
- if (wordLen + i >= len)break;
- for (tPos = 1; tPos <= wordLen; ++tPos)
- {
- unsigned char secondChar = (unsigned char)str[i + tPos];
- if (!(secondChar & head))break;
- }
- if (tPos > wordLen)
- {
- counter += wordLen + 1;
- i += wordLen;
- }
- }
- return counter;
- }
- bool beUtf8(const char *str)
- {
- <span style="white-space:pre"> </span>unsigned int iGBK = countGBK(str);
- unsigned int iUTF8= countUTF8(str);
- if (iUTF8 > iGBK)return true;
- return false;
- }