截取UTF-8编码的汉字,最后一个字出现乱码的问题
问题描述
原来字串内容name为下面内容:
######name=杨乃文做DJ,微信公众号FunRadio。什么样的姿态是小丑姿态?2016046######
需要截取成大小为64的name_rm[64]的数组内容,出现如下乱码:
######name=杨乃文做DJ,微信公众号FunRadio。什么样的姿态斣#####
问题分析
UTF-8编码,汉字占3个字节,英文占一个字节,标点符号占领3个字节。
汉子:15*3=45
英文:10*1=10
标点符号:2*3=6
共61,64-61=3还可存放一个汉字。由于程序将最后一个字节设置为结尾符‘\0’,导致只剩截取需要三个字节存放的汉字,从而出现乱码。
问题解决
如果只能存放有效长度63(除掉结束符)的内容,
则从原来字串里面读取长度为63的内容里面的有效字符串。
上面按例有效字串长度为61,这样从原来字串提取61的长度,就不会出现乱码了。
提取有效字串长度代码:
1 int getsubstringlen(char *string,int len) 2 { 3 4 int j = 0; 5 int n = 0; 6 char *p = NULL; 7 8 int str_length = len; 9 10 p = string; 11 12 while(n <= str_length) 13 { 14 15 if((*p & 0XFC)==0XFC) 16 { 17 j = 6; 18 } 19 else if((*p & 0XF8)==0XF8) 20 { 21 j = 5; 22 } 23 else if((*p & 0XF0)==0XF0) 24 { 25 j = 4; 26 } 27 else if((*p & 0XE0)==0XE0) 28 { 29 j = 3; 30 } 31 else if((*p & 0XC0)==0XC0) 32 { 33 j = 2; 34 } 35 else 36 { 37 j = 1; 38 } 39 40 if (n+j<=str_length) 41 { 42 n += j; 43 }else 44 break; 45 46 p = p+j; 47 } 48 49 return n; 50 51 }
参考资料:
http://blog.csdn.net/chary8088/article/details/21226375
UTF-8的编码规则很简单, 只有两条:
1) 对于单字节的符号, 字节的第一位设为0, 后面7位为这个符号的unicode码. 因此对于
英语字母, UTF-8编码和ASCII码是相同的.
2) 对于n字节的符号(n>1), 第一个字节的前n位都设为1, 第n+1位设为0, 后面字节的前
两位一律设为10. 剩下的没有提及的二进制位, 全部为这个符号的unicode码.
下表总结了编码规则, 字母x表示可用编码的位.
1 <SPAN xmlns="http://www.w3.org/1999/xhtml">// #txt--- 2 | Unicode符号范围 | UTF-8编码方式 3 n | (十六进制) | (二进制) 4 ---+-----------------------+------------------------------------------------------ 5 1 | 0000 0000 - 0000 007F | 0xxxxxxx 6 2 | 0000 0080 - 0000 07FF | 110xxxxx 10xxxxxx 7 3 | 0000 0800 - 0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx 8 4 | 0001 0000 - 0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx 9 5 | 0020 0000 - 03FF FFFF | 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10 6 | 0400 0000 - 7FFF FFFF | 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 11 12 表 1. UTF-8的编码规则 13 // #txt---end 14 </SPAN>