.NET TIPS

文字列を1文字ずつ解析するには?(サロゲート文字対応)[C#、VB]

デジタルアドバンテージ 一色 政彦
2008/04/24

 文字列を加工するなどの目的で、文字列の内容を解析したいような場合がある。この際、一般的には正規表現を利用するが(参考「TIPS:正規表現を使って部分文字列を取得するには?」「TIPS:正規表現を使って文字列から部分文字列を取り除くには?」)、もちろん1文字ずつ解析して処理することもできる(正規表現の方がコードがシンプルになるので便利だが、処理速度が遅くなる場合がある。筆者はコードはかっこ悪くても処理速度の速い「1文字ずつの解析処理」を好んでよく用いる)。本稿ではこの1文字ずつの解析処理の方法を紹介する。

 なお、最近ではWindows Vistaの登場などにより、(エンド・ユーザーによって)Unicodeのサロゲート文字が入力される可能性があり、それが文字列解析の処理で問題となる場合もある。サロゲート文字(もしくはサロゲート・ペア文字)とは、通常「1文字=2bytes」のところが、「1文字=4bytes」となることがある文字だ。そこで本稿では、サロゲート文字も考慮した文字列解析処理について説明する。

文字列解析処理

 (サロゲート文字を考慮しながら)文字列を1文字ずつ処理するには、TextElementEnumeratorオブジェクト(System.Globalization名前空間のTextElementEnumeratorクラスのオブジェクト)を使用する。

 TextElementEnumeratorオブジェクトは、処理したい文字列をパラメータに指定して、StringInfoクラス(System.Globalization名前空間)の静的メソッドであるGetTextElementEnumeratorメソッドを呼び出せば取得できる。

 実際にTextElementEnumeratorオブジェクトを使って1文字ずつ処理するには、まずMoveNextメソッド(パラメータなし)を呼び出して次の1文字を処理対象とし、Currentプロパティからその文字を取得する(Object型であるが、実際の内容は1文字の文字列)。注意点としては、MoveNextメソッドを呼び出して初めて最初の1文字が取得できることだ(MoveNextメソッドを呼び出さずに、Currentプロパティを使うことはできない)。

 次の画面は、文字列を1文字ずつ処理するWindowsアプリケーションのサンプル・プログラムである。

文字列を1文字ずつ処理するWindowsアプリケーションの実行例
このアプリケーションでは[処理実行]ボタンをクリックすると、上のテキストボックスに入力された文字列を1文字ごとに分解して、それぞれの文字を「 」で囲んで再びすべてを1つ文字列に結合し、それを下のテキストボックス(textBox2)に設定する。

 このアプリケーションでは[処理実行]ボタン(button1)をクリックすると、上のテキストボックス(textBox1)に入力された文字列を、上記の説明の手順で処理し、処理後の文字列を下のテキストボックス(textBox2)に設定する。その処理内容が、次のコード(の太字部分)である。

using System.Globalization;
using System.Text;

public Form1()
{
  InitializeComponent();

  this.textBox1.Text = "生徒を\uD842\uDF9Fる";
}

private void button1_Click(object sender, EventArgs e)
{
  string moji = this.textBox1.Text;

  // テキスト要素を列挙するオブジェクトを取得
  TextElementEnumerator charEnum =
  StringInfo.GetTextElementEnumerator(moji);

  // 1文字ずつ解析して、文字列を加工する
  StringBuilder analyzedMoji = new StringBuilder();
  while (true)
  {
    // 次の1文字を取得する
    if (charEnum.MoveNext() == false)
    {
      break; // 取得する文字がない
    }

    // 1文字ずつ処理する
    analyzedMoji.Append("「" + charEnum.Current + "」");
  }

  this.textBox2.Text = analyzedMoji.ToString();
}
Imports System.Globalization
Imports System.Text

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
  Me.textBox1.Text = "生徒を" & ChrW(&HD842) & ChrW(&HDF9F) & "る"
End Sub

Private Sub button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles button1.Click

  Dim moji As String = Me.textBox1.Text

  ' テキスト要素を列挙するオブジェクトを取得
  Dim charEnum As TextElementEnumerator = _
    StringInfo.GetTextElementEnumerator(moji)

  ' 1文字ずつ解析して、文字列を加工する
  Dim analyzedMoji As New StringBuilder()
  While (True)
    ' 次の1文字を取得する
    If charEnum.MoveNext() = False Then
      Exit While ' 取得する文字がない
    End If

    ' 1文字ずつ処理する
    analyzedMoji.Append("「" & charEnum.Current & "」")
  End While

  Me.textBox2.Text = analyzedMoji.ToString()

End Sub
文字列を1文字ずつ処理するWindowsアプリケーションのサンプル・プログラム(上:C#、下:VB)

 ちなみにTextElementEnumeratorオブジェクトのElementIndexプロパティからは、文字(=テキスト要素)のインデックス番号を取得できる。取得した1文字(=Stringオブジェクト)がサロゲート文字かどうかを調べるには、「TIPS:サロゲート文字かどうかを判定するには?」の方法を使えばよい。End of Article

カテゴリ:クラス・ライブラリ 処理対象:文字列
使用ライブラリ:TextElementEnumeratorクラス(System.Globalization名前空間)
使用ライブラリ:StringInfoクラス(System.Globalization名前空間)
関連TIPS:サロゲート文字かどうかを判定するには?
関連TIPS:正規表現を使って部分文字列を取得するには?
関連TIPS:正規表現を使って文字列から部分文字列を取り除くには?

この記事と関連性の高い別の.NET TIPS
サロゲート文字かどうかを判定するには?
文字と文字列を変換するには?
文字数を正確にカウントするには?(サロゲート文字対応)
文字列から特定の文字列を取り除くには?
文字列の長さを取得するには?
このリストは、(株)デジタルアドバンテージが開発した
自動関連記事探索システム Jigsaw(ジグソー) により自動抽出したものです。
generated by

「.NET TIPS」


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Insider.NET 記事ランキング

本日 月間