Page 1 of 1
Line Parser
Posted: Sun Feb 08, 2004 3:06 pm
by NoahPhense
.
I'm looking for a line parser. I could have sworn that I saw one a few
months back. One that didn't use FindString(). It was small and pretty
fast. Fast enough for me anyhow.
It took a simple line:
The dog jumped over the fence.
And split it up based on the space delimeter.
And you were able to choose the delimeter, something like such:
Parse(string.s, delimeter.s)
- np
Posted: Sun Feb 08, 2004 3:19 pm
by LarsG
don't know if this will help you....
Code: Select all
Procedure.s ExtractWord(txt$, number, separator$)
Protected ReturnString$
Protected letter$
Protected cno
letter$ = "" : cno = 0
If number > 0
For x = 1 To Len(txt$)
letter$ = Mid(txt$,x,1)
If letter$ = separator$
; hit!
cno = cno + 1
If cno = number
Break
EndIf
EndIf
Next
EndIf
;we've hit the spot, now extract the string
For y = x+1 To Len(txt$)
letter$ = Mid(txt$,y,1)
If letter$ = separator$
Break
EndIf
ReturnString$ = ReturnString$ + letter$
Next
ProcedureReturn ReturnString$
EndProcedure
Re: Line Parser
Posted: Sun Feb 08, 2004 3:23 pm
by PB
It's the
StringField command. Example from the docs:
Code: Select all
For k=1 To 6
Debug StringField("Hello I am a split string", k, " ")
Next
Posted: Sun Feb 08, 2004 5:02 pm
by Dare2
WooHoo! That's pretty neat.
Is there a better/quicker way than the following to determine how many delimited fields are in the string?
Code: Select all
k=1
w.s=StringField("Hello I am a split string", k, " ")
While Len(w)>0
Debug w
k+1
w=StringField("Hello I am a split string", k, " ")
wend
Debug "Elements = "+Str(k-1)
..
Posted: Sun Feb 08, 2004 8:53 pm
by NoahPhense
Dare2 wrote:WooHoo! That's pretty neat.
Is there a better/quicker way than the following to determine how many delimited fields are in the string?
Code: Select all
k=1
w.s=StringField("Hello I am a split string", k, " ")
While Len(w)>0
Debug w
k+1
w=StringField("Hello I am a split string", k, " ")
wend
Debug "Elements = "+Str(k-1)
Thanks everyone for the help.. this will work great.
- np
Posted: Sun Feb 08, 2004 8:57 pm
by blueznl
iirc the only problem with stringfield() is that it doesn't handle double spaces well, or am i wrong here?
..
Posted: Sun Feb 08, 2004 9:26 pm
by NoahPhense
blueznl wrote:iirc the only problem with stringfield() is that it doesn't handle double spaces well, or am i wrong here?
I did test that theory.. and yes, stringfield sucks when it comes to spaces.
The solution is to make sure you don't have any double spaces. LOL jk
Here's a temp solution. nothing special..
Code: Select all
; Noah Phense
myString.s = "aaaaaaaaa bbbbbbbbbbbb cccccccccccccccccccc ddd eee"
myStringLen.w = Len(myString)
location=1
trueCount=0
nextWord.s = StringField(myString, location, " ")
Repeat
nextWord = StringField(myString, location, " ")
If Len(nextWord) = 0
; do nothing
Else
Debug nextWord
trueCount = trueCount + 1
EndIf
location+1
Until location = myStringLen
Debug "trueCount = " + Str(trueCount)
I'll run it through some speed tests later..
- np
Posted: Sun Feb 08, 2004 9:33 pm
by blueznl
because i do some other parsing as well i converted an old gfa routine of mine to parse whatever... i think i went a bit overboard in this case

..
Posted: Sun Feb 08, 2004 9:49 pm
by NoahPhense
blueznl wrote:because i do some other parsing as well i converted an old gfa routine of mine to parse whatever... i think i went a bit overboard in this case

lol.. ok man.. you made me do it.. 8O heres a procedure
Code: Select all
; Noah Phense
Procedure.l ParseIt(myString.s)
myStringLen.w = Len(myString)
location=1
trueCount=0
nextWord.s = StringField(myString, location, " ")
Repeat
nextWord = StringField(myString, location, " ")
If Len(nextWord) = 0
; do nothing
Else
Debug nextWord
trueCount = trueCount + 1
EndIf
location+1
Until location = myStringLen
ProcedureReturn trueCount
EndProcedure
Debug ParseIT("This is a test...")
- np
Posted: Mon Feb 09, 2004 12:09 am
by Dare2
Another klurge:
Code: Select all
Srce.s="String with some multiple spaces inside."
; ---- eliminate extra spaces
While FindString(Srce, " ", 1)
Srce = ReplaceString(Srce, " ", " ", 1, 1)
Wend
; ---- split
k=1
w.s=StringField(Srce, k, " ")
While Len(w)>0
Debug w
k+1
w=StringField(Srce, k, " ")
Wend
Debug "Elements = "+Str(k-1)
Now if only there was a real split command that created an array.
Any suggestions
Posted: Wed May 25, 2005 7:00 pm
by holyfieldstudios
Code: Select all
Procedure StrSplit(Expression$, Delimiter$)
;Define a new zero lenght array as default result for procedure to return
Dim res.s(0)
count.l = CountString(Expression$, Delimiter$)
;Validate input
If Len(Expression$) < 1
;Return zero lenght array
ProcedureReturn res()
EndIf
If count = 0
res(0) = Expression$
ProcedureReturn res()
EndIf
k=1
Dim ar.s(count)
wt.s = " "
While Len(wt) > 0
wt = StringField(Expression$, k, Delimiter$)
ar(k-1) = wt
k+1
If k > count+1
Break
EndIf
Wend
ProcedureReturn ar()
EndProcedure
Posted: Wed May 25, 2005 8:05 pm
by Xombie
This looked fun

I better add another solution before someone does an ASM version and spoils it all

I did a quick modification to one of my new unicode functions. It'll take a delimiter (as an ascii value) and ignore multiple spaces.
Code: Select all
Procedure.s ParseIt(inString.s, index.l, Delimiter.b) ; Index is 1 based.
;
Protected HoldString.l
;
Protected ReturnString.s
;
Protected CountSeparator.l
;
Protected PositionCharacter.l
;
Protected HoldCharacter.b
;
Protected *MemPosition.l
;
*MemPosition = @inString
;
Protected FoundField.b
;
Protected LastPosition.l
;
Protected FoundSpace.b
;
Protected StringLength.l
;
StringLength = Len(inString)
;
LastPosition = @inString
;
If index = 0 : index = 1 : EndIf
; Our index is 1 based.
Repeat
; Loop through our string.
HoldCharacter = PeekB(*MemPosition)
; Store the current character.
If (HoldCharacter = Delimiter And Delimiter <> 32) Or (HoldCharacter = 32 And Delimiter = 32 And FoundSpace = #False)
; Check if the character is our field divider.
CountSeparator + 1
; Increment our delimiter count.
If CountSeparator + 1 = index
; We're in the field we want to copy.
FoundField = #True
;
ElseIf CountSeparator + 1 > index
;
If FoundField = #True
; We've found a previous separator character so calcluate based on that.
HoldString = AllocateMemory(*MemPosition - LastPosition)
CopyMemory(LastPosition + 1, HoldString, *MemPosition - LastPosition - 1)
;
ReturnString = PeekS(HoldString)
;
FreeMemory(HoldString)
;
Else
; No previous separator character so this is the first field.
HoldString = AllocateMemory((*MemPosition - LastPosition) + 1)
; If we allocate 2 more bytes than needed for the string, the last character will be
; the null character (0) automatically.
CopyMemory(inString, HoldString, *MemPosition - LastPosition)
; So we're copying into all but the last 2 bytes.
ReturnString = PeekS(HoldString)
;
FreeMemory(HoldString)
;
EndIf
;
ProcedureReturn ReturnString
;
EndIf
; Check if we've passed our target field and if so, break out of the loop.
LastPosition = *MemPosition
; Now update with the last separator position.
EndIf
;
If HoldCharacter = 32 : FoundSpace = #True : Else : FoundSpace = #False : EndIf
;
If Delimiter = 32 And HoldCharacter = 32 : LastPosition = *MemPosition : EndIf
;
*MemPosition + 1
; Increment our position in the string.
Until *MemPosition - @inString > StringLength
; Stop either by breaking out of the loop or when we reach the end.
If FoundField = #True
; We found the field but we reached the end before finding another separator character.
HoldString = AllocateMemory(*MemPosition - LastPosition)
CopyMemory(LastPosition + 1, HoldString, *MemPosition - LastPosition - 1)
;
Else
; We did not field the field.
HoldString = AllocateMemory(1)
; And return an empty string. Initialized to 0 automatically.
EndIf
;
ReturnString = PeekS(HoldString)
;
FreeMemory(HoldString)
;
ProcedureReturn ReturnString
; Return the pointer to the return string.
EndProcedure
Posted: Thu May 26, 2005 3:04 pm
by okasvi
doesnt stringfield and trim do the job?

there is countstring too...

Posted: Thu May 26, 2005 3:54 pm
by Trond
Why is everyone posting codes the length of two ropes tied together in both ends?
The string_field function works perfectly when there is any number of spaces between the words. But not with spaces in the ends. To strip the spaces in the end use:
string_field will now work correctly. To count the number of words all you have to do is to count the spaces. It there are for example two, three or four spaces between two words you will get the wrong result. To fix this make sure there are only one space between the words. This can be done as following:
Code: Select all
string = Trim(string)
string = ReplaceString(String, " ", " ")
string = ReplaceString(String, " ", " ")
The code above can handle ANY number of misplaced spaces between words. First it removes leading and trailing spaces. Then it checks for two spaces and replaces them with one. Then it checks for three spaces and replaces them with one. The result: no more misplaces spaces! (and string_field is GUARANTEED to work perfect!)
After fixing double, leading and trailing spaces, you can find the number of words with this code:
Was that so difficult?