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

文章不够精炼。我想把我的思想过程写出来,一遍以后自己读的时候知道我当时的想法。写的时候也尽量精简了一些不必要的话。
如果有什么问题的话,希望看到的各位不吝赐教。

公司用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
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值