Results 1 to 20 of 20

Thread: SuperTrim Function for strings

  1. #1

    Thread Starter
    Addicted Member
    Join Date
    Nov 2016
    Location
    GB
    Posts
    144

    SuperTrim Function for strings

    I created the "SuperTrim" function, quoted by Gary Cornell in "Visual Basic 6 from the Ground Up": the function removes excess spaces in a string.
    Compared to the example found in the book, I have adapted the class, with the code by Marzo Junior (WordWrap_02 found in VbSpeed of Donald Lessau) obtaining excellent results. Here is the source code. To work requires FastString.tlb (In the Zip folder).
    Regards.
    Attached Files Attached Files

  2. #2
    Hyperactive Member
    Join Date
    Aug 2017
    Posts
    380

    Re: SuperTrim Function for strings

    Here's an alternative implementation that doesn't require a TypeLib:

    Code:
    Friend Function CollapseSpaces(ByVal sText As String) As String
        Dim I As Long, J As Long, K As Long
    
        K = Len(sText)
    
        If K Then
            SA1D.pvData = StrPtr(sText)
            SA1D.cElements = K
            I = 1&
    
           'Trim leading spaces
            If iChars(I) = 32 Then
                For I = I To SA1D.cElements
                    If iChars(I) <> 32 Then Exit For
                Next
            End If
    
            For I = I To SA1D.cElements
                J = J + 1&
                iChars(J) = iChars(I)
    
                If iChars(I) = 32 Then
                    For K = I To SA1D.cElements
                        If iChars(K) <> 32 Then Exit For
                    Next
    
                    I = K - 1&
                End If
            Next
        End If
    
       'Trim trailing spaces
        If J Then If iChars(J) = 32 Then J = J - 1&
    
        CollapseSpaces = Left$(sText, J)
    End Function

    Name:  SuperTrim vs SuperTrim_1 vs CollapseSpaces vs RegEx Benchmark.png
Views: 697
Size:  13.8 KB
    Attached Files Attached Files

  3. #3
    Frenzied Member
    Join Date
    Dec 2008
    Location
    Melbourne Australia
    Posts
    1,487

    Re: SuperTrim Function for strings

    Is this only -
    - Trimming all spaces from both ends
    - Replacing multiple internal spaces with single space ?

    If so, how about this -
    Code:
    Option Explicit
    
    Private Sub Command1_Click()
     Dim sBefore As String
     Dim sAfter As String
        sBefore = "   Make      me      slimmer    "
        Me.Print sBefore
        sAfter = SuperTrim(sBefore)
        Me.Print sAfter
        Me.Print "Length = " & Len(sAfter)
    End Sub
    
    Public Function SuperTrim(sIN As String)  'Remove spaces from end, and don't allow multiple spaces
     Dim sWork As String
        sWork = Trim(sIN)  'Get rid of spaces on both ends of the sentence
        Do Until InStr(1, sWork, "  ") = 0
            sWork = Replace(sWork, "  ", " ")
        Loop
        SuperTrim = sWork
    End Function
    Rob

  4. #4
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    9,936

    Re: SuperTrim Function for strings

    Yeah, I was struggling to see what the big deal was as well. The only improvements I'd make to Bobbles's code is to use Trim$() rather than Trim() and also Replace$() rather than Replace(). This will stop all kinds of type-casting between Strings and Variants. Also, we can tighten it to remove the superfluous creation of extra strings. Bobbles, you just don't need that sWork string. In fact, we could do it all with one string if we were willing to use a Sub rather than a Function, but I'll stick with the function. Here's mine:

    Code:
    
    Private Function SuperTrim(s As String)
        SuperTrim = Trim$(s)
        Do While InStr(SuperTrim, "  ")
            SuperTrim = Replace$(SuperTrim, "  ", " ")
        Loop
    End Function
    
    Are we also talking about word-wrap? That wasn't clear to me. If that's so, then, yes, things will change substantially. fabel358, maybe you could outline to us what your objectives were.

    Best Regards,
    Elroy
    Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.

  5. #5

    Thread Starter
    Addicted Member
    Join Date
    Nov 2016
    Location
    GB
    Posts
    144

    Re: SuperTrim Function for strings

    The versions of "SuperTrim" presented by me and "Victor Bravo VI" - CollapseSpaces - have the advantage of being 11 to 13 times faster than these last examples.

  6. #6
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    9,936

    Re: SuperTrim Function for strings

    Hmmm, I added my approach to VBVI's code and got the following:

    Name:  Trim.png
Views: 632
Size:  16.2 KB

    Granted, it's the slowest, but not by a fact of 11 to 13. Sure, anytime we repeatedly use Replace$(), we're going to be shuffling strings around in memory (as oppose to swapping things around in-place. However, at some point, there's got to be a balance between doing simple tasks in an intuitive way versus speed. If we all learned C, I'm sure we could do many things faster. Also, I'm not sure if we're going to be packing spaces a great deal.

    But fabel358, if someone does need maximum speed for this, they've now got it.

    You take care,
    Elroy

    p.s. I didn't test Bobbles', but I'm sure it's slower because of all the typecasting it's doing.
    Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.

  7. #7
    PowerPoster ChrisE's Avatar
    Join Date
    Jun 2017
    Location
    Frankfurt
    Posts
    3,048

    Re: SuperTrim Function for strings

    Hi,

    I use similar like Bobbles

    Textboxes are multiline.

    Code:
    Option Explicit
    
    Private Sub Command1_Click()
    Text2.Text = TrimALL(Text1.Text)
    End Sub
    
    Public Function TrimALL(ByVal TextIN As String) As String
     TrimALL = Trim(TextIN)
     While InStr(TrimALL, String(2, " ")) > 0
     TrimALL = Replace(TrimALL, String(2, " "), " ")
     Wend
    End Function
    
    Private Sub Form_Load()
    
    Text1.Text = " Nel   mezzo    del    cammin di nostra vita" & _
            " mi ritrovai per una selva oscura" & _
            " ché la diritta via era smarrita." & _
            " Ahi quanto a dir qual era è cosa dura" & _
            " esta selva selvaggia e aspra e forte" & _
            " che nel pensier rinova la paura!" & _
            " Tant’è amara che poco è più morte;" & _
            " ma per trattar del ben ch’i’ vi trovai," & _
            " dirò de l’altre cose ch’i’ v’ho scorte." & _
            "   Io non so ben ridir com’i’ v’intrai," & _
            " tant’era pien di sonno a quel punto" & _
            " che la verace via abbandonai." & _
            " Ma poi ch’i’ fui al piè d’un colle giunto, " & _
            " là dove terminava quella valle" & _
            " che m’avea di paura il cor compunto, " & _
            " guardai in alto, e vidi le sue spalle" & _
            " vestite già de’ raggi del pianeta" & _
            " che mena dritto altrui per ogne calle.       "
    
    End Sub
    regards
    Chris
    to hunt a species to extinction is not logical !
    since 2010 the number of Tigers are rising again in 2016 - 3900 were counted. with Baby Callas it's 3901, my wife and I had 2-3 months the privilege of raising a Baby Tiger.

  8. #8

    Thread Starter
    Addicted Member
    Join Date
    Nov 2016
    Location
    GB
    Posts
    144

    Re: SuperTrim Function for strings

    I did not get Elroy's results in my PC; mine are very similar to those of "Victor Bravo VI". A further advantage, in addition to the higher speed of execution, is learning (a unorthodox but effective) programming techniques ...

  9. #9
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    6,582

    Re: SuperTrim Function for strings

    Are you testing a compiled executable, or testing in the IDE? Running in the IDE will be much slower for many things compared to a finished executable.

  10. #10

    Thread Starter
    Addicted Member
    Join Date
    Nov 2016
    Location
    GB
    Posts
    144

    Re: SuperTrim Function for strings

    I test it in a compiled executable with all the advanced optimization.

  11. #11
    PowerPoster
    Join Date
    Jun 2015
    Posts
    2,224

    Re: SuperTrim Function for strings

    just an FYI, you shouldn't be using the "Assume no aliasing" optimization when using SAFEARRAY mapping.

    @Elroy: also I typically like to harass anyone who thinks there is a Replace$ function. Luckily Replace() returns a string and not a Variant.
    Last edited by DEXWERX; Feb 26th, 2018 at 03:50 PM.

  12. #12
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    9,936

    Re: SuperTrim Function for strings

    @Dex: Ahhh, interesting. Since Replace$() works, I just assumed it was like Trim(), Mid(), and others (returning a Variant unless the $ was specified). I actually spent a bit of time with CopyMemory just to convince myself that Replace() is actually returning a String, and it is.

    Also, @fabel358: Just as an FYI, I don't see anything fundamentally wrong with this thread, especially since you've illustrated that your method is faster. I do consider VB6 to be a high-level language though. And, as such, we should expect to occasionally pay some performance penalties. I still have memories of discussions with C programmers, where they could argue for hours about how to pick up individual click cycles. I've just never considered VB6 to be that kind of language. Rather, IMHO, it's a language to "get things out the door". However, learning how to do things faster (in any language) is never a bad thing.

    Y'all Take Care,
    Elroy

    p.s. Here's my CopyMemory "play". With all the auto-type-conversion, I couldn't figure out another way to verify this:

    Code:
    
    Option Explicit
    Private Declare Sub CopyMemory Lib "kernel32.dll" Alias "RtlMoveMemory" (ByRef Dest As Any, ByRef Source As Any, ByVal Bytes As Long)
    
    Private Type VariantDescriptor
        Type As Integer
        Reserved As String * 6
        Data As String * 8
    End Type
    
    Private Sub Form_Load()
        Dim vd As VariantDescriptor
        CopyMemory vd, Replace(" asdf ", " ", ""), 16
        Debug.Print vd.Type
        Stop
    End Sub
    
    Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.

  13. #13
    Frenzied Member
    Join Date
    Dec 2008
    Location
    Melbourne Australia
    Posts
    1,487

    Re: SuperTrim Function for strings

    For many years to come, new members will visit this thread, and leave feeling 'spaced out'

    Rob

  14. #14
    Hyperactive Member
    Join Date
    Aug 2017
    Posts
    380

    Re: SuperTrim Function for strings

    Quote Originally Posted by DEXWERX View Post
    just an FYI, you shouldn't be using the "Assume no aliasing" optimization when using SAFEARRAY mapping.
    Apparently, it doesn't matter:

    Quote Originally Posted by Rockoon
    I would definately avoid using two aliases for the same memory simultaneously. The VB6 optimiser makes the assumption that writing to one array isnt going to effect another, and vise-versa.

    Under the optimization options you will see an 'assume no aliasing' option revealing that this is indeed an issue. Keeping that option turned off will cover an issue such as this:

    Code:
    Dim bar() As Byte
    Function foo(a() As Byte)
      ' process a() and bar() simultaneously
    End Sub
    In the above case, the optimiser will assume that within foo a() and bar() *could* point to the same memory unless the 'assume no aliasing' option is checked off. After all, you might be making the call: foo(bar()) ..

    The 'aliasing' idea only considers 'normal use' possibilities, tho.

    When you are hacking up a safearray to point arbitrarily in memory, all bets are off. The optimiser cannot handle the issue correctly regardless of the state of the aliasing compiler switch so its best to avoid using aliases for the same memory simultaneously.
    Still, that caveat is worth keeping in mind.

  15. #15
    PowerPoster
    Join Date
    Jun 2015
    Posts
    2,224

    Re: SuperTrim Function for strings

    Quote Originally Posted by Victor Bravo VI View Post
    Apparently, it doesn't matter:

    Still, that caveat is worth keeping in mind.
    YMMV.
    I only mention it because this project consistently crashes for me when this flag is set.

    Code:
    30        With New clsCollapseSpaces
    40            Sleep 0&
    50            QueryPerformanceCounter Start
    60                For I = 1& To m_Iterations
    70                    sText = .CollapseSpaces(SrcText) ' <-- Error 91 Object variable or With block variable not set
    80                Next
    90            QueryPerformanceCounter Stop_
    100           Stop_ = Stop_ - Start
    110       End With
    Name:  crash.jpg
Views: 488
Size:  36.6 KB


    edit: I actually mention this in my AryMap class.
    https://github.com/dexwerx/VBWERX/bl...ter/AryMap.cls
    Last edited by DEXWERX; Feb 27th, 2018 at 05:37 PM.

  16. #16
    Hyperactive Member
    Join Date
    Aug 2017
    Posts
    380

    Re: SuperTrim Function for strings

    Apart from adding debugging code, was there anything else in my benchmark project that you've changed? Does it happen only in the IDE or EXE or both? What's your VB6 and service pack version? (mine is VB6 SP6 v9782) I've run the EXE compiled from that code in both XP 32-bit and Windows 7 64-bit (on the same machine) and apparently, it works in Windows 10 as well.

  17. #17
    PowerPoster
    Join Date
    Jun 2015
    Posts
    2,224

    Re: SuperTrim Function for strings

    I added the debug code because it crashed. Oddly it only does it on your code, which uses the same method I use (originally from Curland).
    That's why I knew about this particular issue. I'm also pretty sure Olaf was the one who tipped me off, though possibly not on this forum.
    It's an old bug.

    SP6 v9832 (Windows 7)
    SP6 v9782 (XP)

    The funny thing is if you set up exception handling - Even an On Error Goto 0, in the CollapseSpaces() method, the issue dissappears.

    It'll probably be fun to trace through the differences between compiled output.

    edit: optimizations only change compiled code. it doesn't crash in the IDE.
    Last edited by DEXWERX; Feb 27th, 2018 at 06:00 PM.

  18. #18
    Hyperactive Member
    Join Date
    Aug 2017
    Posts
    380

    Re: SuperTrim Function for strings

    Quote Originally Posted by DEXWERX View Post
    Oddly it only does it on your code, ...
    That's strange... fabel358's class uses SAFEARRAY mapping as well but you're saying it doesn't crash unlike my code? The only difference that I can see that could possibly be the culprit is that fabel358 doesn't set any value for the SAFEARRAY.fFeatures member. I've done some quick tests to see what flags VB6 uses for that member and I've found out that for local and module-level Integer arrays, it always seems to be FADF_HAVEVARTYPE, not FADF_AUTO nor FADF_FIXEDSIZE. Also the cLocks member is 0 rather than 1. Could you please run a test again without those values?

  19. #19
    PowerPoster
    Join Date
    Aug 2010
    Location
    Canada
    Posts
    2,451

    Re: SuperTrim Function for strings

    I only get the Error 91 if I have the Favour Pentium Pro(tm) option selected and the program is compiled.

  20. #20
    Hyperactive Member
    Join Date
    Aug 2017
    Posts
    380

    Re: SuperTrim Function for strings

    Quote Originally Posted by jpbro View Post
    I only get the Error 91 if I have the Favour Pentium Pro(tm) option selected and the program is compiled.
    Ah, yes, now I'm getting that error too. I've never activated that option because it's pointless on modern CPUs.

    I'm beginning to suspect that my algorithm is possibly the real culprit. fabel358 uses 2 SAFEARRAYs for copying characters from the source string to the (temporary) destination string while my algorithm uses only 1 SAFEARRAY. fabel358 copies character-by-character from a separate source string to a separate destination string while mine just shifts characters down on the same output string (I don't overwrite the source string because I make a copy via the ByVal parameter). I'm guessing the optimizations done to the array element shifting is somehow corrupting the (anonymous) object variable (With New clsCollapseSpaces), hence the error.

    I've tested to see if removing the Assume No Aliasing optimization would negatively affect performance but I didn't notice any appreciable decrease in speed, so unselecting that option is indeed probably the safest and most reliable optimization setting. That said, SAFEARRAY hacking is inherently risky, so as noted by Rockoon in the other forum, turning off Assume No Aliasing is no guarantee compiled code will be crash-free.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width