近日在和朋友讨论 MaskMatch 时偶得2个不错的算法。
函数1 只支持'*','?'模糊匹配。速度比采用递归算法的快近2倍,比TMask方法快很多。
函数2 完全支持正规表达式。速度于之前的相同。(不会正规表达式的朋友慎用)
| // =========================== // Function 1 // =========================== // Check if the string can match the wildcard. It can be used for unicode strings as well! // C: 2004-07-24 | M: 2004-07-24 function MaskMatch(const aPattern, 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 // ohne vorangegangenes "*" case PatternPtr^ of #0 : begin Result := StringPtr^ = #0; if Result or (StringRes = nil) or (PatternRes = nil) then Exit; StringPtr := StringRes; PatternPtr := PatternRes; Break; end; '*': begin Inc(PatternPtr); PatternRes := PatternPtr; Break; end; '?': begin if StringPtr^ = #0 then Exit; Inc(StringPtr); Inc(PatternPtr); end; else begin if StringPtr^ = #0 then Exit; if StringPtr^ <> PatternPtr^ then begin if (StringRes = nil) or (PatternRes = nil) then Exit; StringPtr := StringRes; PatternPtr := PatternRes; |
| Break; end else begin Inc(StringPtr); Inc(PatternPtr); end; end; end; until False; repeat // mit vorangegangenem "*" case PatternPtr^ of #0 : begin Result := True; Exit; end; '*': begin Inc(PatternPtr); PatternRes := PatternPtr; end; '?': begin if StringPtr^ = #0 then Exit; Inc(StringPtr); Inc(PatternPtr); end; else begin repeat if StringPtr^ = #0 then Exit; if StringPtr^ = PatternPtr^ then Break; Inc(StringPtr); until False; Inc(StringPtr); StringRes := StringPtr; Inc(PatternPtr); Break; end; end; until False; until False; end; |
| // =========================== // Function 2 // =========================== function _MatchPattern(aPattern, aSource: PChar): Boolean; begin Result := True; while (True) do begin case aPattern[0] of #0 : begin //End of pattern reached. Result := (aSource[0] = #0); //TRUE if end of aSource. Exit; end; '*': begin //Match zero or more occurances of any char. if (aPattern[1] = #0) then begin //Match any number of trailing chars. Result := True; Exit; end else Inc(aPattern); while (aSource[0] <> #0) do begin //Try to match any substring of aSource. if (_MatchPattern(aSource, aPattern)) then begin Result := True; Exit; end; //Continue testing next char... Inc(aSource); end; end; '?': begin //Match any one char. if (aSource[0] = #0) then begin Result := False; Exit; en
|