演習 - 文字列の IndexOf() および LastIndexOf() ヘルパー メソッドを使用する
- 25 分
この演習では、IndexOf() メソッドと LastIndexOf() メソッドを使用して、特定の文字列内の文字と部分文字列の位置を検索します。
IndexOf() および LastIndexOf
.IndexOf() メソッドは、指定した文字列内で指定した文字または部分文字列が最初に出現するインデックスを返します。 メソッド .LastIndexOf() は、特定の文字列内で最後に出現する文字または文字列のインデックス位置を返します。 文字または文字列がIndexof()場合、LastIndexOf()メソッドと メソッドの両方が -1 を返します。
Visual Studio Code エディターですべてのコード行を選択して削除します。
Visual Studio Code エディターで次のようにコードを更新します。
string message = "hello there!"; int first_h = message.IndexOf('h'); int last_h = message.LastIndexOf('h'); Console.WriteLine($"For the message: '{message}', the first 'h' is at position {first_h} and the last 'h' is at position {last_h}.");コード ファイルを保存してから、Visual Studio Code を使ってコードを実行します。 次の出力が表示されます。
For the message: 'hello there!', the first 'h' is at position 0 and the last 'h' is at position 7.出力は、文字列 "hello there!" において、最初の "h" を位置 0 で、最後の "h" を位置 7 で識別します。
部分文字列の最後の出現箇所を取得する
複数のかっこセットを追加して message 変数の複雑さを増し、 最後 のかっこのセット内のコンテンツを取得するコードを記述します。
Visual Studio Code エディターですべてのコード行を選択して削除します。
Visual Studio Code エディターで次のようにコードを更新します。
string message = "(What if) I am (only interested) in the last (set of parentheses)?"; int openingPosition = message.LastIndexOf('('); openingPosition += 1; int closingPosition = message.LastIndexOf(')'); int length = closingPosition - openingPosition; Console.WriteLine(message.Substring(openingPosition, length));コード ファイルを保存してから、Visual Studio Code を使ってコードを実行します。 次の出力が表示されます。
set of parenthesesこの例で重要なのは
LastIndexOf()の使用です。これを使って、最後の始めかっこと終わりかっこの位置を取得します。注
前のサンプル コードは、
message文字列に正しく書式設定されたかっこのペアが含まれている場合のみ、エラーなしで実行されます。 しかし、このコードは脆弱であり、かっこのペアが存在しない場合、または最後のかっこが始めと終わりのペアを形成していない場合、エラーが生成されます。
かっこ内の部分文字列のすべての出現箇所を取得する
ここでは、かっこの対が 3 つになるように message を更新し、かっこ内のテキストをすべて抽出するコードを記述します。 前の作業は部分的に再利用できますが、すべてのかっこの対が検出、抽出、表示されるまで文字列を反復処理するために、while ステートメントを追加する必要があります。
Visual Studio Code エディターで次のようにコードを更新します。
string message = "(What if) there are (more than) one (set of parentheses)?"; while (true) { int openingPosition = message.IndexOf('('); if (openingPosition == -1) break; openingPosition += 1; int closingPosition = message.IndexOf(')'); int length = closingPosition - openingPosition; Console.WriteLine(message.Substring(openingPosition, length)); // Note the overload of the Substring to return only the remaining // unprocessed message: message = message.Substring(closingPosition + 1); }コード ファイルを保存してから、Visual Studio Code を使ってコードを実行します。 次の出力が表示されます。
What if more than set of parentheses少し時間をとって、
whileループ内の最後のコード行を観察してください。抜き出すと次のコードになります。message = message.Substring(closingPosition + 1);長さ入力パラメーターを指定せずに
Substring()を使用すると、指定した開始位置の後にあるすべての文字が返されます。 文字列message = "(What if) there are (more than) one (set of parentheses)?"の処理中に、(What if)の値から最初のかっこの対messageを削除すると便利です。 残りの部分は、whileループの次の反復で処理されます。少し時間をとって、
whileループの最後の反復中、最後の?文字だけが残っているときに何が起こるかを考えてください。次のコードが、文字列の末尾の処理に対応しています。
int openingPosition = message.IndexOf('('); if (openingPosition == -1) break;IndexOf()メソッドでは、文字列に入力パラメーターが見つからない場合は、-1が返されます。 単に値-1をチェックして、ループからbreakして抜けます。
IndexOfAny() を使用してさまざまな種類の記号セットを操作する
今度は、.IndexOfAny() を使用して、かっこの対だけでなく、いくつかの異なる文字記号を検索します。
.IndexOfAny() は、指定した文字配列内の任意の文字が最初に出現するインデックスを報告します。 このメソッドは、文字配列内のすべての文字が見つからない場合に -1 を返します。
次の例では、文字 'a'、'e'、または 'i' の最初に見つかった文字のインデックスが返されます。
Visual Studio Code エディターで次のようにコードを更新します。
string message = "Hello, world!"; char[] charsToFind = { 'a', 'e', 'i' }; int index = message.IndexOfAny(charsToFind); Console.WriteLine($"Found '{message[index]}' in '{message}' at index: {index}.");コード ファイルを保存してから、Visual Studio Code を使ってコードを実行します。
次の出力が表示されます。
Found 'e' in 'Hello, world!' at index: 1.message文字列を更新して、角かっこ[]や中かっこ{}などの異なる種類の記号を追加します。 複数の記号を同時に検索するには、.IndexOfAny()を使用します。.IndexOfAny()を使って検索すると、openSymbols文字列内で見つかった配列messageの最初の記号のインデックスが返されます。Visual Studio Code エディターで次のようにコードを更新します。
string message = "Help (find) the {opening symbols}"; Console.WriteLine($"Searching THIS Message: {message}"); char[] openSymbols = { '[', '{', '(' }; int startPosition = 5; int openingPosition = message.IndexOfAny(openSymbols); Console.WriteLine($"Found WITHOUT using startPosition: {message.Substring(openingPosition)}"); openingPosition = message.IndexOfAny(openSymbols, startPosition); Console.WriteLine($"Found WITH using startPosition {startPosition}: {message.Substring(openingPosition)}");コード ファイルを保存してから、Visual Studio Code を使ってコードを実行します。
次の出力が表示されます。
Searching THIS message: Help (find) the {opening symbols} Found WITHOUT using startPosition: (find) the {opening symbols} Found WITH using startPosition 5: (find) the {opening symbols}少し時間を取って、前に入力したコードを確認します。
.IndexOfAny()を、開始位置のオーバーロードを "指定せず" 使った後、"指定して" 使いました。始め記号が見つかったので、対応する終わり記号を見つける必要があります。
Visual Studio Code エディターで次のようにコードを更新します。
string message = "(What if) I have [different symbols] but every {open symbol} needs a [matching closing symbol]?"; // The IndexOfAny() helper method requires a char array of characters. // You want to look for: char[] openSymbols = { '[', '{', '(' }; // You'll use a slightly different technique for iterating through // the characters in the string. This time, use the closing // position of the previous iteration as the starting index for the //next open symbol. So, you need to initialize the closingPosition // variable to zero: int closingPosition = 0; while (true) { int openingPosition = message.IndexOfAny(openSymbols, closingPosition); if (openingPosition == -1) break; string currentSymbol = message.Substring(openingPosition, 1); // Now find the matching closing symbol char matchingSymbol = ' '; switch (currentSymbol) { case "[": matchingSymbol = ']'; break; case "{": matchingSymbol = '}'; break; case "(": matchingSymbol = ')'; break; } // To find the closingPosition, use an overload of the IndexOf method to specify // that the search for the matchingSymbol should start at the openingPosition in the string. openingPosition += 1; closingPosition = message.IndexOf(matchingSymbol, openingPosition); // Finally, use the techniques you've already learned to display the sub-string: int length = closingPosition - openingPosition; Console.WriteLine(message.Substring(openingPosition, length)); }数分の時間をとって、上記のコードを調べて、コードの理解に役立つコメントを読んでください。
引き続きコードを調べ、
IndexOf()を使用してclosingPositionを定義する次のコード行を見つけます。closingPosition = message.IndexOf(matchingSymbol, openingPosition);変数
closingPositionはSubstring()メソッドに渡される長さを見つけ、次のopeningPosition値を見つけるために使用されます。int openingPosition = message.IndexOfAny(openSymbols, closingPosition);このような理由により、
closingPosition変数をwhileループ スコープの外側で定義し、最初の反復で0に初期化しています。コード ファイルを保存してから、Visual Studio Code を使ってコードを実行します。 次の出力が表示されます。
What if different symbols open symbol matching closing symbol
まとめ
以下の 2 点を気に留めることが重要です。
-
LastIndexOf()を使うと、別の文字列内での文字または文字列の最後の位置を取得できます。 -
IndexOfAny()を使うと、別の文字列内に出現するcharの配列の最初の位置を取得できます。