Entwickler-Ecke
Sonstiges (Delphi) - Stringvergleich mit Wildcards
gispos - Sa 08.12.07 00:36
Titel: Stringvergleich mit Wildcards
Hallo, hat jemand eine gute Routine für Stringvergleich(suchen) mit Wildcards parat?
Wildcards: *?
wenn ja bitte posten
danke gispos
freak4fun - Sa 08.12.07 00:56
Da wirst du wohl auf RegExpress zurückgreifen müssen. ;)
gispos - Sa 08.12.07 21:52
freak4fun hat folgendes geschrieben: |
| Da wirst du wohl auf RegExpress zurückgreifen müssen. ;) |
:?: :?: :?:
Gruß gispos
gispos - So 09.12.07 00:39
Und immer noch :?: :?: :?:
Habe nach einer Routine und nicht nach einem Lexikon gefragt.
Gruß gispos
freak4fun - So 09.12.07 00:44
Soll ich dir dein Programm schreiben oder was willst du? Sag wo dein Problem liegt! Woher soll ich wissen was du genau willst wenn du nur drei Fragezeichen da hast. Bist doch nicht das erste mal in einem Forum unterwegs, oder was?
Atreyu - So 09.12.07 01:13
Prinzipiell würde ich erstmal die Position des * ermitteln. Wenn es am Ende steht, wird der nach dem String VOR dem Wildcard gesucht. Wenn es am Anfang steht, dann eben das dahinter, bzw, ob das dahinter im String drinsteckt.
Lässt sich alles mit gängigen String-Funktionen lösen, auch wenn es etwas kompliziert werden könnte.
Narses - So 09.12.07 02:43
Moin!
Schau mal nach
TREGEXPR, das sollte es sein. ;)
cu
Narses
alzaimar - So 09.12.07 09:47
gispos hat folgendes geschrieben: |
Und immer noch :?: :?: :?:
Habe nach einer Routine und nicht nach einem Lexikon gefragt.
Gruß gispos |
So viel Faulheit (oder Phantasielosigkeit) habe ich hier noch nie gesehen. Selbst meine Tochter weiss damit etwas anzufangen:
1. freak4fun.Posting.Link.Click
2. Eyes.SaveToFile(MyBrain) (Da steht 'regulärer Ausdruck oder RegEx oder RegExp')
3. MyBrain.LoadFromFile (JustSeen)
4. DelphiForm.UseSearch (MyBrain.Contents)
:autsch:
Mods, löscht diesen Beitrag, wenn ihr wollt, aber wenn das gispos wirklich keine Ahnung hätte, wäre er vielleicht nicht so wortkarg gewesen.
gispos - So 09.12.07 14:05
Was soll das hier?
Habe eine ganz einfache Frage nach einer „guten Routine“ gestellt.
freak4fun hat folgendes geschrieben: |
| Da wirst du wohl auf RegExpress zurückgreifen müssen. ;) |
Meine Suche nach RegExpress hatte nichts gebracht. Suchte da natürlich unter Delphi,
zwei Worte mehr dazu hätten sicherlich geholfen. Googel mal nach RegExpress.
Meine Antwort mit
??? war dann in etwa so ausführlich wie der Hinweis
auf RegExpress. Nein, sogar noch aufschlussreicher. Aber dennoch danke für die Mühe.
freak4fun hat folgendes geschrieben: |
Wie ich sowas hasse. :roll:
WIKIPEDIA;) |
Ein Wikipedia zu einer Abhandlung über Stringverarbeitung mit der man seinen
Doktortitel machen könnte…
???
freak4fun hat folgendes geschrieben: |
Soll ich dir dein Programm schreiben oder was willst du? Sag wo dein Problem liegt! Woher soll ich wissen was du genau willst wenn du nur drei Fragezeichen da hast. Bist doch nicht das erste mal in einem Forum unterwegs, oder was?
;) |
Der Reihe nach:
NEIN
Was für Probleme sind hier gemeint?
Habe ich denn keine klare Frage gestellt?
@alzaimar
Möchte hier Dein posting nicht noch einmal zur Schau stellen, deshalb nur
die Frage.
War das ein Ausrutscher?
Und damit das ganze wenigstens etwas Produktives bringt, gibt’s hier zwei bekannte Stringvergleichs-Routinen. Meine Frage nach einer anderen besteht aber Weiterhin.
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 135: 136: 137: 138: 139: 140: 141: 142: 143: 144: 145: 146: 147: 148: 149: 150: 151: 152: 153: 154: 155: 156: 157: 158: 159: 160: 161: 162: 163: 164: 165: 166: 167: 168: 169: 170: 171: 172: 173: 174: 175: 176: 177: 178: 179: 180: 181: 182: 183:
|
function Like(const AString, APattern: String): Boolean; var StringPtr, PatternPtr: PChar; StringRes, PatternRes: PChar; begin Result:=false; StringPtr:=PChar(AString); PatternPtr:=PChar(APattern); StringRes:=nil; PatternRes:=nil; repeat repeat 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 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 CompareWildString(const wild, Name : string) : Boolean; label goback; var w : PChar; n : PChar;
back : array[0..MAXB-1, 0..1] of PChar; s1, s2 : char; bi : integer; begin w := PChar(wild); n := PChar(Name); bi := 0;
while (n^ <> #0) or (w^ <> #0) do begin case w^ of
'*': begin if bi = MAXB then begin raise Exception.CreateFmt('CompareWildString(%s, %s)'#13#10+ 'too many levels of ''*''', [wild, Name]); end; back[bi, 0] := w; back[bi, 1] := n;
Inc(bi); Inc(w); continue;
goback: Dec(bi);
while (bi >= 0) and (back[bi,1]^ = #0) do Dec(bi); if bi < 0 then begin Result := False; Exit; end;
w := back[bi,0]; Inc(w); Inc(back[bi,1]); n := back[bi,1]; Inc(bi); continue; end;
'?': begin if n^ = #0 then begin if bi > 0 then goto goback; Result := False; Exit; end; end;
else begin s1 := n^; s2 := w^;
if s1 <> s2 then begin if bi > 0 then goto goback; Result := False; Exit; end; end; end; if n^ > #0 then Inc(n); if w^ > #0 then Inc(w); end; Result := True; end; |
Gruß gispos
Narses - So 09.12.07 23:07
Moin!
Ich möchte (präventiv) bitten, beim Thema zu bleiben, danke. :)
cu
Narses
Martok - So 09.12.07 23:17
Also, nochmal...
RegExpress war ein Tippfehler, die Dinger heißen RegEx oder Regular Expressions, jedenfalls nicht nur Express. Egal.
Eine Suche hier nach
REGEX oder vielleicht
DELPHI REGEX hätte dich auf verschiedene Units gebacht.
Und jetzt die eigentliche Frage: wenn du schon 2 Routinen hast (von denen Like übrigens ganz nett ist... die verwende ich auch öfter), wozu dann noch eine?
gispos - Mi 12.12.07 00:50
Hallo Martok,
es sind sehr viele Strings die auch mit mehreren Masken durchsucht werden sollen, und da achte ich natürlich auf Geschwindigkeit. Deshalb eben die Suche nach schnellerem, evt. in Assembler.
Danke für die Links
Gruß gispos
alzaimar - Mi 12.12.07 07:21
gispos hat folgendes geschrieben: |
@alzaimar
Möchte hier Dein posting nicht noch einmal zur Schau stellen, deshalb nur
die Frage. War das ein Ausrutscher? |
Mmmpf. So glatt war das doch nicht. Ich stehe jedenfalls noch.
gispos hat folgendes geschrieben: |
| H Deshalb eben die Suche nach schnellerem, evt. in Assembler. |
Das hat mit Assembler nichts zu tun, sondern mit dem Verfahren an sich. Ich würde die vorhandenen RegEx-Verfahren mal hinsichtlich der Performance testen. Reguläre Ausdrücke kann man nämlich gut und schlecht implementieren.
Und nachdem Du Deine Sprache wiedergefunden und sogar Quelltext gepostet hast, würde ich die erste Routine ('Like') als ausreichend empfinden, wenn Du mit dem greedy-Verfahren (finde die längste passende Zeichenkette) zufrieden bist. Assembler bringt hier nichts.
Eventuell könnte die Konstruktion eines endlichen Automaten etwas mehr Performance bringen. Beide Verfahren sind aber vom Aufwand linear, sodaß man schon etwas mehr Gehirnschmalz (modifiziertes Knuth-Morris-Pratt-Verfahren, würde ich tippen) aufwenden müsste, um die Performance zu steigern. DAS widerum bringt aber nur etwas, wenn sowohl Suchstring als auch zu durchsuchender Text etwas länger sind.
Aber auch wenn die zu suchenden regulären Ausdrücke konstant sind (du sucht z.B. nach 10 verschiedenen Ausdrücken in 100000 Strings), würde sich ein KMP eignen, denn der eigentliche Overhead entsteht in der Konstruktion eines endlichen Automaten (allerdings ist der nichtdeterministisch).
Und bezüglich deiner anfänglichen Kritik am Inhalt des Wikipedia-Artikels, würde ich dir empfehlen, dir die Kentnisse anzueignen, die nötig sind, um einen Artikel dieser Kajüte nicht mehr als Doktorarbeit anzusehen. Als Informatiker bzw. Softwareentwickler sollte man soetwas schon verstehen, zumindest im Ansatz. Gute Bücher über Algorithmen gibt es zuhauf.
gispos - Do 13.12.07 22:02
Lieber alzaimar,
danke für deine Umfangreichen Informationen. Möchte mich kurz fassen, da die Moderatoren mich schon mal darauf hingewiesen hatten (Bitte beim Thema bleiben).
Kommt eben immer darauf an, wozu man Lust hat seine Zeit zu investieren, wie bei jedem Programmierer sind da schon Tage, Wochen oder Monate in diverse Routinen investiert worden. Der Hinweis auf Wikipedia ist ja ganz schön wenn man vor hat sich mit der Materie intensiver zu beschäftigen, aber ich möchte meine begrenzte Zeit dann lieber in andere Bereiche investieren, die meinem aktuellen Projekt mehr zugute kommen.
Also noch mal danke für deine Erläuterungen, und vielleicht war ja meine Antwort
mit ??? doch etwas zu übertrieben. :oops:
Gruß gispos
alzaimar - Fr 14.12.07 07:14
gispos hat folgendes geschrieben: |
Lieber alzaimar,
Kommt eben immer darauf an, ... aber ich möchte meine begrenzte Zeit dann lieber in andere Bereiche investieren, die meinem aktuellen Projekt mehr zugute kommen. |
Hier sind aber Hintergrundinformationen nicht nur hilfreich, sondern eher von Nöten, denn ohne Grundkenntnisse wird man kaum mit regEx arbeiten können.
gispos hat folgendes geschrieben: |
| ... vielleicht war ja meine Antwort mit ??? doch etwas zu übertrieben. :oops: |
:shock:
Untertrieben, nicht
übertrieben. Will sagen: Nächstes mal Frage und Antwort ausführlicher.
Nix für ungut.
gispos - So 16.12.07 09:23
alzaimar hat folgendes geschrieben: |
:shock: Untertrieben, nicht übertrieben. Will sagen: Nächstes mal Frage und Antwort ausführlicher.
|
Die Frage war klar gestellt.
Dachte nicht dass drei Fragezeichen solche Reaktionen hervorrufen.
@freak4fun Sorry. :cry:
alzaimar hat folgendes geschrieben: |
Hier sind aber Hintergrundinformationen nicht nur hilfreich, sondern eher von Nöten, denn ohne Grundkenntnisse wird man kaum mit regEx arbeiten können.
|
Da RegEx für mein aktuelles Projekt nicht das passende ist, erspare ich mir dies. :wink:
Habe aber noch eine Interessante Alternative gefunden, bei der auch Argumente mit übergeben werden können.
So kann z.B. auch eine „AND NOT“ Maske erstellt werden: *Der [^Rosen]Krieg* hier wird „Rosen“ als NOT argumentiert. Nur ist diese Routine 70 – 120% langsamer als „Like“.
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 135: 136: 137: 138: 139: 140: 141: 142: 143: 144: 145: 146: 147: 148: 149: 150: 151: 152: 153: 154: 155:
|
function MatchPattern(InpStr,Pattern: PChar): Boolean; begin Result:= True; while(True) do begin case Pattern[0] of #0 :begin Result := (InpStr[0] = #0); Exit; end;
'*':begin if(Pattern[1] = #0)then begin Result := True; Exit; end else Inc(Pattern);
while(InpStr[0] <> #0)do begin if(MatchPattern(InpStr,Pattern))then begin Result := True; Exit; end;
Inc(InpStr); end; end;
'?':begin if(InpStr[0] = #0)then begin Result := False; Exit; end;
Inc(InpStr); Inc(Pattern); end;
'[':begin if(Pattern[1] in [#0,'[',']']) then begin Result := False; Exit; end;
if(Pattern[1] = '^')then begin Inc(Pattern,2); Result := True; while(Pattern[0] <> ']')do begin if(Pattern[1] = '-')then begin if(InpStr[0] >= Pattern[0])and(InpStr[0] <= Pattern[2])then begin Result := False; Break; end else Inc(Pattern,3); end else begin if(InpStr[0] = Pattern[0])then begin Result := False; Break; end else Inc(Pattern); end; end; end else begin Inc(Pattern); Result := False; while(Pattern[0] <> ']')do begin if(Pattern[1] = '-')then begin if(InpStr[0] >= Pattern[0])and(InpStr[0] <= Pattern[2])then begin Result := True; Break; end else Inc(Pattern,3); end else begin if(InpStr[0] = Pattern[0])then begin Result := True; Break; end else Inc(Pattern); end; end; end;
if(Result)then begin Inc(InpStr);
while(Pattern[0] <> ']')and(Pattern[0] <> #0)do Inc(Pattern);
if(Pattern[0] = #0)then begin Result := False; Exit; end else Inc(Pattern); end else Exit; end;
else begin if(InpStr[0] <> Pattern[0])then begin Result := False; Break; end;
Inc(InpStr); Inc(Pattern); end; end; end; end; |
Gruß gispos
GTA-Place - So 16.12.07 09:30
Das ist nichts anderes als eine abgespeckte Version von RegEx.
gispos - So 16.12.07 09:53
GTA-Place hat folgendes geschrieben: |
| Das ist nichts anderes als eine abgespeckte Version von RegEx. |
Ah ja, hatte ich nicht gewusst, kommt aber der Größe wegen für mich eher in frage.
Gruß gispos
alzaimar - So 16.12.07 11:46
Größe ist nicht äquivalent mit Performance.
Ich würde immer noch:
1. Genau umreißen, was ich (heute, und vielleicht in Zukunft) will.
2. Verstehen, wie man mit regulären Ausdrücken arbeitet.
3. Entscheiden, ob RegEx das Richtige für mich ist.
4. Unabhängig von der Größe die unterschiedlichen Implementierungen hinsichtlich der Performance testen.
Ich hab z.B. einen sehr schnellen Stringmatchingalgorithmus gesucht und habe mich zwangsweise durch die Materie durchgearbeitet, eben weil genügend performante Lösungen für Delphi nicht vorhanden sind, bzw. waren.
Nun habe ich erstens einigermaßen Grundwissen über die Techniken und eine Stringmatching-Klasse, die alle gängigen Verfahren schlägt, auch die bei FastCode.org. DAS ist mein optimales Ergebnis.
Das Leben hat folgendes geschrieben: |
| Qualität muss man sich erarbeitem. Sowas gibts nicht auf dem Präsentierteller |
gispos hat folgendes geschrieben: |
| Die Frage war klar gestellt. |
Nö. Wildcards sind z.B. '*' und '?', da reicht auch Delphi. Was Du *genau* benötigst, hast Du uns immer noch nicht verraten. Welche Strings suchst Du, warum, etc. Mittlerweile ist mir das aber auch wurscht.
Und eigentlich will ich nur nochmal sticheln :zwinker: , nänänänänääänää. :mrgreen:
gispos - Di 18.12.07 16:41
@alzaimar > Wie jeder 2. Beitrag in diesem Forum von Dir,
überflüssig, stichelig oder ohne konkrete Hilfe und nur grob Umrissen.
Bei mir war’s ein Ausrutscher, bei Dir scheint’s aber notorisch zu sein.
Deshalb: Halt Dich am besten fern von mir, erzähl deine Weißheiten deinem Friseur! 8)
inc(@alzaimar.MeinEgo)
Aua Full.
Auf nimmer wiederlesen
gispos
alzaimar - Di 18.12.07 17:48
gispos hat folgendes geschrieben: |
| @alzaimar > Wie jeder 2. Beitrag in diesem Forum von Dir, |
Zähl doch nochmal genau nach. Sind ja doch Einige.
gispos hat folgendes geschrieben: |
| inc(@alzaimar.MeinEgo) Aua Full. |
Aber persönlich muss man dann doch nicht werden. Dein Niveau ist das Denkmal Deines Verstandes.
gispos hat folgendes geschrieben: |
| Auf nimmer wiederlesen. |
Ob sich das vermeiden lässt?
Mal im Ernst. Du scheinst beratungsresistent zu sein. Eben gibst du noch zu, das deine Frage und auch die Antwort etwas zu kurz war und bloß weil ich das noch mal betont und mit einem Schmunzel-Icon (für alle, die nicht mal lesen können) versehen habe, wirst Du hier beleidigend. DU hast dich daneben benommen und erstmal alle angepisst, um dann halb zurückzurudern ("Aber die Frage war präzise"). Das war sie aber nicht. Punkt.
Und wer meint, Grundlagen bringen nix, der ist entweder überheblich, dumm, oder Beides. Es kann auch noch eine vierte Möglichkeit geben, aber die fällt mir nicht ein.
Ich werde Dir auch in Zukunft -außer Du erwähnst explizit, das du Hilfe benötigst, aber nicht vom Alz- gerne mit Rat und Tat zur Seite stehen. Ob Du meine Ratschläge annimmst, sei Dir überlassen.
Vorweihnachtliche Grüße aus Berlin.
Und immer locker bleiben.
Narses - Di 18.12.07 18:03
Moin!
Ich mache hier erstmal zu, da vermutlich keine weitere fachliche Erkenntnis zu erwarten ist. ;) So jemand noch was zum Thema beitragen möchte (wie oben bereits angemahnt), bitte Kontakt über den VA aufnhemen. :)
cu
Narses
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2026 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!