CWSTR Array Functions

Started by James Fuller, July 19, 2016, 09:36:29 AM

Previous topic - Next topic

James Fuller

Jose,
  Any CWSTR,CBSTR Array functions (SCAN,SORT) on your ToDo list?

James

José Roca

I'm afraid not. They're not strings, but pointers to classes. This will make the task slow and very difficult.

James Fuller

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


José Roca

The C runtime already provides a qsort function.

José Roca

#4
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.

Paul Squires

Classes are just TYPE's so you should be able to use LEN or SIZEOF to get the size?
Paul Squires
PlanetSquires Software

José Roca

#6
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.

James Fuller

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


José Roca

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...