LoginSignup
43
42

More than 3 years have passed since last update.

Cでの正規表現

Last updated at Posted at 2013-05-21

C+11では正規表現をサポートしているがそれ以前のバージョンだとサポートしていないようなのでC言語の正規表現を利用する

C言語で正規表現を利用する場合regex.hをincludeして、regcompregexecregfreeこの3つの関数を利用する。

main.cpp
#include <iostream>
#include <regex.h>

int main( int argv, char* args[] )
{
    char checkString[] = "abc, def, ghi";                   // チェックをする文字列
    const char regex[] = "([a-z]+), ([a-z]+), ([a-z]+)";    // マッチングをする文字列
    regex_t regexBuffer;                                    // 正規表現オブジェクト

    // 正規表現オブジェクトのコンパイル
    if( regcomp( &regexBuffer, regex, REG_EXTENDED | REG_NEWLINE ) != 0 )
    {
        std::cout << "regex compile failed" << std::endl;
        return 1;
    }

    // パターンにマッチングしたインデックス格納する構造体
    regmatch_t patternMatch[4];

    int size = sizeof( patternMatch ) / sizeof( regmatch_t );
    if( regexec( &regexBuffer, checkString, size, patternMatch, 0 ) != 0 )
    {
        std::cout << "No match!!" << std::endl;
        return 1;
    }

    // マッチした場合patternMatch構造体に文字列のindex番号が入る
    // 配列の数がマッチ数を超えていた場合超えた構造体の各要素には-1が入る
    for( int i = 0; i < size; ++i )
    {
        int startIndex = patternMatch[i].rm_so;
        int endIndex = patternMatch[i].rm_eo;
        if( startIndex == -1 || endIndex == -1 )
        {
            std::cout << "exit" << std::endl;
            continue;
        }
        std::string putStr( checkString, startIndex, endIndex - startIndex );
        std::cout << putStr << std::endl;
    }

    // オブジェクトの開放
    regfree( &regexBuffer );
    return 0;
}

上のコードの結果は下記になる

Terminal.app
abc, def, ghi    #patternMatch[0]の結果の文字列
abc              #patternMatch[1]の結果の文字列
def              #patternMatch[2]の結果の文字列
ghi              #patternMatch[3]の結果の文字列

結果の格納先の配列数が少ない場合その分結果のオブジェクトが削られるがマッチしないことはない
結果はpythonの正規表現と同じように一番指定文字列全体にマッチングした文字列
それ以降はグルーピングごとの順番で格納される。
ただしregcomp 関数をコールする際に指定したREG_EXTENDEDこの指定を行わないとグルーピングなどの拡張正規表現は使えないようだ。
REG_EXTENDED 大事!!
[ ]などとマッチングを指定したい場合メタ文字になっているため\をつけるなど指定には注意が必要

以下は正規表現を行うのに使用した関数の説明

regcomp

int regcomp(regex_t *preg, const char *regex, int cflags)
正規表現のコンパイルを行なう。コンパイル成功時には0を返す。
cflags には以下に示す定数一つ以上のビッ>トごとの OR (bitwise-or) を指定する。

REG_EXTENDED
regex に POSIX 拡張正規表現を使用する。もしこのフラグが設定されない場合、POSIX 標準正規表現が使われる。
REG_ICASE
大文字小文字の違いを無視する。
REG_NOSUB
このフラグを設定してコンパイルされたパターンバッファが regexec の引数に指定されると、パラメータ nmatch, pmatch が無視される。
REG_NEWLINE
全ての文字にマッチするオペレータに改行をマッチさせない。

regexec

int regexec(const regex_t *preg, const char *string, size_t nmatch, regmatch_t pmatch[], int eflags);
正規表現による検索を実行する。
eflags には以下に示す定数一つ以上のビットごとの OR (bitwise-or) を指定する。

REG_NOTBOL
行頭にマッチするオペレータは、必ずマッチに失敗する (コンパイル時のフラグ REG_NEWLINE の項目も参照)。このフラグは、複数行にまたがる文字列を regexec() で検索する際に、文字列の先頭を行の先頭として解釈させない場合に用いる。
REG_NOTEOL
行末にマッチするオペレータは、必ずマッチに失敗する。

regfree

void regfree(regex_t *preg)
正規表現パターンバッファを解放する。
43
42
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
43
42