![]() |
Match funktion?
Moin,
hat jemand eine Idee wie ich eine Funktion schreiben könnte die 2 strings auf übereinstimmung prüft? Als Joke sollen * und ? benutzt werden koennen. Das heisst das wenn die Maske z.b: Zitat:
Zitat:
Jemand ne Idee? die MatchesMask() Funktion geht hierfür nicht, da der Joker "?" dort heisst das ein Zeichen vorkommen KANN, aber nicht MUSS.... ich brauch aber das "muss". |
Re: Match funktion?
Eine Möglichkeit wäre, dass man mit einer Schleife bei jedem "*" alle 255 ACII-Codes einsetzt und dann prüft. ;)
|
Re: Match funktion?
Zitat:
![]()
Delphi-Quellcode:
function PathMatchSpec(pszFile, pszSpec: PAnsiChar): bool; stdcall;
const shlwapi = 'shlwapi.dll'; function PathMatchSpec; external shlwapi name 'PathMatchSpecA';
Code:
wobei mich in dem Zusammenhang gleich interessieren würde, ob es eine im .NET Framework eingebaute Möglichkeit gibt. Das Einbinden der API-Funktion (s. zweiter Codeauszug) ist zwar bequem und funktioniert, aber auf lange Sicht ist sie fürs .NET Framework doch eher ungeeignet. Und reguläre Ausdrücke sind gleich ein bisschen zu dick.
[DllImport("shlwapi.dll")]
static extern bool PathMatchSpec(string pwszFile, string pwszSpec); Wie dem auch sei, Anwendungsmöglichkeit:
Delphi-Quellcode:
if PathMatchSpec('blahierstehteinvölligsinnloserstringirgendwas','bla*irgendwas') then
ShowMessage('Passt'); if PathMatchSpec('abc','???') then ShowMessage('Passt'); |
Re: Match funktion?
Hi Mathias,
Also in .NET könntest Du doch einfach mit regulären Ausdrücken arbeiten - so "dick" sind die ja nun auch nicht. Selbst wenn im Ausgangstring nur ein "*" ist, könnte man das doch problemlos in ein "(.*)" umwandeln und damit könnte man auch mit Windows ähnlichen Wildcards arbeiten. mfG mirage228 |
Re: Match funktion?
Moin Mathias,
eine kleine Einschränkung für die "Zweckentfremdung" sollte aber nicht unerwähnt bleiben: Der erste Parameter darf maximal MAX_PATH Byte lang sein (MAX_PATH = 260) |
Re: Match funktion?
Zitat:
Einfach von Regex ableten und eine versteckte statische Liste führen. Der Constructor wird versteckt und nach außen ist nur ein GetInstance sichtbar, dass einen RegEx string schluckt und eine Instanz deiner Klasse auspuckt. Jetzt braucht er in der internen List nur noch eine Regex mit dem string suchen (für die Liste wäre eine HashTable ganz nett ;) ) die Instanz zurückgeben oder eine neue Instanz für den string anlegen, kompilieren ( :!: ), in die Liste schmeißen und zurückgeben. Auf die Art hast du sackschnelle, kompiliere RegEchsen OHNE dass dir die Kompilierung die Zyklen vom Kopf frisst (wird ja nur einmal pro pattern gemacht :) ). |
Re: Match funktion?
Um mal was zu fragen.. ich mag .NET ja auch, und Robert ist ganz klar der Guru ;) Aber.. @Robert, was hast du grade gesagt? :gruebel: Liegts vielleicht daran, das es so spät ist? Ich kapiers irgendwie nicht :(
|
Re: Match funktion?
Zitat:
Dumm ist nur, dass er jede Regex Instanz kompiliert (und nebenbei eine temporäre Assembly anlegt :? ) egal, ob es nicht schon eine kompilierte Regex für dieses pattern gibt. Wenn du eine private statische HashTable (Key: pattern / Value: DeinRegex) führst, kannst du doch darin nachschauen, ob du für dieses pattern schon eine kompilierte Regex "rumliegt". Um zu verhindern, dass du dich aus Versehen an dem Mechanismus vorbeimogelst sollte der Constructor private sein. Öffentlich wäre dann nur ein
Code:
.
public static DeinRegex CreateInstance(string pattern)
Bin gerade etwas in Eile... wenn ich's diesmal nicht genau erklären konnte... Pech gehabt. :P nachtrag: "static" vergessen... |
Re: Match funktion?
Nein, das reicht schon, habs verstanden :kiss:
|
Re: Match funktion?
Moin!
/EDIT: ok, hat sich erledigt - einen kleinen Satz überlesen... MfG Muetze1 |
Re: Match funktion?
Zitat:
...und mein erster Post war eigentlich nur eine Reaktion auf mirages, der auf einen Satz in Mthias' Beitrag reagiert hat... :freak: |
Re: Match funktion?
ohne jetzt wirklich alles gelesen zu haben. Hast du schonmal versucht statt einem ? ein + zu verwenden? Ich meine, das wäre nämlcih für diesen Zweck...
|
Re: Match funktion?
Mit "zu dick" meinte ich, dass ich reguläre Ausdrücke gleich für zu aufwändig halte. In meinem Fall. Außerdem müsste ich dann vermutlich die Syntax meiner XML-Datei ändern (schon wieder :?), weil die Strings aus einer solchen kommen. Darum dachte ich, es gibt vllt. eine einfach Möglichkeit, schnell zwei Strings miteinander zu vergleichen, wenn einer die typischen DOS-Wildcards * und ? benutzt. Ich habe nichts gegen reguläre Ausdrücke, aber in dem Fall wäre es für mich wie "mit Kanonen auf Spatzen ..." ;)
Muss ich Robert jetzt etwa auch küssen? :gruebel: |
Re: Match funktion?
Hi,
ich hab dafür folgenden Code geschrieben, den ich allerdings erst 2 Wochen testen konnte, also ohne Gewähr ;) Für Verbesserungen bin ich jederzeit offen:
Delphi-Quellcode:
Edit: Folgende Funktion wird auch benötigt:
// Erlaubte Wildcards:
// * = alles oder nichts // ? = einzelnes zeichen MUSS vorkommen // # = Zahl MUSS vorkommen function WildCardMatch(const check, mask:string):boolean; var _next_wc:integer; a,b:string; function find_wildcard(const _check:string):integer; begin if (Pos('*',_check) = 0) then if (Pos('?',_check) = 0) then if (Pos('#',_check) = 0) then result:=-1 else result:=Pos('#',_check) else result:=Pos('?',_check) else result:=Pos('*',_check); end; function parse_from_wc(const wildcard, _check:string):boolean; var next_wc,off_set,first_of:integer; t,tmp:string; begin result:=true; if (copy(wildcard,1,1) = '#') then begin if (length(_check) = 0) or (not IsNumber(copy(_check,1,1))) then begin result:=false; exit; end; t:=copy(wildcard,2,length(wildcard)); next_wc:=find_wildcard(t); if (next_wc = -1) then result:=true else begin tmp:=copy(wildcard,2,next_wc-1); if (length(tmp) = 0) then begin result:=false; exit; end else if (IsNumber(copy(_check,1,length(tmp)))) then if (not parse_from_wc(copy(wildcard,next_wc+1,length(wildcard)),copy(_check,next_wc+1,length(_check)))) then begin result:=false; exit; end else else begin result:=false; exit; end; end; end else if (copy(wildcard,1,1) = '?') then begin if (length(_check) = 0) then begin result:=false; exit; end; t:=copy(wildcard,2,length(wildcard)); next_wc:=find_wildcard(t); if (next_wc = -1) then result:=(t = copy(_check,2,length(_check))) else begin tmp:=copy(wildcard,2,next_wc-1); if (length(tmp) = 0) then begin result:=false; exit; end else if (not parse_from_wc(copy(wildcard,next_wc+1,length(wildcard)),copy(_check,next_wc+1,length(_check)))) then begin result:=false; exit; end; end; end else if (copy(wildcard,1,1) = '*') then begin t:=copy(wildcard,2,length(wildcard)); next_wc:=find_wildcard(t); if (next_wc = -1) then begin if (length(_check) >= length(t)) then result:=(copy(_check,1+length(_check)-length(t),length(_check)) = t) else result:=false; exit; end else begin if (next_wc = 0) then begin result:=parse_from_wc(copy(wildcard,2,length(wildcard)),_check); exit; end else begin off_set:=1; tmp:=copy(wildcard,2,next_wc-1); while (true) do begin first_of:=Pos(tmp,copy(_check,off_set,length(_check))); if (first_of = 0) then begin result:=false; exit; end else begin off_set:=first_of+length(tmp); if (parse_from_wc(copy(wildcard,next_wc+2,length(wildcard)), copy(_check,off_set,length(_check)))) then begin result:=true; exit; end; end; end; end; end; end; end; begin if (length(check) = 0) then begin result:=false; exit; end; result:=true; _next_wc:=find_wildcard(mask); if (_next_wc = 0) then result:=parse_from_wc(mask,check) else if (_next_wc = -1) then result:=(check = mask) else begin a:=copy(check,1,_next_wc-1); b:=copy(mask,1,_next_wc-1); if (a <> b) then begin result:=false; exit; end; if (not parse_from_wc(copy(mask,_next_wc,length(mask)-_next_wc+1), copy(check,_next_wc,length(check)-_next_wc+1))) then begin result:=false; exit; end; end; end;
Delphi-Quellcode:
Viel Spaß ;)
function IsNumber(const s:string): Boolean;
var c:integer; const nums:string = '0123456789'; begin result:=(length(s) > 0); for c:=1 to length(s) do if (Pos(copy(s,c,1),nums) = 0) then begin result:=false; Break; end; end; cu |
Re: Match funktion?
Zitat:
![]() ![]() |
Re: Match funktion?
Hi,
@MathiasSimmack: Ich programmiere nicht so gern mit Exceptions, das ist für mich so die Hau-Drauf-Methode à la "Frag ihn nicht ob das eine Platzwunde ist, drück drauf und wenn er schreit ist es eine" ;) Ist die Methode mit Exceptions denn erheblich schneller als meine? cu |
Re: Match funktion?
Was heißt schneller? Es ging nur um die Ziffernerkennung:
Delphi-Quellcode:
ist ebenso elegant wie
try
StrToInt(stringVariable); Result := true; except Result := false; end;
Delphi-Quellcode:
Auf jeden Fall ist beides vermutlich besser als der Weg, den du gewählt hast. :stupid: Zumal deine Funktion bei einer negativen Zahl wie -1,-2, ... versagen würde. ;)
Val(stringVariable, integerVariable, errorCode);
Result := errorCode = 0; |
Re: Match funktion?
Zitat:
Wenn du das ganze Stringkopieren sein lässt und einfach einen PChar auf den Eingabe string legst (Durch den kannst du easy per increment iterieren. ;) ),dürfte auch deine nicht mehr so lagsam sein, bzw. nicht mehr so viel Speicher verbraten. Und wie MS schon sagte... bei deiner gehen nur positive ints. ;) |
Re: Match funktion?
Hi,
gut, mag sein. In meinem Fall will ich aber nur positive Ganzzahlen zulassen, von daher brauch ich die negativen gar nicht zu beachten ;) Wer in den Wildcards auch negative Zahlen zulassen will kann ja den von MathiasSimmack geposteten Vorschlag verwenden. Danke für die Vorschläge, cu |
Re: Match funktion?
danke euch allen :)
Ich hab mich für Mathias Simmacks's Funktion entschieden. @Mathias: Kannst du mir noch erklären, wie bzw warum die funktion 2mal existiert? bzw sie unterteilt ist? Edit: Und kann ich die Funktion irgendwie in eine Klasse packen so das sie von aussen nicht sichtbar ist? Hier:
Delphi-Quellcode:
meint der compiler das external ein feld sei und es damit nicht nach einer funktion erlaubt ist...
TIAL = class(TObject)
private function PathMatchSpec(pszFile, pszSpec: PAnsiChar): bool; stdcall; external 'shlwapi.dll' name 'PathMatchSpecA'; public end; |
Re: Match funktion?
Ich kaper euer Anfangsproblem irgendwie nicht.
Zitat:
Zitat:
Delphi-Quellcode:
oh is schon ok.
if matchesmask('','?') then showmessage('jo')
else showmessage ('nein'); denn das gibt jo aus
Delphi-Quellcode:
if matchesmask('a','??') then showmessage('jo')
else showmessage ('nein'); |
Alle Zeitangaben in WEZ +1. Es ist jetzt 23:16 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz