zoukankan      html  css  js  c++  java
  • std::string在多字节字符集环境下substr的实现方法

    昨天写到《使用多字节字符集的跨平台(PC、Android、IOS、WP)编码/解码方法》中提到服务端使用std::string处理字符串,std::string对多字节字符集支持并不是很完善,std::string中的函数没有对多字节字符集进行直接的支持。

    例如直接调用std::string的substr函数,就会导致某些情况下截取的字符串尾部产生非法字符。

    GB系列多字节字符集基础知识:

    VC环境下工程设置为多字节字符集,默认使用的是GBK编码,GB2312、GBK、GB18030,这3个都是中文编码方式,并向下兼容。

    1、GB2312包含7000多个汉字和字符,GBK包含21000多个,GB18030包含27000多个。

    2、GBK中的中文字符是双字节来表示的,英文字符是用ASCII码表示的,也就是单字节表示的。

    3、GBK编码表中也有英文字符的双字节表示形式,所以英文字母可以有2中GBK表示方式。

    4、GBK编码中的中文字符将其最高位都定成1,英文字符单字节最高位都为0。

    5、当用GBK解码时,若高字节最高位为0,则用ASCII码表解码;若高字节最高位为1,则用GBK编码表解码。

    以上5点就可以解释了std::string中substr为什么会在尾部产生非法字符的问题了,substr只考虑了字节长度,没考虑多字节字符集编码。

    对于使用substr截断的字符串,在IOS环境下使用NSString初始化时会失败,而Android的String类型则会容忍非法字符。

    为了彻底解决平台兼容性问题,必须自己实现截取函数:

    int GbkSubString(const char *s, int iLeft)  
    {  
    	int len = 0, i = 0;  
    
    	if( s == NULL || *s == 0 || iLeft <= 0 )   
    		return(0);  
    
    	while( *s )  
    	{  
    		if( (*s & 0x80) == 0 )  
    		{  
    			i ++;  
    			s ++;  
    			len ++;  
    		}  
    		else  
    		{  
    			if( *(s + 1) == 0 ) break;  
    
    			i += 2;  
    			s += 2;  
    			len += 2;  
    		}  
    
    		if( i == iLeft ) break;  
    		else if( i > iLeft )  
    		{  
    			len -= 2;  
    			break;  
    		}  
    	}  
    
    	return(len);  
    }  
    

    先使用GbkSubString函数对长度进行处理,再使用返回的准确长度调用substr。


    记录,为更好的自己!

  • 相关阅读:
    noip模拟赛 软件software
    bzoj1070: [SCOI2007]修车
    bzoj2947: [Poi2000]促销
    bzoj2940: [Poi2000]条纹
    bzoj3714: [PA2014]Kuglarz
    bzoj3717: [PA2014]Pakowanie
    说明
    Hello World!
    牛客网PAT练兵场-旧键盘打字
    牛客网PAT练兵场-锤子剪刀布
  • 原文地址:https://www.cnblogs.com/ym123/p/4256835.html
Copyright © 2011-2022 走看看