正規表現を実装する 第一回「リテラル」

正規表現とはある文字列のパターン一致するかどうかをチェックするものです。

正規表現 - Wikipedia

今回これを自分で実装してみようと思います。

当然、もうすでにCで作られた素晴らしい正規表現ライブラリがあるらしいのですが、勉強用として何も見ずにC++でやってみようと思っています。ちなみにまだ16章までしか勉強してないので無駄な処理とかも満載だとは思います。

高度な機能は今の知識では無理だと思うので少しずつ機能拡張していければいいなと思っています。

とりあえず第一回ということで基本中の基本となる単なるリテラルにマッチするものを作りたいと思います。

// -- myregex.h --
#ifndef __MYREGEX_H__
#define __MYREGEX_H__
class MyRegex {
public:
    MyRegex ();
    ~MyRegex ();
    int match (const char* str,const char* regex);
};
#endif
// -- myregex.cpp --
#include "myregex.h"
#include <cstring>

// --------------------------
// MyRegex
// コンストラクタ
// 特に処理なし
// --------------------------
MyRegex::MyRegex () {
}

// --------------------------
// ~MyRegex
// デストラクタ
// 特に処理なし
// --------------------------
MyRegex::~MyRegex () {
}

// --------------------------
// match
// strが元文字列、regexが正規表現字列となる
// マッチしていたら真、それ以外は偽を返す
// --------------------------
int MyRegex::match (const char* str,const char* regex) {
    if ( !*regex ) return 1;
    
    int flag = 0;
    for(int i=0;str[i];i++) {
        if ( str[i] == *regex ) {
            flag = 1;
            for(int j=1;regex[j];j++) {
                // 元文字列が終端まで来たか、文字が違ったらマッチしない
                if ( !str[i+j] || str[i+j] != regex[j] ) {
                    flag = 0;
                    break;
                }
            }
        }
    }
    
    return flag;
}
// -- main.cpp --
#include <iostream>
#include "myregex.h"

int main () {
    MyRegex rep;
    
    std::cout << rep.match("abcdef","bc") << std::endl;
    std::cout << rep.match("abcdef","bcdefg") << std::endl;
    std::cout << rep.match("ababcd","abc") << std::endl;
    return 0;
}
$ main
1
0
1

うまく動いています。

今回はクラスを別ファイルに分けてみました。

とりあえずMyRegexという名前にし、matchという関数を用意してそこで処理をしています。

まずは単純にリテラルのチェックだけをしています。これから処理を増やしていきたいと思います。

文字列が含まれているかの処理なんですが、string.hにstrstrという関数があるのでそれを使おうかとも思いましたが、strstrの第一引数がchar*型なのでconst char*型が渡せません。

前回の記事に書いたような方法で対処も可能でしたが、勉強用なので自分で実装した方が良いなと思ったので実装しました。