用来替换 MaskMatch 的通配符比较函数

原创 2004年09月10日 01:08:00
Delphi 提供的通配符匹配函数 TMask.Matches 有些问题:如果通配符字符串太长,比如进入 hotmail 邮箱时的地址有大概250个字符。这会导致 TMask.Matches 函数出错,并导致整个程序崩溃。我在网上找了一些不同的实现,并且做了性能比较。现在我优化过的版本分享出来。
 
type
  TMaskMatchResult = 
record
    Offset: Integer;  
    PatternLength: Integer;
    LeadingFlexibleLength: Integer;
  
end;


function HasWildcardsA(const S: string): Boolean;
var
  I: Integer;
begin
  Result := False;
  
for I := 1 to Length(S) do
    
if S[I] in ['*''?'then
    
begin
      Result := True;
      Exit;
    
end;
end;

// Indicates whether a string matches a wildcard pattern.
function MatchMaskA(const APattern, ASource: string): Boolean;
var
  I: Integer;
begin
  
if APattern = '' then
    Result := ASource = 
''
  
else if ASource = '' then
  
begin
    
for I := 1 to Length(APattern) do
      
if APattern[I] <> '*' then
      
begin
        Result := False;
        Exit;
      
end;
    Result := True;
  
end else
    Result := MatchMaskExA(APattern, ASource).PatternLength = Length(ASource);
end;

// Indicates whether a string matches a wildcard pattern. 
//
When not matched, Result.PatternLength = 0.
function MatchMaskExA(const APattern, ASource: string; Offset: Integer = 1;
 ScanPattern: Boolean = True): TMaskMatchResult;
var
  StringPtr, StringRes, PatternPtr, PatternRes: PChar;
  CountingFlexibleLength: Boolean;
  I: Integer;
begin
  FillChar(Result, SizeOf(Result), 
#0);
  
if Offset < 1 then
    Offset := 
1;

  
if ScanPattern and not HasWildcardsA(APattern) then
  
begin
    
if Offset = PosEx{ANSI only}(APattern, ASource, Offset) then
    
begin
      Result.PatternLength := Length(APattern)
{! >0};
      Result.Offset := Offset;
    
end;
    Exit;
  
end;

  StringPtr := PChar(ASource);
  
if Offset > 1 then
    Inc(StringPtr, Offset - 
1);
  PatternPtr := PChar(APattern);
  StringRes := 
nil;
  PatternRes := 
nil;
  CountingFlexibleLength := (Length(APattern) > 
0and (APattern[1] = '*');
  
repeat
    
repeat // ohne vorangegangenes "*"
      
case PatternPtr^ of
        
#0 : begin
               Result.PatternLength := Length(ASource) + (
1 - Offset) - Length(StringPtr);
               
if Result.PatternLength > 0 then
                 Result.Offset := Offset;
               Exit;
             
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 = nilor (PatternRes = nilthen
                   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.PatternLength := Length(ASource) + (
1 - Offset);
               
if AnsiLastChar(APattern) <> '*' then
                 Dec(Result.PatternLength, Length(StringPtr));
               
if Result.PatternLength > 0 then
                 Result.Offset := Offset;
               
if CountingFlexibleLength then
                 Result.LeadingFlexibleLength := Result.PatternLength;
               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;

    
if CountingFlexibleLength then
    
begin
      Result.LeadingFlexibleLength := Length(ASource) - Offset - Length(StringPtr);
      CountingFlexibleLength := False;
    
end;
  
until False;
end;
 

makefile函数使用 字符串处理函数

一、函数的调用语法 函数调用,很像变量的使用,也是以“$”来标识的,其语法如下: $( ) 或是 ${ } 这里,就是函数名,make支持的函数不多。是函数的参数,参数间以逗号“,”分隔,而...
  • xietingcandice
  • xietingcandice
  • 2014年11月26日 11:40
  • 1070

C++字符串的处理-----全部用库函数,效率高

string定义: a) string s; //生成一个空字符串s string a="eholldfs";     a="dfgdfg";     cin>>a; ...
  • briup_acmer
  • briup_acmer
  • 2014年07月07日 21:57
  • 1313

NSIS文字及字符串函数与头文件介绍

转自 http://hi.csdn.net/jinglidong 文字函数,顾名思义就是处理字符串的函数。使用这些字符串函数前,必须先包含头文件WordFunc.nsh。该头文件目前包含如下...
  • FoxBryant
  • FoxBryant
  • 2013年12月10日 15:40
  • 3367

通配符 校验 C语言 函数库

  • 2009年03月03日 17:51
  • 2KB
  • 下载

关于通配符的所有处理函数

  • 2009年03月04日 15:21
  • 36KB
  • 下载

Word查找和替换通配符.doc

  • 2012年06月06日 00:12
  • 269KB
  • 下载

Word查找和替换通配符完全版

  • 2017年12月27日 22:57
  • 167KB
  • 下载

Word查找和替换通配符

  • 2017年02月22日 09:29
  • 35KB
  • 下载

Word查找替换之代码和通配符一览表

  • 2010年06月18日 09:54
  • 119KB
  • 下载

Word查找替换之代码和通配符一览表

  • 2008年01月12日 12:01
  • 66KB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:用来替换 MaskMatch 的通配符比较函数
举报原因:
原因补充:

(最多只允许输入30个字)