Got an idea for enhancing PureBasic? New command(s) you'd like to see?
PB
PureBasic Expert
Posts: 7581 Joined: Fri Apr 25, 2003 5:24 pm
Post
by PB » Thu Dec 04, 2008 12:52 pm
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
Posts: 573 Joined: Fri Apr 25, 2003 4:57 pm
Post
by naw » Thu Dec 04, 2008 1:06 pm
More Useful would be a
command - you could use the regular
as usual.
Ta - N
PB
PureBasic Expert
Posts: 7581 Joined: Fri Apr 25, 2003 5:24 pm
Post
by PB » Thu Dec 04, 2008 1:14 pm
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
Posts: 573 Joined: Fri Apr 25, 2003 4:57 pm
Post
by naw » Mon Dec 08, 2008 12:42 pm
Oh - maybe my understanding of what a ReverseFindString is incorrect then. I presumed it would search from right to left - so
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
Michael Vogel
Addict
Posts: 2797 Joined: Thu Feb 09, 2006 11:27 pm
Contact:
Post
by Michael Vogel » Mon Dec 08, 2008 5:02 pm
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
blueznl
PureBasic Expert
Posts: 6166 Joined: Sat May 17, 2003 11:31 am
Contact:
Post
by blueznl » Mon Dec 08, 2008 7:16 pm
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
Posts: 740 Joined: Sat Dec 03, 2011 5:54 pm
Location: Oldenburg (Germany)
Post
by uwekel » Sat Dec 22, 2012 2:36 pm
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
skywalk
Addict
Posts: 4211 Joined: Wed Dec 23, 2009 10:14 pm
Location: Boston, MA
Post
by skywalk » Sat Dec 22, 2012 7:33 pm
This is faster.
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
Posts: 740 Joined: Sat Dec 03, 2011 5:54 pm
Location: Oldenburg (Germany)
Post
by uwekel » Sun Dec 23, 2012 9:14 am
Cool, especially on longer strings it is very much faster!
PB 5.70 LTS (x64) - Debian Testing, Gnome 3.30.2
davido
Addict
Posts: 1890 Joined: Fri Nov 09, 2012 11:04 pm
Location: Uttoxeter, UK
Post
by davido » Tue Dec 25, 2012 9:17 pm
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
skywalk
Addict
Posts: 4211 Joined: Wed Dec 23, 2009 10:14 pm
Location: Boston, MA
Post
by skywalk » Tue Dec 25, 2012 9:43 pm
Not always. For very long strings, you will suffer the entire ReverseString() before you begin your search.
The nice thing about standards is there are so many to choose from. ~ Andrew Tanenbaum
MachineCode
Addict
Posts: 1482 Joined: Tue Feb 22, 2011 1:16 pm
Post
by MachineCode » Wed Dec 26, 2012 1:41 am
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!
skywalk
Addict
Posts: 4211 Joined: Wed Dec 23, 2009 10:14 pm
Location: Boston, MA
Post
by skywalk » Wed Dec 26, 2012 4:17 am
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
Posts: 1890 Joined: Fri Nov 09, 2012 11:04 pm
Location: Uttoxeter, UK
Post
by davido » Wed Dec 26, 2012 2:46 pm
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