使い方

インストール方法

  1. パッケージに含まれているヘッダファイルをプロジェクトフォルダに全てコピー

これだけでインストールは完了です。 ディレクトリ構造はそのままにしておいてください。

複数のプロジェクトで使う場合や複数の開発者が使う場合等は共有ディレクトリに入れて、そこにパスを通してもよいでしょう。 他のライブラリ・ヘッダファイルと混ざらないように、mercuryフォルダごとコピーしてください。

使用方法

  1. 正規表現を使う場所で"mercury/regex.h"をインクルード
  2. mercury::basic_regexのオブジェクトを作成(正規表現パターンはコンストラクタに渡すか、オブジェクト作成後にcompile()メンバ関数に渡す)
  3. match()メンバ関数でマッチングを行い、一致箇所を取得

メタ文字 "^", "$" を使うことで、前方一致・後方一致・部分一致を指定可能です。 詳しくは正規表現リファレンスを参照してください。

サンプルコード

Mercury::Regexを使ったサンプルコードを以下に示します。 様々な文字型や文字列(データ構造)に対応していることがわかると思います。 下のサンプルの他にも、文字型・文字列・一致情報をいろいろ組み合わせて使うこともできます。

一致情報は、mercury::regex::MATCH_INFO<> で得られます。 これはテンプレート構造体で、テンプレートパラメータにはイテレータを指定します。

構文エラー等が起こった場合にmercury::REGEX_ERROR型のエラーコードがスローされますので、必ずこの例外をキャッチして下さい。

文字型=char, 文字列=ポインタ

C言語では最もオーソドックスな方法です。 エスケープシーケンスは、"\w"ではなく"\\w"とする必要があります。 理由は…わかりますね?

#include <string>
#include <iostream>
#include "mercury/regex.h"

int main(void)
{
	typedef const char *charptr_t;
	charptr_t pattern = "^https?://([\\w.~?&%#=-]+/?)+$";
	charptr_t text    = "http://sourceforge.jp/";

	try
	{
		mercury::regex::MATCH_INFO<charptr_t> match_info;

		// 配列と文字数を渡す
		const mercury::regex re(pattern, strlen(pattern));
		if(re.match(text, match_info))          // NUL文字で終わっている場合、文字数は省略可
		{
			// beginで一致場所の先頭イテレータ(ポインタ)、endで末尾イテレータを取得できる
			std::cout << "マッチしました: " << std::string(match_info.begin, match_info.end) << std::endl;
		}
		else
		{
			std::cout << "マッチしませんでした" << std::endl;
		}
	}
	catch(mercury::REGEX_ERROR error)
	{
		std::string message = "Error";
		switch(error)
		{
		case mercury::REGERR_SYNTAX       : message = "Syntax Error"            ; break;
		case mercury::REGERR_SET_RANGE    : message = "Invalid Range of Sets"   ; break;
		case mercury::REGERR_REPEAT_MINMAX: message = "Invalid Number of Repeat"; break;
		}
		std::cout << message << std::endl;
	}
	return 0;
}

文字型=wchar_t, 文字列=std::wstring

国際派のアナタはwchar_tを、C++なアナタはstd::wstringを使いましょう。 さらに、get() を使えば一致部分をコンテナとして取り出すことができます。

以下のコードはMicrosoft Visual C++で動作確認しています。 Borland C++ Compiler 5.5.1では文字が表示されませんが、マッチングには成功しています。 また、素のMinGW G++ 3.4.5では"`wcout' is not a member of `std'"というエラーが出ますが、これはG++のライブラリの問題で、Mercury::Regexの問題ではありません。

#include <string>
#include <iostream>
#include "mercury/regex.h"

int main(void)
{
	// wchar_t型なら日本語も無問題
	const std::wstring pattern = L"https?://([\\w.~?&%#=-]+/?)+";
	const std::wstring text    = L"アドレスはhttp://sourceforge.jp/です";

	try
	{
		std::wcout.imbue(std::locale("japanese"));

		// wchar_t型はwregexを使う
		mercury::wregex::MATCH_INFO<std::wstring::const_iterator> match_info;

		// オブジェクト作成後にcompile()に渡してもOK(その場合はconstオブジェクトにしないこと)
		mercury::wregex re;
		re.compile(pattern);
		if(re.match(text, match_info))
		{
			// get() を使えば、一致部分を任意のコンテナで取り出せる
			std::wcout << L"マッチしました: " << match_info.get<std::wstring>() << std::endl;
		}
		else
		{
			std::wcout << L"マッチしませんでした" << std::endl;
		}
	}
	catch(mercury::REGEX_ERROR error)
	{
		std::string message = "Error";
		switch(error)
		{
		case mercury::REGERR_SYNTAX       : message = "Syntax Error"            ; break;
		case mercury::REGERR_SET_RANGE    : message = "Invalid Range of Sets"   ; break;
		case mercury::REGERR_REPEAT_MINMAX: message = "Invalid Number of Repeat"; break;
		}
		std::cout << message << std::endl;
	}
	return 0;
}

文字型=その他クラス, 文字列=その他コンテナ

組み込み型だけでなく、文字型としてクラスを使うこともできます。 また、文字列としてリストや双方向キューも使えます。 詳細は使える文字型・データ構造を参照してください。

#include <list>
#include <deque>
#include <string>
#include <iostream>
#include "mercury/regex.h"

// こんな文字型も使えます。
class character
{
public:
	character(const char ch = 0) { m_ch = ch; }
	bool operator==(const character &rhs) const { return m_ch == rhs.m_ch; }
	bool operator< (const character &rhs) const { return m_ch <  rhs.m_ch; }

	character operator+(const int value) const { return character(static_cast<char>(m_ch + value)); }

private:
	char m_ch;
};

int main(void)
{
	// データをセットするのが面倒だけど、その気になれば配列やstd::string以外でもできないことはない
	typedef std::list <character> pattern_t;
	typedef std::deque<character> text_t;

	// "(a|bc)*d+e?$"
	pattern_t pattern;
	pattern.push_back('(');
	pattern.push_back('a');
	pattern.push_back('|');
	pattern.push_back('b');
	pattern.push_back('c');
	pattern.push_back(')');
	pattern.push_back('*');
	pattern.push_back('d');
	pattern.push_back('+');
	pattern.push_back('e');
	pattern.push_back('?');
	pattern.push_back('$');

	// "1234abcde"
	text_t text;
	text.push_back('1');
	text.push_back('2');
	text.push_back('3');
	text.push_back('4');
	text.push_back('a');
	text.push_back('b');
	text.push_back('c');
	text.push_back('d');
	text.push_back('e');

	try
	{
		// char, wchar_t以外の型はbasic_regexを使う
		typedef mercury::basic_regex<character> cregex;

		// 一致情報は、パターンではなくテキストのデータ型に合わせる
		// constでないオブジェクトの場合は、const_iteratorでなくiteratorにする
		cregex::MATCH_INFO<text_t::iterator> match_info;

		// 文字配列もしくはコンテナは、代入演算子でもコンパイルできる
		// コンストラクタ・compile()・match()は、コンテナもイテレータも両方渡せる(イテレータは不可)
		cregex re;
		re = pattern;                                       // コンテナをそのまま渡してもいいし…
		if(re.match(text.begin(), text.end(), match_info))  // イテレータを渡してもいい
		{
			// offsetで一致場所、lengthで一致長を取得できる
			std::cout << "マッチしました(場所,長さ)=(" << match_info.offset << ", " << match_info.length << ")" << std::endl;
		}
		else
		{
			std::cout << "マッチしませんでした" << std::endl;
		}
	}
	catch(mercury::REGEX_ERROR error)
	{
		std::string message = "Error";
		switch(error)
		{
		case mercury::REGERR_SYNTAX       : message = "Syntax Error"            ; break;
		case mercury::REGERR_SET_RANGE    : message = "Invalid Range of Sets"   ; break;
		case mercury::REGERR_REPEAT_MINMAX: message = "Invalid Number of Repeat"; break;
		}
		std::cout << message << std::endl;
	}
	return 0;
}