UTF8编码

简介

UTF-8 虽然也属于UNICODE一种,但其实是一种变长multiy-byte编码,可直接用char或者std:string来存储操作。也就是说兼容ascii的,而且可在同一个字符串中包含多种语言(如中日韩同时显示)。linux软件中,UTF-8是比较通用的编码方式,尤其在网络和各种开源软件以及开源库中,基本上都支持UTF-8。原因我猜是因为开源软件作者以英语为母语的占绝对多数,UTF8兼容其他语言时最省事,代码基本上不用改。

UTF8缺点:长度统计不能直接用strlen函数,汉字较多情况下比unicode或者gbk占用更多存储。

微软对UTF8支持相对没那么给力,微软以UTF16和CP_ACP各国本地编码为主,例如中文的多字节就是GBK或者GB2312。

Visual Studio 2010 对UTF8的支持


源码级别的支持:

源代码本身编码(.cpp,.h文件)是直接支持UTF8的
VS2010中: 菜单-》文件-》高级保存选项, 存为带bom的utf8 就可以。

编译后内存中的常量字符串编码:

缺省情况下是不会编译为UTF8的,例如,你在代码中写:

char * str ="中文";

编译后二进制exe文件中会用CP_ACP 参数缺省编译为GB2312或者GBK编码。

如果希望编译后编码仍为UTF8,可以用下面的方法:

首先打SP1补丁,

然后代码中加上:

#pragma execution_character_set("utf-8")


VS中对UTF16的支持就很好,代码中直接用L"中文",会正确编码为UTF16

调试时编码:

调试环境中,缺省支持Unicode(UTF16)和 GBK,也就是鼠标悬停时能正确的看到中文字符串,但是UTF8字符串看不到。

UTF8字符串可以用下面的方法看到:
需要将要显示的字符串拉到Watch中,并在变量后面添加s8即可显示


多个不同编码库共存时解决方法

如果程序中同时用了不同编码方式的库,我的处理方式是代码中尽量用UTF8编码,

首先源代码本身用UTF8,方便代码共享,上传到网站等,

其次代码里面的常量字符串尽量能够编译成UTF8的二进制码,这样可以直接输出到一些开源库中,例如MYSQL直接支持UTF8,可以在源代码中写含有中文内容的SQL查询语句。

最后各种配置文件,文本文件也使用UTF8编码,程序里可以直接用std:string变量操作

在碰到不支持UTF8的库时,例如SFML库,基本上都会支持UNICODE, 可以调用utf8转unicode的代码转过去,VC中是MultibyteToUnicode函数


STL中要特别注意local


从文件中读取中文字符串,用下面的函数去除空格会出现异常,不管是utf8编码还是gb2312编码,原因是缺少local
std::string ltrim(std::string s) 
{
      s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun<int, int>(std::isspace))));
      return s;
}


自己重新定义带local的函数就没有问题:

struct my_isspace : std::unary_function<int, int>
{
   int operator()(int i) const 
        {
		return std::isspace(i, std::locale("chs"));
	}
};


std::string ltrim(std::string s) 
{
	s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(my_isspace())));
        return s;
}


AIML中格式化输入串,将utf8的中文用空格分割

void aiml::clean_pattern(string& pattern)
{
	std::string out;
	std::string ch;   
	for(size_t i = 0, len = 0; i < pattern.length(); i += len) 
	{  
		unsigned char byte = (unsigned)pattern[i];  
		if (byte >= 0xFC)  //1111110x  lenght 6
			len = 6;    
		else if (byte >= 0xF8)  
			len = 5;  
		else if(byte >= 0xF0)  
			len = 4;  
		else if (byte >= 0xE0)  
			len = 3;  
		else if (byte >= 0xC0)  
			len = 2;  
		else
			len = 1;  
		
		if(len == 1)  //ascii
		{
			char c = pattern[i];
			if(!isalnum(c) && c != '*' && c != '_' && c != ' ')
				out += ' ';
			else
				out += toupper(c);
		}
		else   //utf8  add ' ' after each word
		{
			ch = pattern.substr(i, len);  
			out += ch;
			out += ' ';
		}
	}  	
	pattern = out;
}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值