What's wrong here?

New to FreeBASIC? Post your questions here.
Post Reply
UEZ
Posts: 988
Joined: May 05, 2017 19:59
Location: Germany

What's wrong here?

Post by UEZ »

I just want to split a string into an array whereas Chr(10) is the delimiter.

Code: Select all

#Define LF	Chr(10)

Sub PrintDirStructur(sPathes As String)
	ReDim As String aPathes(1000)
	Dim As String char
	Dim As integer i = 1, ii = 1, c = 0
	While i <= Len(sPathes)
		char = Mid(sPathes, i, 1)
		If Asc(char) = 10 Then
			? Asc(char), ii, i - 1, Mid(sPathes, ii, i - 1)
			aPathes(c) = Mid(sPathes, ii, i - 1)
			c += 1
			i += 1
			ii = i
		Else
			i += 1
		End If	
	Wend
	If ii < i Then
		aPathes(c) = Mid(sPathes, ii, i - 1)
	Else
		c -= 1
	End If
	Redim Preserve aPathes(c)
End Sub

Dim As String sPathes =  "/path1/path2/itemB" & LF & _
						 "/path3/itemC" & LF & _
						 "/path1/path2/itemA" & LF & _
						 "/path3/itemA" & LF & _
						 "/itemD"

PrintDirStructur(sPathes)

Sleep
The result is different than I expect

Code: Select all

10             1             18           /path1/path2/itemB
10             20            31           /path3/itemC
/path1/path2/itemA
10             33            50           /path1/path2/itemA
/path3/itemA
/itemD
10             52            63           /path3/itemA
/itemD
Can you explain why this happens?
UEZ
Posts: 988
Joined: May 05, 2017 19:59
Location: Germany

Re: What's wrong here?

Post by UEZ »

I found the issue -> I used Mid wrongly.

Code: Select all

#Define LF	Chr(10)

Sub PrintDirStructur(sPathes As String)
	ReDim As String aPathes(1000)
	Dim As String char
	Dim As integer i = 1, ii = 1, c = 0
	While i <= Len(sPathes)
		char = Mid(sPathes, i, 1)
		If Asc(char) = 10 Then
			aPathes(c) = Mid(sPathes, ii, i - ii)
			c += 1
			i += 1
			ii = i
		Else
			i += 1
		End If	
	Wend
	If ii < i Then
		aPathes(c) = Mid(sPathes, ii, i - ii)
	Else
		c -= 1
	End If
	Redim Preserve aPathes(c)
	For i = 0 To c
		? aPathes(i)
	Next
End Sub

Dim As String sPathes =  "/path1/path2/itemB" & LF & _
						 "/path3/itemC" & LF & _
						 "/path1/path2/itemA" & LF & _
						 "/path3/itemA" & LF & _
						 "/itemD"

PrintDirStructur(sPathes)

Sleep
dodicat
Posts: 7983
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: What's wrong here?

Post by dodicat »

I can use this splitter.

Code: Select all


Function StringSplit(s_in As String,chars As String,result() As String) As Long
    Dim As Long ctr,ctr2,k,n,LC=len(chars)
    dim As boolean tally(Len(s_in))
    #macro check_instring()
        n=0
        while n<Lc
        If chars[n]=s_in[k] Then 
        tally(k)=true
        If (ctr2-1) Then ctr+=1
        ctr2=0
        exit while
        end if
        n+=1
       wend
    #endmacro
   
    #macro split()
    If tally(k) Then
        If (ctr2-1) Then ctr+=1:result(ctr)=Mid(s_in,k+2-ctr2,ctr2-1)
        ctr2=0
    End If
    #endmacro
    '==================  LOOP TWICE =======================
    For k  =0 To Len(s_in)-1
        ctr2+=1:check_instring()
    Next k
    if ctr=0 then
         if len(s_in) andalso instr(chars,chr(s_in[0])) then ctr=1':beep
         end if
    If ctr Then Redim result(1 To ctr): ctr=0:ctr2=0 Else  Return 0
    For k  =0 To Len(s_in)-1
        ctr2+=1:split()
    Next k
    '===================== Last one ========================
    If ctr2>0 Then
        Redim Preserve result(1 To ctr+1)
        result(ctr+1)=Mid(s_in,k+1-ctr2,ctr2)
    End If
    Return Ubound(result)
End Function


dim as string p

p=!"/path1/path2/itemA\n"
p+=!"/path1/path2/itemB\n"
p+=!"/path3/itemC\n"
p+=!"/itemD\n"
print p

'this macro is a comment
#macro required_outcome
root
+ itemD (items before paths)
+ path1
  + path2
    + itemA
    + itemB
+ path3
  + itemC
  TODO
  FROM THE ELEMENTS:
 1            path1
 2            path2
 3            itemA
 4            path1
 5            path2
 6            itemB
 7            path3
 8            itemC
 9            itemD
 CREATE THE ARRAY I() TO order
  #endmacro

redim as string a()
stringsplit(p,chr(asc("/"),10),a())
for n as long=lbound(a) to ubound(a)
    print n, a(n)
next n

print
dim as long I(1 to 7)={9,1,2,3,6,7,8} 'arrray elements needed in order

dim as string p2="root"+chr(10)
for n as long=1 to 7
    dim as string sp
    if n>1 and n<6 then sp=string(n\2," ") else sp=""'handle the spaces optional
   p2+=sp+" + "+a(i(n))+chr(10)
next

print p2
sleep

 
It splits by any of the deliminator characters.
MrSwiss
Posts: 3910
Joined: Jun 02, 2013 9:27
Location: Switzerland

Re: What's wrong here?

Post by MrSwiss »

My StringSplit Function, which uses 'strtok' from FB's CRT:

Code: Select all

' this is part of my: String_Procs.bi -- (c) 2019, MrSwiss
#Include "crt/string.bi"                ' needed for: SplitString()

Private Function SplitString( _         ' uses CRT's strtok() Function
    ByRef ssrc  As Const String, _      ' string to be searched
    ByRef chrs  As Const String, _      ' character(s), to search for
          res() As String _             ' result String array (ByRef, implicit!)
    ) As Long                           ' negative = error | >= 0 = OK
    Dim As Long     retv = 0            ' to hold return value

    If Len(chrs) = 0 Then retv -= 2     ' nothing to search for, set err
    If Len(ssrc) = 0 Then retv -= 1     ' no source string, set err
    If retv < 0 Then Return retv        ' return ERROR code (negative value)

    Erase(res)                          ' delete dyn. array's content (if any)
    Dim As String       s = ssrc        ' local variables: s = keeps ssrc
    Dim As ZString Ptr  psz = 0         ' result ptr (from strtok())
    Dim As UInteger     i = 0           ' counter, used as: array-index

    psz = strtok(s, chrs)               ' destroys s (must be reset! before reuse)
    While psz                           ' just to get required array size
        i += 1 : psz = strtok(0, chrs)  ' i - 1 = UBound(res)
    Wend

    retv = i - 1                        ' set arrays upper bound (return value)
    ReDim res(0 To retv)                ' size array (using retv)
    i = 0 : s = ssrc : psz = 0          ' reset i, s and psz (for next run)

    psz = strtok(s, chrs)               ' get first token (string-part)
    While psz                           ' run until psz is = 0
        res(i) = *psz                   ' assign token to array
        psz = strtok(0, chrs)           ' get next token (string-part)
        i += 1                          ' increment index
    Wend

    Return retv                         ' upper array bound (lower = 0 = default)
End Function
Tested on WIN (myself)/LIN (dodicat) and working ...
UEZ
Posts: 988
Joined: May 05, 2017 19:59
Location: Germany

Re: What's wrong here?

Post by UEZ »

Thank you both for your splitter functions - might be useful someday... ^^
Post Reply