PlanetSquires Forums

Support Forums => General Board => Topic started by: James Fuller on July 19, 2016, 09:36:29 AM

Title: CWSTR Array Functions
Post by: James Fuller on July 19, 2016, 09:36:29 AM
Jose,
  Any CWSTR,CBSTR Array functions (SCAN,SORT) on your ToDo list?

James
Title: Re: CWSTR Array Functions
Post by: José Roca on July 19, 2016, 10:19:28 AM
I'm afraid not. They're not strings, but pointers to classes. This will make the task slow and very difficult.
Title: Re: CWSTR Array Functions
Post by: James Fuller on July 20, 2016, 01:46:41 PM
Probably not very speedy but ....


'=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
'I believe the QuickSort is from Ethan Winers ported to Fb by yetifoot.
'=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
#include "Afx/AfxStr.inc"

Sub QuickSort(ArrayToSort() As CWSTR, ByVal StartEl As Long, ByVal NumEls As Long)
'************************************************************
'Standard Non-Recursive QuickSort Routine
'************************************************************
  Dim As CWStr Temp
  Dim As Long First, Last, i, j, StackPtr
  Redim As Long QStack(NumEls \ 5 + 10)
    First = StartEl
    Last = StartEl + NumEls - 1
    Do
      Do
        Temp = ArrayToSort((Last + First) \ 2)
        i = First
        j = Last
        Do
          While ArrayToSort(i) < Temp   ' Swap < for > to do in descending order
            i = i + 1
          Wend
          While ArrayToSort(j) > Temp   ' Swap > for < to do in descending order
            j = j - 1
          Wend
          If i > j Then Exit Do
          If i < j Then Swap ArrayToSort(i), ArrayToSort(j)
          i = i + 1
          j = j - 1
        Loop While i <= j
        If i < Last Then
          QStack(StackPtr) = i
          QStack(StackPtr + 1) = Last
          StackPtr = StackPtr + 2
        End If
        Last = j
      Loop While First < Last
      If StackPtr = 0 Then Exit Do
      StackPtr = StackPtr - 2
      First = QStack(StackPtr)
      Last = QStack(StackPtr + 1)
    Loop
  Erase QStack
End Sub
'==============================================================================
'Case insensitive Array Scan
'------------------------------------------------------------------------------
Function CWStrArrayScan(sArray() As CWStr,sToMatch As CWStr) As Long
    Dim As Long i,j,sToMatchLen
    Dim As CWStr S1,S2
    S1 = Ucase(sToMatch)
    sToMatchLen = Len(sToMatch)
    Function = 1
    For i = LBound(sArray) To UBound(sArray)
        j+=1
        If Len(sArray(i)) = sToMatchLen Then
            S2 = Ucase(sArray(i))
            If S2 = S1 Then
                Return j
            EndIf
        EndIf
    Next i
End Function

'==============================================================================
Dim As CWStr str_array(0 To 4)
Dim As Long i

str_array(0) = "Zob"
str_array(1) = "Bob"
str_array(2) = "Hello"
str_array(3) = "Job"
str_array(4) = "Fob"

QuickSort(str_array(), 0, 5)

For i = 0 To 4
  Print str_array(i)
Next i
i = CWstrArrayScan(str_array(),"job")
Print "i = ";i
sleep

Title: Re: CWSTR Array Functions
Post by: José Roca on July 20, 2016, 03:43:11 PM
The C runtime already provides a qsort function.
Title: Re: CWSTR Array Functions
Post by: José Roca on July 20, 2016, 07:44:06 PM
There are a couple of problems to use qsort with an array of CWSTRs.


'// qsort CWStr comparison function
FUNCTION AfxCWstrCompare CDECL (BYVAL a AS WSTRING PTR, BYVAL b AS WSTRING PTR) AS LONG
   FUNCTION = wcscmp(a, b)
END FUNCTION

DIM rg(5) AS CWSTR = {"Zorro", "Alex", "Celine", "Bill", "Forest", "Dexter"}
qsort @rg(0), 6, 544, CPTR(ANY PTR, @AfxCWstrCompare)


1) How do I get the size of the class? Currently, it is 544 bytes (when using the 64-bit compiler), but this may change if I modify the code.

2) qsort does the sorting correctly, but after calling it, the programs GPFs when the array goes out of scope and the destructor for each CWSTR is called.
Title: Re: CWSTR Array Functions
Post by: Paul Squires on July 20, 2016, 08:15:18 PM
Classes are just TYPE's so you should be able to use LEN or SIZEOF to get the size?
Title: Re: CWSTR Array Functions
Post by: José Roca on July 20, 2016, 08:38:39 PM
No. LEN and SIZEOF only returns the size of the variables used, as if it was a type without functions, not the total size allocated for an instance of it. A type with functions is not longer a type, but a class.
Title: Re: CWSTR Array Functions
Post by: James Fuller on July 21, 2016, 10:38:02 AM
Jose,
This seems to work. Do you see any problems?
James

'==============================================================================
#define unicode
#define _WIN32_WINNT &h0602
#include Once "windows.bi"
#include Once "Afx/AfxStr.inc"
'==============================================================================
Private Sub QuickSort OVERLOAD (ArrayToSort() As CWSTR)
    Dim As CWStr Temp
    Dim As Long First, Last, i, j, StackPtr,StartEl,NumEls
    StartEl = LBound(ArrayToSort)
    NumEls = (UBound(ArrayToSort) - StartEl) + 1
    Redim As Long QStack(NumEls \ 5 + 10)
    First = StartEl
    Last = StartEl + NumEls - 1
    Do
      Do
        Temp = ArrayToSort((Last + First) \ 2)
        i = First
        j = Last
        Do
          While ArrayToSort(i) < Temp   ' Swap < for > to do in descending order
            i = i + 1
          Wend
          While ArrayToSort(j) > Temp   ' Swap > for < to do in descending order
            j = j - 1
          Wend
          If i > j Then Exit Do
          If i < j Then Swap ArrayToSort(i), ArrayToSort(j)
          i = i + 1
          j = j - 1
        Loop While i <= j
        If i < Last Then
          QStack(StackPtr) = i
          QStack(StackPtr + 1) = Last
          StackPtr = StackPtr + 2
        End If
        Last = j
      Loop While First < Last
      If StackPtr = 0 Then Exit Do
      StackPtr = StackPtr - 2
      First = QStack(StackPtr)
      Last = QStack(StackPtr + 1)
    Loop
  Erase QStack
End Sub

'==============================================================================
Dim As Long ff1,i,j
Dim As String sWord,sBuf,sList
Dim AS CWStr cws(1 To 395)
ff1 = FreeFile
Open "slist.txt" For Input As ff1
'Line Input #ff1,sList
Line Input #ff1,sList
Close #ff1
? AfxStrParseCount(sList)
For i = 395 To 1 Step -1
    j += 1
    cws(j) = AfxStrParse(sList,i)
Next
For i = 1 To 395
    ? cws(i)
Next
QuickSort(cws())
For i = 1 To 395
    ? cws(i)
Next

Sleep

Title: Re: CWSTR Array Functions
Post by: José Roca on July 23, 2016, 04:54:41 PM
I have been thinking about it and CWSTR have too much overhead (about 534 bytes each one) to be used efficiently in big arrays. It will be better to use safearrays. Writing a class for one dimensional safearrays is not too difficult, but as soon as I will post it, someone will ask about multidimensional safearrays...