Unicodeの文字数を書記素単位で数える
書記素を自力で判定するのはほぼ不可能。(もちろんちゃんと仕様を理解すれば実装する事はできる)
仕様は以下に書かれている。
UAX #29 UNICODE TEXT SEGMENTATION https://www.unicode.org/reports/tr29/
通常はライブラリを使う事になる。
ICU https://unicode-org.github.io/icu/
ICU4C C/C++用
ICU4J Java 用
Unicode の書記素自体が持つ問題
長さは無限(長さ制限がない)
縦幅横幅はフォントで実際に描画するまで分からない。
等幅フォントならワンチャン?
書記素とはまた別にレンダリング時に合字(リガチャー)(fi(fi) のようなもの。)が現れる可能性はある。一字ごとにサイズを測るというアプローチはうまく行かない。
通信などで分割されて送られてきてしまうことがある。明確に分割可能と言える文字が現れるまでは継続している可能性がある。
多くのライブラリでは、単純に文字列をそのまま解釈しようとするため、ここが正しく動かない。最後の1文字はペンディングさせておく必要がある。
「あ゙」のような結合文字だと濁点が分かれて受信されるかもしれない。
C/C++
ICUでUTF-8の文字列を1文字ごとに分割する https://qiita.com/zinbe/items/f8501b8da709dfad8b11
C#
最近のWindows 10で絵文字を書記素クラスタ単位で数える https://blog.tmyt.jp/entry/2019/04/20/205754
ICU4C をC#から呼び出す例
.NET グローバリゼーションと ICU https://docs.microsoft.com/ja-jp/dotnet/core/extensions/globalization-icu
JavaScript
JavaScript における文字コードと「文字数」の数え方 https://blog.jxck.io/entries/2017-03-02/unicode-in-javascript.html
現在は Intl.Segmenter というAPIが増えた。
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Intl/Segmenter
「文字数を数える」「1文字とは」問題、または、Intl.Segmenterへの警鐘https://qiita.com/KageShiron/items/22824ff22d09b0e45158
https://github.com/orling/grapheme-splitter
Rust
https://crates.io/crates/unicode-segmentation
参考
合字は糞!Unicodeは糞!(WindowsTerminal)https://zenn.dev/zetamatta/books/b820d588f4856bcf836c/viewer/0637c8
どのキャラクター端末なら正しく書記素が表示できるかは分からない…
プログラムで書記素を正しく計数しても、表示でずれるかもしれない。
書記素単位で処理する事で避けられるのは、1つの書記素をうっかりバラバラにしてしまうトラブル。
#文字列操作API