Cocos2d-x学习笔记:完全掌握C++ API与游戏项目开发 (未来书库)
上QQ阅读APP看书,第一时间看更新

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平台下的中文乱码问题根本不需要担心。