您的位置:首页 > 其它

创建角色名如何在中英文混排的情况下精确限制长度

2015-10-14 23:53 393 查看
文章不够精炼。我想把我的思想过程写出来,一遍以后自己读的时候知道我当时的想法。写的时候也尽量精简了一些不必要的话。

如果有什么问题的话,希望看到的各位不吝赐教。

公司用cocos2dx做游戏,使用语言是lua。

最近做角色创建。要求最多英文14个,中文7个,超过的就不能输入。(不知道什么时候起我记忆中英文是一个字节的,而中文是两个字节的。这也是比较普遍的想法吧。)

开始尝试了一下cocos2dx自带的EditBox控件的setMaxLength方法。

local editBox = ccui.EditBox:create(cc.size(inputBgSize.width - 30,inputBgSize.height - 16),"pop_input_text.png")
editBox:setMaxLength(14)


效果不好,发现cocos2dx把任何语言都当成一个字节去计算。也就是中文可以输入14个它才会去限制。

只能通过editbox的事件来重新计算长度了。

尝试了一下lua的string.len方法返回的长度是什么。发现一个中文返回的长度是3。有点傻眼。马上去百度了一下utf8的中文。发现回答都是

大部分的图形语言都是3个字节组成的。这颠覆了我以前的记忆……

经过了曲折的思想,这中间尝试了很多方法(比如计算出所有英文的总数,然后把剩下的字节除以3,得到剩下中文个数,这显然不可行,一不能确定所有的中文都是3个字节,就算都是3个字节,那要是输入其他文字呢?要知道utf8最多是6个字节的。)发现都无法如意,没办法,继续查找百度看有没有解决方法。

终于找到这篇文章:lua中截取UTF8字符串的方法(无乱码)

其中有一段

if dropping >= 128 and dropping < 192 then 这里的话,UTF8是多字符集,但是第一个字符的最高位是11XXXXXX,其他的字符最高位是10XXXXXX

这里就应该很清楚的说明了utf8中,最高位是以11XXXXXX开头的。所以可以计算出它在这一位的最小数是192(11000000)。也就是说utf8最高位的最小值是192.(非英文)

在这里我不放心,因为该博主只说了事实没有其他说明,我不能确定他说的是否是正确的,是否具有普遍性,而不仅仅是中文。所以又开始查utf8的规范。

在这篇博文中我们可以看到utf8的构成:

UCS-4 range (hex.) UTF-8 octet sequence (binary)

  0000 0000-0000 007F 0xxxxxxx

  0000 0080-0000 07FF 110xxxxx 10xxxxxx

  0000 0800-0000 FFFF 1110xxxx 10xxxxxx 10xxxxxx

  0001 0000-001F FFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

  0020 0000-03FF FFFF 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx

  0400 0000-7FFF FFFF 1111110x 10xxxxxx … 10xxxxxx

其他不管。是否发现从2字节开始所有的组成都是以11开头的?

现在没有顾虑了。既然除了1字节的文字外,所有的2字节以上的文字的最高位的最小值是192,那么我们可以通过

每个最高位是否不小于192来计算文字的长度:

下面代码只验证了中文是可行的,未验证其他语言,如果有问题的话,请予以指正。谢谢。

if eventType == "began" then
-- triggered when an edit box gains focus after keyboard is shown
elseif eventType == "ended" then
-- triggered when an edit box loses focus after keyboard is hidden.
elseif eventType == "changed" then
local str = editBox:getText()
str = string.gsub(str," ","")--过滤掉空格
local count = string.len(str)
local reCount = 0
local beginIndex = -1
local reString = ""
for i = 1, count do
local s = string.sub(str, i, i)
local t = string.byte(s)
if t < 128 then
reCount = reCount + 1--1字节文字,长度加1
elseif t >= 192 then
reCount = reCount + 2--1字节以上文字,长度加2
end
if reCount > CharacterLayer.nameMaxLength then
beginIndex = i - 1
break
end
beginIndex = i
end
reString = string.sub(str, 1, beginIndex)
editBox:setText(reString)
elseif eventType == "return" then
-- triggered when the return button was pressed or the outside area of keyboard was touched.
end
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: