雑記
 

文字列の長さ

2024/1/5

       

目次

 

1.「文字列の長さ」の違い

String.Length などで正確に数えられるのは Unicode 第0面(BMP)に収録されている文字だけです。

.NETの文字数の取得機能のほとんどはString.Lengthに依存しています。

Unicode 第1面以降の文字や結合文字の見かけの文字数を数えたい場合は、Runeの数を数えたり、StringInfoクラスの機能を使用します。

日本や中国などを含めて日常的に使う文字はUnicode 第0面(BPM)に含まれています。通常Unicode第1面以降の文字や結合文字を使用することはありません。

🗿などの多くの絵文字はUnicode第1面に収録されており、最近は絵文字を使う人が増えているように感じます。このような絵文字を1文字と数えるにはString.Length以外の手段が必要です。

日本や中国ではごくまれに地名や人名などの固有名詞にUnicode第1面以降の文字が使われている場合があります。

また、日本の漢字は同じ漢字なのに点の位置など形が微妙に違うバリエーション(異字体)が非常に多いものがあり、そのような違いを結合文字を使って表現することが可能です。しかし、この使い方は2024年現在ではほとんど普及していません。

古代エジプトのヒエログリフのような古代文字や特殊な用途で使用される文字がUnicode第1面以降に収録されている場合があります。

みなさんが試せるように上の画像で使っている文字をここに掲載しておきます。

A1&あ각★☃ΩⒽ山竜你𩸽𓀉𫛣🗿🗻🗼

あ゙あ゚あ̰👩‍👨‍👦‍👧🏴‍☠⚔️

 

2.サンプルプログラム

それぞれの方法で文字数を数えるコンソールアプリ(.NET 8)のサンプルを紹介します。

ご利用の環境によっては文字がうまく表示されないかもしれません。使っているフォントにその文字が収録されていなかったり、ソフトウェアがUnicodeに完全に対応していなかったりする場合があるからです。

C#

namespace CsConsole
{
    internal class Program
    {
        static void Main(string[] args)
        {
            PrintLength("A");
            PrintLength("あ");
            PrintLength("☃");
            PrintLength("山");
            PrintLength("𩸽");
            PrintLength("𓀉");
            PrintLength("🗿");
            PrintLength("あ゙");
            PrintLength("👩‍👨‍👦‍👧");
            PrintLength("⚔️");
        }

        private static void PrintLength(string text)
        {
            int len1 = text.Length; //String.Length
            int len2 = text.EnumerateRunes().Count(); //Runeの数
            int len3 = EnumerateTextElements(text).Count(); //TextElementの数
            System.Diagnostics.Debug.WriteLine($"{text} Length:{len1} Runes:{len2} Text Elements:{len3}");
        }

        private static IEnumerable<string> EnumerateTextElements(string text)
        {
            var enumerator = System.Globalization.StringInfo.GetTextElementEnumerator(text);
            while (enumerator.MoveNext())
            {
                yield return (string)enumerator.Current;
            }
        }
    }
}

Debug.WriteLineで出力される場所

 

VB

Module Program
    Sub Main(args As String())
        PrintLength("A")
        PrintLength("あ")
        PrintLength("☃")
        PrintLength("山")
        PrintLength("𩸽")
        PrintLength("𓀉")
        PrintLength("🗿")
        PrintLength("あ゙")
        PrintLength("👩‍👨‍👦‍👧")
        PrintLength("⚔️")
    End Sub

    Private Sub PrintLength(text As String)

        Dim len1 As Integer = text.Length 'String.Length
        Dim len2 As Integer = text.EnumerateRunes().Count() 'Runeの数
        Dim len3 As Integer = EnumerateTextElements(text).Count() 'TextElementの数
        Debug.WriteLine($"{text} Length:{len1} Runes:{len2} Text Elements:{len3}")

    End Sub

    Private Iterator Function EnumerateTextElements(text As String) As IEnumerable(Of String)
        Dim enumerator = Globalization.StringInfo.GetTextElementEnumerator(text)
        While enumerator.MoveNext()
            Yield CStr(enumerator.Current)
        End While
    End Function
End Module

Debug.WriteLineで出力される場所

 

 

実行すると出力ウィンドウに次のように出力されます。

A Length:1 Runes:1 Text Elements:1
あ Length:1 Runes:1 Text Elements:1
☃ Length:1 Runes:1 Text Elements:1
山 Length:1 Runes:1 Text Elements:1
𩸽 Length:2 Runes:1 Text Elements:1
𓀉 Length:2 Runes:1 Text Elements:1
🗿 Length:2 Runes:1 Text Elements:1
あ゙ Length:2 Runes:2 Text Elements:1
👩‍👨‍👦‍👧 Length:11 Runes:7 Text Elements:1
⚔️ Length:2 Runes:2 Text Elements:1

 

出典

例: char、Rune、テキスト要素のインスタンス数を数える

https://learn.microsoft.com/ja-jp/dotnet/standard/base-types/character-encoding-introduction#example-count-char-rune-and-text-element-instances

 

Unicodeの世界 ~絵文字の連結編~

https://qiita.com/noritsune/items/46134cb7a50236540be5

 

 


English Version