Seite 2 von 4

Re: Funktion, die Platzhalter ("*" und "?") in String prüft

Verfasst: 25.07.2011 00:13
von c4s
Danke schonmal! Bin jetzt aber doch weiter am probieren mit deinem Code. :wink:

Ich brauche es eigentlich genauso wie bspw. bei der Windows-Suche: Der Benutzer gibt den String ein und dann wird dieser mit einem Text (z.B. Dateipfad) verglichen.

"#" habe ich bereits eingebaut. Einfach folgendes in den Select-Block bei Pattern_Find() hinzufügen:

Code: Alles auswählen

Case '#'  ; Wildcard for exactly one number
	If *String\c[StringIndex + PatternIndex] < 48 Or *String\c[StringIndex + PatternIndex] > 57
		Break 2
	EndIf
Nun war ich gerade dabei noch eine Procedure zu erstellen, die mir ähnlich wie RegEx einfach #True bzw. #False zurückgibt - Je nachdem ob String und Pattern zusammenpassen. Hier mein erster Anfang dazu:

Code: Alles auswählen

Procedure StringPatternMatch(String.s, Pattern.s)
	Protected Position, FoundLength
	Protected Result = #False

	Position = FindPattern(String, Pattern, 1, @FoundLength)
	If Position = 1
		If FoundLength = Len(String)  ;!!! FoundLength ist unzuverlässig!
			Result = #True
		EndIf
	EndIf

	ProcedureReturn Result
EndProcedure
...Dabei ist mir aber die Frage gekommen was FoundLength eigentlich zurückgibt? Nach meinem Verständnis sollte bei dem String "Beispiel123.exe" und dem Pattern "*" 15 herauskommen - was auch der Fall ist. Der Pattern "*.*" ergibt jedoch 16, "?*?" ist 1 und "?ei*###.*" ist 19 (mit der obigen Nummernerweiterung). Hast du eine Idee woran das liegt?


Bisschen Offtopic:
Nach welcher Regel schreibst du eigentlich "StringIndex+PatternIndex" oder "Number + 7"? Es geht mir ums setzten der Leerzeichen.
Mich interessiert es, weil ich mir mittlerweile angewöhnt habe, zwischen Allem Leerzeichen zu setzen. Aber dein Stil erscheint mir sinnvoller und z.T. übersichtlicher, obwohl ich in gewissen Teilen keine Logik dahinter finden kann... deshalb frage ich. :wink:

Re: Funktion, die Platzhalter ("*" und "?") in String prüft

Verfasst: 25.07.2011 01:38
von STARGÅTE
"Nun war ich gerade dabei noch eine Procedure zu erstellen,
die mir ähnlich wie RegEx einfach #True bzw. #False zurückgibt -
Je nachdem ob String und Pattern zusammenpassen."


Aber das hatte ich doch schon drin: FindPattern()
Wo du den String, das Muster übergibst. Zurück bekommst du wie bei FindString die Position der Fundstelle.
Aber wie ich sehe, wolltest du ja zusätzlich, dass der String voll umschlossen wird, dann ist deins natürlich richtig.

"Dabei ist mir aber die Frage gekommen was FoundLength eigentlich zurückgibt? Nach meinem Verständnis sollte bei dem String "Beispiel123.exe" und dem Pattern "*" 15 herauskommen - was auch der Fall ist. Der Pattern "*.*" ergibt jedoch 16, "?*?" ist 1 und "?ei*###.*" ist 19 (mit der obigen Nummernerweiterung). Hast du eine Idee woran das liegt?"

Auf die schnelle konnte ich das Problem noch nicht beheben, aber es liegt an der Schachtelung, werde mich darum kümmern und so schnell wie möglich ein Update posten.

"Nach welcher Regel schreibst du eigentlich "StringIndex+PatternIndex" oder "Number + 7"? Es geht mir ums setzten der Leerzeichen."

Also: Ich setzten immer ein Leerzeichen vor/nach einem Operator außer:
- er befindert sich innerhalb eines Array-Indizes (Platzgründe)
- er befindet sich ein einer komplexeren Rechung (Vorrangregel->"ennger") : A + B*C , A * (B+C)

Re: Funktion, die Platzhalter ("*" und "?") in String prüft

Verfasst: 25.07.2011 03:15
von STARGÅTE
Nach langen hin und her habe ich nun eine neue funktionsfähige Version.
Detailinformation:
Mein Code war vorher "faul", dass heißt B*e war für ihn gleich Beispiel ohne noch Beispiel zu finden.
Das ist nun "abgeschaltet". Das heißt, die Prozedur geht nun alle möglichkeiten durch.

Hinweis an die nutzer: Mit bedacht das * einsetzten. (*** wird aber zu * gekürtzt)

Der Code arbeitet nun so wie du wolltest, die Tests waren bisher alle erfolgreich.

Code: Alles auswählen

Structure CharacterArray
	c.c[0]
EndStructure

Global *LowCaseCharacter.CharacterArray = ?LowCaseCharacter

Procedure Pattern_Find(*String.CharacterArray, *Pattern.CharacterArray, *FoundLength.Integer=#Null)
	
	Protected StringIndex.i, PatternIndex.i, Position.i, TempPosition.i
	Protected FoundLength.i, TempFoundLength.i, BestFoundLength.i
	
	While *String\c[StringIndex]
		Repeat
			While *Pattern\c[PatternIndex]
				Select *Pattern\c[PatternIndex]
					Case '?' ; Platzhalter für genau ein Zeichen
						If *String\c[StringIndex+PatternIndex] = ''
							Break 2 ; Unpassend
						EndIf
					Case '#' ; Platzhalter für genau eine Zahl
						If *String\c[StringIndex+PatternIndex] < '0' Or *String\c[StringIndex+PatternIndex] > '9'
							Break 2 ; Unpassend
						EndIf 
					Case '*' ; Platzhalter für eine beliebige Anzahl von Zeichen (auch keins)
						While *Pattern\c[PatternIndex+1] = '*'
							PatternIndex + 1
							FoundLength + 1
						Wend
						Position = 0
						BestFoundLength = 0
						Repeat
							TempPosition = Pattern_Find(@*String\c[StringIndex+PatternIndex+Position], @*Pattern\c[PatternIndex+1], @TempFoundLength)
							TempFoundLength + FoundLength
							Position + TempPosition
							If Not TempPosition
								If BestFoundLength
									FoundLength = BestFoundLength
									Break 2 ; Passend
								Else
									Break 3 ; Unpassend
								EndIf
							Else
								TempFoundLength + Position-1
								If *Pattern\c[PatternIndex+1] = ''
									While *String\c[StringIndex+TempFoundLength]
										TempFoundLength + 1
									Wend
								EndIf
								If TempFoundLength > BestFoundLength
									BestFoundLength = TempFoundLength
								EndIf
							EndIf
						ForEver
					Default ; Beliebiges anderes Zeichen
						If *LowCaseCharacter\c[*String\c[StringIndex+PatternIndex]] <> *LowCaseCharacter\c[*Pattern\c[PatternIndex]]
							Break 2 ; Unpassend
						EndIf
				EndSelect
				PatternIndex + 1
				FoundLength + 1
			Wend
			If *FoundLength
				*FoundLength\i = FoundLength
			EndIf
			ProcedureReturn StringIndex+1
		Until #True
		PatternIndex = 0
		StringIndex + 1
		FoundLength = 0
	Wend
	
EndProcedure

DataSection
	LowCaseCharacter:
	Data.c $00, $01, $02, $03, $04, $05, $06, $07, $08, $09, $0A, $0B, $0C, $0D, $0E, $0F
	Data.c $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $1A, $1B, $1C, $1D, $1E, $1F
	Data.c $20, $21, $22, $23, $24, $25, $26, $27, $28, $29, $2A, $2B, $2C, $2D, $2E, $2F
	Data.c $30, $31, $32, $33, $34, $35, $36, $37, $38, $39, $3A, $3B, $3C, $3D, $3E, $3F
	Data.c $40, $61, $62, $63, $64, $65, $66, $67, $68, $69, $6A, $6B, $6C, $6D, $6E, $6F
	Data.c $70, $71, $72, $73, $74, $75, $76, $77, $78, $79, $7A, $5B, $5C, $5D, $5E, $5F
	Data.c $60, $61, $62, $63, $64, $65, $66, $67, $68, $69, $6A, $6B, $6C, $6D, $6E, $6F
	Data.c $70, $71, $72, $73, $74, $75, $76, $77, $78, $79, $7A, $7B, $7C, $7D, $7E, $7F
	Data.c $80, $81, $82, $83, $84, $85, $86, $87, $88, $89, $9A, $8B, $9C, $8D, $9E, $8F
	Data.c $90, $91, $92, $93, $94, $95, $96, $97, $98, $99, $9A, $9B, $9C, $9D, $9E, $FF
	Data.c $A0, $A1, $A2, $A3, $A4, $A5, $A6, $A7, $A8, $A9, $AA, $AB, $AC, $AD, $AE, $AF
	Data.c $B0, $B1, $B2, $B3, $B4, $B5, $B6, $B7, $B8, $B9, $BA, $BB, $BC, $BD, $BE, $BF
	Data.c $E0, $E1, $E2, $E3, $E4, $E5, $E6, $E7, $E8, $E9, $EA, $EB, $EC, $ED, $EE, $EF
	Data.c $F0, $F1, $F2, $F3, $F4, $F5, $F6, $D7, $F8, $F9, $FA, $FB, $FC, $FD, $FE, $DF
	Data.c $E0, $E1, $E2, $E3, $E4, $E5, $E6, $E7, $E8, $E9, $EA, $EB, $EC, $ED, $EE, $EF
	Data.c $F0, $F1, $F2, $F3, $F4, $F5, $F6, $F7, $F8, $F9, $FA, $FB, $FC, $FD, $FE, $FF
EndDataSection

Procedure StringPatternMatch(String.s, Pattern.s)
	
	Protected Position, FoundLength
	Protected Result = #False
	
	Position = Pattern_Find(@String, @Pattern, @FoundLength)
	If Position = 1 And FoundLength = Len(String)
		ProcedureReturn #True
	EndIf
	
EndProcedure 


;- Beispiel

Debug StringPatternMatch("Beispiel123.exe", "*.*")
Debug StringPatternMatch("Beispiel123.exe", "?*?")
Debug StringPatternMatch("Beispiel123.exe", "?ei*###.*")
Debug StringPatternMatch("Beispiel123.exe", "*.?*")
PS: Bin nun müde, optimieren tue ich "nachher"

Re: Funktion, die Platzhalter ("*" und "?") in String prüft

Verfasst: 25.07.2011 10:57
von c4s
Huiuiui, bin ganz aufgeregt. Gleichmal testen. <)
STARGÅTE hat geschrieben:Also: Ich setzten immer ein Leerzeichen vor/nach einem Operator außer:
- er befindert sich innerhalb eines Array-Indizes (Platzgründe)
- er befindet sich ein einer komplexeren Rechung (Vorrangregel->"ennger") : A + B*C , A * (B+C)
Danke für die Erläuterung. Ich glaube in deinem vorherigen Code war dann ein Fehler bzw. Regelbruch, der mich verwirrte.
STARGÅTE hat geschrieben:PS: Bin nun müde
Eine Münze schlaf hast du dir aber nun auch wirklich verdient. :allright:

Re: Funktion, die Platzhalter ("*" und "?") in String prüft

Verfasst: 26.07.2011 12:12
von c4s
Ich habe StringPatternMatch() ein bisschen erweitert, damit der Vergleich von zwei leeren Strings (bzw. Pattern enthält nur "*") auch #True ergibt:

Code: Alles auswählen

Procedure StringPatternMatch(String.s, Pattern.s)
	Protected Position, FoundLength
	Protected Result

	Position = StringPatternFindMemory(@String, @Pattern, @FoundLength)
	If Position = 1 And FoundLength = Len(String)
		Result = #True  ; Found at first position and equals entire string
	ElseIf String = RemoveString(Pattern, "*")
		Result = #True  ; Both are empty or pattern only contains "*"
	Else
		Result = #False  ; No match
	EndIf

	ProcedureReturn Result
EndProcedure
Wichtig: Außerdem ist es besser die ganze *LowCaseCharacter-Sache aus Pattern_Find() herauszunehmen, da die Unicode-Zeichen damit sowieso nicht abgedeckt werden!


@STARGÅTE
Ich denke du solltest deinen Code in "Tipps und Tricks" posten, damit er hier nicht untergeht.

Re: Funktion, die Platzhalter ("*" und "?") in String prüft

Verfasst: 26.07.2011 12:56
von STARGÅTE
"Wichtig: Außerdem ist es besser die ganze *LowCaseCharacter-Sache aus Pattern_Find() herauszunehmen, da die Unicode-Zeichen damit sowieso nicht abgedeckt werden!"
Das ist richtig, ich hatte es damals drin, damit ich unabhängig von groß/klein vergleichen kann ohne auf die String-Funktion LCase zugreifen zu müssen.
Da man aber eh nichts ersetzen will, kann man nun auch gleich am anfang (wenn gewollt) LCase() auf beide Strings anwenden.

"Ich denke du solltest deinen Code in "Tipps und Tricks" posten, damit er hier nicht untergeht."
Kann ich machen, wenn ich ihn dann "fertig" habe.

Re: Funktion, die Platzhalter ("*" und "?") in String prüft

Verfasst: 26.07.2011 13:52
von NicTheQuick
Ich hatte auch mal eine Funktion dafür programmiert. Diese scheint auch noch zu funktionieren: CompareWithWildcards

Re: Funktion, die Platzhalter ("*" und "?") in String prüft

Verfasst: 09.08.2011 23:27
von c4s
@STARGÅTE
Ich ärgere mich hier die ganze Zeit mit einem Fehler herum und hatte erst gerade eben festgestellt, dass der Code gar nicht mit Unicode funktioniert! Ich war mir zwar sicher, dass ich ihn bereits vor einiger Zeit erfolgreich darauf geprüft hatte, aber dem war wohl nicht so.

Hast du einen Tipp, wie ich ihn Unicode-Kompatibel machen kann?

Auf die Schnelle fällt mir nur ein alle Stellen mit \c[Index+1] und ähnlichem, durch \c[Index+SizeOf(Character)] zu ersetzen. Ich werde es morgen mal testen und ggf. berichten, ob es funktioniert bzw. ausreicht.

Re: Funktion, die Platzhalter ("*" und "?") in String prüft

Verfasst: 09.08.2011 23:37
von STARGÅTE
Es sollte mit Unicode ohne probleme laufen.
Denn ich verwende ja gerade ein Character-Array und kein ByteArray.

Deswegen ist spreche ich mit \c[Index] wirklich immer genau ein Zeichen an und alle Indizes arbeiten auf Character-Ebene.

Also ich habs eben getestet und es läuft ohne Probleme.

Was natürlich sein kann ist, das du wirklich Zeichen über 255 nutzt, weil dann meine LowCase-Tabelle nicht mehr reicht.
Warum ich die brauche hab ich ja schon davor gepostet.
"Wichtig: Außerdem ist es besser die ganze *LowCaseCharacter-Sache aus Pattern_Find() herauszunehmen, da die Unicode-Zeichen damit sowieso nicht abgedeckt werden!"
Das ist richtig, ich hatte es damals drin, damit ich unabhängig von groß/klein vergleichen kann ohne auf die String-Funktion LCase zugreifen zu müssen.
Da man aber eh nichts ersetzen will, kann man nun auch gleich am anfang (wenn gewollt) LCase() auf beide Strings anwenden.
Das wäre die einzige Stelle die man ändern müsste, die es aber langsammer macht.

Re: Funktion, die Platzhalter ("*" und "?") in String prüft

Verfasst: 10.08.2011 00:21
von c4s
Stimmt, stimmt. Hatte wohl vorhin irgendetwas verwechselt. Hab jetzt gerade nochmal nachgesehen und siehe da: Im Eifer der Entfernung des LowCase-Blocks, hatte ich aus mir unbekannten Gründen das Character- in ein Ascii-Array (.a) abgeändert... Naja das wird wohl die Lösung sein. :lol:

Also danke für den Hinweis!