Sugesstion String Split in FB

General FreeBASIC programming questions.
Post Reply
IBMInfo78
Posts: 3
Joined: May 16, 2022 0:08

Sugesstion String Split in FB

Post by IBMInfo78 »

Sugesstion Adding String internal Split() in FB.
Split(String)=>String Array.
grindstone
Posts: 862
Joined: May 05, 2015 5:35
Location: Germany

Re: Sugesstion String Split in FB

Post by grindstone »

This job can be done with just a few lines of code. No need for a new FB feature.

Code: Select all

Function SplitString(StringToSplit As String = "", array() As String) As UInteger
	Dim As String text = StringToSplit 'remind StringToSplit as working copy
	Dim As UInteger b = 1, e = 1 'pointer to text, begin and end
	Dim As UInteger x 'counter
	
	ReDim Array(0) 'reset array
	
	Do Until e = 0
		x += 1
		ReDim Preserve array(x) 'create new array element
		e = InStr(e + 1, text, " ") 'set end pointer to next space
		array(x) = Mid(text, b, e - b) 'cut text between the pointers and write it to the array
		b = e + 1 'set begin pointer behind end pointer for the next word
	Loop
	
	Return x 'return number of words
End Function

ReDim As String StringArray(0)

Print SplitString("The big brown fox jumped over the lazy dog", StringArray())

Print
For x As Integer = 1 To UBound(StringArray)
	Print stringArray(x)
Next

Sleep
FB_user_22
Posts: 3
Joined: Jan 30, 2022 18:30

Re: Sugesstion String Split in FB

Post by FB_user_22 »

These are unrelated statements for many users, especially new ones:
This job can be done with just a few lines of code.
No need for a new FB feature.
Just because something can be done with external code doesn't mean everyone who wants to use this language should be required to incorporate numerous workarounds to perform standard tasks.

And I would expect a built-in feature to be much faster than the external code, which has multiple "Redim" and "Mid" operations.

Each occasional user who wants this functionality will need to:
  • Do their own testing to ensure it will work as they intend
  • Put the related code in a private repository
  • Ensure they have enough documentation on how to use the external code
The occasional user might write FB code on more than one machine. Now they need to ensure their private repositories for typical (but not built-in) features are synchronized their desktop machine, tablet, etc.

The reasons I am adopting a language written by others include:
  • I don't have the time to write one myself.
  • It offers features that are absent in another language I am already using.
Even VB Script knows how to split a string to an array with a built in function.

It seems like a reasonable expectation that the effort to port a program from VBS to FB should not include creating the "split" function that exists in the program I already have working in VBS, but now want to move to FB for easier access to the clipboard -- which this post suggests may require more effort than I had hoped: viewtopic.php?p=290669

I would have expected a BASIC language to spare me the details of pointers, Windows handles, global constants named by others, and memory management when trying to use the Windows clipboard.
coderJeff
Site Admin
Posts: 4358
Joined: Nov 04, 2005 14:23
Location: Ontario, Canada
Contact:

Re: Sugesstion String Split in FB

Post by coderJeff »

moved to general
FB_user_22 wrote: Jun 04, 2022 0:00 I don't have the time to write one myself.
Fair enough. I should be so lucky that there are an over abundance of contributors to manage.

An old feature request: https://sourceforge.net/p/fbc/feature-requests/160/

If anyone wanted to work on this to learn how to add I'd be happy to share my thoughts.
fxm
Moderator
Posts: 12198
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Sugesstion String Split in FB

Post by fxm »

grindstone wrote: Jun 02, 2022 8:52 This job can be done with just a few lines of code
10 months ago I also proposed 3 different 'split()' / 'join()' functions:
viewtopic.php?p=284846#p284846
The third version has a split() function the most optimized from a runtime point of view (to avoid to execute a 'Redim Preserve string_array(...)' in a loop).
dodicat
Posts: 7997
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Sugesstion String Split in FB

Post by dodicat »

My old splitstring, compared with recent split by fxm.

Code: Select all

'#cmdline "-gen gcc -Wc -O2"
Function tally (somestring As const String,partstring As const String,arr() As Long) As Ulong
    Dim As Long i=-1,ln=Len(somestring),lnp=Len(partstring),count=0
     Redim arr(1 To ln)
    Do
        i+=1
        If somestring[i] <> partstring[0] Then continue do
        If somestring[i] = partstring[0] Then
            For j as long=0 To lnp-1
                If somestring[j+i]<>partstring[j] Then continue do
            Next j
        End If
        count+=1
        arr(count)=i+1
        i=i+lnp-1
    Loop Until i>=ln-1
    Redim Preserve arr(1 To count)
    Return count
End Function

Function splitstring(somestring As const String,partstring As const String,a() As String) As Long
    Redim As Long x()
    Var t= tally(somestring,partstring,x()),lps=Len(partstring)
    If t=0 Or Len(somestring)=0 Or lps=0 Then Return 0
    Redim a(1 To t+1)
    a(1)=Mid(somestring,1,x(1)-1)
    For n As Long=1 To Ubound(x)-1
        a(n+1)= Mid(somestring,x(n)+lps,x(n+1)-x(n)-lps)
    Next n
    a(Ubound(a))=Mid(somestring,x(Ubound(x))+lps)
    Return (t+1)=0
End Function

#include once "fbc-int/array.bi"

Function split(Byref s As Const String, result() As String, Byref delimiter As Const String = ",") As Integer
   
    Dim As Integer i
    Dim As String sindex = Mki(1)
    Dim As Integer used = Sizeof(Integer)
    Dim As Integer Ptr pindex = Cptr(Integer Ptr Ptr, @sindex)[0]
    Dim As Integer Ptr pused = Cptr(Integer Ptr, @sindex) + 1
    Dim As Integer Ptr pallocated = Cptr(Integer Ptr, @sindex) + 2
   
    If delimiter = "" Then Return 1  '' supplied delimiter empty
   
    Do
        Dim As Integer n = Instr(pindex[i], s, delimiter)
        If n = 0 Then Exit Do
        i += 1
        If used + Sizeof(Integer) > *pallocated Then
            *pused = used
            sindex &= Mki(n + Len(delimiter))
            pindex = Cptr(Integer Ptr Ptr, @sindex)[0]
        Else
            pindex[i] = n + Len(delimiter)
        End If
        used += Sizeof(Integer)
    Loop
   
    If i = 0 Then Return 2  '' no delimiter found in string
   
    If Ubound(result) - Lbound(result) < i Then
        Dim As Const FBC.FBARRAY Ptr pd = FBC.ArrayConstDescriptorPtr(result())
        If (pd->flags And FBC.FBARRAY_FLAGS_FIXED_LEN) Then Return 3  '' supplied fix-len result array() too small
        Redim Preserve result(Lbound(result) To Lbound(result) + i)
    End If
   
    For j As Integer = 0 To i - 1
        result(Lbound(result) + j) = Mid(s, pindex[j], pindex[j + 1] - pindex[j] - Len(delimiter))
    Next j
    result(Lbound(result) + i) = Mid(s, pindex[i])
    Return 0  '' OK
   
End Function


Dim As String g="123 456 789 345666abcd45600"
Dim As String delim="456 789 345"
Redim As String s(0)

For n As Long=1 To 23
    g+=g  'inflate the string
Next

Print "Length of string ";Len(g)
Print
Dim As Double t=Timer
Var n=splitstring(g,delim,s())

If n=0 Then
    Print Timer-t;"   seconds "
    Print
    print "index","value"

    For n As Long=Lbound(s) To 5
        Print n, s(n)
    Next
    Print ". . ."
    Print ". . ."
    For n As Long=Ubound(s) -5 To Ubound(s)
        Print n,s(n)
    Next
    Print
    Print "array dimensions ";Lbound(s);"  to  ";Ubound(s)
End If
print "___________________________________________"

redim s(0)
 t=Timer
 n=split(g,s(),delim)
If n=0 Then
    Print Timer-t;"   seconds "
    Print
    print "index","value"

    For n As Long=Lbound(s) To 5
        Print n, s(n)
    Next
    Print ". . ."
    Print ". . ."
    For n As Long=Ubound(s) -5 To Ubound(s)
        Print n,s(n)
    Next
    Print
    Print "array dimensions ";Lbound(s);"  to  ";Ubound(s)
End If

Sleep
 
tested 32/64, -gen gas, gcc, gas64 on official build and stw build.
Mine is slightly faster just now.
Post Reply