16番会議室「玉石混淆みんなで作るSample蔵」に寄せられたサンプル
"ワイルドカード処理(長文)"
この発言に対し以下のコメントが寄せられています
#00836 わいわい さん ワイルドカード処理(2)
別の会議室で少し前に話題になっていた*や?を
含んだファイル名のチェックです。
長いソースです。(よりよい方法がありましたら
どなたかお願いします。(^^;))
このソースのみそは、maskのstringをいったん
整えることです。例えば******.*****は*.*と
同じです。同様に*?*?*?a*?*.*?は???*a?*.?*と
同じことになります。後は力技です。なお、
ooo*.又はooo*?.のように、ワイルドカード+.で
終る場合はooo*.*又はooo?*.*と同等になる
ようです。
by Quiri(JAC01052)
function TForm1.Check_LongMask(filename,
longmask: string): boolean;
var
SL:TStringlist;
S1,S2:string;
i:integer;
begin
SL:=TStringList.Create;
result:=false;
{-----longmaskを;で区切ってSLに収納する。----}
S1:='';
for i:=1 to Length(WideString(longmask)) do
begin
S2:=copy(WideString(longmask),i,1);
if S2<>';' then
begin
S1:=S1+S2;
end
else
begin
if S1<>'' then SL.Append(S1);
S1:='';
end;
end;
if S1<>'' then SL.Append(S1);
{短いMask一つ一つ適合するかチェックし、
一つでも合えば結果を真にして終了}
for i:=0 to SL.Count-1 do
begin
S1:=SL.Strings[i];
if Check_ShortMask(filename,S1) then
begin
result:=true;
break;
end;
end;
SL.Free;
end;
function TForm1.Check_ShortMask(filename,
shortmask: string): boolean;
var
flag_n,flag_a:boolean;
S1,S2,S_next:string;
i,i_mask,i_file: integer;
xi_mask,xi_file: integer;
length_mask,length_filename: integer;
num_a,num_q: integer;{*の数、?の数}
begin
{---------maskの形を整える。--------------}
length_mask:=length(widestring(shortmask));
num_a:=0;
num_q:=0;
S1:='';
for i_mask:=1 to length_mask do
begin
S2:=copy(WideString(shortmask),i_mask,1);
if S2='*' then
inc(num_a)
else
if S2='?' then
inc(num_q)
else
begin
{*,?以外の文字がでたらそこまでの
文字列を整理する。}
if num_q>0 then
for i:=1 to num_q do
S1:=S1+'?';
if num_a>0 then
S1:=S1+'*';
S1:=S1+S2;
num_a:=0;
num_q:=0;
end;
end;
{文字列の終りについている*,?の分}
if num_q>0 then
for i:=1 to num_q do
S1:=S1+'?';
if num_a>0 then
S1:=S1+'*';
{最後が.の時の処理}
if copy(WideString(S1),
length(WideString(S1)),1)='.' then
if copy(WideString(S1),
length(WideString(S1))-1,1)='*' then
S1:=S1+'*';
{----------新しいMaskで比較開始-------------}
length_mask:=length(widestring(S1));
length_filename:=length(widestring(filename));
result:=false;
i_mask:=1;
i_file:=1;
xi_mask:=1;
xi_file:=1;
flag_a:=true;
repeat
S2:=copy(WideString(S1),i_mask,1);
if S2='?' then
begin
if i_file>length_filename then exit;
{?には長さがあるのでfilenameの長さが
足りなくては合致することはない。}
if (i_mask=length_mask) and
(i_file=length_filename) then
begin
{最後の文字どうしでぴたり合致した。}
result:=true;
exit;
end;
inc(i_mask);
inc(i_file);
end
else
if S2='*' then
begin
if i_mask=length_mask then
begin
{*は長さ0からいくつでも可なので、
ここまで合致していて、これ以上比較する
ものがなければ全て合致するはず。}
result:=true;
exit;
end;
S_next:=copy(WideString(S1),i_mask+1,1);
{*の次の文字を得る。}
flag_n:=true;
for i:=i_file to length_filename do
if comparetext(S_next,
copy(WideString(filename),i,1))=0 then
begin
{一致する文字が見つかった。しかし
その後にも一致する文字がある可能性
があるのでとりあえず、flag_aをたて
また、見つかった位置を保管。}
flag_a:=false;
flag_n:=false;
xi_mask:=i_mask;
xi_file:=i;
break;
end;
if flag_n then exit;
{*の次の文字と一致する文字が
見つからなかった。}
inc(i_mask);
i_file:=xi_file;
end
else
if comparetext(S2,
copy(WideString(filename),i_file,1))=0 then
begin
if (i_mask=length_mask) and
(i_file=length_filename) then
begin
{最後の文字どうしでぴたり合致した。}
result:=true;
exit;
end;
inc(i_mask);
inc(i_file);
end
else
begin
{不一致、しかし前にやり直すべき場所が
ある可能性がある。*の位置へ戻る。}
if flag_a then exit;
flag_a:=true;
i_mask:=xi_mask;
i_file:=xi_file+1;
end;
until false;
end;
Original document by Quiri 氏 ID:(JAC01052)
ここにあるドキュメントは NIFTY SERVEの Delphi Users' Forum の16番会議室「玉石混淆みんなで作るSample蔵」に投稿されたサンプルです。これらのサンプルはボーランド株式会社がサポートする公式のものではありません。また、必ずしも動作が検証されているものではありません。これらのサンプルを使用したことに起因するいかなる損害も投稿者、およびフォーラムスタッフはその責めを負いません。使用者のリスクの範疇でご使用下さい。
Copyright 1996-2002 Delphi Users' Forum
|