VB's InStrRev Xojo Equivalent

  1. 7 years ago

    Barry T

    13 Aug 2013 Pre-Release Testers, Xojo Pro

    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!

    Barry Traver

  2. Rick A

    13 Aug 2013 Pre-Release Testers (Brazil. UTC-3:00)
    Edited 7 years ago

    I miss that too. Probably your best guess to find a substring at the end of a string is using regular expressions. http://docs.xojo.com/index.php/RegEx
    It's like using a gun to kill a fly.

    I don't know why only in 2012 this request appeared: Feedback Case #20181 . Should be older.

  3. Edited 7 years ago

    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
  4. Edited 7 years ago

    Does this do what you want:

    Dim s as string
    Dim delimiter as string
    Dim lastVal as integer

    s = "This is a test"
    delimiter = " "

    lastVal = s.InStr( s.len - s.NthField(delimiter, s.CountFields(delimiter)).Len, delimiter)

  5. Edited 7 years ago

    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
  6. Dave S

    13 Aug 2013 San Diego, California USA
    Edited 7 years ago

    Mark... doesn't that only work if you are looking for the last occurance of a CHARACTER?

    FUNCTION instrRev(s as string,t as string)
    last=0
    do
       x=instr(last+1,s,t)
       if x>0 then 
           last=x
       else
         exit do
       end if
    loop
    return last
    END FUNCTION
     
  7. Edited 7 years ago

    @Dave S Mark... doesn't that only work if you are looking for the last occurance of a CHARACTER?

    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
  8. Barry T

    14 Aug 2013 Pre-Release Testers, Xojo Pro

    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

    Thanks for the posts. You didn't disappoint me.

    Barry Traver

  9. Kem T

    14 Aug 2013 Pre-Release Testers, Xojo Pro, XDC Speakers, MVP Connecticut

    FYI, an optimized InStrRev is in my M_String module.

    http://www.mactechnologies.com/index.php?page=downloads

  10. Kem T

    14 Aug 2013 Pre-Release Testers, Xojo Pro, XDC Speakers, MVP Connecticut

    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

or Sign Up to reply!