<1>原因:这是因为VC采用GBK编码,而cocos2d-x采用UTF-8编码,编码方法不一致造成的。
<2>解决办法:
添加libiconv.lib。步骤:引用-->配置属性-->连接器-->输入-->附加依赖项 添加libiconv.lib
<3>将iconv.h添加到Classes下面。其中iconv.h的内容如下:
/* Copyright (C) 1999-2003 Free Software Foundation, Inc.
This file is part of the GNU LIBICONV Library.
The GNU LIBICONV Library is free software; you can redistribute it
and/or modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
The GNU LIBICONV Library is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU LIBICONV Library; see the file COPYING.LIB.
If not, write to the Free Software Foundation, Inc., 59 Temple Place -
Suite 330, Boston, MA 02111-1307, USA. */
/* When installed, this file is called "iconv.h". */
#ifndef _LIBICONV_H
#define _LIBICONV_H
#define _LIBICONV_VERSION 0x0109 /* version number: (major<<8) + minor */
extern int _libiconv_version; /* Likewise */
/* We would like to #include any system header file which could define
iconv_t, 1. in order to eliminate the risk that the user gets compilation
errors because some other system header file includes /usr/include/iconv.h
which defines iconv_t or declares iconv after this file, 2. when compiling
for LIBICONV_PLUG, we need the proper iconv_t type in order to produce
binary compatible code.
But gcc's #include_next is not portable. Thus, once libiconv's iconv.h
has been installed in /usr/local/include, there is no way any more to
include the original /usr/include/iconv.h. We simply have to get away
without it.
Ad 1. The risk that a system header file does
#include "iconv.h" or #include_next "iconv.h"
is small. They all do #include <iconv.h>.
Ad 2. The iconv_t type is a pointer type in all cases I have seen. (It
has to be a scalar type because (iconv_t)(-1) is a possible return value
from iconv_open().) */
/* Define iconv_t ourselves. */
#undef iconv_t
#define iconv_t libiconv_t
typedef void* iconv_t;
/* Get size_t declaration. */
#include <stddef.h>
/* Get errno declaration and values. */
#include <errno.h>
/* Some systems, like SunOS 4, don't have EILSEQ. Some systems, like BSD/OS,
have EILSEQ in a different header. On these systems, define EILSEQ
ourselves. */
#ifndef EILSEQ
/* Igor: called upon EILSEQ from glibc, since autogeneration of this header
on Windows didn't do the job. */
/* #define EILSEQ @EILSEQ@ */
#define EILSEQ 84
#endif
#ifdef __cplusplus
extern "C" {
#endif
/* Allocates descriptor for code conversion from encoding `fromcode' to
encoding `tocode'. */
#ifndef LIBICONV_PLUG
#define iconv_open libiconv_open
#endif
extern iconv_t iconv_open (const char* tocode, const char* fromcode);
/* Converts, using conversion descriptor `cd', at most `*inbytesleft' bytes
starting at `*inbuf', writing at most `*outbytesleft' bytes starting at
`*outbuf'.
Decrements `*inbytesleft' and increments `*inbuf' by the same amount.
Decrements `*outbytesleft' and increments `*outbuf' by the same amount. */
#ifndef LIBICONV_PLUG
#define iconv libiconv
#endif
extern size_t iconv (iconv_t cd, const char* * inbuf, size_t *inbytesleft, char* * outbuf, size_t *outbytesleft);
/* Frees resources allocated for conversion descriptor `cd'. */
#ifndef LIBICONV_PLUG
#define iconv_close libiconv_close
#endif
extern int iconv_close (iconv_t cd);
#ifndef LIBICONV_PLUG
/* Nonstandard extensions. */
/* Control of attributes. */
#define iconvctl libiconvctl
extern int iconvctl (iconv_t cd, int request, void* argument);
/* Requests for iconvctl. */
#define ICONV_TRIVIALP 0 /* int *argument */
#define ICONV_GET_TRANSLITERATE 1 /* int *argument */
#define ICONV_SET_TRANSLITERATE 2 /* const int *argument */
#define ICONV_GET_DISCARD_ILSEQ 3 /* int *argument */
#define ICONV_SET_DISCARD_ILSEQ 4 /* const int *argument */
/* Listing of locale independent encodings. */
#define iconvlist libiconvlist
extern void iconvlist (int (*do_one) (unsigned int namescount,
const char * const * names,
void* data),
void* data);
/* Support for relocatable packages. */
/* Sets the original and the current installation prefix of the package.
Relocation simply replaces a pathname starting with the original prefix
by the corresponding pathname with the current prefix instead. Both
prefixes should be directory names without trailing slash (i.e. use ""
instead of "/"). */
extern void libiconv_set_relocation_prefix (const char *orig_prefix,
const char *curr_prefix);
#endif
#ifdef __cplusplus
}
#endif
#endif /* _LIBICONV_H */
<4>添加文件Tool.h和Tool.cpp,内容如下:
Tool.h
#ifndef _Tool_
#define _Tool_
#include "cocos2d.h"
#include "iconv.h"
#include <iostream>
#include <string.h>
int code_convert(const char *from_charset, const char *to_charset, const char *inbuf, size_t inlen, char *outbuf, size_t outlen);
/*UTF8תΪGB2312*/
std::string u2a(const char *inbuf);
/*GB2312תΪUTF8*/
std::string a2u(const char *inbuf);
#endif
Tool.cpp
#include "Tool.h"
int code_convert(const char *from_charset, const char *to_charset, const char *inbuf, size_t inlen, char *outbuf, size_t outlen)
{
iconv_t cd;
const char *temp = inbuf;
const char **pin = &temp;
char **pout = &outbuf;
memset(outbuf,0,outlen);
cd = iconv_open(to_charset,from_charset);
if(cd==0) return -1;
if(iconv(cd,pin,&inlen,pout,&outlen)==-1) return -1;
iconv_close(cd);
return 0;
}
/*UTF8תΪGB2312*/
std::string u2a(const char *inbuf)
{
size_t inlen = strlen(inbuf);
char * outbuf = new char[inlen * 2 + 2];
std::string strRet;
if(code_convert("utf-8", "gb2312", inbuf, inlen, outbuf, inlen * 2 + 2) == 0)
{
strRet = outbuf;
}
delete [] outbuf;
return strRet;
}
/*GB2312תΪUTF8*/
std::string a2u(const char *inbuf)
{
size_t inlen = strlen(inbuf);
char * outbuf = new char[inlen * 2 + 2];
std::string strRet;
if(code_convert("gb2312", "utf-8", inbuf, inlen, outbuf, inlen * 2 + 2) == 0)
{
strRet = outbuf;
}
delete [] outbuf;
return strRet;
}
<4>使用a2u即可。
<5>判断字段文本是否是utf8格式,是的话,不需要转码,不是就需要转码.
#ifndef _UTFUtils_
#define _UTFUtils_
class MyUTF
{
public:
static bool isUTF8(const char *pText, int nLen)
{
// octets to go in this UTF-8 encoded character
unsigned long dwOctets;
unsigned char chr;
bool bAllAscii= true;
// 循环检测
dwOctets = 0;
for (int i = 0; i < nLen; i++)
{
// 取出当前字符
chr = *(pText + i);
if ((chr & 0x80) != 0)
// 当前字符不是 ascii
bAllAscii = false;
if (dwOctets == 0)
{
// 7 bit ascii after 7 bit ascii is just fine. Handle start of encoding case
if (chr >= 0x80)
{
// count of the leading 1 bits is the number of characters encoded
do
{
chr <<= 1;
dwOctets++;
} while ((chr & 0x80) != 0);
// count includes this character
dwOctets--;
//if (dwOctets == 0)
if (dwOctets < 2)
// must start with 11xxxxxx
return false;
}
}
else
{
// non-leading bytes must start as 10xxxxxx
if ((chr & 0xC0) != 0x80)
return false;
// processed another octet in encoding
dwOctets--;
}
}
// End of text. Check for consistency
if (dwOctets > 0)
// anything left over at the end is an error
return false;
if (bAllAscii)
// Not utf-8 if all ascii. Forces caller to use code pages for conversion
return false;
return true;
}
};
#endif
引用的话使用类似于:
#include "C:/cocos2d-x-2.2.5/cocos2d-x-2.2.5/projects/IGuanGanKing_2014_10_29/Classes/UTFUtils.h"
的绝对路径.
<6>UILabel
void Label::setText(const std::string& text)<7>UILabelBMFont
{
if(!MyUTF::isUTF8(text.c_str(), text.size()))
_labelRenderer->setString(a2u(text.c_str()).c_str());
else
_labelRenderer->setString(text.c_str());
labelScaleChangedWithSize();
}
void LabelBMFont::setText(const char* value){ if (!value) { return; } _stringValue = value; if (!_fntFileHasInit) { return; } const std::string& str = value; if(!MyUTF::isUTF8(str.c_str(), str.size())) _labelBMFontRenderer->setString(a2u(value).c_str()); else _labelBMFontRenderer->setString(value); labelBMFontScaleChangedWithSize();}
注意一个问题:当unicode和utf8一起混编时,就不可以再执行setText了,会出现显示不出来.例如:
btn->setTitleText(toStr("签到%i次",info->getMaxNum())->getCString());info->getMaxNum()是从服务器读取的,是utf8编码,而vs本身带的字体"签到","次"是Unicode,所以整体在一起,就出现乱码了.
解决方案:
string signStr = a2u("签到");对应关系:
signStr += CCString::createWithFormat("%i", info->getMaxNum())->getCString();
signStr += a2u("次");
Unicode<-->GBK
ANSI<-->utf8