字符集

unicode 多字节字符集 string wstring MultiByteToWideChar

 

顺序:

1 一个常量字符串如何放到一个cstring中,

 CString name;
// name.Format(_T("%s"), _T("china"));
 name.Format(_T("%s"), "china");

 

“china”在内存中存放的方式与项目属性中的“字符集”和是否在串前加了_T宏有关,由两者共同决定。

但是不管如何设定字符集,不管是否加_T宏,程序都可以编译通过。但是如果程序字符集设为“unicode”但却没有加_T宏,那么

name将表现出乱码。如果字符集为“未设定”,则不管是否加_T,都不会有影响,不会出现乱码,因为_T是个智能宏,它判断如果

程序使用的是unicode,则以双字节存储。否则以单字节存储。cstring的format函数受程序字符集影响,如果是unicode,则取出时

把两个字节的内容当成一个字符, 否则将一个字节的内容当成一个字符。 所以如果放入时(即赋值时)与取出时是按相同的规则来做的话,就不会出现乱码了。

 

 

string 与 wstring:

当字符集为unicode时 ,把“china”串赋给string时,即string kid = "this";

那么kid中的this是按单字节来存放的。给"this"加上_T宏,编译都不能通过。

 

在unicode下,我们应该使用wstring来代替string. 在此时如果不加_T宏会编译不过。

 

在ansi 下,不能使用wstring, 在unicode下,可以使用string.

 

 

 

 

1 并不是说程序字符集为unicode后,所有的字符串都是以“两个字节存储一个字符”的方式来存放的,而只是说该程序具备处理很多字符的能力。但是字符集设为unicode会影响许多函数的功能,因为同一功能的函数有两个版本, 一个是ANSI版的,一个是unicode版的,

那么既然程序打算支持复杂字符,那么相应的函数一定要按双字节来存取,如果是按单字节来存取就不能支持复杂字符了。这样就产生了一个问题,当你的程序决定支持unicode而使用双字节的话,那么系统中的函数会按双字节为一个字符来处理数据(这个完全由系统决定),

但是在程序中是否把一个常量串按UNICODE格式存储则是由用户来操作,加了_T宏,就是宽的,否则就是窄的。所以如果不一致的话就会导致乱码。

 

 

在unicode下,我们应该使用wstring, 而不应该使用string, 但是有时候我们使用别人提供的接口时,该接口返回的是string型的值,

我们要用string型的变量来存储该接口返回的值,这时如果我们直接调用我们的函数(unicode版),则肯定会出现乱码。

解决方法是先将string转换成wstring.

 

为edit框添加一个cstring变量, 该变量以单字节或双字节来存储完全由项目配置(使不使用unicode)来决定。

 

 #include<string>
using namespace std;

//将string转换成wstring
wstring string2wstring(string str)
{
wstring result;
//获取缓冲区大小,并申请空间,缓冲区大小按字符计算
int len = MultiByteToWideChar(CP_ACP, 0, str.c_str(), str.size(), NULL, 0);
TCHAR* buffer = new TCHAR[len + 1];
//多字节编码转换成宽字节编码
MultiByteToWideChar(CP_ACP, 0, str.c_str(), str.size(), buffer, len);
buffer[len] = '/0'; //添加字符串结尾
//删除缓冲区并返回值
result.append(buffer);
delete[] buffer;
return result;
}

//将wstring转换成string
string wstring2string(wstring wstr)
{
string result;
//获取缓冲区大小,并申请空间,缓冲区大小事按字节计算的
int len = WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), wstr.size(), NULL, 0, NULL, NULL);
char* buffer = new char[len + 1];
//宽字节编码转换成多字节编码
WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), wstr.size(), buffer, len, NULL, NULL);
buffer[len] = '/0';
//删除缓冲区并返回值
result.append(buffer);
delete[] buffer;
return result;
}

vs2003 到vs2005代码升级要点(part)

   影响到大多数程序设计人员的是默认的charset由原先的Ansi改成了Unicode。所有的Windows程序也把默认的字符型参数有单字节改成了双字节。一个最简单的方法,是在程序属性里面的charset属性由默认的Unicode改成not set. 不过这个并不能解决所有问题。当一个字符串全部由英文和字符组成时,程序没有什么问题。而当字符串中包含汉字时,也许只有自己费力的去转换了。
 
    要指出的一点是,在2003里面,给大多数函数传字符型参数,是可以用std::string.c_str()传值的,而在2005里面,默认的情况需要传递std::wstring.c_str().如果以前的程序中大量用了string的话,也许定义一个string到wstring的转换函数,定义一个从wstring到string的转换函数,会是一个合理的解决方案。
 
    不要太多的尝试使用改变charset来使以前的程序可以运行,更不要在2005的环境下,用charset = not set来编写新的程序,在未来的语言环境中,使用Unicode字符集,是大势所趋(远东地区)。如果你不能改变,接受吧^_^
 
    另外一个重要转变是对C#库的支持。请注意,这里谈论的是C++而不是C#。从VS2003开始,C++程序中支持调用C#的库函数。如果你对这个方面接触不多,大可不看下面这些内容。如果你手上的代码是在2003下面写的,而里面又用了Managed Extensions for C++的话,你需要接着往下看。
 
    在2005里,对C#库支持进化到了C++/CLI,这个进化,除了废除了一些关键字,引入了一些新的关键字,还有其他的升级。...所以,你原先的程序是肯定不能编译通过了。
 
    解决方案也很简单,同样是在属性页,将Common Language Runtime Support选项选择Common Language Runtime Support, Old Syntax (/clr:oldSyntax),大致就能编译通过了。不过,更可取得解决方案仍是代码升级,然后按新的规范编写代码。
 
    关于代码升级,有一篇Stan. Lippman(这个大牛,学C++的很多人都知道吧)的文档,Translation Guide: Moving Your Programs from Managed Extensions for C++ to C++/CLI, 可以找来看看。呵呵,这个在网上应该很容易找到,我偷下懒吧。
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值