Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Experimenting with a "StringList" type for simpler handling of string arrays/lists
#1
Question 
Hey!

I'm quite new to QB64, although I dabbled with some QuickBasic a few decades ago.

It seems that QB64 has no "list" data type, but only arrays. Since I have an irrational fear of arrays, I am experimenting with creating a "StringList" container instead, which behind the scenes is based on arrays, but will keep me away from most of the work related to dealing with array sizes etc. and provides a few nifty functions for handling the list. Specifically, the code adds a type, "StringList", which relies on a 2d array with a defined max size. It might not be the most memory efficient solution, since each array is max'ed at the size of the largest StringList used, but at least in some basic testing it seems to work decently.

Current functions are (not tested extensively, so some of them might be buggy):
  • StringList_Init (ListName) - Initialize the stringlist after DIM'ing it
  • StringList_AddItem (ListName, String) - Add a new string as the last item
  • StringList_InsertItem (ListName, String, Pos) - Insert a new string at a specified index/position
  • StringList_RemoveItem (ListName, ItemNo/Index) - Remove the specified item no.
  • StringList_SetItem (ListName, ItemNo, String) - Set/replace a specific list item
  • StringList_Clear (ListName) - Clear the entire string list
  • StringList_GetItem$ (ListName, index) - Get the text at item no./index
  • StringList_ItemCount& (sl As StringList)  - Return the number of items in the list
  • StringList_Text$ (sl As StringList)  - Return the entire contents of the stringlist in one string
  • StringList_Swap (ListName, indexA, indexB) - Swap two items in the list
  • StringList_SaveToFile%% (ListName, filename) - Save the string list to the specified plain text file
  • StringList_LoadFromFile%% (ListName, filename) - Load list from the specified plain text file

Before I spend too much time on this, I'd be curious to hear from someone with more QB64 experience, whether this concept is solid and whether something better already exists? I can't imagine that I am the first to try something like this, and maybe there is some big disadvantage, that I haven't yet discovered?

What do you think?

Here's the code as it looks right now:

Code: (Select All)

Type StringList
    id As Long
End Type


'==========================================================================
' Subs and Functions
'--------------------------------------------------------------------------

'__________________________________________________________________________

' To limit potential memory issues, do not set too high!
Const SL_MAX_LISTS = 10 ' Maximum number of lists
Const SL_MAX_ITEMS = 1000000 ' Maximum items per list

' Shared storage
Dim Shared SL_Data(1 To SL_MAX_LISTS, 1 To SL_MAX_ITEMS) As String
Dim Shared SL_Count(1 To SL_MAX_LISTS) As Long
Dim Shared SL_Used(1 To SL_MAX_LISTS) As _Byte

'__________________________________________________________________________

' Initialize a StringList

Sub StringList_Init (sl_id As StringList)
    Dim i As Long
    For i = 1 To SL_MAX_LISTS
        If SL_Used(i) = 0 Then
            SL_Used(i) = -1
            SL_Count(i) = 0
            sl_id.id = i
            Exit Sub
        End If
    Next
    Print "No free StringList slots!"
End Sub
'__________________________________________________________________________

' Add item to end

Sub StringList_AddItem (sl_id As StringList, txt_str As String)
    If SL_Count(sl_id.id) >= SL_MAX_ITEMS Then
        Print "Error: List exceeded maximum items."
        Exit Sub
    End If
    SL_Count(sl_id.id) = SL_Count(sl_id.id) + 1
    SL_Data(sl_id.id, SL_Count(sl_id.id)) = txt_str
End Sub
'__________________________________________________________________________

' Insert item at position

Sub StringList_InsertItem (sl_id As StringList, txt_str As String, insertAt As Long)
    Dim i As Long
    If insertAt < 1 Or insertAt > SL_Count(sl_id.id) + 1 Then
        Print "Error: Invalid insert sl_index."
        Exit Sub
    End If
    If SL_Count(sl_id.id) >= SL_MAX_ITEMS Then
        Print "Error: List exceeded maximum items."
        Exit Sub
    End If

    For i = SL_Count(sl_id.id) To insertAt Step -1
        SL_Data(sl_id.id, i + 1) = SL_Data(sl_id.id, i)
    Next

    SL_Data(sl_id.id, insertAt) = txt_str
    SL_Count(sl_id.id) = SL_Count(sl_id.id) + 1
End Sub
'__________________________________________________________________________

' Remove item at sl_index

Sub StringList_RemoveItem (sl_id As StringList, sl_index As Long)
    Dim i As Long
    If sl_index < 1 Or sl_index > SL_Count(sl_id.id) Then
        Print "Error: Invalid remove sl_index."
        Exit Sub
    End If

    For i = sl_index To SL_Count(sl_id.id) - 1
        SL_Data(sl_id.id, i) = SL_Data(sl_id.id, i + 1)
    Next

    SL_Data(sl_id.id, SL_Count(sl_id.id)) = ""
    SL_Count(sl_id.id) = SL_Count(sl_id.id) - 1
End Sub
'__________________________________________________________________________

' Replace item at sl_index

Sub StringList_SetItem (sl_id As StringList, sl_index As Long, txt_str As String)
    If sl_index < 1 Or sl_index > SL_Count(sl_id.id) Then
        Print "Error: Invalid sl_index in SetItem."
        Exit Sub
    End If

    SL_Data(sl_id.id, sl_index) = txt_str
End Sub
'__________________________________________________________________________

' Clear entire list

Sub StringList_Clear (sl_id As StringList)
    Dim i As Long
    For i = 1 To SL_Count(sl_id.id)
        SL_Data(sl_id.id, i) = ""
    Next
    SL_Count(sl_id.id) = 0
End Sub
'__________________________________________________________________________

' Get item at sl_index

Function StringList_GetItem$ (sl_id As StringList, sl_index As Long)
    If sl_index < 1 Or sl_index > SL_Count(sl_id.id) Then Exit Function
    StringList_GetItem = SL_Data(sl_id.id, sl_index)
End Function
'__________________________________________________________________________

' Item count

Function StringList_ItemCount& (sl_id As StringList)
    StringList_ItemCount = SL_Count(sl_id.id)
End Function
'__________________________________________________________________________

' Full text (all items)

Function StringList_Text$ (sl_id As StringList)
    Dim i As Long
    Dim result As String
    For i = 1 To SL_Count(sl_id.id)
        result = result + SL_Data(sl_id.id, i)
        If i < SL_Count(sl_id.id) Then result = result + Chr$(10)
    Next
    StringList_Text = result
End Function
'__________________________________________________________________________

' Swap two items

Sub StringList_Swap (sl_id As StringList, sl_indexA As Long, sl_indexB As Long)
    Dim tmp As String

    If sl_indexA < 1 Or sl_indexA > SL_Count(sl_id.id) Then Exit Sub
    If sl_indexB < 1 Or sl_indexB > SL_Count(sl_id.id) Then Exit Sub
    If sl_indexA = sl_indexB Then Exit Sub

    tmp = SL_Data(sl_id.id, sl_indexA)
    SL_Data(sl_id.id, sl_indexA) = SL_Data(sl_id.id, sl_indexB)
    SL_Data(sl_id.id, sl_indexB) = tmp
End Sub
'__________________________________________________________________________

' Save StringList to file

Function StringList_SaveToFile%% (sl_id As StringList, sl_filename As String)

    Dim i As Long
    Dim ff As Integer

    ' Reject empty sl_filename
    If Len(sl_filename) = 0 Then
        StringList_SaveToFile = _FALSE
        Exit Function
    End If

    ' Get a free file handle
    ff = FreeFile

    ' Try opening file
    Open sl_filename For Output As #ff

    ' If OPEN failed, QB64 sets ERR
    If Err <> 0 Then
        StringList_SaveToFile = _FALSE
        Exit Function
    End If

    ' Write items
    For i = 1 To SL_Count(sl_id.id)
        Print #ff, SL_Data(sl_id.id, i)
    Next

    Close #ff
    StringList_SaveToFile = _TRUE

End Function
'__________________________________________________________________________

' Load StringList from file

Function StringList_LoadFromFile%% (sl_id As StringList, sl_filename As String)

    Dim ff As Integer
    Dim lineIn As String

    ' Validate sl_filename
    If Len(sl_filename) = 0 Then
        StringList_LoadFromFile = _FALSE
        Exit Function
    End If

    ' File must exist
    If _FileExists(sl_filename) = 0 Then
        StringList_LoadFromFile = _FALSE
        Exit Function
    End If

    ' Clear current contents
    StringList_Clear sl_id

    ' Open file safely
    ff = FreeFile
    Open sl_filename For Input As #ff

    ' Check for open failure
    If Err <> 0 Then
        StringList_LoadFromFile = _FALSE
        Exit Function
    End If

    ' Read file
    Do Until EOF(ff)
        If SL_Count(sl_id.id) >= SL_MAX_ITEMS Then Exit Do
        Line Input #ff, lineIn
        SL_Count(sl_id.id) = SL_Count(sl_id.id) + 1
        SL_Data(sl_id.id, SL_Count(sl_id.id)) = lineIn
    Loop

    Close #ff
    StringList_LoadFromFile = _TRUE

End Function

And here's a quick, messy example of some the functions:

Code: (Select All)

' First DIM the lists
Dim L As StringList
Dim N As StringList

' Remember to initialize the lists
StringList_Init L
StringList_Init N

' Add some test items to the stringlist:
StringList_AddItem L, "One"
StringList_AddItem L, "Two"
StringList_AddItem L, "Three"

' Add items to numeric list
'For i = 1 To 10
'StringList_AddItem N, Str$(i)
'Next
StringList_AddItem N, "1"
StringList_AddItem N, "2"
StringList_AddItem N, "3"
StringList_AddItem N, "4"
StringList_AddItem N, "5"
StringList_AddItem N, "6"
StringList_AddItem N, "7"
StringList_AddItem N, "8"
StringList_AddItem N, "9"
StringList_AddItem N, "10"

' Manipulate text list
StringList_InsertItem L, "Inserted", 2
StringList_SetItem L, 3, "Replaced"
StringList_RemoveItem L, 1

StringList_AddItem N, "11"
StringList_AddItem N, "12"
StringList_AddItem N, "13"

Print "Text List:"
Print StringList_Text(L)
Print , "Count is: " + Str$(StringList_ItemCount(L))


Print
Print "Numeric List:"
Print StringList_Text(N)
Print , "Count is: " + Str$(StringList_ItemCount(N))


If StringList_SaveToFile(N, "myexport-tempdelete.txt") = _TRUE Then
    Print "All saved!"
    Else
    Print "Not saved!"
End If
Reply


Messages In This Thread
Experimenting with a "StringList" type for simpler handling of string arrays/lists - by Heimdall - 12-15-2025, 08:54 PM

Possibly Related Threads…
Thread Author Replies Views Last Post
  Sub not Reconizing Dim as String pmackay 18 1,476 10-16-2025, 03:32 PM
Last Post: pmackay
  for performance, what's the best variable type to use for boolean _TRUE & _FALSE ? madscijr 12 1,257 09-29-2025, 02:59 PM
Last Post: dakra137
  Using modulo to loop through lists fistfullofnails 3 723 09-03-2025, 11:50 PM
Last Post: fistfullofnails
  Loading from file into _MEM? and LEN a TYPE... Unseen Machine 9 976 08-03-2025, 02:55 AM
Last Post: SMcNeill
  Illegal string-number conversion Herve 7 774 07-07-2025, 09:53 AM
Last Post: a740g

Forum Jump:


Users browsing this thread: 1 Guest(s)