文字列の基本
C#における文字列は、string
型で表されます。文字列はテキストデータを扱うための基本的なデータ型です。
文字列を使用するにはstring型の変数(この場合hoge1
)を宣言し、文字列"Hello"
を代入しています。文字列は"
ダブルクォーテーションで囲みます。また、string型の宣言をvar
に置き換える事もできます。
string hoge1 = "Hello";
var hoge2 = "World";
(補足)C#におけるvar
キーワードは、変数の型を明示的に指定せずに変数を宣言するために使います。これは「型推論」と呼ばれる機能で、コンパイラが代入される値から自動的に変数の型を推論します。これは文字列以外でも使用可能です。
var message = "Hello World"; // string型
var number = 10; // int型
var isTrue = true; // bool型
文字列配列を使う
文字列配列とは、string型の要素からなる配列のことを指します。文字列配列は、関連する複数の文字列を一緒に管理したいときなどに使用します。
string[] greetings = new string[3]; // 3つの要素を持つstring型の配列を作成
greetings[0] = "Hello";
greetings[1] = "World";
greetings[2] = "!";
// 配列の要素を表示
foreach (string s in greetings)
{
Console.Write(s + " "); // 出力:Hello World !
}
初期化と同時に文字列配列を作成することも可能です
string[] greetings = { "Hello", "World", "!" };
配列は0から始まるインデックスを使ってアクセスします。例えば、greetings[0]
が最初の"Hello"
を指し、greetings[2]
が3番目の!
要素を指します。
配列のサイズは固定です。もし配列のサイズを後から変更する必要がある場合、List<string>
のような別のデータ構造を使用することを検討してください。
配列の範囲外のインデックスにアクセスしようとすると、ランタイムエラー(IndexOutOfRangeException
)が発生します。例えば、3つの要素を持つ配列でgreetings[3]
にアクセスしようとすると4番目のデータは無いのでエラーが発生します。
逐語的文字列リテラル(verbatim string literal)を使う
これは文字列の前に@
記号を付けることで使用することができ、逐語的文字列リテラル内ではエスケープシーケンスが無効になります。これは、特にファイルパスのようなバックスラッシュ(\
)を多用する場面で便利です。
string path = @"C:\Users\MyName\Documents";
この例では、@
記号のおかげで、バックスラッシュを2回重ねてエスケープする必要がなくなります。もし逐語的文字列リテラルを使わなければ、次のように書かなければなりません。
string path = "C:\\Users\\MyName\\Documents";
注意点として、逐語的文字列リテラルの中でダブルクォーテーション("
)を表示したい場合は、2つ連続させて(""
)エスケープします。また、逐語的文字列リテラルはエスケープシーケンスを無効にしますので、特別な文字(例えば、改行\n
やタブ\t
など)を表現するためのエスケープシーケンスを使うことはできません。
string quote = @"He said, ""Hello, Alice!""";
文字列を連結(つなげる) [string.Concat()]
+
演算子を使って二つ以上の文字列を連結することができます。
string hello = "Hello, ";
string world = "World!";
string message = hello + world;
// messageは「 Hello, World!」 となります
string.Concat()を使用する
string str1 = "Hello, ";
string str2 = "World!";
string result = string.Concat(str1, str2); // "Hello, World!"
string.Concat()
を使用するメリットは以下の通りです。
- 効率性:
string.Concat()
は内部的に非常に効率的に実装されており、大量の文字列を連結する場合には+
演算子よりもパフォーマンスが良い場合があります。C#の文字列はイミュータブル(変更不能)で、+
演算子を使って文字列を連結すると、毎回新しい文字列オブジェクトが生成されます。しかし、string.Concat()
は一度にすべての文字列を連結するため、このようなオーバーヘッドを減らすことができます。 - 可読性:
string.Concat()
を使うと、文字列の連結が明示的に示されるため、コードの意図がより明確になります。 - 柔軟性:
string.Concat()
はパラメータとして文字列の配列やリストを取ることもできます。これにより、動的な数の文字列を効率的に連結することが可能です。
ただし、現代のコンパイラは+
演算子を使った文字列の連結も最適化してくれます。そのため、短い文字列を少数連結するだけであれば、string.Concat()
を使わなくてもパフォーマンスに大きな影響はありません。しかし、大量の文字列を連結する場合や、パフォーマンスが重要な場合には、string.Concat()
を使うことを検討してみてください。
文字列を比較する [string.Equals()]
==
演算子を使って二つの文字列が等しいかどうかを比較することができます。また、string.Equals()
メソッドも同じ目的で使うことができます。比較結果により同じ文字列の場合はtrue
、同じではない場合はfalse
となります。
string string1 = "Hello";
string string2 = "Hello";
bool areEqual = string1 == string2; // true
bool areAlsoEqual = string1.Equals(string2); // true
文字列の長さを取得する [string.Length()]
文字列の長さ(含まれる文字の数)を取得するには、Length
プロパティを使用します。
string greeting = "Hello, World!";
int length = greeting.Length; // 13文字
文字列を分割する [string.Split()]
特定の区切り文字に基づいて文字列を分割するにはstring.Split()を使用します。
string message = "Hello,World!";
string[] words = message.Split(','); // シングルコートで区切り文字を指定します
// words配列には 0:"Hello" 1:"World!" が入ります
シングルクォーテーションで囲み','
カンマを区切り文字としてSplit
メソッドを呼び出しています。この結果、”Hello”と”World!”の2つの部分文字列を含む配列が生成されます。
キーボードのシングルクォーテーション'
の入力はShiftキー
と数字7
ボタンです、@
ボタンにも似た記号`
があるので注意しましょう。
文字列を大文字もしくは小文字に変換する [string.ToUpper()][string.ToLower()]
文字列中のすべての文字を大文字に変換するにはToUpper()
を使用します。また、文字列中のすべての文字を小文字に変換するにはToLower()
を使用します。
string lowerCase = "hello, world!";
string upperCase = lowerCase.ToUpper(); // "HELLO, WORLD!"に変換される
string upperCase = "HELLO, WORLD!";
string lowerCase = upperCase.ToLower(); // "hello, world!"に変換される
文字列から指定数の文字を取得する [string.Substring()]
Substring(int startIndex)
を使用する場合
引数で開始位置のみ指定すると文字列の最後までを取り出します。文字列の最初の位置は0と数えます。
string str = "Hello, World!";
string sub = str.Substring(7); // 7文字目の"World!"から切り出されます
Substring(int startIndex, int length)
を使用する場合
開始位置と終了位置を指定した場合は指定した長さだけ文字列を取り出します。
string str = "Hello, World!";
string sub = str.Substring(7, 2); // 7文字目の"W"から2文字なので"Wo"が切り出されます
文字列を置き換える[string.Replace()]
文字列内の特定の部分を別の文字列に置き換えるために Replace()
メソッドを使用します。このメソッドは元の文字列の中にあるすべての指定した文字列(または文字)を新しい文字列に置き換えます。
注意点として、Replace()
メソッドは新しい文字列を作成し、元の文字列は変更されません。これは文字列が不変(immutable)であるためです。また、Replace()
メソッドは大文字と小文字を区別します。つまり、"World"
と"world"
は異なる文字列として扱われます。
string original = "Hello, World!";
string replaced1 = original.Replace("World", "C#");
// 結果: "Hello, C#!"
string replaced2 = original.Replace(",", "").Replace("!", ".");
// 結果: "Hello World."
string original = "Hello, World!";
string replaced = original.Replace("World", "C#");
// 結果: "Hello, C#!"
文字列を指定フォーマットで生成する [string.Format()]
string.Format()
メソッドは、フォーマット指定文字列とそれに対応するオブジェクトの配列を受け取り、指定されたフォーマットに従って文字列を返すメソッドです。
string.Format()
メソッドの最初の引数でフォーマット指定文字列を指定し、2つ目以降の引数でフォーマット内で使用する2つの値を渡しています。フォーマット指定文字列の中の{0}
と{1}
はプレースホルダーと呼ばれ、それぞれのプレースホルダーは引数のインデックスに対応します。つまり、{0}
は第2引数(MyName
)に、{1}
は第3引数(age
)に対応します。
string format = "My name is {0} and I am {1} years old.";
string myName = "Yamada";
int age = 30;
string result = string.Format(format, myName, age);
// resultは "My name is Yamada and I am 30 years old." になります
また、フォーマット指定文字列中に{
や}
を直接書くことはできません。これらの文字を含めるためには、二重にする({{
や}}
)ことでエスケープします。
string format = "My name is {{{0}}} and I am {1} years old.";
// この場合、"My name is {Yamada} and I am 30 years old." となります
文字列補間($記号を使用)
C# 6.0以降、文字列補間という機能が追加されました。これは、文字列の中に直接変数を埋め込むことができる機能で、文字列の前に$
記号を付けることで使用できます。
string myName = "Yamada";
int age = 30;
string result = $"My name is {myName} and I am {age} years old.";
// resultの値は "My name is Yamada and I am 30 years old."
文字列を指定文字で連結する(カンマ区切りなど)[string.Join()]
配列やリストなどの複数の要素を持つデータをカンマ区切りの文字列に変換する場合は、string.Join()
メソッドを使います。このメソッドは、配列やリストの要素を指定した区切り文字(この場合はカンマ)で連結した文字列を作成します。
string[] words = { "apple", "banana", "cherry" };
string joined = string.Join(",", words);
// 結果: "apple,banana,cherry"
List<string> wordList = new List<string>() { "apple", "banana", "cherry" };
string joinedData = string.Join(",", wordList);
// 結果: "apple,banana,cherry"
このメソッドは配列やリストの要素が文字列でなくても使うことができます。数値や他のオブジェクトの配列やリストを連結する場合も、string.Join()
メソッドは各要素を文字列に変換して連結します。
文字列(string型)を数値(int型)に変換する [int.Parse()][int.TryParse()]
int.Parse()メソッド
このメソッドは、数値を表す文字列を整数に変換します。しかし、このメソッドには注意点があります。もし変換しようとする文字列が数値を表していない場合(例えば”abc”や”123.45″など)、FormatException
という例外が発生します。このような例外はプログラムの実行を停止させる可能性があるため、このメソッドを使用する際は注意が必要です。その場合、後述のint.TryParse()メソッドを使用します。
string numberStr = "123";
int number = int.Parse(numberStr); // number は 123
int.TryParse()メソッド
このメソッドは、数値を表す文字列を整数に変換しようとします。しかし、int.Parse()
とは違い、変換できない場合でも例外を発生させません。また、指定文字列が変換可能であるかをメソッドの戻り値(返り値)で取得できます。変換可能な場合はtrue
、変換出来ない場合はfalse
が返ります。
string numberStr = "123";
int number;
bool success = int.TryParse(numberStr, out number);
// 変換できるのでsuccess は true, number は 123 となります
string numberStr = "abc";
bool success = int.TryParse(numberStr, out int number);
// 変換でないのでsuccess は false, number は int初期値の 0 となります
入力が必ず数値であることが保証されている場合はint.Parse()
を、そうでない場合はint.TryParse()
を使用すると良いでしょう。
文字列(string型)を数値(float型)に変換する [float.Parse()][float.TryParse()]
int同様にfloatにもfloat.Parse()
メソッドとfloat.TryParse()
メソッドがあります。
float.Parse()メソッド
このメソッドは、数値を表す文字列を浮動小数点数に変換します。
string floatStr = "123.45";
float number = float.Parse(floatStr); // numberは123.45f
ただし、このメソッドもint.Parse()
と同じく、もし変換しようとする文字列が数値を表していない場合(例えば”abc”や”123.45.67″など)、FormatException
という例外が発生します。このような例外はプログラムの実行を停止させる可能性があるため、このメソッドを使用する際は注意が必要です。
また、浮動小数点数は精度の問題から、変換した結果が元の数値と微妙に異なることがあります。これは浮動小数点数の性質上避けられない問題です。
float.TryParse()メソッド
このメソッドは、数値を表す文字列を浮動小数点数に変換しようとします。しかし、float.Parse()
とは違い、変換できない場合でも例外を発生させません。また、指定文字列が変換可能であるかをメソッドの戻り値(返り値)で取得できます。変換可能な場合はtrue
、変換出来ない場合はfalse
が返ります。
string floatStr = "123.45";
float number;
bool success = float.TryParse(floatStr, out number);
// 変換できるのでsuccessはtrue, numberは123.45fとなります
string invalidFloatStr = "abc";
bool invalidSuccess = float.TryParse(invalidFloatStr, out float invalidNumber);
// 変換でないのでinvalidSuccessはfalse, invalidNumberはfloat初期値の 0.0f となります
こちらも入力が必ず数値であることが保証されている場合はfloat.Parse()
を、そうでない場合はfloat.TryParse()
を使用すると良いでしょう。
文字列でStringBuilderを使用する
StringBuilder
クラスは、特に大量の文字列の連結(concatenation)を行う際に非常に便利です。string
型は不変(immutable)であるため、2つの文字列を連結すると新しい文字列が作成され、メモリの効率が低下します。しかし、StringBuilder
は可変(mutable)で、連結操作を行っても新しい文字列を作成せず、既存の文字列に変更を加えます。
StringBuilder sb = new StringBuilder();
sb.Append("Hello, ");
sb.Append("World!");
Console.WriteLine(sb.ToString()); // 出力結果:Hello, World!
StringBuilderを利用するメリット
- 大量の文字列連結を行う場合、
StringBuilder
はstring
の+
演算子やConcat
メソッドよりも高速でメモリ効率が良いです。 StringBuilder
は文字列の末尾だけでなく、任意の位置に文字列を挿入したり削除したりするメソッド(Insert
やRemove
)を提供しています。
注意点
- 小さな数の文字列の連結のみを行う場合、
StringBuilder
はそれほどメリットありません。StringBuilder
のインスタンス化にはコストがかかり、その利点は大量の連結を行うときにのみ顕著になります。 StringBuilder
のToString
メソッドは新しいstring
インスタンスを作成します。そのため、頻繁にToString
を呼び出すのは避け、必要なときにだけ使用するべきです。
コメント