String-Vergleich mit Wildcards

Hier könnt Ihr gute, von Euch geschriebene Codes posten. Sie müssen auf jeden Fall funktionieren und sollten möglichst effizient, elegant und beispielhaft oder einfach nur cool sein.
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8809
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

String-Vergleich mit Wildcards

Beitrag von NicTheQuick »

Hi Leute!

Da gewünscht wurde, dass man bei meiner kleinen Datenbank beim Suchen
auch Wildcards benutzen kann, habe ich mich eben mal rangesetzt und etwas
zusammengeschustert, was nicht schön aussieht, aber funktioniert.

Ein paar Kommentare hätte ich mir wohl mal leisten sollen, aber naja.

Der optionale Suchmasken-Parameter ist für Suchen gedacht, die man immer
wieder mit der selben Suchmaske ausführen will.

///Edit 1:
Added: Nach Remis Idee ist der Code nun auch kompatibel mit UNICODE-Strings.

///Edit 2:
Changed: Jetzt wird das Array nicht mehr gebraucht. Somit ist die
Procedure jetzt speicherschonender und sogar minimal schneller.

Hier ist der Code:

Code: Alles auswählen

Procedure CompareWithWildcards(String.s, StringToFind.s = "")
  Static oldStringToFind.s, max.l
  Static NewList vPart.s()
  Protected *c.Character, p.s = "", a.l, fr.l = #False, *c2.Character, *tmp
 
  Macro Add(zstring)
    If AddElement(vPart()) : vPart() = zstring : max + 1 : EndIf
  EndMacro
 
  If StringToFind = ""
    If oldStringToFind = "" : ProcedureReturn #False : EndIf
    StringToFind = oldStringToFind
  Else
    oldStringToFind = StringToFind
    ClearList(vPart())
    *c = @StringToFind : a = 0 : max = 0
    While *c\c
      If *c\c = '*'
        If a
          If ((Not PeekC(*c - SizeOf(Character)) = '*') And fr) Or max = 0
            If max Or fr : Add(p) : EndIf
            Add("*") : p = ""
            fr = #False
          Else
            p = ""
          EndIf
        Else
          Add("*")
        EndIf
      ElseIf *c\c = '?'
        If fr Or a = 0 : p + Chr(*c\c) : EndIf
      Else
        p + Chr(*c\c)
        fr = #True
      EndIf
      *c + SizeOf(Character) : a + 1
    Wend
   
    If p <> "" : Add(p) : EndIf
    max - 1
  EndIf
 
  a = 0
  *c = @String
  FirstElement(vPart())
  Repeat
    If vPart() = "*"
      If a = max
        ProcedureReturn #True
      EndIf
      *tmp = *c
      NextElement(vPart())
      Repeat
        *c = *tmp
        *c2 = PeekL(@vPart()) ;anders als bei Arrays
        While *c2\c
          If *c\c = 0 : ProcedureReturn #False : EndIf
          If *c2\c <> *c\c And *c2\c <> '?' : Break : EndIf
          *c + SizeOf(Character) : *c2 + SizeOf(Character)
        Wend
        If *c2\c = 0 : Break : EndIf
        *tmp + SizeOf(Character)
      ForEver
      *c = *tmp
    Else
      *c2 = PeekL(@vPart()) ;anders als bei Arrays
      While *c2\c
        If *c\c = 0 : ProcedureReturn #False : EndIf
        If *c2\c <> *c\c And *c2\c <> '?' : ProcedureReturn #False : EndIf
        *c + SizeOf(Character) : *c2 + SizeOf(Character)
      Wend
      If a = max And *c\c : ProcedureReturn #False : EndIf
      NextElement(vPart())
    EndIf
    a + 1
  Until a = max + 1
 
  ProcedureReturn #True
EndProcedure

Debug CompareWithWildcards("May", "*May*")

Debug CompareWithWildcards("Mayer ist schlau", "M??er *schlau*")
Debug CompareWithWildcards("Meyer ist sehr schlauer", "")
Debug CompareWithWildcards("Meier ist ultra schlauer", "")
Debug CompareWithWildcards("Mayar ist ganz schön schlau", "")

text.s="2030501"
Suchmuster.s="??3"
Debug CompareWithWildcards(text, Suchmuster)

text.s="2030501"
Suchmuster.s="*5"
Debug CompareWithWildcards(text, Suchmuster)

text.s="2030501"
Suchmuster.s="*6?1"
Debug CompareWithWildcards(text, Suchmuster)
Zuletzt geändert von NicTheQuick am 23.10.2006 19:33, insgesamt 4-mal geändert.
Benutzeravatar
remi_meier
Beiträge: 1078
Registriert: 29.08.2004 20:11
Wohnort: Schweiz

Beitrag von remi_meier »

Scheint zu funktionieren :allright:
Nur ein kleiner 'Bug': Benutze doch *c+Sizeof(CHARACTER) anstatt *c+1
um auch Unicode zu unterstützen :)
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8809
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Beitrag von NicTheQuick »

DarkDragon hat mich gerade darauf hingewiesen, dass du was gepostet
hast. Das hab ich wohl irgendwie übersehen. /:->

Aber jetzt gibt es oben auch den UNICODE-kompatiblen Code. :allright:
Benutzeravatar
remi_meier
Beiträge: 1078
Registriert: 29.08.2004 20:11
Wohnort: Schweiz

Beitrag von remi_meier »

Super, danke!
Diese Prozedur wird mir sicher einmal die Arbeit erleichtern :allright:
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8809
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Beitrag von NicTheQuick »

Demnächst wollte ich sie noch verbessern, damit man nicht ein Array und
eine LinkedList braucht, sondern nur noch die LinkedList. :)
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8809
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Beitrag von NicTheQuick »

Somit wäre das auch erledigt. Das hatte ich schon so lange vor... (s. 1. Post)
Benutzeravatar
AND51
Beiträge: 5220
Registriert: 01.10.2005 13:15

Beitrag von AND51 »

Bug:

Code: Alles auswählen

Debug CompareWithWildcards("May", "*May*") 
Funktioniert nicht...
PB 4.30

Code: Alles auswählen

Macro Happy
 ;-)
EndMacro

Happy End
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8809
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Beitrag von NicTheQuick »

Aha, ein Übeltäter!

Habs korrigiert.

Das heißt also, dass * auch gar nichts sein kann?
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Beitrag von Kaeru Gaman »

NicTheQuick hat geschrieben:Das heißt also, dass * auch gar nichts sein kann?
yup, sollte es zumindest.
wird nicht in allen interfaces unterstützt, ist aber die bedeutung.
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Antworten