程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> Delphi >> 2個不錯的通配符比較函數

2個不錯的通配符比較函數

編輯:Delphi

近日在和朋友討論 MaskMatch 時偶得2個不錯的算法。
  函數1 只支持'*','?'模糊匹配。速度比采用遞歸算法的快近2倍,比TMask方法快很多。
  函數2 完全支持正規表達式。速度於之前的相同。(不會正規表達式的朋友慎用)

  
  
  
// ===========================
  // Funtion 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;
  
  
  // ===========================
  // Funtion 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;
               end;
  
               //Continue testing next char...
               Inc(aSource);
               Inc(aPattern);
             end;
  
        '[': begin //Match given set of chars.
               if (aPattern[1] in [#0,'[',']']) then
               begin
                 //Invalid Set - So no match.
                 Result := False;
                 Exit;
               end;
  
               if (aPattern[1] = '^') then
               begin
                 //Match for exclusion of given set...
                 Inc(aPattern, 2);
                 Result := True;
                 while (aPattern[0] <> ']') do
                 begin
                   if (aPattern[1] = '-') then
                   begin
                     //Match char exclusion range.
                     if (aSource[0] >= aPattern[0]) and (aSource[0] <= aPattern[2]) then
                     begin
                       //Given char failed set exclusion range.
                       Result := False;
                       Break;
                     end else
                       Inc(aPattern, 3);
                   end else
                   begin
                     //Match individual char exclusion.
                     if (aSource[0] = aPattern[0]) then
                     begin
                       //Given char failed set element exclusion.
                       Result := False;
                       Break;
                     end else
                      Inc(aPattern);
                   end;
                 end;
               end else
               begin
                 //Match for inclusion of given set...
                 Inc(aPattern);
                 Result := False;
                 while (aPattern[0] <> ']') do
                 begin
                   if (aPattern[1] = '-') then
                   begin
                     //Match char inclusion range.
                     if (aSource[0] >= aPattern[0]) and (aSource[0] <= aPattern[2]) then
                     begin
                       //Given char matched set range inclusion.
                       // Continue testing...
                       Result := True;
                       Break;
                     end else
                      Inc(aPattern, 3);
                   end else
                   begin
                     //Match individual char inclusion.
                     if (aSource[0] = aPattern[0]) then
                     begin
                       //Given char matched set element inclusion.
                       // Continue testing...
                       Result := True;
                       Break;
                     end else
                       Inc(aPattern);
                   end;
                 end;
               end;
  
               if (Result) then
               begin
                 //Match was found. Continue further.
                 Inc(aSource);
                 //Position Pattern to char after "]"
                 while (aPattern[0] <> ']') and (aPattern[0] <> #0) do Inc(aPattern);
                 if (aPattern[0] = #0) then
                 begin
                   //Invalid Pattern - missing "]"
                   Result := False;
                   Exit;
                 end else
                   Inc(aPattern);
               end else
                 Exit;
             end;
  
        else begin //Match given single char.
               if (aSource[0] <> aPattern[0]) then
               begin
                 Result := False;
                 Break;
               end;
  
               //Continue testing next char...
               Inc(aSource);
               Inc(aPattern);
             end;
      end;
    end;
  end;
  
  function MatchPattern(const aPattern, aSource: string): Boolean;
  begin
    Result := _MatchPattern(PChar(aPattern), PChar(aSource));
  end;

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved