UTF8字符串在lua的截取和字数统计【转载】

转载自:GitHub:pangliang/pangliang.github.com

需求

按字面个数来截取
函数(字符串, 开始位置, 截取长度)

utf8sub("你好1世界哈哈",2,5)    =    好1世界哈
utf8sub("1你好1世界哈哈",2,5)    =    你好1世界
utf8sub("你好世界1哈哈",1,5)    =    你好世界1
utf8sub("12345678",3,5)    =    34567
utf8sub("øpø你好pix",2,5)    =    pø你好p

错误方法

网上找了一些算法, 都不太正确; 要么就是乱码, 要么就是只考虑了4 byte 中文的情况, 不够全面

1. string.sub(s,1,截取长度*4)

  网上很多直接使用"`""string.sub(s,1,截取长度*4)`"是肯定不对的, 因为如果中英文混合的字符串, 例如`你好1世界`的字符长度分别是`4,4,1,4,4`, 如果截取4个字, 4*4=4+4+1+4+3, 那`世界`的`界`字将会被取前3个byte, 就会出现乱码

2. if byte>128 then index = index + 4

问题关键

1. utf8字符是变长字符

2. 字符长度有规律

UTF-8字符规律

字符串的首个byte表示了该utf8字符的长度

0xxxxxxx - 1 byte

110yxxxx - 192, 2 byte

1110yyyy - 225, 3 byte

11110zzz - 240, 4 byte

正确算法

 1 --
 2 -- lua
 3 -- 判断utf8字符byte长度
 4 -- 0xxxxxxx - 1 byte
 5 -- 110yxxxx - 192, 2 byte
 6 -- 1110yyyy - 225, 3 byte
 7 -- 11110zzz - 240, 4 byte
 8 local function chsize(char)
 9     if not char then
10         print("not char")
11         return 0
12     elseif char > 240 then
13         return 4
14     elseif char > 225 then
15         return 3
16     elseif char > 192 then
17         return 2
18     else
19         return 1
20     end
21 end
22
23 -- 计算utf8字符串字符数, 各种字符都按一个字符计算
24 -- 例如utf8len("1你好") => 3
25 function utf8len(str)
26     local len = 0
27     local currentIndex = 1
28     while currentIndex <= #str do
29         local char = string.byte(str, currentIndex)
30         currentIndex = currentIndex + chsize(char)
31         len = len +1
32     end
33     return len
34 end
35
36 -- 截取utf8 字符串
37 -- str:            要截取的字符串
38 -- startChar:    开始字符下标,从1开始
39 -- numChars:    要截取的字符长度
40 function utf8sub(str, startChar, numChars)
41     local startIndex = 1
42     while startChar > 1 do
43         local char = string.byte(str, startIndex)
44         startIndex = startIndex + chsize(char)
45         startChar = startChar - 1
46     end
47
48     local currentIndex = startIndex
49
50     while numChars > 0 and currentIndex <= #str do
51         local char = string.byte(str, currentIndex)
52         currentIndex = currentIndex + chsize(char)
53         numChars = numChars -1
54     end
55     return str:sub(startIndex, currentIndex - 1)
56 end
57
58 -- 自测
59 function test()
60     -- test utf8len
61     assert(utf8len("你好1世界哈哈") == 7)
62     assert(utf8len("你好世界1哈哈 ") == 8)
63     assert(utf8len(" 你好世 界1哈哈") == 9)
64     assert(utf8len("12345678") == 8)
65     assert(utf8len("øpø你好pix") == 8)
66
67     -- test utf8sub
68     assert(utf8sub("你好1世界哈哈",2,5) == "好1世界哈")
69     assert(utf8sub("1你好1世界哈哈",2,5) == "你好1世界")
70     assert(utf8sub(" 你好1世界 哈哈",2,6) == "你好1世界 ")
71     assert(utf8sub("你好世界1哈哈",1,5) == "你好世界1")
72     assert(utf8sub("12345678",3,5) == "34567")
73     assert(utf8sub("øpø你好pix",2,5) == "pø你好p")
74
75     print("all test succ")
76 end
77
78 test()
时间: 2024-10-06 00:11:04

UTF8字符串在lua的截取和字数统计【转载】的相关文章

Lua实现计算 UTF8 字符串的长度,每一个中文算一个字符

-- 计算 UTF8 字符串的长度,每一个中文算一个字符 -- @function [parent=#string] utf8len -- @param string input 输入字符串 -- @return integer#integer  长度 计算 UTF8 字符串的长度,每一个中文算一个字符 local input = "你好World" print(string.utf8len(input)) -- 输出 7 function string.utf8len(input)

php中的中文字符串长度计算以及截取

一.中文字符串截取:mb_substr() mb_substr($str, $start, $length, $encoding); $str,需要截断的字符串 $start,截断开始处,起始处为0 $length,要截取的字数 $encoding,网页编码,如utf-8,GB2312,GBK 例: $str = "这个字符串是我想要截取的"; 截取"这个字"; echo mb_substr($str,0,3,"utf-8"); 二.中文字符串长

截取指定字数

截取指定字数,可以按照半角全角以及字母来截取,兼容IE9以及以上浏览器 html: <h2>控制只显示32个字过长显示省略号</h2> <div id="divbox"></div> css: #divbox{ width:300px; color:red; height:200px; background:#efefef; } js: /* * 处理过长的字符串,截取并添加省略号 * 注:半角长度为1,全角长度为2 * * pStr:字

[C++] zlatlcv: ATL字符串转换辅助库。能很方便的将UTF-8字符串转为TCHAR等字符串

作者:zyl910 如今,UTF-8字符串的使用频率越来越多了.但是在VC中,不能直接处理UTF-8字符串,得专门去写UTF-8与窄字符串.宽字符串.TCHAR字符串相互转换的代码.不仅费时费力,而且稍不留心就容易造成内存泄露问题.于是我便想专门编写个库来解决UTF-8字符串编码问题. 特性——支持 TCHAR,能随时切换项目字符集配置.兼容 32位(x86)与64位(x64)Windows环境.兼容 VC2005 及更高版本的 VC. 一.设计思路 ATL中的字符串转换宏用起来很方便,于是我打

TinyXML 解析 UTF-8 字符串的问题

TinyXML 在解析 UTF-8 格式的 XML 文件时,如果文件中含有以下两个字符串:“<name>文史经典</name>” 和 “<name>资讯速递</name>” 时,解析失败. 分析代码,发现失败的原因是如下的代码: tinyxmlparser.cpp 文件中的函数:const char* TiXmlBase::ReadText() 1 int len; 2 char cArr[4] = { 0, 0, 0, 0 }; 3 p = GetChar

UTF-8编码的字符串拆分成单字、获取UTF-8字符串的字符个数的代码及原理

一.字符编码简介 1. ASCII码 在计算机内部,所有的信息最终都表示为一个二进制的字符串.每一个二进制位(bit)有0和1两种状态,因此八个二进制位就可以组合出256种状态,这被称为一个字节(byte).也就是说,一个字节一共可以用来表示256种不同的状态,每一个状态对应一个符号,就是256个符号,从0000000到11111111.上个世纪60年代,美国制定了一套字符编码,对英语字符与二进制位之间的关系,做了统一规定.这被称为ASCII码,一直沿用至今.ASCII码一共规定了128个字符的

c语言判断是否是utf8字符串,计算字符个数

#include <stdio.h> #include <string.h> #include <stdlib.h> /**************************************************************************** Unicode符号范围 | UTF-8编码方式 (十六进制) | (二进制) 0000 0000-0000 007F:0xxxxxxx 0000 0080-0000 07FF:110xxxxx 10x

UTF8字符串转换为汉字 c#

1 using System; 2 3 4 5 /// <summary> 6 /// UTF8字符串转换为汉字用的类 7 /// 转换如"\\u8d35"之类的字符串为对应的汉字 8 /// </summary> 9 class UTF8String 10 { 11 string m_strContent = ""; 12 /// <summary> 13 /// 构造函数 14 /// </summary> 15

数据转换||数据判断||数据操作||日期||字符串长度区分中英文截取

MXS&Vincene  ─╄OvЁ  &0000016 ─╄OvЁ  MXS&Vincene MXS&Vincene  ─╄OvЁ:今天很残酷,明天更残酷,后天很美好,但是绝大部分人是死在明天晚上,只有那些真正的英雄才能见到后天的太阳. MXS&Vincene  ─╄OvЁ:We're here to put a dent in the universe. Otherwise why else even be here? 正文>>>>>