2019年1月20日日曜日

さらに番外編からの・・・Cで正規表現

前回、前々回と、VBAとC#で書いてみた正規表現の扱い方でしたが、せっかくだからCで書いたらどうなるか、書いてみました。Qiitaのこの記事美味しいもの様の記事を参考にさせていただきました。

C#では、正規表現オブジェクトのコンストラクターが正規表現パターンのコンパイルをしてしまうのですが、Cにはそのような概念がないので、プログラマが明示的にコンパイル指示をしなければいけませんね。

/*
  *  Cで正規表現を使う
  */

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

/*
  * 与えられた文字列のstart文字目からend文字目までをfpで与えられたファイルポインターに出力
  */
 void outputstring( fp, string, start, end )
 FILE *fp;
 char *string;
 int start, end;
 {
     int i;

     for( i=start; i<end; ++i )
     {
         fputc( string[i], fp );
     }

 }

 int main( argc, argv )
 int argc;
 char *argv[];
  {
     char checkString[] = "000aaa111bbb";
     const char regex[] = "(^.)(..)..(.+$)";
     regex_t regexBuffer;
     regmatch_t patternMatch[4];
     int size = sizeof(patternMatch)/sizeof(regmatch_t);
     int i;

    if( regcomp( &regexBuffer, regex, REG_EXTENDED | REG_NEWLINE) != 0 ) {
        fprintf( stderr, "regex compile failed¥n" );
        return 0xffffffff;
    }

    if( regexec( &regexBuffer, checkString, size, patternMatch,0) != 0 )
    {
        fprintf( stderr, "No match!!¥n");
        return 0xffffffff;
    }

    for( i=0; i<size; ++i) {
        int startIndex = patternMatch[i].rm_so;
        int endIndex = patternMatch[i].rm_eo;
        if( startIndex == -1 || endIndex == -1 ) {
            fprintf(stderr, "exit¥n");
            continue;
        }
        outputstring( stdout, checkString, startIndex, endIndex);
        fprintf( stdout, "\n");
    }
    
    regfree( &regexBuffer);
    return 0;
 }
これを実行すると、以下のような出力を出します。
000aaa111bbb
0
00
a111bbb

なお、マッチした文字列を取得するのにpatternMatch[i].rm_soとpatternMatch[i].rm_eoという変数を使用しています。これはちょっと使い方に注意が必要で、patternMatch[i].rm_soはマッチした文字列の先頭を示しますが、patternMatch[i].rm_eoは、マッチした文字列の次の文字を示します。

上のプログラムでは、patternMatch[i]_rm_soをstartIndex、patternMatch[i].rm_eoをendIndexという変数に入れて使っていますが、これを使ってマッチした文字列を表すためには、文字列checkStringにおいて、checkString[startIndex]からcheckString[endIndex-1]までの文字を参照する必要があります。

0 件のコメント:

コメントを投稿

コメントを頂ければ幸いです。