FindStringReverse()

Got an idea for enhancing PureBasic? New command(s) you'd like to see?
PB
PureBasic Expert
PureBasic Expert
Posts: 7581
Joined: Fri Apr 25, 2003 5:24 pm

FindStringReverse()

Post 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.
I compile using 5.31 (x86) on Win 7 Ultimate (64-bit).
"PureBasic won't be object oriented, period" - Fred.
naw
Enthusiast
Enthusiast
Posts: 573
Joined: Fri Apr 25, 2003 4:57 pm

Post by naw »

More Useful would be a

Code: Select all

ReverseString()
command - you could use the regular

Code: Select all

FindString()
as usual.
Ta - N
PB
PureBasic Expert
PureBasic Expert
Posts: 7581
Joined: Fri Apr 25, 2003 5:24 pm

Post 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. :)
I compile using 5.31 (x86) on Win 7 Ultimate (64-bit).
"PureBasic won't be object oriented, period" - Fred.
naw
Enthusiast
Enthusiast
Posts: 573
Joined: Fri Apr 25, 2003 4:57 pm

Post 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...
Ta - N
User avatar
Michael Vogel
Addict
Addict
Posts: 2797
Joined: Thu Feb 09, 2006 11:27 pm
Contact:

Post 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
User avatar
blueznl
PureBasic Expert
PureBasic Expert
Posts: 6166
Joined: Sat May 17, 2003 11:31 am
Contact:

Post by blueznl »

I'd rather call it RFindString...
( PB6.00 LTS Win11 x64 Asrock AB350 Pro4 Ryzen 5 3600 32GB GTX1060 6GB)
( The path to enlightenment and the PureBasic Survival Guide right here... )
uwekel
Enthusiast
Enthusiast
Posts: 740
Joined: Sat Dec 03, 2011 5:54 pm
Location: Oldenburg (Germany)

Re: FindStringReverse()

Post 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!
PB 5.70 LTS (x64) - Debian Testing, Gnome 3.30.2
User avatar
skywalk
Addict
Addict
Posts: 4211
Joined: Wed Dec 23, 2009 10:14 pm
Location: Boston, MA

Re: FindStringReverse()

Post 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
The nice thing about standards is there are so many to choose from. ~ Andrew Tanenbaum
uwekel
Enthusiast
Enthusiast
Posts: 740
Joined: Sat Dec 03, 2011 5:54 pm
Location: Oldenburg (Germany)

Re: FindStringReverse()

Post by uwekel »

Cool, especially on longer strings it is very much faster!
PB 5.70 LTS (x64) - Debian Testing, Gnome 3.30.2
User avatar
luis
Addict
Addict
Posts: 3893
Joined: Wed Aug 31, 2005 11:09 pm
Location: Italy

Re: FindStringReverse()

Post 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.
"Have you tried turning it off and on again ?"
A little PureBasic review
davido
Addict
Addict
Posts: 1890
Joined: Fri Nov 09, 2012 11:04 pm
Location: Uttoxeter, UK

Re: FindStringReverse()

Post 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")
DE AA EB
User avatar
skywalk
Addict
Addict
Posts: 4211
Joined: Wed Dec 23, 2009 10:14 pm
Location: Boston, MA

Re: FindStringReverse()

Post by skywalk »

Not always. For very long strings, you will suffer the entire ReverseString() before you begin your search. :wink:
The nice thing about standards is there are so many to choose from. ~ Andrew Tanenbaum
MachineCode
Addict
Addict
Posts: 1482
Joined: Tue Feb 22, 2011 1:16 pm

Re: FindStringReverse()

Post 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.
Microsoft Visual Basic only lasted 7 short years: 1991 to 1998.
PureBasic: Born in 1998 and still going strong to this very day!
User avatar
skywalk
Addict
Addict
Posts: 4211
Joined: Wed Dec 23, 2009 10:14 pm
Location: Boston, MA

Re: FindStringReverse()

Post 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")
The nice thing about standards is there are so many to choose from. ~ Andrew Tanenbaum
davido
Addict
Addict
Posts: 1890
Joined: Fri Nov 09, 2012 11:04 pm
Location: Uttoxeter, UK

Re: FindStringReverse()

Post 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$)
DE AA EB
Post Reply