c++ builder XE4, 10.2 Tokyo > 正規表現 > 特定の1文字だけ違うものを許容する


動作確認
C++ Builder XE4

"あいうえお"
"あいええお"

上記の両方ともをtrueとするような判断を行う。
"あい[任意の1文字]えお"を許容したい。

code

関連 http://www.megasoft.co.jp/mifes/seiki/
関連 http://qiita.com/7of9/items/61955e00d0138e272a1a

Unit1.cpp
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include <System.RegularExpressions.hpp>

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;

#ifdef _WIN32 && !defined(_WIN64)
#pragma alias "toupper" = "_toupper"
#pragma alias "tolower" = "_tolower"
#pragma alias  "isupper" = "_isupper"
#pragma alias  "isalnum" = "_isalnum"
#pragma alias  "isalpha" = "_isalpha"
#pragma alias  "iscntrl" = "_iscntrl"
#pragma alias  "isdigit" = "_isdigit"
#pragma alias  "isgraph" = "_isgraph"
#pragma alias  "isleadbyte" = "_isleadbyte"
#pragma alias  "islower" = "_islower"
#pragma alias  "isprint" = "_isprint"
#pragma alias  "ispunct" = "_ispunct"
#pragma alias  "isspace" = "_isspace"
#pragma alias  "isxdigit" = "_isxdigit"
#pragma alias  "strchr" = "_strchr"
#pragma alias  "strncmp" = "_strncmp"
#pragma alias  "memcmp" = "_memcmp"
#pragma alias  "memmove" = "_memmove"
#endif

//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{

    String strA = L"あいうえお";
    String strB = L"あいええお";

    String forms[3] = {
        L"あい.*えお",
        L"あい.えお",
        L"あい.うお",
    };

    bool res;
    String msg;

    for(int fi=0; fi<3; fi++) {
        res = TRegEx::IsMatch(strA, forms[fi]);
        msg = "strA:" + BoolToStr(res);
        OutputDebugString(msg.c_str());
        res = TRegEx::IsMatch(strB, forms[fi]);
        msg = "strB:" + BoolToStr(res);
        OutputDebugString(msg.c_str());
    }

}
//---------------------------------------------------------------------------
結果
デバッグ出力: strA:-1 プロセス Project1.exe (1912)
デバッグ出力: strB:-1 プロセス Project1.exe (1912)
デバッグ出力: strA:-1 プロセス Project1.exe (1912)
デバッグ出力: strB:-1 プロセス Project1.exe (1912)
デバッグ出力: strA:0 プロセス Project1.exe (1912)
デバッグ出力: strB:0 プロセス Project1.exe (1912)

-1となっているのはres==trueの時。

forms[1](=L"あい.えお")の正規表現で対応できそう。

特定の2文字に対して任意文字許容

1文字だけであれば、その場所の情報を使ってSubString()などで文字列を分離して、Pos()などを使えば対応はできそう。

正規表現を使う理由としては、許容する任意の文字の数が1から増えた時にも同じ処理で済ませられるという狙い。

Unit1.cpp
void __fastcall TForm1::Button1Click(TObject *Sender)
{

    String strA = L"あいうえおかきくけこ";
    String strB = L"あいええおききくけこ";
    String strC = L"あいええすききくけこ";

    String form = L"あい.えお.きくけこ";

    bool res;
    String msg;

    res = TRegEx::IsMatch(strA, form);
    msg = "strA:" + BoolToStr(res);
    OutputDebugString(msg.c_str());

    res = TRegEx::IsMatch(strB, form);
    msg = "strB:" + BoolToStr(res);
    OutputDebugString(msg.c_str());

    res = TRegEx::IsMatch(strC, form);
    msg = "strB:" + BoolToStr(res);
    OutputDebugString(msg.c_str());
}
結果
デバッグ出力: strA:-1 プロセス Project1.exe (3456)
デバッグ出力: strB:-1 プロセス Project1.exe (3456)
デバッグ出力: strB:0 プロセス Project1.exe (3456)

補足

過去に実装したコードを見直すと、文字列の中の単位(cmなど)を取り除いて比較する実装をしていた。30行近いコードになっている。
正規表現を使っていれば数行で実装できる。

10.2 Tokyo

動作確認
RAD Studio 10.2 Tokyo Update 2 (追記: 2017/12/27)

10.2 Tokyoでは#ifdef _WIN32 && !defined(_WIN64)の部分は不要になる。

C++ Builder 10.2 Tokyo > 正規表現 > XE4で出ていたエラーは解消 > toupperが....System.RegularExpressionsAPIから参照されています | (XE4から10.2Tokyoへの移行)

Unit1.cpp
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"

#include <System.RegularExpressions.hpp>

//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
{

}

void __fastcall TForm1::Button1Click(TObject *Sender)
{
    String strA = L"あいうえおかきくけこ";
    String strB = L"あいええおききくけこ";
    String strC = L"あいええすききくけこ";

    String form = L"あい.えお.きくけこ";

    bool res;
    String msg;

    res = TRegEx::IsMatch(strA, form);
    msg = "strA:" + BoolToStr(res);
    OutputDebugString(msg.c_str());

    res = TRegEx::IsMatch(strB, form);
    msg = "strB:" + BoolToStr(res);
    OutputDebugString(msg.c_str());

    res = TRegEx::IsMatch(strC, form);
    msg = "strB:" + BoolToStr(res);
    OutputDebugString(msg.c_str());
}
//---------------------------------------------------------------------------