[C++] std::string内で特定文字列を検索し個数をカウントする方法

C++で文字列操作を行う際、std::string内で特定の文字列を検索し、その出現回数をカウントする方法があります。

この操作は、std::string::findメソッドを使用して実現できます。

このメソッドは、指定した文字列が見つかった位置を返し、見つからない場合はstd::string::nposを返します。

ループを使用して文字列全体を検索し、見つかった位置を基に次の検索を開始することで、特定の文字列の出現回数をカウントできます。

この記事でわかること
  • std::stringを用いた特定文字列の検索方法
  • 文字列の出現回数をカウントするためのさまざまな手法
  • 大文字小文字を区別しない検索の実現方法
  • 複数の文字列を同時にカウントする方法
  • 文字列の出現位置を記録するテクニック

目次から探す

特定文字列の検索方法

std::stringを用いて文字列内で特定の文字列を検索するための便利なメソッドがいくつか提供されています。

ここでは、代表的なメソッドについて解説します。

findメソッドの使い方

findメソッドは、文字列内で特定の文字列を検索し、その最初の位置を返します。

見つからない場合はstd::string::nposを返します。

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

この例では、text内で"プログラミング"を検索し、その開始位置を出力しています。

rfindメソッドの使い方

rfindメソッドは、文字列内で特定の文字列を逆方向(末尾から先頭)に検索し、その最初の位置を返します。

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

この例では、text内で"プログラミング"を末尾から検索し、その開始位置を出力しています。

find_first_ofとfind_last_ofの違い

find_first_offind_last_ofは、指定した文字集合の中で最初または最後に見つかる文字の位置を返します。

#include <iostream>
#include <string>
int main() {
    std::string text = "C++プログラミング";
    std::string characters = "プラ";
    
    // 最初に見つかる文字を検索
    size_t first_position = text.find_first_of(characters);
    // 最後に見つかる文字を検索
    size_t last_position = text.find_last_of(characters);
    
    std::cout << "最初に見つかる文字の位置: " << first_position << std::endl;
    std::cout << "最後に見つかる文字の位置: " << last_position << std::endl;
    
    return 0;
}
最初に見つかる文字の位置: 3
最後に見つかる文字の位置: 5

この例では、text内で"プラ"のいずれかの文字が最初と最後に見つかる位置を出力しています。

find_first_not_ofとfind_last_not_ofの使い方

find_first_not_offind_last_not_ofは、指定した文字集合に含まれない最初または最後の文字の位置を返します。

#include <iostream>
#include <string>
int main() {
    std::string text = "C++プログラミング";
    std::string characters = "C+";
    
    // 最初に見つからない文字を検索
    size_t first_not_position = text.find_first_not_of(characters);
    // 最後に見つからない文字を検索
    size_t last_not_position = text.find_last_not_of(characters);
    
    std::cout << "最初に見つからない文字の位置: " << first_not_position << std::endl;
    std::cout << "最後に見つからない文字の位置: " << last_not_position << std::endl;
    
    return 0;
}
最初に見つからない文字の位置: 3
最後に見つからない文字の位置: 9

この例では、text内で"C+"に含まれない最初と最後の文字の位置を出力しています。

文字列のカウント方法

特定の文字列や文字の出現回数をカウントするためのさまざまな方法が提供されています。

ここでは、代表的な方法について解説します。

std::countの利用

std::countは、指定した範囲内で特定の文字の出現回数をカウントするために使用されます。

<algorithm>ヘッダーをインクルードする必要があります。

#include <iostream>
#include <string>
#include <algorithm>
int main() {
    std::string text = "C++プログラミングは楽しいです。";
    char target = 'プ';
    
    // 文字'プ'の出現回数をカウント
    int count = std::count(text.begin(), text.end(), target);
    
    std::cout << "文字'プ'の出現回数: " << count << std::endl;
    
    return 0;
}
文字'プ'の出現回数: 1

この例では、text内で文字'プ'の出現回数をカウントし、その結果を出力しています。

ループを用いたカウント方法

ループを用いて、特定の文字列の出現回数をカウントする方法もあります。

これは、std::string::findを利用して実装できます。

#include <iostream>
#include <string>
int main() {
    std::string text = "C++プログラミングは楽しいです。プログラミングは面白いです。";
    std::string keyword = "プログラミング";
    size_t position = 0;
    int count = 0;
    
    // 文字列"プログラミング"の出現回数をカウント
    while ((position = text.find(keyword, position)) != std::string::npos) {
        ++count;
        position += keyword.length(); // 検索位置を更新
    }
    
    std::cout << "文字列'プログラミング'の出現回数: " << count << std::endl;
    
    return 0;
}
文字列'プログラミング'の出現回数: 2

この例では、text内で"プログラミング"の出現回数をループを用いてカウントし、その結果を出力しています。

std::regexを用いたカウント方法

std::regexを用いると、正規表現を使って文字列の出現回数をカウントすることができます。

<regex>ヘッダーをインクルードする必要があります。

#include <iostream>
#include <string>
#include <regex>
int main() {
    std::string text = "C++プログラミングは楽しいです。プログラミングは面白いです。";
    std::regex pattern("プログラミング");
    
    // 正規表現を用いて"プログラミング"の出現回数をカウント
    auto words_begin = std::sregex_iterator(text.begin(), text.end(), pattern);
    auto words_end = std::sregex_iterator();
    
    int count = std::distance(words_begin, words_end);
    
    std::cout << "文字列'プログラミング'の出現回数: " << count << std::endl;
    
    return 0;
}
文字列'プログラミング'の出現回数: 2

この例では、text内で正規表現を用いて"プログラミング"の出現回数をカウントし、その結果を出力しています。

正規表現を使うことで、より柔軟なパターンマッチングが可能です。

応用例

文字列の検索やカウントは、さまざまな応用が可能です。

ここでは、いくつかの応用例を紹介します。

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

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

#include <iostream>
#include <string>
#include <algorithm>
int main() {
    std::string text = "C++ Programming is Fun.";
    std::string keyword = "programming";
    
    // 文字列を小文字に変換
    std::string lower_text = text;
    std::transform(lower_text.begin(), lower_text.end(), lower_text.begin(), ::tolower);
    
    // 検索キーワードも小文字に変換
    std::string lower_keyword = keyword;
    std::transform(lower_keyword.begin(), lower_keyword.end(), lower_keyword.begin(), ::tolower);
    
    // 小文字に変換した文字列で検索
    size_t position = lower_text.find(lower_keyword);
    
    if (position != std::string::npos) {
        std::cout << "見つかりました: 位置 " << position << std::endl;
    } else {
        std::cout << "見つかりませんでした。" << std::endl;
    }
    
    return 0;
}
見つかりました: 4

この例では、textkeywordを小文字に変換してから検索を行い、大文字小文字を区別しない検索を実現しています。

複数の文字列を同時にカウントする方法

複数の文字列を同時にカウントするには、ループとマップを組み合わせて使用します。

#include <iostream>
#include <string>
#include <map>
int main() {
    std::string text = "C++プログラミングは楽しいです。プログラミングは面白いです。";
    std::map<std::string, int> keywords = {{"プログラミング", 0}, {"楽しい", 0}, {"面白い", 0}};
    
    for (auto& [keyword, count] : keywords) {
        size_t position = 0;
        while ((position = text.find(keyword, position)) != std::string::npos) {
            ++count;
            position += keyword.length();
        }
    }
    
    for (const auto& [keyword, count] : keywords) {
        std::cout << "文字列'" << keyword << "'の出現回数: " << count << std::endl;
    }
    
    return 0;
}
文字列'プログラミング'の出現回数: 2
文字列'楽しい'の出現回数: 1
文字列'面白い'の出現回数: 1

この例では、text内で複数のキーワードの出現回数を同時にカウントし、その結果を出力しています。

特定の条件での文字列カウント

特定の条件で文字列をカウントするには、条件を満たすかどうかをチェックしながらカウントを行います。

#include <iostream>
#include <string>
int main() {
    std::string text = "C++プログラミングは楽しいです。プログラミングは面白いです。";
    std::string keyword = "プログラミング";
    size_t position = 0;
    int count = 0;
    
    // 文字列"プログラミング"が文の先頭にある場合のみカウント
    while ((position = text.find(keyword, position)) != std::string::npos) {
        if (position == 0 || text[position - 1] == '。') {
            ++count;
        }
        position += keyword.length();
    }
    
    std::cout << "文の先頭にある'プログラミング'の出現回数: " << count << std::endl;
    
    return 0;
}
文の先頭にある'プログラミング'の出現回数: 1

この例では、text内で"プログラミング"が文の先頭にある場合のみカウントしています。

文字列の出現位置を記録する方法

文字列の出現位置を記録するには、検索しながら位置をベクターに保存します。

#include <iostream>
#include <string>
#include <vector>
int main() {
    std::string text = "C++プログラミングは楽しいです。プログラミングは面白いです。";
    std::string keyword = "プログラミング";
    size_t position = 0;
    std::vector<size_t> positions;
    
    // 文字列"プログラミング"の出現位置を記録
    while ((position = text.find(keyword, position)) != std::string::npos) {
        positions.push_back(position);
        position += keyword.length();
    }
    
    std::cout << "文字列'プログラミング'の出現位置: ";
    for (size_t pos : positions) {
        std::cout << pos << " ";
    }
    std::cout << std::endl;
    
    return 0;
}
文字列'プログラミング'の出現位置: 3 18 

この例では、text内で"プログラミング"の出現位置をすべて記録し、その結果を出力しています。

よくある質問

findメソッドはどのように動作しますか?

findメソッドは、std::stringクラスのメンバー関数で、文字列内で指定した文字列や文字を検索します。

検索は左から右に行われ、最初に見つかった位置を返します。

見つからない場合は、std::string::nposが返されます。

例:size_t position = text.find("keyword");のように使用します。

文字列が見つからない場合の処理はどうすれば良いですか?

文字列が見つからない場合、findメソッドstd::string::nposを返します。

この値を利用して、見つからなかった場合の処理を行うことができます。

例えば、if (position == std::string::npos) { /* 見つからなかった場合の処理 */ }のように条件分岐を行います。

std::regexを使う際の注意点は何ですか?

std::regexを使用する際の注意点として、以下の点が挙げられます:

  • 正規表現の構文が正しくないと、例外が発生する可能性があります。

正規表現のパターンを慎重に設計してください。

  • std::regexは、特に複雑なパターンを扱う場合、パフォーマンスに影響を与えることがあります。

必要に応じて、パフォーマンスを考慮した設計を行ってください。

  • C++の正規表現は、他の言語の正規表現と微妙に異なる場合があります。

C++の正規表現仕様に従ってパターンを記述してください。

まとめ

この記事では、std::stringを用いた特定文字列の検索とカウント方法について詳しく解説しました。

findrfindといった基本的なメソッドから、std::regexを用いた高度な検索方法まで、さまざまな手法を紹介しました。

これらの知識を活用して、より効率的な文字列操作を実現し、プログラムの精度を向上させてみてください。

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