lisz-works

技術と興味の集合体

C言語で正規表現を使うには?思ったより簡単だった!

【スポンサーリンク】

プログラムのソースコード

「C言語で正規表現って使えるの?」

という疑問が湧き、調べてみたら……ありました。

思ったより簡単にできたので、ご紹介します!

コード

#include <stdio.h>
#include <string.h>
#include <regex.h>

int main(void)
{
    int i;
    char name [] = "result-0001.dat";
    const char pattern[] = "result-[0-9]{4}\\.dat";
    regex_t regexBuffer;
    regmatch_t match[4];
    int size;
    char result[128];

    // 正規表現オブジェクトをコンパイル
    if ( regcomp(&regexBuffer, pattern, REG_EXTENDED | REG_NEWLINE ) != 0 )
    {
        printf("regcomp failed\n");
        return 1;
    }

    // 正規表現パターンとマッチする?
    size = sizeof(match) / sizeof(regmatch_t); // 4
    if ( regexec(&regexBuffer, name, size, match, 0) != 0 )
    {
        printf("no match\n");
        return 1;
    }

    // パターンマッチした場合の処理
    for ( i = 0; i < size; i++ )
    {
        // マッチした位置の開始・終了インデックス
        int startIndex = match[i].rm_so;    // 開始インデックス
        int endIndex = match[i].rm_eo;      // 終了インデックス
        if ( startIndex == -1 || endIndex == -1 )
        {
            printf("exit");
            continue;
        }
        printf("index [start, end] = %d, %d\n", startIndex, endIndex);
        strncpy(result, name + startIndex, endIndex - startIndex);
        printf("%s\n", result);
    }

    regfree(&regexBuffer);
    return 0;
}

解説

それでは解説です。

準備

このヘッダをインクルードします。

#include <regex.h>

正規表現用のバッファを用意。

regex_t regexBuffer;

このバッファは、開放する必要があります。
なのでコードの最後か、不要になったら

regfree(&regexBuffer);

で開放しましょう!

あとはパターン判定用の変数を用意します。

regmatch_t match[4];

正規表現オブジェクトのコンパイル

正規表現を使用するためのオブジェクトを作り出します。

regcomp(&regexBuffer, pattern, REG_EXTENDED | REG_NEWLINE )

基本問題ないと思いますが、結果が「0」でない場合失敗となります。

念の為チェックです。

正規表現のパターンマッチ

正規表現のパターンマッチ……
つまり「思っていたパターンと一致するか?」
をチェックします。

regexec(&regexBuffer, name, size, match, 0)

この結果が「0」だった場合「一致」、そうでない場合「不一致」となります。

パターンマッチ後

パターンマッチしたあと、マッチしたもののインデックス情報が「regmatch_t match[4]」に入ります。

regmatch_tの構造体変数に、マッチした箇所の「開始・終了インデックス」が入っています。

int startIndex = match[i].rm_so;    // 開始インデックス
int endIndex = match[i].rm_eo;      // 終了インデックス

なので、元データの入っているnameから、パターンマッチした文字列を、resultにコピーするには

strncpy(result, name + startIndex, endIndex - startIndex);

のようにします。

今回の例の場合、「完全一致するか?」を見ています。

例えばpatternを、このように「4桁の数字」を指定した場合

const char pattern[] = "[0-9]{4}";

resultは

0001

となります。

参考

コチラを参考にしました。ありがとうございました。

qiita.com

edu.clipper.co.jp

あとがき

C言語で正規表現を扱う方法でした!

正規表現がC言語にあると知らなかったので、コレを知ったときは驚きました(笑)

最近の言語のように、超絶簡単に扱う!ということはできませんが、そこまで難しくないので、何かあったら使っていくと楽ちんですね!