DOBON.NET プログラミング道: .NET Framework, VB.NET, C#, Visual Basic, Visual Studio, インストーラ, ...

文字列から1文字取得する、文字列内の文字を列挙する

文字列の中から任意の位置にある1文字を取得したり、文字列の先頭から順番に文字を列挙していくには、String.Charsプロパティを使用すると簡単です。Charsプロパティは、VB.NETでは既定のプロパティ(.NET Framework 2.0以降)、C#ではインデクサとして定義されていますので、あたかも配列のようにアクセスできます。返される値はChar型で、String型ではありません。

補足:VB.NETでは、GetChar関数を使うこともできます。

以下に、文字列の1文字目を取得する例と、先頭から順番に1文字ずつ列挙していく例を示します。

VB.NET
コードを隠すコードを選択
Dim str As String = "あいうえおかきくけこ"

'1文字目の文字を取得する
Dim c1 As Char = str(0)
'.NET Framework 1.1以前では、次のようにする
'Dim c1 As Char = str.Chars(0)
'あ

'Forを使って1文字ずつ列挙する
Dim i As Integer
For i = 0 To str.Length - 1
    Console.WriteLine(str(i))
    '.NET Framework 1.1以前では、次のようにする
    'Console.WriteLine(str.Chars(i))
Next

'For Eachを使って1文字ずつ列挙する
Dim c As Char
For Each c In str
    Console.WriteLine(c)
Next
C#
コードを隠すコードを選択
string str = "あいうえおかきくけこ";

//1文字目の文字を取得する
char c1 = str[0];
//あ

//forを使って1文字ずつ列挙する
for (int i = 0; i < str.Length; i++)
{
    Console.WriteLine(str[i]);
}

//foreachを使って1文字ずつ列挙する
foreach (char c in str)
{
    Console.WriteLine(c);
}

くどいようですが、このようにして取得できる文字はChar型ですので、比較する場合はChar型と比較します。以下に、特定の文字を探す例を示します。

VB.NET
コードを隠すコードを選択
Dim str As String = "あいうえおかきくけこ"

'「か」という文字を探す
Dim i As Integer
For i = 0 To str.Length - 1
    If str(i) = "か"c Then
        Console.WriteLine("{0}文字目に「か」を見つけました", i + 1)
    End If
Next
C#
コードを隠すコードを選択
string str = "あいうえおかきくけこ";

//「か」という文字を探す
for (int i = 0; i < str.Length; i++)
{
    if (str[i] == 'か')
    {
        Console.WriteLine("{0}文字目に「か」を見つけました", i + 1);
    }
}

String.ToCharArrayメソッドを使う

String.ToCharArrayメソッドを使うと、文字列をChar型の配列に変換して取得することができます。上記のString.Charsプロパティと違い、新しい配列を作成します。また、String.Charsプロパティは読み取り専用で書き換えができませんが、String.ToCharArrayメソッドで作成した配列は書き換えができます。書き換えたChar型の配列からStringオブジェクトを作成するには、Stringクラスのコンストラクタにパラメータとして指定します。

以下に、String.ToCharArrayメソッドを使った例を示します。

VB.NET
コードを隠すコードを選択
Dim str As String = "あいうえおかきくけこ"

'Char型の配列に変換する
Dim cs As Char() = str.ToCharArray()

'1文字目の文字を取得する
Dim c1 As Char = cs(0)
'あ

'Forを使って1文字ずつ列挙する
For i As Integer = 0 To cs.Length - 1
    Console.WriteLine(cs(i))
Next

'For Eachを使って1文字ずつ列挙する
For Each c As Char In cs
    Console.WriteLine(c)
Next
C#
コードを隠すコードを選択
string str = "あいうえおかきくけこ";

//Char型の配列に変換する
char[] cs = str.ToCharArray();

//1文字目の文字を取得する
char c1 = cs[0];
//あ

//forを使って1文字ずつ列挙する
for (int i = 0; i < cs.Length; i++)
{
    Console.WriteLine(cs[i]);
}

//foreachを使って1文字ずつ列挙する
foreach (char c in cs)
{
    Console.WriteLine(c);
}

String.Substringメソッドを使う

文字列の中から指定した部分の文字列を取得するメソッドとして、String.Substringメソッドがあります。これを使えば、指定した位置の1文字を取得することができます。

ただしこの方法は前述したCharsプロパティの方法と比べてパフォーマンスが劣りますので、おすすめは出来ません。

VB.NET
コードを隠すコードを選択
Dim str As String = "あいうえおかきくけこ"

'1文字目の文字を取得する
Dim s1 As String = str.Substring(0, 1)
'あ

'1文字ずつ列挙する
Dim i As Integer
For i = 0 To str.Length - 1
    Dim s As String = str.Substring(i, 1)
    Console.WriteLine(s)
Next
C#
コードを隠すコードを選択
string str = "あいうえおかきくけこ";

//1文字目の文字を取得する
string s1 = str.Substring(0, 1);
//あ

//1文字ずつ列挙する
for (int i = 0; i < str.Length; i++)
{
    string s = str.Substring(i, 1);
    Console.WriteLine(s);
}

サロゲートペアや結合文字列も1文字として列挙する

サロゲートペア(代用対)や結合文字列(Combining Character Sequence、組み合わせ文字シーケンス)は2つ以上のCharオブジェクトで1つの文字を表します。しかし上記の方法ではバラバラのCharオブジェクトとしてしか取得できません。

補足:サロゲートペアや結合文字列については、「サロゲートペアや結合文字が含まれているか調べる」で簡単に説明しています。

これらを1文字として取得するには、StringInfoクラスを使います。

まずは1文字ずつ列挙する例を示します。以下のサンプルでは、StringInfoクラスを使って、文字列の先頭から順番に1文字ずつ取得し、その文字と位置(String.Charsプロパティでの先頭のインデックス)をラベルコントロール(Label1)に表示しています。

VB.NET
コードを隠すコードを選択
'結合文字列を含む文字列
Dim str As String = "a" & ChrW(&H301) & "a" & ChrW(&H302) & "a" & _
    ChrW(&H303) & "a" & ChrW(&H304) & "a" & ChrW(&H305)

'TextElementEnumeratorを作成する
Dim tee As System.Globalization.TextElementEnumerator = _
    System.Globalization.StringInfo.GetTextElementEnumerator(str)
'読み取る位置をテキストの先頭にする
tee.Reset()
'1文字ずつ取得する
Dim res As String = ""
While tee.MoveNext()
    '文字と、その位置を取得する
    res += String.Format("文字:{0} 位置:{1}" & vbCrLf, _
                         tee.GetTextElement(), tee.ElementIndex)
End While

'結果をラベルに表示する
Label1.Text = res
C#
コードを隠すコードを選択
//結合文字列を含む文字列
string str = "a\u0301a\u0302a\u0303a\u0304a\u0305";

//TextElementEnumeratorを作成する
System.Globalization.TextElementEnumerator tee =
    System.Globalization.StringInfo.GetTextElementEnumerator(str);
//読み取る位置をテキストの先頭にする
tee.Reset();
//1文字ずつ取得する
string res = "";
while (tee.MoveNext())
{
    //文字と、その位置を取得する
    res += string.Format("文字:{0} 位置:{1}\n",
        tee.GetTextElement(), tee.ElementIndex);
}

//結果をラベルに表示する
Label1.Text = res;

結果として、ラベルには以下のように表示されます。

StringInfoのサンプルの結果

この例ではGetTextElementメソッドで1文字をString型で取得しましたが、CurrentプロパティでObject型を取得することもできます。CurrentプロパティはGetTextElementメソッドの返す値をObject型にしただけのものです。

サロゲートペアや結合文字列も1文字として指定した位置から取得する

サロゲートペアや結合文字列も1文字として指定した位置から1文字を取得するには、上記の方法以外に、.NET Framework 2.0以降ではStringInfo.SubstringByTextElementsメソッドを、.NET Framework 1.1以前ではParseCombiningCharactersメソッドを使う方法があります。これらの説明は、「サロゲートペアや結合文字列を含む文字列でも正しく部分文字列を取得する」をご覧ください。

  • 履歴:
  • 2011/3/12 String.ToCharArrayメソッドの説明を追加。

注意:この記事では、基本的な事柄の説明が省略されているかもしれません。初心者の方は、特に以下の点にご注意ください。

  • .NET Tipsをご利用いただく際は、注意事項をお守りください。