Seite 1 von 5

FindLastString() »»» Letztes Vorkommen von Strings ermitteln

Verfasst: 23.04.2007 19:21
von AND51
Hallo!

Möchte mal ne Competition starten, ein Gegenstück von FindString(), welches das erste Vorkommen eines Strings ermittelt. Ich will aber das letzte Vorkommen im String haben :)
Später folgt noch eine Prozedur, die das n. Vorkommen ermittelt (dazu am besten nen separatren Thread aufmachen!).

Ich fang mal an mit dem hier:

Code: Alles auswählen

Procedure FindLastString(String$, StringToFind$)
	Protected neu=FindString(String$, StringToFind$, 1), alt=neu
	While neu
		alt=neu
		neu=FindString(String$, StringToFind$, alt+1)
	Wend
	ProcedureReturn alt
EndProcedure


Debug FindLastString("anna", "a")
Es gelten die üblichen Mitmachregeln:
  • -Unicode+Threadsafe Support, wenn möglich
    -EnableExplicit Kompatiblität
    -Größte Bequemlichkeit für den Benutzer (optionale Parameter einbauen, etc.)
    -Möglichst gute Performance
Es gibt nix zu gewinnen, macht aber nichts, da sowieso Mitarbeiter und deren Angehörige von "Fantasiesoftware" nicht mitmachen dürfen. Der Rechtsweg ist ausgeschlossen.

Verfasst: 23.04.2007 20:08
von Fluid Byte
Ist doch eigentlich Käse. Du must doch lediglich die Länge des Strings beim 'StartPosition' Paremeter angeben.

Verfasst: 23.04.2007 20:14
von AND51
Käse ist es, stimmt. Aber Recht hast du auch nicht.
Was soll ich denn mit der Länge des Strings beim 3. Parameter von FindString()?

Ich verbessere meine obige Version eben mal.

Verfasst: 23.04.2007 20:18
von Fluid Byte
Ich dachte FindString() durchsucht immer den ganzen String unabhängig von der StartPosition. Insofern haste Recht. Ma' guckn' ob Ich was zusammenbastel. Bild

Verfasst: 23.04.2007 20:20
von AND51
> Ich dachte FindString() durchsucht immer den ganzen String unabhängig von der StartPosition.
Nein, da irrst du dich. StartPosition sagt, ab welcher Position er mit der Suche beginnen soll. Nützlich, wenn ich weiß, dass ein bestimtmes zeichen sowieso nur ab Position 32 oder so vorkommt oder ich das erste Ergebnis überspringen will.

Trotzdem hast du Recht, das brauchte ich hier nicht, bzw. hier bringt das nicht die Performance.

Bin auf deine Version gespannt! <)

Verfasst: 23.04.2007 20:23
von bobobo
also

Code: Alles auswählen

haystack.s="Hier wird die Nadel drin gesucht. Also die Nadel im Heuhaufen."
needle.s="Nadel"


firstpos=FindString(haystack,needle,0)

lastpos=firstpos
Debug lastpos
While FindString(haystack,needle,lastpos+1)
lastpos =FindString(haystack,needle,lastpos+1)
Wend
Debug "letztes Vorkommen an Stelle "+Str(FindString(haystack,needle,lastpos))

Verfasst: 23.04.2007 20:35
von edel

Code: Alles auswählen

Repeat 
  lastpos = pos
  pos = FindString(haystack,needle,pos+1)
Until pos = 0
sollte auch reichen .

Verfasst: 23.04.2007 20:36
von AND51
Das ist doch im Prinzip, dasselbe was ich gepostet habe.
Aber bei dir hat man's nicht als Befehl/Procedure. Und die optisch besseren Einrückungen fehlen. :|

//Edit: Ach edel du hast ja auch was gepostet! hab ich nicht gesehen, als ich gepostet habe...

Verfasst: 23.04.2007 21:20
von AND51
Ich habe hier eine Prozedur, die von hinten gebinnt zu suchen. Desshalb müsste die performanter sein.

Sie vergleicht den 1. Buchstaben des StringToFind$ mit jedem Buchstaben von String$ von hitnen beginnend. Bei Treffer wird Buchstabe für Buchstabe der beiden Strings miteinander vergichen. Bei vollständiger Übereinstimmung gilt StringToFind$ als gefunden und das Ergebnis wird zurückgegeben.

Testergebnisse / Performance: Ich habe den ersten Code, der bisher euren Codes entspricht mit diesem verglichen. Außerdem habe ich noch den Code aus dem bisherigen Thread hier in einer FOR-Schleifen-Version.

Alle drei miteinander verglichen zeigt, dass der neue Code von mir hier der schnellste ist. Je länger die Strings, desto effektiver arbeitet dieser Algorithmus.

Code: Alles auswählen

Procedure.l FindLastString3(String$, StringToFind$)
	Protected n, i, l=StringByteLength(String$)-SizeOf(Character), l2=StringByteLength(StringToFind$)-SizeOf(Character)
	For n=l To 0 Step -SizeOf(Character)
		If PeekC(@String$+n) = PeekC(@StringToFind$)
			For i=0 To l2 Step SizeOf(Character)
				If PeekC(@String$+n+i) <> PeekC(@StringToFind$+i)
					Break
				EndIf
			Next
			If i = l2+SizeOf(Character)
				Break
			EndIf
		EndIf
	Next
	ProcedureReturn (n+SizeOf(Character))/SizeOf(Character)
EndProcedure


Debug FindLastString("Diese Prozedur sucht von hinten. Deshalb sollte diese Prozedur performanter sein als die bisherigen Prozeduren.", "Prozedur")

Verfasst: 23.04.2007 21:23
von Thorium
Vielen Dank für diese Idee! :allright:

Habe gerade mal versucht das ganze in Assembler umzusetzen. Hat leider net so funktioniert wie ich mir das dachte, gab nen IMA. Ich also mit OllyDebugger drann um zu schauen was vorsich geht. Und siehe da in OllyDbg lauft die .exe, ohne OllyDbg gibts eine IMA-Exception. Das is saugeil, weil man das verwenden kann um zu prüfen ob das Programm unter OllyDbg läuft.

Thx, thx, thx. :mrgreen: