4.1 Cocos2d-x中的字符串
在Cocos2d-x中能够使用的字符串有const char*、std::string和cocos2d::__String等,其中const char*是C风格的字符串,std::string是C++风格的字符串,它封装了const char*。cocos2d::__String才是Cocos2d-x引擎提供的字符串类,这些字符串都可以互相转换,它们会在不同的场景下使用,具体使用哪个可以参考具体的API。
4.1.1 使用const char*和std::string
在C++中两种类型都可以使用,但是std::string是一个类,具有面向对象的优点,而const char*没有。下面的代码初始化std::string对象。
std::string name = "tony"; std::string name = std::string("tony");
不需要使用指针,也不需要关心内存释放问题,在作用域超出之后std::string对象被释放。我们可以通过下面的语句把std::string转化为const char*类型。
const char* cstring = name.c_str();
可以使用std::string指针类型,但是要配合使用new关键字开辟内存空间,然后不使用的时候要通过delete释放内存。
std::string* name =new std::string("tony"); … delete name;
使用std::string指针对象时,可以通过下面的代码转化为const char*类型。
const char* cstring = name->c_str();
const char*和std::string的应用在Cocos2d-x中还有很多,我们会在后面的学习中继续介绍。
4.1.2 使用cocos2d::__String
cocos2d::__String是Cocos2d-x的一个通用字符串类,它的设计模仿了Objective-C的NSString类,这由于Cocos2d-x源自于Cocos2d-iphone,cocos2d::__String也是基于Unicode双字节编码。
cocos2d::__String的类图如图4-1所示,创建它的主要静态create函数如下:
●static __String * create (const std::string &str)
●static __String * createWithFormat (const char *format,...)
图4-1 __String类图
使用create函数的实例代码如下:
__String* name= __String::create("Hi,Tony"); int num=123; __String* ns = __String::createWithFormat("%d",num);
提示
cocos2d::__String也提供了一些构造函数,如__String ()和__String (const char *str)等。使用它们时,我们自己管理内存释放,不是很方便。create静态函数创建的对象不需要我们管理内存释放。
cocos2d::__String还提供了一些数据类型之间的转换函数。例如,cocos2d::__String转换为const char*类型,这种转换用的比较多,示例代码如下:
__String* name= __String::create("Hi,Tony"); const char *cstring= name->getCString();
const char*转换为cocos2d::__String类型,示例代码如下:
const char* cstring = "Hi, Tony"; __String* ns=__String::createWithFormat("%s",cstring);
std::string转换为cocos2d::__String类型,示例代码如下:
std::string string = "Hi, Tony"; __String* ns=__String::createWithFormat("%s",string.c_str());
cocos2d::__String转换为int类型,示例代码如下:
int num = 123; __String* ns = __String::createWithFormat("%d",num); int num2 = ns->intValue();
还有很多函数我们会在以后的学习中继续介绍。
4.1.3 Win32平台下的中文乱码问题
在Win32平台,我们会发现通过log输出中文字符时,会出现中文乱码问题,例如下面的代码:
__String* ns = __String::create("大家好"); log("%s",ns->getCString());
在Win32平台时,日志输出是乱码。但是在同样的代码中,iOS和Android下就没有问题。这个问题究其根本是因为默认情况下Windows中文环境是采用GBK编码,源程序文件HelloWorldScene.cpp编码默认也是GBK,如果源程序代码中有中文,它的字符集是GBK,我们需要将中文字符GBK编码转换为UTF-8编码,
为此,我们添加了一个MyUtility类,并在MyUtility类中编写编码转化函数gbk_2_utf8,它的代码如下:
string MyUtility::gbk_2_utf8(const string text) { #if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32) //采用Lambda表达式,将string转换成wstring wstring tes = [=]() { setlocale(LC_ALL, "chs"); const char* _Source = text.c_str(); size_t _Dsize = text.size() + 1; wchar_t *_Dest = new wchar_t[_Dsize]; wmemset(_Dest, 0, _Dsize); mbstowcs(_Dest,_Source,_Dsize); std::wstring result = _Dest; delete []_Dest; setlocale(LC_ALL, "C"); return result; }(); int asciSize = WideCharToMultiByte(CP_UTF8,0,tes.c_str(),tes.size(),NULL,0,NULL,NULL); if (asciSize == ERROR_NO_UNICODE_TRANSLATION || asciSize == 0) { return string(); } char *resultString = new char[asciSize]; int conveResult = WideCharToMultiByte(CP_UTF8,0,tes.c_str(),tes.size(), resultString,asciSize,NULL,NULL); if (conveResult != asciSize) { return string(); } string buffer = ""; buffer.append(resultString,asciSize); delete[] resultString; return buffer; # else return text; # endif }
该函数是静态函数,不需要实例化MyUtility类就可以直接调用该函数,它的作用是将GBK格式编码转化成UTF-8。
注意
中文乱码在Android和iOS不会发生,除非我们源代码不是UTF-8编码。Android和iOS本身都是采用UTF-8编码,log日志输出时不会出现中文乱码。如果考虑未来应用发布到Android和iOS平台,而目前的Win32平台下的中文乱码问题根本不需要担心。