Visual Basic has a useful function called InStrRev, which is (as the name suggests) sort of an InStr in Reverse, i.e., it starts counting characters at the right rather then at the left.
I know that there are many ways that a Xojo equivalent could be written (e.g., reversing the original string, using a backwards For/Next loop (with Downto, etc.), so it shouldn’t be difficult for me to write a Xojo equivalent myself.
I don’t mind re-inventing the wheel, but what I come up with is likely NOT to be the BEST solution to the problem. I’d be much interested in what people here have come up with as the BEST answer to the question.
What I’m hoping for is something that may be an elegantly simple (or simply elegant?) solution. (Doesn’t an Xojo counterpart to VB’s InStrRev deserve to be simple and elegant?) But please post code you’ve found useful even if you aren’t convinced that it fully meets tne previous description. Thanks!
I miss that too. Probably your best guess to find a substring at the end of a string is using regular expressions. Page Not Found — Xojo documentation
It’s like using a gun to kill a fly.
The following is from the Internet, few months earlier. So not sure about the source.
Function InStrRev(ByVal strSourceString As String, ByVal strFindString As String, ByVal blnMatchCase As Boolean = False) As Integer
Dim k As integer
Dim lastFound As Integer
Dim limit As Integer
If blnMatchCase =False Then
k = InStr(strSourceString, strFindString )
Else
k = InStrB(strSourceString, strFindString )
End If
lastFound = k
limit=Len(strSourceString)
While k > 0
lastFound = k
If k<limit Then
If blnMatchCase =False Then
k = InStr( lastFound+1, strSourceString, strFindString)
Else
k = InStrB( lastFound+1, strSourceString, strFindString)
End If
Else
Exit While
End If
Wend
Return lastFound
End Function
Added to a module as a string extension method with the ‘binary’ comparison added:
Function InStrRev(extends s as string, delimiter as String, binary as boolean = false) As integer
if binary then
return s.InStrB( s.len - s.NthFieldB(delimiter, s.CountFieldsB(delimiter)).Len, delimiter)
else
return s.InStr( s.len - s.NthField(delimiter, s.CountFields(delimiter)).Len, delimiter)
end if
End Function
[quote=26929:@Dave S]Mark… doesn’t that only work if you are looking for the last occurance of a CHARACTER?
[/quote]
Ah, yes, I didn’t take into account the length of the delimiter. I believe this should work:
Function InStrRev(extends s as string, delimiter as String, binary as boolean = false) As integer
if binary then
return s.InStrB( s.len - s.NthFieldB(delimiter, s.CountFieldsB(delimiter)).Len - (delimiter.len - 1), delimiter)
else
return s.InStr( s.len - s.NthField(delimiter, s.CountFields(delimiter)).Len - (delimiter.len - 1), delimiter)
end if
End Function
I’m glad I asked the question. The comments posted by other people here are much better and fit more situations than my faltering first steps toward a InStrRev.
To illustrate that point, here’s where I begain, which is too specific (rather than fitting different situations, including different length of delimiter as diiscussed here in this thread) and wastes time unnecessarily looking at the entire string. In short, here’s an example of bad programming, even if I had gotten from this to a more general definition:
// The following finds the filename wIthout the extension
// if the filename contains one period or more than one.
Dim I, Pos1 As Integer
Dim Filename, FilenameWithoutTheExtension As String
Filename = "one.two.three.four.five"
For I = 1 To Len (FileName)
If Mid ( FileName, I, 1) = "." Then
Pos1 = I
End If
Next I
MsgBox Str ( Pos1 )
FilenameWithoutTheExtension = Left ( Filename, Pos1 -1 )
MsgBox Filename + EndOfLine + FilenameWIthoutTheExtension
Here is the actual code. In my tests, this turned out to be faster than anything else I tried (which is counter-intuitive, IMO). You can see my other attempts in M_String.
Function InStrRev_MTC(Extends src As String, start As Integer = 0, find As String) As Integer
#pragma BackgroundTasks False
#pragma BoundsChecking False
#pragma NilObjectChecking False
dim pos as integer
dim curPos as integer = 0
if start > 0 then src = src.Left( start )
do
curPos = src.InStr( curPos + 1, find )
if curPos = 0 then
exit
else
pos = curPos
end if
loop
return pos
End Function