包含中日韩字符的字符串长度

3
当给定一个包含CJK字符的字符串时,String.length返回字符串中字符数量错误,因为它计算的是字节数。例如:
# String.length "第1";;
- : int = 4

字符串中有两个字符,但是String.length返回的是4(这是字符串中字节的数量)。

我该如何获取包含CJK字符的字符串的真实长度?


1
OCaml在编码方面没有任何本地支持,并且在这些方面非常幼稚,只是依赖外部世界来理解字符字节转换步骤(不幸的是,它与许多其他编程语言共享这种特征)。尝试使用Camomile(免责声明:无个人经验)。 - Jeroen Mostert
1
相关:https://dev59.com/g2Qo5IYBdhLWcg3wUd-L - Flux
电池还包含一个处理UTF8的模块,如果我没记错的话。 - Nephanth
你如何定义字符串的“长度”?是指Unicode代码点的数量吗?还是指由多个代码点组成的合并字符的数量? - newacct
@newacct 字符数。例如,第1的长度为23G电话4문명2hello5 - Flux
2个回答

4

如果您想计算扩展字形簇(也称为图形字符)的数量,您可以使用 Uuseg 进行分割:

let len = Uuseg_string.fold_utf_8 `Grapheme_cluster (fun x _ -> x + 1) 0
;; len "春"

1

这种方法具有优势,即在存在非预组合字符(例如韩文中的分解韩文字母)的情况下仍然准确。

 ;; len "\u{1112}\u{1161}\u{11AB}"

1

这是正确的结果,因为即使使用3个Unicode标量值进行书写,前面的字符串也应该显示为


1

如评论所述,OCaml没有本地支持任何特定编码的功能,因此长度是以字节为单位计算的。

现在,假设您正在使用Utf8编码(这是混合ascii和CJK AFAIK的最简单方法),有几种方法可以计算该大小。

例如,使用非常轻量级的Uutf库 [EDIT],正如octachron指出的那样,这将返回标量值而不是字符长度,您应该使用octachron的答案。

let utf8_length s = (* returns the number of unicode scalar values *)
 let decoder = Uutf.decoder ~encoding:`UTF_8 (`String s) in
 let rec loop () = match Uutf.decode decoder with | `End -> () | _ -> loop () in
 loop ();
 Uutf.decoder_count decoder

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接