Page 1 of 2

FindStringReverse()

Posted: Thu Dec 04, 2008 12:52 pm
by PB
Any plans to implement such a command? Been requested before but never
done. Or maybe if the "StartPosition" flag of "FindString()" is bigger than the
length of the string, then the string is searched in reverse? Example:

Code: Select all

Debug FindString("hello","l",1) ; Returns 3 because first "l" is at position 3.
Debug FindString("hello","l",6) ; Returns 4 because first "l" from end is at position 4.
Or even just a dedicated flag for it:

Code: Select all

Debug FindString("hello","l",#PB_FindString_End) ; Returns 4 like the other example.

Posted: Thu Dec 04, 2008 1:06 pm
by naw
More Useful would be a

Code: Select all

ReverseString()
command - you could use the regular

Code: Select all

FindString()
as usual.

Posted: Thu Dec 04, 2008 1:14 pm
by PB
No, reversing the string and doing a FindString gives the wrong result:

Code: Select all

Debug FindString("olleh","l",1) ; Incorrectly returns 2, not 4.
But I agree that PureBasic is missing a ReverseString() command too. :)

Posted: Mon Dec 08, 2008 12:42 pm
by naw
Oh - maybe my understanding of what a ReverseFindString is incorrect then. I presumed it would search from right to left - so

Code: Select all

FindString("1234","3",0)
should return 3

and

Code: Select all

FindString(ReverseString("1234"),"3",0
should return 2

But I see that you want to do something different - Do you want to find a certain instance of a string such as:

Code: Select all

FindStringInstance("123412341234","4",2)
would return 8

Yes - that would be very useful...

Posted: Mon Dec 08, 2008 5:02 pm
by Michael Vogel
The "only" useful function would be (something like) ReverseFindString.

Using a parameter bigger than the length of a string would never allow to find the second occurence of a substring from the right :(

Example:
Find the directory name "THIS" from a path like "C:\win\sys\a\THIS\x.dll"

Code: Select all

right=ReverseFindString(path.s,"\",#MAXINT)
if right : left=ReverseFindString(path.s,"\",right-1)
if left : dir.s=Mid(path.s,left+1,right-left-1) : endif : endif
Reversing the string itself wouldn't be useful for normal :?

Michael

Posted: Mon Dec 08, 2008 7:16 pm
by blueznl
I'd rather call it RFindString...

Re: FindStringReverse()

Posted: Sat Dec 22, 2012 2:36 pm
by uwekel
Ok, this thread is really old, but i just found it and for me it is new :-)
I did this work-around for the missing command:

Code: Select all

Procedure FindStringReverse(String.s, StringToFind.s, StartPosition=0)
  Protected x
  ;returns the most right position of StringToFind
  If Not StartPosition
    StartPosition = Len(String)
  EndIf
  For x = StartPosition To 1 Step -1
    If Mid(String, x, Len(StringToFind)) = StringToFind
      Break
    EndIf
  Next
  ProcedureReturn x
EndProcedure
Anyhow i would appreciate an embedded and most likely much faster version!

Re: FindStringReverse()

Posted: Sat Dec 22, 2012 7:33 pm
by skywalk
This is faster. :wink:

Code: Select all

Procedure.i SF_FindStringRev(String$, StringToFind$, UseCase.i=#PB_String_CaseSensitive)
  Protected.i length = Len(StringToFind$)
  Protected.i *position = @String$ + (Len(String$)-length) * SizeOf(Character)
  While @String$ <= *position
    If CompareMemoryString(*position, @StringToFind$, UseCase, length) = #PB_String_Equal ; = 0
      ProcedureReturn (*position - @String$) / SizeOf(Character) + 1
    EndIf 
    *position - SizeOf(Character)
  Wend 
  ProcedureReturn 0
EndProcedure 
Debug SF_FindStringRev("123-abc-123","23") ; = 10, <> 2
Debug SF_FindStringRev("123-abc-123-ABC","a",#PB_String_NoCase) ; = 13

Re: FindStringReverse()

Posted: Sun Dec 23, 2012 9:14 am
by uwekel
Cool, especially on longer strings it is very much faster!

Re: FindStringReverse()

Posted: Sun Dec 23, 2012 1:10 pm
by luis
uwekel wrote:Cool, especially on longer strings it is very much faster!
Originally posted by AND51 here -> http://www.purebasic.fr/german/viewtopi ... 71#p148871

... with many other similar procs.

Re: FindStringReverse()

Posted: Tue Dec 25, 2012 9:17 pm
by davido
Wouldn't the simple code below also do the job?
It seems fast enough at about 50,000,000 per second.

Code: Select all

FindString(ReverseString("Hello K WorKld"),"K")

Re: FindStringReverse()

Posted: Tue Dec 25, 2012 9:43 pm
by skywalk
Not always. For very long strings, you will suffer the entire ReverseString() before you begin your search. :wink:

Re: FindStringReverse()

Posted: Wed Dec 26, 2012 1:41 am
by MachineCode

Code: Select all

FindString(ReverseString("Hello K WorKld"),"K")
That returns 3, not 12. The original request wants the last position in the string, as shown in the example.

Re: FindStringReverse()

Posted: Wed Dec 26, 2012 4:17 am
by skywalk
Yeah, I understood what he was implying. I still think it's faster/easier to search from the end.

Code: Select all

s$ = "Hello K WorKld"
Debug Len(s$) + 1 - FindString(ReverseString(s$),"K")
Debug Len(s$) + 1 - FindString(ReverseString(s$),"l")

Re: FindStringReverse()

Posted: Wed Dec 26, 2012 2:46 pm
by davido
Thanks Skywalk.

Yes, you are right for very long strings it could be a problem.
I've kept a template of your code as it is a nice lesson in using memory.

My current requirement is not affected by speed and the strings are small.

Timings on my Core i3 at 3 GHZ for 1 million iterations are:

10 chars: 90ms
100 chars: 390ms
1000 chars: 3,950ms
10,000 chars: 39,000ms

Code: Select all

EnableExplicit
Define A$, MS1$, MS2$, Dt.I, M.I
A$=RSet("Hello K WorKld",100,"A")
Dt=ElapsedMilliseconds()
For M=1 To 1000000
FindString(ReverseString(A$),"K")
Next M
MS1$ = "Time for: "+Str(M-1)+" iterations:"
MS2$ = Str(ElapsedMilliseconds()-Dt)+"ms Place = "+Str(FindString(ReverseString("Hello K WorKld"),"K"))
MessageRequester(MS1$,MS2$)