[C++] string内で文字列を検索する方法

C++では、文字列内で特定の文字列を検索するために、std::stringクラスのメンバー関数findを使用します。

この関数は、検索対象の文字列が最初に現れる位置のインデックスを返します。

もし文字列が見つからない場合、std::string::nposが返されます。

また、find関数はオプションで検索を開始する位置を指定することも可能です。

この機能を活用することで、文字列操作を効率的に行うことができます。

この記事でわかること
  • std::string::findやstd::string::rfindを用いた基本的な文字列検索の方法
  • std::string::find_first_not_ofやstd::string::find_last_not_ofを使った特定文字以外の検索
  • std::searchアルゴリズムを用いた複数の文字列検索の実装方法
  • 正規表現を用いた柔軟な文字列検索の手法
  • 文字列の置換と検索を組み合わせた応用例

目次から探す

基本的な文字列検索方法

C++における文字列検索は、std::stringクラスのメンバ関数を利用することで簡単に行うことができます。

ここでは、基本的な文字列検索方法について解説します。

std::string::findの使い方

std::string::findは、文字列内で特定の部分文字列を検索するための基本的な関数です。

基本的な使用例

以下の例では、文字列内で特定の単語を検索しています。

#include <iostream>
#include <string>
int main() {
    std::string text = "C++プログラミングは楽しいです。";
    std::string word = "プログラミング";
    
    // 部分文字列を検索
    size_t position = text.find(word);
    
    if (position != std::string::npos) {
        std::cout << "見つかりました: 位置 " << position << std::endl;
    } else {
        std::cout << "見つかりませんでした。" << std::endl;
    }
    
    return 0;
}
見つかりました: 位置 3

このコードは、文字列text内でwordを検索し、見つかった場合はその位置を出力します。

部分文字列の検索

std::string::findを使用して、部分文字列を検索することができます。

以下の例では、部分文字列の検索を行っています。

#include <iostream>
#include <string>
int main() {
    std::string text = "C++プログラミングは楽しいです。";
    
    // 部分文字列を検索
    size_t position = text.find("楽しい");
    
    if (position != std::string::npos) {
        std::cout << "部分文字列が見つかりました: 位置 " << position << std::endl;
    } else {
        std::cout << "部分文字列が見つかりませんでした。" << std::endl;
    }
    
    return 0;
}
部分文字列が見つかりました: 位置 9

このコードは、文字列text内で”楽しい”という部分文字列を検索し、その位置を出力します。

位置指定による検索

std::string::findは、検索を開始する位置を指定することができます。

#include <iostream>
#include <string>
int main() {
    std::string text = "C++プログラミングは楽しいです。プログラミングは素晴らしい。";
    
    // 位置指定による検索
    size_t position = text.find("プログラミング", 10);
    
    if (position != std::string::npos) {
        std::cout << "指定位置から見つかりました: 位置 " << position << std::endl;
    } else {
        std::cout << "指定位置から見つかりませんでした。" << std::endl;
    }
    
    return 0;
}
指定位置から見つかりました: 位置 18

このコードは、文字列text内で”プログラミング”を10文字目以降から検索し、その位置を出力します。

std::string::rfindの使い方

std::string::rfindは、文字列の末尾から逆方向に検索を行う関数です。

逆方向からの検索

以下の例では、文字列の末尾から特定の単語を検索しています。

#include <iostream>
#include <string>
int main() {
    std::string text = "C++プログラミングは楽しいです。プログラミングは素晴らしい。";
    
    // 逆方向からの検索
    size_t position = text.rfind("プログラミング");
    
    if (position != std::string::npos) {
        std::cout << "逆方向から見つかりました: 位置 " << position << std::endl;
    } else {
        std::cout << "逆方向から見つかりませんでした。" << std::endl;
    }
    
    return 0;
}
逆方向から見つかりました: 位置 18

このコードは、文字列text内で”プログラミング”を末尾から検索し、その位置を出力します。

使用例と注意点

std::string::rfindは、文字列の末尾から検索を行うため、最初に見つかった位置ではなく、最後に見つかった位置を返します。

検索が成功した場合、見つかった位置を返し、失敗した場合はstd::string::nposを返します。

std::string::find_first_ofとfind_last_of

std::string::find_first_ofstd::string::find_last_ofは、指定した文字集合の中から最初または最後に見つかった文字の位置を返します。

複数文字の検索

以下の例では、複数の文字の中から最初に見つかった文字を検索しています。

#include <iostream>
#include <string>
int main() {
    std::string text = "C++プログラミングは楽しいです。";
    std::string chars = "プラ";
    
    // 複数文字の検索
    size_t position = text.find_first_of(chars);
    
    if (position != std::string::npos) {
        std::cout << "最初に見つかった文字: 位置 " << position << std::endl;
    } else {
        std::cout << "文字が見つかりませんでした。" << std::endl;
    }
    
    return 0;
}
最初に見つかった文字: 位置 3

このコードは、文字列text内で”プラ”のいずれかの文字を検索し、最初に見つかった位置を出力します。

使用例と違い

std::string::find_first_ofは、指定した文字集合の中から最初に見つかった文字の位置を返します。

一方、std::string::find_last_ofは、最後に見つかった文字の位置を返します。

以下にその違いを示します。

#include <iostream>
#include <string>
int main() {
    std::string text = "C++プログラミングは楽しいです。";
    std::string chars = "プラ";
    
    // 最初に見つかった文字
    size_t firstPosition = text.find_first_of(chars);
    // 最後に見つかった文字
    size_t lastPosition = text.find_last_of(chars);
    
    std::cout << "最初に見つかった文字: 位置 " << firstPosition << std::endl;
    std::cout << "最後に見つかった文字: 位置 " << lastPosition << std::endl;
    
    return 0;
}
最初に見つかった文字: 位置 3
最後に見つかった文字: 位置 9

このコードは、文字列text内で”プラ”のいずれかの文字を検索し、最初と最後に見つかった位置をそれぞれ出力します。

高度な文字列検索

C++では、基本的な文字列検索に加えて、より高度な検索方法も提供されています。

ここでは、特定の条件に基づく検索や正規表現を用いた検索について解説します。

std::string::find_first_not_ofとfind_last_not_of

std::string::find_first_not_ofstd::string::find_last_not_ofは、指定した文字集合に含まれない最初または最後の文字を検索するための関数です。

特定文字以外の検索

以下の例では、特定の文字以外の最初の文字を検索しています。

#include <iostream>
#include <string>
int main() {
    std::string text = "aaaabbbcccdde";
    std::string chars = "abc";
    
    // 特定文字以外の最初の文字を検索
    size_t position = text.find_first_not_of(chars);
    
    if (position != std::string::npos) {
        std::cout << "特定文字以外の最初の文字: 位置 " << position << std::endl;
    } else {
        std::cout << "特定文字以外の文字が見つかりませんでした。" << std::endl;
    }
    
    return 0;
}
特定文字以外の最初の文字: 位置 9

このコードは、文字列text内で”abc”以外の最初の文字を検索し、その位置を出力します。

使用例と応用

std::string::find_first_not_ofstd::string::find_last_not_ofは、特定の文字集合に含まれない文字を見つけるのに便利です。

例えば、文字列の先頭や末尾から特定の文字をトリムする際に使用できます。

#include <iostream>
#include <string>
int main() {
    std::string text = "   C++プログラミング   ";
    std::string whitespace = " ";
    
    // 先頭の空白をトリム
    size_t start = text.find_first_not_of(whitespace);
    // 末尾の空白をトリム
    size_t end = text.find_last_not_of(whitespace);
    
    std::string trimmed = text.substr(start, end - start + 1);
    
    std::cout << "トリムされた文字列: '" << trimmed << "'" << std::endl;
    
    return 0;
}
トリムされた文字列: 'C++プログラミング'

このコードは、文字列textの先頭と末尾の空白をトリムし、トリムされた文字列を出力します。

std::searchアルゴリズム

std::searchは、指定された範囲内で部分シーケンスを検索するための汎用アルゴリズムです。

概要と使用方法

std::searchは、イテレータを使用して範囲を指定し、その範囲内で部分シーケンスを検索します。

以下の例では、文字列内で部分シーケンスを検索しています。

#include <iostream>
#include <string>
#include <algorithm>
int main() {
    std::string text = "C++プログラミングは楽しいです。";
    std::string sequence = "プログラミング";
    
    // 部分シーケンスを検索
    auto it = std::search(text.begin(), text.end(), sequence.begin(), sequence.end());
    
    if (it != text.end()) {
        std::cout << "部分シーケンスが見つかりました: 位置 " << std::distance(text.begin(), it) << std::endl;
    } else {
        std::cout << "部分シーケンスが見つかりませんでした。" << std::endl;
    }
    
    return 0;
}
部分シーケンスが見つかりました: 位置 3

このコードは、文字列text内でsequenceを検索し、その開始位置を出力します。

使用例とパフォーマンス

std::searchは、線形探索アルゴリズムを使用しているため、検索対象のサイズが大きくなるとパフォーマンスに影響を与える可能性があります。

効率的な検索が必要な場合は、他のアルゴリズムやデータ構造の使用を検討することが重要です。

正規表現による検索

正規表現を使用すると、より柔軟で強力な文字列検索が可能になります。

C++では、std::regexライブラリを使用して正規表現を扱うことができます。

std::regex_searchの使い方

std::regex_searchは、文字列内で正規表現に一致する部分を検索するための関数です。

#include <iostream>
#include <string>
#include <regex>
int main() {
    std::string text = "C++プログラミングは楽しいです。";
    std::regex pattern("プログラミング");
    
    // 正規表現による検索
    if (std::regex_search(text, pattern)) {
        std::cout << "正規表現に一致する部分が見つかりました。" << std::endl;
    } else {
        std::cout << "正規表現に一致する部分が見つかりませんでした。" << std::endl;
    }
    
    return 0;
}
正規表現に一致する部分が見つかりました。

このコードは、文字列text内で正規表現patternに一致する部分を検索し、結果を出力します。

正規表現の基本

正規表現は、文字列のパターンを記述するための特別な文字列です。

以下は、正規表現の基本的な構成要素です。

スクロールできます
構成要素説明
.任意の1文字
*直前の文字の0回以上の繰り返し
+直前の文字の1回以上の繰り返し
?直前の文字の0回または1回の出現
[]文字クラス(例: [abc]はa, b, cのいずれか)
^行の先頭
$行の末尾

使用例と注意点

正規表現を使用する際は、パターンの記述に注意が必要です。

特に、特殊文字をエスケープする必要がある場合があります。

また、正規表現のパフォーマンスは、パターンの複雑さに依存するため、効率的なパターンを設計することが重要です。

#include <iostream>
#include <string>
#include <regex>
int main() {
    std::string text = "メールアドレスはexample@example.comです。";
    std::regex emailPattern(R"((\w+)(\.\w+)*@(\w+)(\.\w+)+)");
    
    // 正規表現によるメールアドレスの検索
    if (std::regex_search(text, emailPattern)) {
        std::cout << "メールアドレスが見つかりました。" << std::endl;
    } else {
        std::cout << "メールアドレスが見つかりませんでした。" << std::endl;
    }
    
    return 0;
}
メールアドレスが見つかりました。

このコードは、文字列text内でメールアドレスの形式に一致する部分を検索し、結果を出力します。

正規表現のパターンは、メールアドレスの一般的な形式を表しています。

応用例

文字列検索の基本を理解したら、次は応用的な検索方法を学びましょう。

ここでは、大文字小文字を区別しない検索、複数の文字列を一度に検索する方法、そして文字列の置換と検索について解説します。

大文字小文字を区別しない検索

C++の標準的な文字列検索は大文字小文字を区別しますが、場合によっては区別しない検索が必要です。

変換方法と検索手法

大文字小文字を区別しない検索を行うには、文字列をすべて小文字または大文字に変換してから検索を行います。

以下の例では、std::transformを使用して文字列を小文字に変換しています。

#include <iostream>
#include <string>
#include <algorithm>
#include <cctype>
int main() {
    std::string text = "C++ Programming is Fun!";
    std::string word = "programming";
    
    // 文字列を小文字に変換
    std::string lowerText = text;
    std::transform(lowerText.begin(), lowerText.end(), lowerText.begin(), ::tolower);
    
    std::string lowerWord = word;
    std::transform(lowerWord.begin(), lowerWord.end(), lowerWord.begin(), ::tolower);
    
    // 大文字小文字を区別しない検索
    size_t position = lowerText.find(lowerWord);
    
    if (position != std::string::npos) {
        std::cout << "見つかりました: 位置 " << position << std::endl;
    } else {
        std::cout << "見つかりませんでした。" << std::endl;
    }
    
    return 0;
}
見つかりました: 位置 4

このコードは、文字列text内でwordを大文字小文字を区別せずに検索し、その位置を出力します。

大文字小文字を区別しない検索は、ユーザー入力を処理する際に特に有用です。

例えば、ユーザーが入力した検索キーワードをそのまま使用して検索を行う場合に役立ちます。

複数の文字列を一度に検索

複数の文字列を一度に検索する場合、std::searchとカスタムアルゴリズムを組み合わせることができます。

std::searchとカスタムアルゴリズム

以下の例では、複数のキーワードを一度に検索するためのカスタムアルゴリズムを実装しています。

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
bool containsAny(const std::string& text, const std::vector<std::string>& keywords) {
    for (const auto& keyword : keywords) {
        if (text.find(keyword) != std::string::npos) {
            return true;
        }
    }
    return false;
}
int main() {
    std::string text = "C++プログラミングは楽しいです。";
    std::vector<std::string> keywords = {"プログラミング", "楽しい", "素晴らしい"};
    
    // 複数の文字列を一度に検索
    if (containsAny(text, keywords)) {
        std::cout << "いずれかのキーワードが見つかりました。" << std::endl;
    } else {
        std::cout << "キーワードが見つかりませんでした。" << std::endl;
    }
    
    return 0;
}
いずれかのキーワードが見つかりました。

このコードは、文字列text内でkeywordsのいずれかが見つかるかどうかをチェックし、結果を出力します。

複数のキーワードを一度に検索する方法は、フィルタリングや検索機能を実装する際に役立ちます。

例えば、ニュース記事の中から特定のトピックに関連するキーワードを検索する場合に使用できます。

文字列の置換と検索

文字列の検索と置換を組み合わせることで、特定のパターンを別の文字列に置き換えることができます。

std::string::replaceの使い方

std::string::replaceを使用すると、文字列内の特定の部分を別の文字列に置き換えることができます。

#include <iostream>
#include <string>
int main() {
    std::string text = "C++プログラミングは楽しいです。";
    std::string target = "楽しい";
    std::string replacement = "素晴らしい";
    
    // 文字列の置換
    size_t position = text.find(target);
    if (position != std::string::npos) {
        text.replace(position, target.length(), replacement);
    }
    
    std::cout << "置換後の文字列: " << text << std::endl;
    
    return 0;
}
置換後の文字列: C++プログラミングは素晴らしいです。

このコードは、文字列text内の”楽しい”を”素晴らしい”に置き換え、その結果を出力します。

検索と置換の組み合わせ

検索と置換を組み合わせることで、特定のパターンを効率的に置き換えることができます。

以下の例では、すべての出現箇所を置き換えています。

#include <iostream>
#include <string>
int main() {
    std::string text = "C++プログラミングは楽しいです。プログラミングは素晴らしい。";
    std::string target = "プログラミング";
    std::string replacement = "コーディング";
    
    // すべての出現箇所を置き換え
    size_t position = 0;
    while ((position = text.find(target, position)) != std::string::npos) {
        text.replace(position, target.length(), replacement);
        position += replacement.length();
    }
    
    std::cout << "置換後の文字列: " << text << std::endl;
    
    return 0;
}
置換後の文字列: C++コーディングは楽しいです。コーディングは素晴らしい。

このコードは、文字列text内のすべての”プログラミング”を”コーディング”に置き換え、その結果を出力します。

よくある質問

std::string::findはどのように動作しますか?

std::string::findは、文字列内で指定された部分文字列を検索するためのメンバ関数です。

この関数は、検索を開始する位置を指定することができ、デフォルトでは文字列の先頭から検索を開始します。

検索が成功した場合は、見つかった部分文字列の開始位置を返し、失敗した場合はstd::string::nposを返します。

例:size_t position = text.find("word");

文字列が見つからない場合、findは何を返しますか?

std::string::findが指定された部分文字列を見つけられなかった場合、std::string::nposを返します。

std::string::nposは、size_t型の最大値であり、検索が失敗したことを示す特別な値です。

この値を使用して、検索結果を確認することができます。

例:if (position == std::string::npos) { /* 見つからなかった場合の処理 */ }

正規表現を使う際の注意点は何ですか?

正規表現を使用する際には、以下の点に注意が必要です:

  • パフォーマンス: 複雑な正規表現は、特に大きな文字列に対してパフォーマンスに影響を与える可能性があります。

効率的なパターンを設計することが重要です。

  • エスケープシーケンス: 特殊文字(例:.*+など)を文字通りに検索する場合は、エスケープする必要があります。

例:std::regex pattern("\\.");

  • 互換性: 正規表現の構文は、言語やライブラリによって異なる場合があります。

C++のstd::regexは、ECMAScriptの正規表現構文をサポートしていますが、他の言語の正規表現とは異なる場合があります。

まとめ

この記事では、C++における文字列検索の基本から高度なテクニックまでを詳しく解説しました。

std::stringの基本的な検索機能から、正規表現を用いた柔軟な検索方法まで、さまざまな手法を学ぶことで、文字列操作の幅が広がります。

これらの知識を活用して、実際のプログラムで効率的な文字列処理を試してみてください。

  • URLをコピーしました!
目次から探す