Strings

Everything else that doesn't fall into one of the other PB categories.
Polo
Addict
Addict
Posts: 2422
Joined: Tue May 06, 2003 5:07 pm
Location: UK

Strings

Post by Polo »

Hi !
I've got a silly thing to do :
Let's say I have a string like that :

Code: Select all

mystring.s="Firstword      Secondword;"
but the string can also be

Code: Select all

mystring.s="   FirstWordwithoutsecondword;"
I want to get rid of all spaces that are in the string (at the left, at the right, and in the middle if there is a middle, but if there is a middle I want to keep one space between the two words), and also I want to get rid of the ";" at the end.
We consider that the number of words is illimited.
Ok, the aim is to do the fastest way as possible, and I don't know the way to do it :)
I could use severals ReplaceString and RemoveString but it would be slow, what would you suggest ?
MrMat
Enthusiast
Enthusiast
Posts: 762
Joined: Sun Sep 05, 2004 6:27 am
Location: England

Post by MrMat »

I'd do it as a state machine that passes once over the string:

Code: Select all

Procedure.s tidystring(pass.s)
    len.l = Len(pass)
    *passpos.BYTE = @pass
    *new = AllocateMemory(len + 1)
    *newpos.BYTE = *new
    *lastnonspace.BYTE = *new ; Last non-space and non semi-colon
    state.l = 0
    For loop = 0 To len - 1
        val.l = *passpos\b
        If state = 0 ; We'll have this character if it isn't a space
            If val <> ' '
                *newpos\b = val
                If val <> ';'
                    *lastnonspace = *newpos
                EndIf
                *newpos + 1
                state = 1
            EndIf
        Else ; We'll have this character whatever it is
            *newpos\b = val
            If val = ' '
                state = 0
            ElseIf val <> ';'
                *lastnonspace = *newpos
            EndIf
            *newpos + 1
        EndIf
        *passpos + 1
    Next
    If *lastnonspace\b = ';'
        *lastnonspace - 1
    EndIf
    *lastnonspace + 1
    *lastnonspace\b = 0
    newstring.s = PeekS(*new)
    FreeMemory(*new)
    ProcedureReturn newstring
EndProcedure

mystring.s = "    Fi rst word      S ec o n                 d    word           Third wor d     ;    "
res.s = tidystring(mystring)
Debug(">" + res + "<")
But this is the kind of code that would really benefit from being written in asm!
Mat
Polo
Addict
Addict
Posts: 2422
Joined: Tue May 06, 2003 5:07 pm
Location: UK

Post by Polo »

Wow, nice code !
You're right, if there's some asm guys here ? 8)
Polo
Addict
Addict
Posts: 2422
Joined: Tue May 06, 2003 5:07 pm
Location: UK

Post by Polo »

This code is faster than the ReplaceString without the debugger, and slower with the debugger :)
I need an ASM version :)
Dare2
Moderator
Moderator
Posts: 3321
Joined: Sat Dec 27, 2003 3:55 am
Location: Great Southern Land

Post by Dare2 »

Just for fun:

Code: Select all

Procedure.s MaybeSlowAsAWetWick(s.s)
  w.s=Trim(s)
  If Right(w,1)=";"
    w=Left(w,Len(w)-1)
  EndIf
  x.s=""
  sp.s = ""
  For i = 1 To CountString(w," ") + 1
    tmp.s = StringField(w, i, " ")
    If tmp <> ""
      x + sp + tmp
      sp = " "
    EndIf
  Next
  ProcedureReturn x
EndProcedure

Debug MaybeSlowAsAWetWick("   able   baker    j;")
Debug MaybeSlowAsAWetWick("   able;")
Debug MaybeSlowAsAWetWick("able   baker ;  ")
Debug MaybeSlowAsAWetWick(";")
:)
@}--`--,-- A rose by any other name ..
Nik
Addict
Addict
Posts: 1017
Joined: Fri May 13, 2005 11:45 pm
Location: Germany
Contact:

Post by Nik »

I would subsititute BYTE for CHARACTER and use Sizeof(CHARACTER) then you can enable it for Unicode, you also have to use the Len Command
Post Reply