<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) { if(!MyUTF::isUTF8(text.c_str(), text.size())) _labelRenderer->setString(a2u(text.c_str()).c_str()); else _labelRenderer->setString(text.c_str()); labelScaleChangedWithSize(); }<7>UILabelBMFont
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