トップC# > 文字列処理

文字列処理

1.文字列の一部を取り出す[1]

    string str = "ABC1234あいうえお5678";

    // 3 文字目の後から 9 文字の文字列を取得する
    string str1 = str.Substring(3, 9);

    // 4 文字目の後から末尾までの文字列を取得する
    string str2 = str.Substring(4);

2.文字列を探索する

String.IndexOfメソッドは、文字列内に指定した文字列と一致する部分があるかを探し、 見つかったら、最初に見つかった位置を 0 以上の整数で返す(先頭文字の位置が 0)。 見つからなければ、-1 を返す[2]。

string s1 = "あいうえおあいうえお";

Console.WriteLine(s1.IndexOf("うえ"));      // 結果は "2"
Console.WriteLine(s1.IndexOf("ウエ"));      // 結果は "-1"
Console.WriteLine(s1.IndexOf(""));          // 結果は "0"

Console.WriteLine(s1.IndexOf("うえ",5));    // 5文字目から探索,結果は "7"

位置は必要なく、文字列内に指定した文字列が存在するかどうかだけを知るには Containsメソッドを使用する。

string s1 = "あいうえおあいうえお";

Console.WriteLine(s1.Contains("うえ"));      // 結果は true
Console.WriteLine(s1.Contains("ウエ"));      // 結果は false

3.文字列中の文字にアクセスする

Javaでは String str = "abc123"; の文字 'c' は str.charAt(2) として読みだすが、 c# では string str = "abc123"; の文字 'c' は str[2] として読みだせる。 見かけは配列のアクセスに似ているが、インデクサ[3]と呼ばれるものであり、全ての操作が配列と同じというわけではない。 この場合 str[2] は読み取り専用であり、str[2] = 'C'; のようにして、この文字を書き換えることはできない。 分かりやすく言えば、".charAt(2)" の表記を "[2]" に変えただけのものと解釈できる。C++でオペレータ[]をオーバーライドする場合と類似の機能である。

4.文字列の連結

文字列の連結は Java と同様で、 C# で文字列連結するとき、string 型を += で連結するとパフォーマンスが落ちるので、ある程度の回数以上の文字列連結には StringBuilder を使う。 string は不変なので、+= での連結の度に新しいオブジェクトの生成と破棄がおこなわれる。

改行を付けるには stringBuffer.AppendLine("abc"); が便利である。AppendFormatもある。

5.Regex.Split

Regex.Split[4]が単純な字句解析に役立つ。

using System;
using System.Text.RegularExpressions;

class Program {
    static void Main() {
        string operation = "3 * 5 = 15";
        string[] operands = Regex.Split(operation, @"\s+"); // 空白文字で分割
        foreach (string operand in operands) {
            Console.WriteLine(operand);
        }
    }
}
3
*
5
=
15
using System;
using System.Text.RegularExpressions;

class Program {
    static void Main() {
        string sentence = "10 cats, 20 dogs, 40 fish and 1 programmer.";
        string[] digits = Regex.Split(sentence, @"\D+");    // 非数字(0,1, ... ,9)で分割
        foreach (string value in digits) {
            Console.WriteLine(value);
        }
    }
}
10
20
40
1

コンパイラの字句解析にはちょっと無理そう。 コンパイラの字句解析では、空白だけでなく、字種の変わり目でも分割しなければならない。 例えば int n+=_k+1 は、int, n, +=, _k, +, 1 に分割する。 C言語をルーツとするプログラミング言語では「_」(アンダーバー)は英字と同様の扱いとなることが多い。 字句規則に従った分割となるため、字句解析は一般に、数行のプログラムでは済まない。

例1[2014.12.30]

"-170(-0.87%)" のような記述から、"-170" と "-0.87" を抽出したい。 C言語では strtok(s, "(") で、"-170" 、次いで strtok(NULL, "%") で "-0.87" が取り出せる。

C# では、符号 +, - 、小数点 . および数字以外で分割すればよいので、 Splitメソッドの第二引数を @"[^\+-\.\d]+" とすればよい。 

6.末尾の文字列と一致するか調べる

末尾の文字列と一致するか調べるには EndsWithメソッドを使う。

    string url = "http://home.a00.itscom.net/hatada/index.html";

    // 末尾の文字列と一致するかどうかを判断する
    if (url.EndsWith(".html")) {
        MessageBox.Show("HTMLファイルです");
    }

先頭の文字列と一致するか調べるには StartsWithメソッドを使う。

7.文字が数字かどうか調べる

文字 ch が10進数の数字かどうか調べるには char.IsDigit(ch) を使う。 string型文字列 s の n 番目(先頭が0)の文字が数字かどうか調べるには char.IsDigit(s,n) を使う。 全角文字0、1、2、... 、9 も10進数とみなされるが、 漢字数字一、二、三、... やローマ数字T、U、V、... は10進数とみなさない。

文字列がASCIIの数値かどうかは次のようにして調べられる。

    bool IsNumber(string str) {
        foreach (char c in str) {
            if (c < '0' || '9' < c) return false;
        }
        return true;
    }

ā, ī, ū, ē, ō は UNICODE では 0x101, 0x12B, 0x16B, 0x113, 0x14D である。

C#の 文字列 name が英数字記号または ā, ī, ū, ē, ō のみで構成されるかどうかを調べるプログラムを下に示す。

    bool IsAscii(string name) {
        return new Regex("^[\x20-\x7E\u0101\u012B\u016B\u0113\u014D]+$").IsMatch(name);
    }   // ASCIIコードおよび長音aiueo(2バイトコード)

8.文字列を比較する

文字列 strA と strB が等しいかどうか調べるには strA == strB を使う。 辞書順の並びを調べるには String.Compare(strA, strB) を使う。この値が負の時は strA の方が辞書順では先(小さい)、 ゼロのときは二つの文字列が等しい、正のときは辞書順では strA の方が後(大きい)。

9.文字列を置換する

文字列 s 中のある文字列 src を別の文字列 dst に置き換えるには String.Replaceメソッドを sReplaced = s.Replace(src, dst) のように使う。また、文字 cSrc を文字 cDst に置き換えるには sReplaced = s.Replace(cSrc, cDst) とする。

10.文字列の配列を区切り文字列で連結して文字列をつくる

文字列の配列を区切り文字列で連結した文字列に変換するには、String.Join メソッドを使用する。 Join メソッドの第1引数には、区切り文字列、第2引数には、文字列配列を指定する。 第3、第4引数を指定して、配列要素の一部を連結することもできる。

A.リファレンス

[1] 文字列の一部を取り出す
[2] 文字列内に指定された文字列があるか調べ、その位置を知る
[3] インデクサとプロパティ
[4] C# Regex.Split