[C++] 正規表現で数字を検索・抽出する方法
C++で正規表現を使用して数字を検索・抽出するには、標準ライブラリの<regex>
を利用します。
std::regex
で正規表現パターンを定義し、std::smatch
を使ってマッチ結果を格納します。
std::regex_search
で文字列内の最初の一致を検索し、std::regex_iterator
を用いるとすべての一致を反復処理で取得可能です。
正規表現パターンとして\d+
を使用すると、1つ以上の連続した数字を抽出できます。
数字を検索する方法
C++で正規表現を使用して数字を検索する方法について解説します。
正規表現は、特定のパターンに一致する文字列を検索するための強力なツールです。
C++では、<regex>
ライブラリを使用して正規表現を扱います。
以下に、数字を検索するための基本的なサンプルコードを示します。
#include <iostream>
#include <regex>
#include <string>
int main() {
// 検索対象の文字列
std::string text = "今日は2023年10月5日です。";
// 正規表現パターン(数字を検索)
std::regex pattern(R"(\d+)");
// マッチ結果を格納するためのオブジェクト
std::smatch matches;
// 最初のマッチを検索
if (std::regex_search(text, matches, pattern)) {
// マッチした数字を出力
std::cout << "見つかった数字: " << matches[0] << std::endl;
} else {
std::cout << "数字は見つかりませんでした。" << std::endl;
}
return 0;
}
見つかった数字: 2023
このコードでは、std::regex
を使用して、文字列内の数字を検索しています。
R"(\d+)"
というパターンは、1つ以上の数字にマッチします。
std::regex_search
関数を使って、最初のマッチを検索し、見つかった数字を出力しています。
数字を抽出する方法
C++で正規表現を使用して文字列から数字を抽出する方法を解説します。
数字を抽出する際には、std::sregex_iterator
を使用することで、文字列内のすべての数字を効率的に取得できます。
以下に、数字を抽出するためのサンプルコードを示します。
#include <iostream>
#include <regex>
#include <string>
#include <vector>
int main() {
// 検索対象の文字列
std::string text = "2023年10月5日、次は2024年の予定です。";
// 正規表現パターン(数字を抽出)
std::regex pattern(R"(\d+)");
// マッチ結果を格納するためのベクター
std::vector<std::string> numbers;
// sregex_iteratorを使用してすべてのマッチを抽出
auto it = std::sregex_iterator(text.begin(), text.end(), pattern);
auto end = std::sregex_iterator();
for (; it != end; ++it) {
// マッチした数字をベクターに追加
numbers.push_back(it->str());
}
// 抽出した数字を出力
std::cout << "抽出した数字: ";
for (const auto& number : numbers) {
std::cout << number << " ";
}
std::cout << std::endl;
return 0;
}
抽出した数字: 2023 10 5 2024
このコードでは、std::sregex_iterator
を使用して、文字列内のすべての数字を抽出しています。
R"(\d+)"
というパターンは、1つ以上の数字にマッチし、見つかった数字をベクターに格納します。
最後に、抽出した数字を出力しています。
実践例:正規表現で数字を抽出するプログラム
ここでは、実際に正規表現を使用して数字を抽出するプログラムの例を示します。
このプログラムは、ユーザーから入力された文字列からすべての数字を抽出し、表示します。
以下のサンプルコードを見てみましょう。
#include <iostream>
#include <regex>
#include <string>
#include <vector>
int main() {
// ユーザーからの入力を受け取るための変数
std::string inputText;
// ユーザーに入力を促す
std::cout << "文字列を入力してください: ";
std::getline(std::cin, inputText);
// 正規表現パターン(数字を抽出)
std::regex pattern(R"(\d+)");
// マッチ結果を格納するためのベクター
std::vector<std::string> numbers;
// sregex_iteratorを使用してすべてのマッチを抽出
auto it = std::sregex_iterator(inputText.begin(), inputText.end(), pattern);
auto end = std::sregex_iterator();
for (; it != end; ++it) {
// マッチした数字をベクターに追加
numbers.push_back(it->str());
}
// 抽出した数字を出力
std::cout << "抽出した数字: ";
for (const auto& number : numbers) {
std::cout << number << " ";
}
std::cout << std::endl;
return 0;
}
このプログラムは、ユーザーから文字列を入力させ、その中からすべての数字を抽出します。
std::getline
を使用して、改行を含む入力を受け取ります。
正規表現パターンR"(\d+)"
を使用して、1つ以上の数字を検索し、std::sregex_iterator
でマッチを繰り返し取得します。
最後に、抽出した数字をコンソールに表示します。
このプログラムを実行すると、ユーザーが入力した文字列に含まれるすべての数字が表示されます。
例えば、入力が「2023年10月5日、次は2024年の予定です。」であれば、出力は次のようになります。
抽出した数字: 2023 10 5 2024
よくあるエラーとその対処法
C++で正規表現を使用する際に遭遇する可能性のあるエラーと、その対処法について解説します。
以下に、一般的なエラーとその解決策をまとめました。
エラー内容 | 原因 | 対処法 |
---|---|---|
std::regex_error | 正規表現パターンが無効である場合 | 正規表現の構文を確認し、正しい形式に修正する。 |
std::out_of_range | マッチ結果にアクセスする際にインデックスが範囲外である場合 | マッチ結果のサイズを確認し、適切なインデックスを使用する。 |
std::bad_alloc | メモリ不足により、オブジェクトの割り当てに失敗した場合 | プログラムのメモリ使用量を見直し、不要なオブジェクトを削除する。 |
入力が空の場合 | ユーザーが何も入力しなかった場合 | 入力が空でないかを確認し、適切なメッセージを表示する。 |
正規表現が期待通りに動作しない | パターンが意図したマッチを行わない場合 | 正規表現のパターンを再確認し、必要に応じて修正する。 |
エラーの詳細と対処法
1. std::regex_error
- 原因: 正規表現の構文が誤っている場合に発生します。
- 対処法: 正規表現の文法を確認し、特にエスケープが必要な文字(例:
.
や*
など)を適切に処理します。
2. std::out_of_range
- 原因: マッチ結果にアクセスする際に、存在しないインデックスを指定した場合に発生します。
- 対処法:
matches.size()
を使用して、マッチ結果の数を確認し、適切なインデックスを使用します。
3. std::bad_alloc
- 原因: プログラムがメモリを使い果たした場合に発生します。
- 対処法: メモリ使用量を見直し、必要のないオブジェクトを解放するか、プログラムのロジックを見直します。
4. 入力が空の場合
- 原因: ユーザーが何も入力しなかった場合、正規表現はマッチしません。
- 対処法: 入力が空でないかを確認し、空の場合はエラーメッセージを表示します。
5. 正規表現が期待通りに動作しない
- 原因: 正規表現のパターンが意図したマッチを行わない場合があります。
- 対処法: 正規表現のパターンを再確認し、必要に応じて修正します。
特に、量指定子やグループ化の使い方に注意が必要です。
これらのエラーを理解し、適切に対処することで、正規表現を用いたプログラムの信頼性を向上させることができます。
応用的な使い方
C++の正規表現を使用して数字を抽出する基本的な方法を学んだ後、さらに応用的な使い方を考えてみましょう。
ここでは、特定の条件に基づいて数字をフィルタリングしたり、複雑なパターンを使用してデータを処理する方法を紹介します。
以下にいくつかの応用例を示します。
1. 特定の範囲の数字を抽出する
特定の範囲内の数字を抽出するためには、正規表現のパターンを工夫する必要があります。
例えば、1から100までの数字を抽出する場合、次のようなパターンを使用します。
#include <iostream>
#include <regex>
#include <string>
#include <vector>
int main() {
std::string inputText = "1, 25, 50, 101, 75, 200, 99";
std::regex pattern(R"(\b([1-9][0-9]?|100)\b)"); // 1から100までの数字を抽出
std::vector<std::string> numbers;
auto it = std::sregex_iterator(inputText.begin(), inputText.end(), pattern);
auto end = std::sregex_iterator();
for (; it != end; ++it) {
numbers.push_back(it->str());
}
std::cout << "抽出した数字 (1-100): ";
for (const auto& number : numbers) {
std::cout << number << " ";
}
std::cout << std::endl;
return 0;
}
抽出した数字 (1-100): 1 25 50 75 99
2. 小数点を含む数字を抽出する
小数点を含む数字を抽出する場合、正規表現のパターンを変更する必要があります。
以下のコードでは、小数点を含む数字を抽出します。
#include <iostream>
#include <regex>
#include <string>
#include <vector>
int main() {
std::string inputText = "価格は100.50円、200.75円、300円です。";
std::regex pattern(R"(\b\d+(\.\d+)?\b)"); // 整数または小数を抽出
std::vector<std::string> numbers;
auto it = std::sregex_iterator(inputText.begin(), inputText.end(), pattern);
auto end = std::sregex_iterator();
for (; it != end; ++it) {
numbers.push_back(it->str());
}
std::cout << "抽出した数字 (小数を含む): ";
for (const auto& number : numbers) {
std::cout << number << " ";
}
std::cout << std::endl;
return 0;
}
抽出した数字 (小数を含む): 100.50 200.75 300
3. 数字のフォーマットを検証する
正規表現を使用して、特定のフォーマットの数字を検証することも可能です。
例えば、電話番号や郵便番号の形式を確認する場合、次のようなコードを使用します。
#include <iostream>
#include <regex>
#include <string>
int main() {
std::string phoneNumber = "090-1234-5678";
std::regex pattern(R"(^\d{3}-\d{4}-\d{4}$)"); // 電話番号のフォーマットを検証
if (std::regex_match(phoneNumber, pattern)) {
std::cout << "有効な電話番号です。" << std::endl;
} else {
std::cout << "無効な電話番号です。" << std::endl;
}
return 0;
}
有効な電話番号です。
4. 複数の条件を組み合わせる
複数の条件を組み合わせて、より複雑なパターンを作成することもできます。
例えば、特定の接頭辞を持つ数字を抽出する場合、次のようにします。
#include <iostream>
#include <regex>
#include <string>
#include <vector>
int main() {
std::string inputText = "ID: 12345, ID: 67890, ID: 54321";
std::regex pattern(R"(ID:\s*(\d{5}))"); // "ID: "に続く5桁の数字を抽出
std::vector<std::string> ids;
auto it = std::sregex_iterator(inputText.begin(), inputText.end(), pattern);
auto end = std::sregex_iterator();
for (; it != end; ++it) {
ids.push_back(it->str(1)); // グループ1を取得
}
std::cout << "抽出したID: ";
for (const auto& id : ids) {
std::cout << id << " ";
}
std::cout << std::endl;
return 0;
}
抽出したID: 12345 67890 54321
これらの応用例を通じて、正規表現を使った数字の抽出や検証の幅を広げることができます。
正規表現のパターンを工夫することで、さまざまなデータ処理に対応できるようになります。
まとめ
この記事では、C++における正規表現を使用して数字を検索・抽出する方法について詳しく解説しました。
基本的な数字の検索から、特定の範囲やフォーマットに基づく抽出、さらには複雑な条件を組み合わせた応用例まで幅広く取り上げました。
正規表現を活用することで、データ処理の効率を高めることができるため、ぜひ実際のプログラムに取り入れてみてください。