Seite 3 von 5

Verfasst: 23.04.2007 23:27
von al90
Ich hatte es mit einer Procedure und Memory-Befehlen versucht.
Weist schon, Peek + Poke und so. Brachte aber alles nix, hab den
Code auch nicht mehr.

Verfasst: 24.04.2007 11:28
von bobobo
AND51 hat geschrieben:Das ist doch im Prinzip, dasselbe was ich gepostet habe.
Aber bei dir hat man's nicht als Befehl/Procedure.
genau deshalb ist meins schneller <)
Und die optisch besseren Einrückungen fehlen. :|
Schönheit war nicht gefragt. Mein Code ist kürzer als Deiner :wink:

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

Verfasst: 24.04.2007 13:00
von nco2k
fast doppelt so schnell wie die version von AND51:

Code: Alles auswählen

Procedure FindLastString(String.s, StringToFind.s, CaseSensitive=1)
  
  If CaseSensitive = 0
    String = LCase(String)
    StringToFind = LCase(StringToFind)
  EndIf
  
  Protected StringLength = StringByteLength(String), StringToFindLength = StringByteLength(StringToFind), Offset = StringLength - StringToFindLength, CharacterLength = SizeOf(Character), Result
  
  While Offset > -1
    If CompareMemory(@String + Offset, @StringToFind, StringToFindLength)
      Result = Offset / CharacterLength + 1
      Break
    EndIf
    Offset - CharacterLength
  Wend
  
  ProcedureReturn Result
  
EndProcedure

Debug FindLastString("Diese Prozedur sucht von hinten. Deshalb sollte diese Prozedur performanter sein als die bisherigen Prozeduren.", "Prozedur")
ps: habs jetzt nicht gross getestet, wer fehler findet darf sie behalten. <)

c ya,
nco2k

Verfasst: 24.04.2007 13:13
von AND51
Ach DAS meint ihr mit CompareMemory()... Ich gebe zu, das ist gut! Da hätte ich auch drauf kommen müssen...

Danke nco2k !!!! :allright:


> Und die optisch besseren Einrückungen fehlen.
>> Schönheit war nicht gefragt.
>>> -Größte Bequemlichkeit für den Benutzer
Ist es nicht Bequemlichkeit, dem Benutzer einen besseren Überblick über den Code zu bieten, damit dieser ihn besser ansehen/bearbeiten kann? Sonst muss er ja alles manuell einrücken... :wink:

Verfasst: 24.04.2007 14:44
von ChristianK
Edel hat geschrieben:

Code: Alles auswählen

Repeat
  lastpos = pos
  pos = FindString(haystack,needle,pos+1)
Until pos = 0 
bobobo hat geschrieben: der von Edel geht nicht
Natürlich geht der Code von Edel, und sogar bestens! Das Ergebnis steht korrekt in 'lastpos'. Einfach ud simpel. gefällt mir! Beste Programmierkunst!:allright:
AND51 hat geschrieben:

Code: Alles auswählen

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


Debug FindLastString("Ich liebe PureBasic! Du auch?", "Ich")
man kann alles bis zur unleserlichkeit (Geschwindigkeits-)optimieren. Aber bringts das? muss jede Zeile 5x lesen um den Sinn zu versthene. 21 Programmzeilen wo 4 genügen umd das Problem zu lösen? :?

Verfasst: 24.04.2007 14:56
von AND51
Hallo!

Ich habe mal CopyMemoryString() benutzt. Hat eine eingebaute Case(In)Sensitive-Funktion, die sich um alles kümmert.
Außerdem ist meine Prozedur kürzer und ein paar ms schneller als die von co2k:

Code: Alles auswählen

Procedure.l FindLastString(String$, StringToFind$, CaseInSensitive=0)
	Protected length=Len(StringToFind$), *position=@String$+(Len(String$)-length)*SizeOf(Character)
	While @String$ < *position
		If CompareMemoryString(*position, @StringToFind$, CaseInSensitive, length) = 0
			ProcedureReturn (*position-@String$)/SizeOf(Character)+1
		EndIf
		*position-SizeOf(Character)
	Wend
	ProcedureReturn 0
EndProcedure


Debug FindLastString("Am Anfang sollte der Suchstring sollte stehen, um die Prozedur zu fordern!", "anfang", 1)

> Aber bringts das? muss jede Zeile 5x lesen um den Sinn zu versthene.
Dazu kann man den Code ja kommentieren. Ich habs aber nicht gemacht, weil ich ja weiß, wie der Code arbeitet.

Der von dir zitierte Code ist aber schon wieder alt, hab hier einen neueren, wo man den SInn auch mit 1x Lesen erfassen kann :wink:

Verfasst: 24.04.2007 15:09
von ts-soft
>> man kann alles bis zur unleserlichkeit (Geschwindigkeits-)optimieren. Aber bringts das?
Nur wenn Geschwindigkeit erforderlich ist. Dann kann man aber durch
verzicht auf z.B. Peek, Poke, FindString, StringField usw. eine Menge ein-
sparen. Wenn ich z.B. einen Parser schreibe, sind diese Optimierungen
unverzichtbar. Wenn ich sowas nicht so oft benötige, mit kurzen Texten,
dann kann man sich die Umstände natürlich sparen, weil das bringts dann
nicht :mrgreen:

Verfasst: 24.04.2007 20:04
von bobobo
ChristianK hat geschrieben:
bobobo hat geschrieben: der von Edel geht nicht
Natürlich geht der Code von Edel, und sogar bestens! Das Ergebnis steht korrekt in 'lastpos'. Einfach ud simpel. gefällt mir! Beste Programmierkunst!:allright:
achso .. blind war


Das stand aber sehr nutzerunfreundlich nicht dabei. :D

Verfasst: 24.04.2007 21:22
von Xaby
Was haltet ihr von der Idee:

Den String umdrehen, den SuchString umdrehen.
Dann FindString()

Dann braucht man nur noch von der Gesamtlänge des Strings die ermittelte Position abziehen und weiß, wo das letzte Vorkommen ist.

Nun braucht man sich nur noch um die schnellste Methode zu kümmern, die den String umdreht.

Aber schneller als der von Edel wird es wohl auch nicht sein.
Naja, wenn vergleichen lange dauert und viele SuchStrings drin sind, dann ist meine Idee vielleicht einen Tick angesagter.

Zu Edel: Ich denke, genauso ist es gedacht gewesen, deshalb kann man die Position gleich angeben und muss nicht immer erst Stückeln und von den Stücken dann die Position finden.

Edel zeigt, was man alles schaffen kann, wenn man zwei Minuten mal die Augen auf macht und eine Vision hat :shock:

:freak:

Verfasst: 24.04.2007 21:30
von Thorium
Xaby hat geschrieben:Was haltet ihr von der Idee:

Den String umdrehen, den SuchString umdrehen.
Dann FindString()

Dann braucht man nur noch von der Gesamtlänge des Strings die ermittelte Position abziehen und weiß, wo das letzte Vorkommen ist.

Nun braucht man sich nur noch um die schnellste Methode zu kümmern, die den String umdreht.

:freak:
Man kann auch einfach von hinten suchen.
Das versuche ich gerade in inline-Assembler umzusetzen. Da ich da aber selber noch Anfänger bin, dauert das noch ein bissel. :D