C#言語での文字列
C#言語での文字列は、文字型の配列ではなく、文字列型のオブジェクトです。つまり、System.Char構造体の配列ではなく、System.Stringクラスのオブジェクトです。
Stringとstring
Stringとstringは同じ意味です。前者が.NETの型を表すのに対し後者はC#型のキーワード(エイリアス)です。文字列操作
文字列操作は頻出の重要な処理です。ほとんどのことは既に用意されている機能で賄えます。
下記のメソッドはいずれも多くのオーバーロードが定義されています。
生成
stringは参照型なのですが、new演算子無しで直接リテラルを設定することが出来ます。勿論new演算子で生成することもでき、いろんなコンストラクタが定義されています。
// 直接文字列を指定
string s1 = "いろはにほへと";
// コンストラクタに文字の配列を指定
char[] array = { 'い','ろ','は','に','ほ' };
string s2 = new string(array); // いろはにほへと
// 文字配列の2番目から三文字分
string s3 = new string(array, 2, 3); // はにほ
// 指定文字の繰り返し
string s4 = new string('い', 3); // いいい
配列とインデクサ
文字列中の各文字へは添え字でアクセスできます。配列のように扱えますが、インデクサという文法によるものです。
配列への変換メソッドは用意されていますが、リストへの変換はLinqが必要です。
string s1 = "いろはにほへと";
// インデクサ
char c1 = s1[3]; // に
// 文字型配列へ変換
char[] array = s1.ToCharArray();
// 文字型のリストへ変換(uing System.Linq;が必要)
List<char> list = s1.ToList();
等価比較
文字列同士の比較は==演算子で行えます。Equalsメソッドも同じように扱えます。
String.Compareでも比較ができますがその方法が異なります。
string s1 = "abcdefg";
string s2 = "abcdefg";
string s3 = "hijklmn";
string s4 = "ABCDEFG";
bool ret1 = s1 == s2; // true
bool ret2 = s1 == s3; // false
bool ret3 = s1 == s4; // false
bool ret4 = s1.Equals(s2); // true
bool ret5 = s1.Equals(s3); // false
bool ret6 = s1.Equals(s4); // false
int ret7 = String.Compare(s1, s2); // 0
int ret8 = String.Compare(s1, s3); // -1
int ret9 = String.Compare(s1, s4); // -1
// 大文字小文字の区別なし
int ret0 = String.Compare(s1, s4, true); // 0
置換
string s1 = "いろはにほへと ちりぬるを わかよたれそ つねならむ";
string ret1 = s1.Replace("ちりぬるを", "散りぬるを"); // いろはにほへと 散りぬるを わかよたれそ つねならむ
// 挿入
string ret2 = s1.Insert(10, "aaaa"); // いろはにほへと ちりaaaaぬるを わかよたれそ つねならむ
分割
string s1 = "いろはにほへと ちりぬるを わかよたれそ つねならむ";
string[] ret1 = s1.Split(" "); // 空白で分割された4つの文字列になります
抜き出し
string ret3 = s1.Substring(8, 13); // ちりぬるを わかよたれそ
削除
// 8文字目から13文字分を削除
string ret2 = s1.Remove(8,13); // いろはにほへと つねならむ
空白削除
string s2 = " abc def ghi ";
string ret4 = s2.Trim(); // "abc def ghi"
string ret5 = s2.TrimStart(); // "abc def ghi "
string ret6 = s2.TrimEnd(); // " abc def ghi"
結合
string[] array = { "いろはにほへと", "ちりぬるを", "わかよたれそ", "つねならむ" };
// いづれも実行結果は "いろはにほへと ちりぬるを わかよたれそ つねならむ"
string s1 = string.Join(" ", array);
string s2 = string.Concat(array[0], " ", array[1], " ", array[2], " ", array[3]);
string s3 = string.Format("{0} {1} {2} {3}", array[0], array[1], array[2], array[3]);
string s4 = $"{array[0]} {array[1]} {array[2]} {array[3]}";
C#6.0から文字列補間(先頭に$を付けて{}の間に変数を設定できる文法)が追加されました。
精査
string s1 = "いろはにほへと ちりぬるを わかよたれそ つねならむ";
// 含まれるか
bool ret1 = s1.Contains("ちりぬるを"); // true
bool ret2 = s1.Contains("うゐのおくやま"); // false
// 最初に見つかったインデックス
int ret3 = s1.IndexOf(" "); // 7
int ret4 = s1.IndexOf("あ"); // -1
// 最後に見つかったインデックス
int ret5 = s1.LastIndexOf(" "); // 20
int ret6 = s1.LastIndexOf("あ"); // -1
// どれかが最初/最後に見つかったインデックス
int ret7 = s1.IndexOfAny(new char[] { 'ち','わ'}); // 8
int ret8 = s1.LastIndexOfAny(new char[] { 'ち', 'わ' }); // 14
int ret9 = s1.IndexOfAny(new char[] { 'う', 'け' }); // -1
NULLと空文字列と空白
NULL・空文字列・空白の文字列はそれぞれ全く異なるものです。
string s1 = null;
string s2 = string.Empty;
string s3 = " "; // 半角スペース
string s4 = " "; // 全角スペース
bool ret1 = string.Empty == ""; // true
bool ret2 = string.IsNullOrEmpty(s1); // true
bool ret3 = string.IsNullOrEmpty(s2); // true
bool ret4 = string.IsNullOrEmpty(s3); // false
bool ret5 = string.IsNullOrEmpty(s4); // false
bool ret6 = string.IsNullOrWhiteSpace(s1); // true
bool ret7 = string.IsNullOrWhiteSpace(s2); // true
bool ret8 = string.IsNullOrWhiteSpace(s3); // true
bool ret9 = string.IsNullOrWhiteSpace(s4); // true
変換
// 大文字小文字変換
string ret1 = "ABCDE".ToLower(); // abcde
string ret2 = "abcde".ToUpper(); // ABCDE
// 文字列に変換
string ret3 = new SampleClass().ToString(); // クラス(参照型)
string ret4 = new SampleStruct().ToString(); // 構造体(値型)
// 数値に変換
int ret5 = int.Parse("123"); // 123
// 数値を変換
string ret6 = 123.ToString(); // "123"
string ret7 = "12".PadLeft(4); // " 12"
string ret8 = "12".PadLeft(4, 'A'); //"AA12"
// 文字列をバイト配列に変換
System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance);
string s1 = "いろはにほへと";
byte[] array = System.Text.Encoding.GetEncoding("shift_JIS").GetBytes(s1);
// バイト配列を文字列に変換
string ret9 = System.Text.Encoding.GetEncoding("shift_JIS").GetString(array);
.NET Core以降でSJISを使うにはEncoding.RegisterProviderの処理が必要になりました。
文字列の長さとバイト長
string s1 = "abcd";
string s2 = "いろはにほへと";
string s3 = "𠮟"; // サロゲ
System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance);
int ret1 = s1.Length; // 4
int ret2 = s2.Length; // 7
int ret3 = s3.Length; // 2
int ret4 = System.Text.Encoding.GetEncoding("shift_JIS").GetByteCount(s1); // 4
int ret5 = System.Text.Encoding.GetEncoding("shift_JIS").GetByteCount(s2); // 7
int ret6 = System.Text.Encoding.GetEncoding("shift_JIS").GetByteCount(s3); // 2
改行コード
string ret1 = Environment.NewLine;
逐語的識別子
ダブルクォーテーションに囲まれた文字列内で\(バックスラッシュ)はエスケープシーケンスを表しますが、先頭に@を付与するとそのまま文字列として解釈されます。また、予約語に@を付与すると変数名としても使えます。
//string s1 = "c:\code\Sample";
string s2 = @"c:\code\Sample";
string @string = "test";
その他
インターンプーリング
C#では、一度使われた文字列は特殊なディクショナリにプールされ、同じ文字列は生成されず再利用されます。String.Intern(String) メソッド (System)
指定した String へのシステム参照を取得します。
正規表現
.NETの正規表現は他の代表的な言語とほぼ一緒です。.NET の正規表現 - .NET
正規表現を使用して、特定の文字パターンの検索、テキストの検証、テキスト部分文字列の処理、抽出した文字列の .NET のコレクションへの追加を行います。
StringBuilderクラス
文字列操作に特化したクラスもあります。 連結・削除・置換・削除などを高速軽量に行えます。StringBuilder クラス (System.Text)
可変型の文字列を表します。 このクラスは継承できません。
Linqと文字列
文字列自体のフィルタリングや並べ替えも出来ますし、文字列を配列(コレクション)にすればその操作も勿論可能です。C# の統合言語クエリ (LINQ)
C# の統合言語クエリ (LINQ) について説明します。