2个不错的通配符比较函数近日在和朋友讨论MaskMatch时偶得2个不错的算法。
函数2完全支持正规表达式。速度于之前的相同。(不会正规表达式的朋友慎用) //Funtion1 //=========================== //Checkifthestringcanmatchthewildcard.Itcanbeusedforunicodestringsaswell! //C:2004-07-24|M:2004-07-24 functionMaskMatch(constaPattern,aSource:string):Boolean; var StringPtr,PatternPtr:PChar; StringRes,PatternRes:PChar; begin Result:=False; StringPtr:=PChar(UpperCase(aSource)); PatternPtr:=PChar(UpperCase(aPattern)); StringRes:=nil; PatternRes:=nil; repeat repeat//ohnevorangegangenes"*" casePatternPtr^of #0:begin Result:=StringPtr^=#0; ifResultor(StringRes=nil)or(PatternRes=nil)thenExit; StringPtr:=StringRes; PatternPtr:=PatternRes; Break; end; '*':begin Inc(PatternPtr); PatternRes:=PatternPtr; Break; end; '?':begin ifStringPtr^=#0thenExit; Inc(StringPtr); Inc(PatternPtr); end; elsebegin ifStringPtr^=#0thenExit; ifStringPtr^<>PatternPtr^then begin if(StringRes=nil)or(PatternRes=nil)thenExit; StringPtr:=StringRes; PatternPtr:=PatternRes; Break; endelse begin Inc(StringPtr); Inc(PatternPtr); end; end; end; untilFalse; repeat//mitvorangegangenem"*" casePatternPtr^of #0:begin Result:=True; Exit; end; '*':begin Inc(PatternPtr); PatternRes:=PatternPtr; end; '?':begin ifStringPtr^=#0thenExit; Inc(StringPtr); Inc(PatternPtr); end; elsebegin repeat ifStringPtr^=#0thenExit; ifStringPtr^=PatternPtr^thenBreak; Inc(StringPtr); untilFalse; Inc(StringPtr); StringRes:=StringPtr; Inc(PatternPtr); Break; end; end; untilFalse; untilFalse; end; //=========================== //Funtion2 //=========================== function_MatchPattern(aPattern,aSource:PChar):Boolean; begin Result:=True; while(True)do begin caseaPattern[0]of #0:begin //Endofpatternreached. Result:=(aSource[0]=#0);//TRUEifendofaSource. Exit; end; '*':begin//Matchzeroormoreoccurancesofanychar. if(aPattern[1]=#0)then begin //Matchanynumberoftrailingchars. Result:=True; Exit; endelse Inc(aPattern); while(aSource[0]<>#0)do begin //TrytomatchanysubstringofaSource. if(_MatchPattern(aSource,aPattern))then begin Result:=True; Exit; end; //Continuetestingnextchar... Inc(aSource); end; end; '?':begin//Matchanyonechar. if(aSource[0]=#0)then begin Result:=False; Exit; end; //Continuetestingnextchar... Inc(aSource); Inc(aPattern); end; '[':begin//Matchgivensetofchars. if(aPattern[1]in[#0,'[',']'])then begin //InvalidSet-Sonomatch. Result:=False; Exit; end; if(aPattern[1]='^')then begin //Matchforexclusionofgivenset... Inc(aPattern,2); Result:=True; while(aPattern[0]<>']')do begin if(aPattern[1]='-')then begin //Matchcharexclusionrange. if(aSource[0]>=aPattern[0])and(aSource[0]<=aPattern[2])then begin //Givencharfailedsetexclusionrange. Result:=False; Break; endelse Inc(aPattern,3); endelse begin //Matchindividualcharexclusion. if(aSource[0]=aPattern[0])then begin //Givencharfailedsetelementexclusion. Result:=False; Break; endelse Inc(aPattern); end; end; endelse begin //Matchforinclusionofgivenset... Inc(aPattern); Result:=False; while(aPattern[0]<>']')do begin if(aPattern[1]='-')then begin //Matchcharinclusionrange. if(aSource[0]>=aPattern[0])and(aSource[0]<=aPattern[2])then begin //Givencharmatchedsetrangeinclusion. //Continuetesting... Result:=True; Break; endelse Inc(aPattern,3); endelse begin //Matchindividualcharinclusion. if(aSource[0]=aPattern[0])then begin //Givencharmatchedsetelementinclusion. //Continuetesting... Result:=True; Break; endelse Inc(aPattern); end; end; end; if(Result)then begin //Matchwasfound.Continuefurther. Inc(aSource); //PositionPatterntocharafter"]" while(aPattern[0]<>']')and(aPattern[0]<>#0)doInc(aPattern); if(aPattern[0]=#0)then begin //InvalidPattern-missing"]" Result:=False; Exit; endelse Inc(aPattern); endelse Exit; end; elsebegin//Matchgivensinglechar. if(aSource[0]<>aPattern[0])then begin Result:=False; Break; end; //Continuetestingnextchar... Inc(aSource); Inc(aPattern); end; end; end; end; functionMatchPattern(constaPattern,aSource:string):Boolean; begin Result:=_MatchPattern(PChar(aPattern),PChar(aSource)); end; |
|