Author Topic: Variable Length String Array-like Strings - Tools  (Read 2716 times)

0 Members and 1 Guest are viewing this topic.

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Variable Length String Array-like Strings - Tools
« on: February 20, 2021, 01:42:40 am »
Something I had to figure out again to add to Interpreter along lines of Luke's Get and Set for Longs and Doubles, fixed lengths is easy! ;-))

Code: QB64: [Select]
  1. OPTION _EXPLICIT '  b+ 2021-02-19
  2. _TITLE "Tools for Variable Length Array-Like Strings"
  3. '2021-02-19 all tests work with comma space delimiter, try comma alone next, OK! how about abc OK
  4. '2021-02-20 renaming done all tests look OK, go over tomorrow before add to SB1.
  5.  
  6. ' Todo change names of these functions
  7. REDIM test$(1 TO 20), deli$, i&, ins$, result$, insertplace AS LONG, testN AS LONG, getUser
  8.  
  9. deli$ = ", ":
  10. test$(1) = "1, 2, 3, 4"
  11. test$(2) = "1, 2, 3"
  12. test$(3) = "1, 2"
  13. test$(4) = "1"
  14. test$(5) = ""
  15.  
  16. 'deli$ = ",":
  17. 'test$(1) = "1,2,3,4"
  18. 'test$(2) = "1,2,3"
  19. 'test$(3) = "1,2"
  20. 'test$(4) = "1"
  21. 'test$(5) = ""
  22.  
  23. 'deli$ = "abc":
  24. 'test$(1) = "1abc2abc3abc4"
  25. 'test$(2) = "1abc2abc3"
  26. 'test$(3) = "1abc2"
  27. 'test$(4) = "1"
  28. 'test$(5) = ""
  29.  
  30.  
  31. ins$ = "insert"
  32.  
  33.     INPUT "Test GetVS$ function, give us an index to look up, 0 quits "; getUser
  34.     PRINT "*"; GetVS$(deli$, getUser, test$(1)); "*"
  35.     PRINT
  36. LOOP UNTIL getUser = 0
  37. '----------------------------------------- Test Delimiter/Word counter
  38. PRINT "test StrCount&, counting *" + deli$ + "*"
  39. FOR i& = 1 TO 5
  40.     PRINT test$(i&), "# of "; deli$; StrCount&(deli$, test$(i&))
  41. ' ---------------------------------------- Test Delimiter/Word locator
  42. PRINT: PRINT "test StrPlace&"
  43. PRINT "testing: "; test$(1)
  44. FOR i& = 1 TO 5
  45.     PRINT "Find: " + TS$(i&) + "th delimiter is at "; StrPlace&(deli$, i&, test$(1))
  46. ' ---------------------------------------- Test Insert between Multi Char Delimiters
  47. PRINT: PRINT: INPUT "Press enter for some Insert tests... enter "; insertplace
  48. FOR testN = 2 TO 5
  49.     PRINT "Insert from right to left in this string: "; test$(testN)
  50.     FOR insertplace = 6 TO 1 STEP -1
  51.         PRINT: PRINT "Test Insert, test string is *" + test$(testN) + "* insert at place #" + TS$(insertplace)
  52.         result$ = AStringInsert$(deli$, ins$, insertplace, test$(testN))
  53.         PRINT result$
  54.     NEXT
  55.     PRINT: INPUT "Press enter to continue... "; insertplace 'reuse variable instead of dim another
  56.     CLS
  57. ' ------------------------------------------ Test Replace String between Multi-Char Delimiters
  58. PRINT: PRINT: INPUT "Press enter for some Replace tests... enter "; insertplace
  59. FOR testN = 2 TO 5
  60.     PRINT "Replace from right to left in this string: " + test$(testN)
  61.     FOR insertplace = 6 TO 1 STEP -1
  62.         PRINT: PRINT "Test Replace, test string is *" + test$(testN) + "* Replace item #" + TS$(insertplace)
  63.         result$ = SetVS$(deli$, ins$, insertplace, test$(testN))
  64.         PRINT result$
  65.     NEXT
  66.     PRINT: INPUT "Press enter to continue... "; insertplace 'reuse variable instead of dim another
  67.     CLS
  68. PRINT "end of tests, goodbye! "
  69.  
  70.  
  71.  
  72.  
  73. FUNCTION AStringInsert$ (Delimiter$, Insert$, NthPlace&, AStringCopy$)
  74.     'use: Function StrCount& (Char$, AString$)
  75.     'use: Function StrPlace& (Char$, Nth&, Astring$)
  76.     'use: FUNCTION StrCopies$ (NumberOfCopies&, S$)
  77.  
  78.     REDIM Astring$, wCnt&, nthPlaceAt&, head$, tail$
  79.     Astring$ = AStringCopy$ 'AstringCopy$ gets changed so return result through function name$
  80.     wCnt& = StrCount&(Delimiter$, Astring$) + 1
  81.     'make sure we have enough delimiters
  82.     IF wCnt& <= NthPlace& THEN Astring$ = Astring$ + StrCopies$(NthPlace& - wCnt&, Delimiter$) ' string$ is the problem!!!!!
  83.     IF NthPlace& <= 1 THEN 'If something there then it comes before but if nothing probably just starting out.
  84.         IF Astring$ <> "" THEN Astring$ = Insert$ + Delimiter$ + Astring$ ELSE Astring$ = Insert$
  85.     ELSEIF NthPlace& > wCnt& THEN ' AString$ will be modified such that only insert has to be tacked to end after delimiter
  86.         Astring$ = Astring$ + Insert$
  87.     ELSEIF NthPlace& <= wCnt& THEN
  88.         nthPlaceAt& = StrPlace&(Delimiter$, NthPlace& - 1, Astring$)
  89.         head$ = MID$(Astring$, 1, nthPlaceAt& + LEN(Delimiter$) - 1) 'include delim
  90.         tail$ = MID$(Astring$, nthPlaceAt& + LEN(Delimiter$)) 'no delim
  91.         IF tail$ <> "" THEN
  92.             Astring$ = head$ + Insert$ + Delimiter$ + tail$
  93.         END IF
  94.     END IF
  95.     AStringInsert$ = Astring$
  96.  
  97. FUNCTION SetVS$ (Delimiter$, Insert$, NthPlace&, AStringCopy$) ' VS = Variable Siring Lengths
  98.     'use: FUNCTION StrCount& (S$, AString$)
  99.     'use: FUNCTION StrPlace& (S$, Index AS LONG, Astring$)
  100.     'use: FUNCTION StrCopies$ (NumberOfCopies&, S$)
  101.  
  102.     REDIM Astring$, wCnt&, nthPlaceAt&, nextAt&
  103.     Astring$ = AStringCopy$ 'AstringCopy$ gets changed so return result through function name$
  104.     wCnt& = StrCount&(Delimiter$, Astring$) + 1
  105.     'make sure we have enough delimiters
  106.     IF wCnt& <= NthPlace& THEN Astring$ = Astring$ + StrCopies$(NthPlace& - wCnt&, Delimiter$) ' string$ is the problem!!!!!
  107.     IF NthPlace& > wCnt& THEN ' AString$ will be modified such that only insert has to be tacked to end after delimiter
  108.         Astring$ = Astring$ + Insert$
  109.     ELSEIF wCnt& = 1 THEN 'If something there then it comes before but if nothing probably just starting out.
  110.         Astring$ = Insert$
  111.     ELSE ' NthPlace& is between 2 delimiters
  112.         nthPlaceAt& = StrPlace&(Delimiter$, NthPlace& - 1, Astring$)
  113.         nextAt& = StrPlace&(Delimiter$, NthPlace&, Astring$)
  114.         IF NthPlace& = wCnt& THEN 'no delim  on right end
  115.             Astring$ = MID$(Astring$, 1, nthPlaceAt& + LEN(Delimiter$) - 1) + Insert$
  116.         ELSEIF NthPlace& <= 1 THEN 'no delim of left end
  117.             IF nextAt& THEN Astring$ = Insert$ + MID$(Astring$, nextAt&) ELSE Astring$ = Insert$
  118.         ELSE 'between 2 delimiters
  119.             Astring$ = MID$(Astring$, 1, nthPlaceAt& + LEN(Delimiter$) - 1) + Insert$ + MID$(Astring$, nextAt&)
  120.         END IF
  121.     END IF
  122.     SetVS$ = Astring$
  123.  
  124. FUNCTION GetVS$ (Delimiter$, Index AS LONG, AString$) ' VS for Variable length string,
  125.     'use: FUNCTION StrCount& (S$, AString$)
  126.     'use: FUNCTION StrPlace& (S$, Index AS LONG, Astring$)
  127.     REDIM cnt AS LONG, p1 AS LONG, p2 AS LONG
  128.     cnt = StrCount&(Delimiter$, AString$) + 1
  129.     p1 = StrPlace&(Delimiter$, Index - 1, AString$)
  130.     p2 = StrPlace&(Delimiter$, Index, AString$)
  131.     IF Index > cnt OR Index < 1 THEN
  132.         EXIT FUNCTION ' beyond the limit of string
  133.     ELSEIF Index = 1 THEN
  134.         GetVS$ = MID$(AString$, 1, p2 - 1)
  135.     ELSEIF Index = cnt THEN
  136.         GetVS$ = MID$(AString$, p1 + LEN(Delimiter$))
  137.     ELSE 'between
  138.         GetVS$ = MID$(AString$, p1 + LEN(Delimiter$), p2 - p1 - LEN(Delimiter$))
  139.     END IF
  140.  
  141. FUNCTION StrCopies$ (NumberOfCopies&, S$) ' Concatenate repeated copies of S$
  142.     DIM i&
  143.     FOR i& = 1 TO NumberOfCopies&
  144.         StrCopies$ = StrCopies$ + S$
  145.     NEXT
  146.  
  147. FUNCTION StrCount& (S$, AString$) ' Count S$ in Astring$
  148.     REDIM place AS LONG, cnt AS LONG, lenS AS LONG
  149.     place = INSTR(AString$, S$): lenS = LEN(S$)
  150.     WHILE place
  151.         cnt = cnt + 1
  152.         place = INSTR(place + lenS, AString$, S$)
  153.     WEND
  154.     StrCount& = cnt
  155.  
  156. FUNCTION StrPlace& (S$, Index AS LONG, Astring$) ' Locate the Index number S$ in Astrin$
  157.     REDIM place AS LONG, cnt AS LONG, lenS AS LONG
  158.     place = INSTR(Astring$, S$): lenS = LEN(S$)
  159.     WHILE place
  160.         cnt = cnt + 1
  161.         IF cnt = Index THEN StrPlace& = place: EXIT FUNCTION
  162.         place = INSTR(place + lenS, Astring$, S$)
  163.     WEND
  164.  
  165.  
  166.  
  167. FUNCTION TS$ (n AS LONG)
  168.     TS$ = _TRIM$(STR$(n))
  169.  
  170.  
  171.  
  172.  

I wonder if you gamers would ever need this ;-))

EDIT: forgot name changes in the functions using other functions notes.
« Last Edit: February 20, 2021, 02:01:28 am by bplus »

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Variable Length String Array-like Strings - Tools
« Reply #1 on: February 20, 2021, 09:41:54 am »
BTW these type tools are THE workaround for TYPE not having arrays!

Now you can Type a Variable as string and var$ = GetVS$(MyDelim$, MyIndex&, MyType(i).MyArrInAString) after setting up with:

NewMyArrInAString$ = SetVS$(MyDelim$, MyNewOrModStr$, MyIndex&, MyType(i).MyArrInAString)

Yeah, clunky is better than nothing :)

Such tools give your code Unlimited Parameter strings to use, so you are not forced comma delimited arguments and maybe even don't have to order your arguments or list a complete set.

SUB MySub(parameters$)
      parse parameters for Arguments with GetVS$
end sub