最近在处理游戏敏感词之类的东西,为了增强屏蔽处理,因此须要过滤掉字符串中的除汉字以外的是其余东西如数字,符号,英文字母等。php
首先我查阅资料并写了个函数:c++
示例:返回输入字符串中汉字的个数:数组
std::string StrWithOutSymbol(const std::string &source) { string sourceWithOutSymbol; int i = 0; while (source[i] != 0) { if (source[i] & 0x80 ) { sourceWithOutSymbol += source[i]; sourceWithOutSymbol += source[i + 1]; i += 2; else { i ++; } } return
sourceWithOutSymbol;
}
80对应的二进制代码为1000 0000,最高位为一,表明汉字汉字编码格式通称为10格式一个汉字占2字节,但只表明一个字符函数
"Windows中,中文简体字符集的编码是同时用1个字节和2个字节来表示的。当高位是0x00~0x7f时,为一个字节,高位为0x80以上时用2个字节表示"编码
当你发现一个字节的内容大于0x7f,那它确定是个(跟另一个字节拼凑成一个)汉字,如何判断确定大于0x7f呢?
0x7f(1111111)后面一个数就是0x80(10000000),因此想要大于0x7f,这个字节的最高位都确定是1,咱们只须要判断这个最高位是否为1就好了。lua
判断方法:
位与(相同的位都是1的才为1,不然为0):
如:要判断一个数的第三位是不是1,只要跟4(100)位与,判断一个数的第2位是否为1就跟2(10)位与.
同理判断第八位是否为1只要跟(10000000)也就是0x80位与了.spa
这里为何不用>0x7f?php可能还行,但在其余强类型语言里面,1个字节的最高位用来标示负数,一个负数确定不可能大于0x7f(最大的整数)code
再举个例子:
a的assic码是97(1100001)
A的assic码是65(1000001)blog
b的assic码是98(1100010)
B的assic码是66(1000010)游戏
发现一个规律:一个a-z的字母,只要是小写字母,第六位确定是1,咱们能够用这个来判断大小写:
这时候只要跟用以个字母跟0x20(100000)来位与判断:
if(ord($a)&0x20){
//大写
}
如何把全部字母改为大写?第六位的1改为0就好了:
$a='a';
$a = chr(ord($a)&(~0x20));
echo $a;
而后我信心满满的吧这个函数加入到项目中去,点击运行,输入中文进行检查,当!项目报错了????数组越界????
这是为何,我又定位到报错的地方,发现我使用的cocos-lua,在向c++传递字符串的时候传进来的字符串是以UTF-8来进行编码的,我又去找UIF-8的编码规则发现
而我以前的是按照GBK编码进行操做的,GBK每一个中文字符只占两个字节,而utf-8的话中文可能占3个字节,四个字节,甚至是五个六个,因此用刚才那样的函数就会有越界的状况发生,因此对用UTF-8进行编码的字符串,就须要进行另外的处理,因此我写了一个新函数:
对UTF-8编码的字符串进行中文筛选的函数:
std::string censorStrWithOutSymbol(const std::string &source) { string sourceWithOutSymbol; int i = 0; while (source[i] != 0) { if (source[i] & 0x80 && source[i] & 0x40 && source[i] & 0x20) { int byteCount = 0; if (source[i] & 0x10) { byteCount = 4; } else { byteCount = 3; } for (int a = 0; a < byteCount; a++) { sourceWithOutSymbol += source[i]; i++; } } else if (source[i] & 0x80 && source[i] & 0x40) { i += 2; } else { i += 1; } } return sourceWithOutSymbol; }
点击运行,成功了!舒服。