Einzelnen Beitrag anzeigen

Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.063 Beiträge
 
Delphi 12 Athens
 
#3

Re: Stringvergleich mit Wildcards

  Alt 13. Dez 2008, 00:19
für die CodeLibMods: Stringvergleich mit Wildcards (* und ?)


@Willie:
deiner Beschreibung nach, hab ich also mit Ha*rg arge Probleme?

Was sind die "noch mehr Möglichkeiten"?

Ja und bei den Modi versteh ich die Beschreibung nicht ganz ... was macht demnach die 2?
*nicht in den QuellCode guck*



Und bezüglich des GOTOs ... IfThen, Repeat und While sind sind auch nur GOTOs (von Seite des Prozessors / in ASM).
Man muß hierbei halt nur besser aufpassen, da der Programmablauf recht unübersichtlich und fehleranfällig sein kann.


[edit 20.06.2009]
* neues/zweites CompareWildEx eingefügt
* und fitt für D2009 gemacht
* ganz aktuelle Version, siehe Post #25
[/edit]


gern nochma von mir
Delphi-Quellcode:
Type TCompareFlags = Set of (cfNotCaseSensitive, cfCanMask);

Function CompareWildString (Wild, Name: String; Flags: TCompareFlags = []): Boolean;
Function CompareWildText(Const Wild, Name: String; Flags: TCompareFlags = []): Boolean;
Function CompareWildStringEx (Wild, Name: String; Flags: TCompareFlags = []): TStringDynArray; Overload;
Function CompareWildStringEx (Wild, Name: String; Flags: TCompareFlags; Offset: Integer; Out EndOffset: Integer): TStringDynArray; Overload;

Function CompareWildString(Wild, Name: String; Flags: TCompareFlags = []): Boolean;
  Var W, N, We, Ne, WildW, WildN: PChar;

  Label goWild, goElse;

  Begin
    If cfNotCaseSensitive in Flags Then Begin
      Wild := LowerCase(Wild);
      Name := LowerCase(Name);
    End;
    Result := False;
    W := PChar(Wild); We := W + Length(Wild); WildW := nil;
    N := PChar(Name); Ne := N + Length(Name); WildN := nil;
    While (W < We) or (N < Ne) do Begin
      Case W^ of
        '*': Begin
          While W^ = '*do Inc(W);
          WildW := W;
          WildN := N + 1;
          Continue;

          goWild:
          W := WildW;
          N := WildN;
          Inc(WildN);
          If (W = nil) or (N > Ne) Then Exit;
          Continue;
        End;
        '?': If N >= Ne Then GoTo goWild;
        '\': Begin
          If (cfCanMask in Flags) and ((W + 1)^ in ['*', '?', '\']) Then Inc(W);
          GoTo goElse;
        End;
        Else
          goElse:
          If N^ <> W^ Then GoTo goWild;
      End;
      If (W >= We) or (N >= Ne) Then GoTo goWild;
      Inc(W);
      Inc(N);
    End;
    Result := True;
  End;

Function CompareWildText(Const Wild, Name: String; Flags: TCompareFlags = []): Boolean;
  Begin Result := CompareWildString(Wild, Name, Flags + [cfNotCaseSensitive]); End;

Function CompareWildStringEx(Wild, Name: String; Flags: TCompareFlags = []): TStringDynArray;
  Var W, N, We, Ne, WildW, WildN: PChar;
    WildLA, WildLS, i: Integer;
    isWild: Boolean;

  Label goWild, goElse;

  Begin
    If cfNotCaseSensitive in Flags Then Begin
      Wild := LowerCase(Wild);
      Name := LowerCase(Name);
    End;
    Result := nil;
    WildLA := 0; WildLS := 0;
    isWild := False;
    W := PChar(Wild); We := W + Length(Wild); WildW := nil;
    N := PChar(Name); Ne := N + Length(Name); WildN := nil;
    While (W < We) or (N < Ne) do Begin
      Case W^ of
        '*': Begin
          While W^ = '*do Inc(W);
          WildW := W;
          WildN := N + 1;
          If not isWild Then SetLength(Result, Length(Result) + 1);
          i := Length(Result);
          WildLA := i;
          WildLS := Length(Result[i - 1]);
          isWild := True;
          Continue;

          goWild:
          W := WildW;
          N := WildN;
          Inc(WildN);
          If (W = nil) or (N > Ne) Then Begin
            Result := nil;
            Exit;
          End;
          SetLength(Result, WildLA);
          Result[WildLA - 1] := Copy(Result[WildLA - 1], 1, WildLS) + (N - 1)^;
          Inc(WildLS);
          isWild := True;
          Continue;
        End;
        '?': Begin
          If N >= Ne Then GoTo goWild;
          If not isWild Then SetLength(Result, Length(Result) + 1);
          i := High(Result);
          Result[i] := Result[i] + N^;
          isWild := True;
        End;
        '\': Begin
          If (cfCanMask in Flags) and ((W + 1)^ in ['*', '?', '\']) Then Inc(W);
          GoTo goElse;
        End;
        Else
          goElse:
          If N^ <> W^ Then GoTo goWild;
          isWild := False;
      End;
      If (W >= We) or (N >= Ne) Then GoTo goWild;
      Inc(W);
      Inc(N);
    End;
    If Result = nil Then SetLength(Result, 1);
  End;

Function CompareWildStringEx(Wild, Name: String; Flags: TCompareFlags; Offset: Integer; Out EndOffset: Integer): TStringDynArray;
  Var W, N, We, Ne, WildW, WildN: PChar;
    WildLA, WildLS, i: Integer;
    isWild: Boolean;

  Label goWild, goElse;

  Begin
    If cfNotCaseSensitive in Flags Then Begin
      Wild := LowerCase(Wild);
      Name := LowerCase(Name);
    End;
    Result := nil;
    EndOffset := Offset;
    Dec(Offset);
    If Offset >= Length(Name) Then Exit
    Else If Offset < 0 Then Offset := 0;
    WildLA := 0; WildLS := 0;
    W := PChar(Wild); We := W + Length(Wild); WildW := nil;
    N := PChar(Name) + Offset; Ne := N + Length(Name) - Offset; WildN := nil;
    isWild := False;
    While (W < We) or (N < Ne) do Begin
      Case W^ of
        '*': Begin
          While W^ = '*do Inc(W);
          WildW := W;
          WildN := N + 1;
          If not isWild Then Begin
            EndOffset := N - PChar(Name) + 1;
            SetLength(Result, Length(Result) + 1);
          End;
          i := Length(Result);
          WildLA := i;
          WildLS := Length(Result[i - 1]);
          isWild := True;
          Continue;

          goWild:
          W := WildW;
          N := WildN;
          Inc(WildN);
          If (W = nil) or (N > Ne) Then Begin
            Result := nil;
            Exit;
          End;
          SetLength(Result, WildLA);
          Result[WildLA - 1] := Copy(Result[WildLA - 1], 1, WildLS) + (N - 1)^;
          Inc(WildLS);
          isWild := True;
          Continue;
        End;
        '?': Begin
          If N >= Ne Then GoTo goWild;
          EndOffset := N - PChar(Name) + 1;
          If not isWild Then SetLength(Result, Length(Result) + 1);
          i := High(Result);
          Result[i] := Result[i] + N^;
          isWild := True;
        End;
        '\': Begin
          If (cfCanMask in Flags) and ((W + 1)^ in ['*', '?', '\']) Then Inc(W);
          GoTo goElse;
        End;
        Else
          goElse:
          If N^ <> W^ Then GoTo goWild;
          isWild := False;
      End;
      If (W >= We) or (N >= Ne) Then GoTo goWild;
      Inc(W);
      Inc(N);
    End;
    If Result = nil Then SetLength(Result, 1);
  End;
cfNotCaseSensitive sollte klar sein (klingt zwar ein bissl blöd, aber da CaseSensitive Standard ist...)

bei cfCanMask kann mit einem vorrangestellem "\" das "*" oder "?" maskiert werden und in diesem Fall natürlich auch das "\" (sich selbst).
Code:
Maske      String

test*123  = test0123
test\*123 = test*123
CompareWildStringEx liefert nicht TRUE bei erfolgreichem Vergleich, sondern die in den WildCards enthaltenen Zeichen/Strings.

Delphi-Quellcode:
Program Project1;

{$APPTYPE CONSOLE}

Uses Types, SysUtils, WildCards;

Var A: TStringDynArray;
  i: Integer;

Begin
  WriteLn('Maske = String Ergebnis');

  WriteLn;
  WriteLn('te*23 = test0123 ', CompareWildString('te*23', 'test0123'));
  WriteLn('te\*23 = test0123 ', CompareWildString('te\*23', 'test0123', [cfCanMask]));
  WriteLn('te\*23 = te*23 ', CompareWildString('te\*23', 'te*23', [cfCanMask]));

  WriteLn;
  WriteLn('te*23 = test0123');
  A := CompareWildStringEx('te*23', 'test0123');
  For i := 0 to High(A) do WriteLn(' [', i, '] = ', A[i]);

  WriteLn;
  WriteLn('te*23?56*9 = test0123456789');
  A := CompareWildStringEx('te*23?56*9', 'test0123456789');
  For i := 0 to High(A) do WriteLn(' [', i, '] = ', A[i]);

  WriteLn;
  WriteLn('te*23 = test012');
  A := CompareWildStringEx('te*23', 'test012');
  WriteLn(' nil = ', A = nil);
  WriteLn(' Length = ', Length(A));

  WriteLn;
  WriteLn;
  WriteLn('Beenden mit [Enter]');
  ReadLn;
End.
Code:
Maske = String    Ergebnis

te*23  = test0123   TRUE
te\*23 = test0123   FALSE
te\*23 = te*23      TRUE

te*23  = test0123
   [0] = st01

te*23?56*9  = test0123456789
   [0] = st01
   [1] = 4
   [2] = 78

te*23  = test012
   nil   = TRUE
   Length = 0
[edit 22.06.2009]
Anhang entfernt > aktuelle Version siehe Beitrag #26
Neuste Erkenntnis:
Seit Pos einen dritten Parameter hat,
wird PoSex im Delphi viel seltener praktiziert.
  Mit Zitat antworten Zitat