![]() |
Forum Index : Microcontroller and PC projects : Question on field$() function
Author | Message | ||||
William Leue Guru ![]() Joined: 03/07/2020 Location: United StatesPosts: 405 |
I noticed that the field$() does not support strings where the delimiters can be multi-character strings. This is different from the way similar functions work in C and other languages. Running this little test program: string1$ = "A B C " string2$ = "A B C " n = 1 do s$ = field$(string1$, n, " ") print "n: ";n; " s$: ";s$ inc n loop until s$ = "" print "" n = 1 do s$ = field$(string2$, n, " ") print "n: ";n; " s$: ";s$ inc n loop until s$ = "" end you get: n: 1 s$: A n: 2 s$: B n: 3 s$: C n: 4 s$ n: 1 s$: A n: 2 s$: B n: 3 s$: B n: 4 s$: C n: 5 s$: C n: 6 s$: C n: 7 s$: C n: 8 Of course I can write a wrapper that compresses multi-character delimiter fields to single characters. But I wonder if anyone else has encountered this and has a nice solution. -Bill |
||||
Mixtel90![]() Guru ![]() Joined: 05/10/2019 Location: United KingdomPosts: 7937 |
I used Field$ to try to get delimiters of space *and* comma but it didn't work. I found the manual a little confusing on this point as it says "...'string2' is a string holding the delimiters (more than one can be used)." Ideally I'd have liked to get "load a, 5" but Field$ lets you have either the space or the comma, but not both. String2=" ," lets you have "load a,5" or "load a 5". Mick Zilog Inside! nascom.info for Nascom & Gemini Preliminary MMBasic docs & my PCB designs |
||||
CaptainBoing![]() Guru ![]() Joined: 07/09/2016 Location: United KingdomPosts: 2170 |
this does. VB-work-a-like Split() function . returns the number of elements and populates a global array with them . |
||||
William Leue Guru ![]() Joined: 03/07/2020 Location: United StatesPosts: 405 |
For what it's worth, here's a little wrapper around field$() that will work with multi-character delimiter fields. It's not very efficient. ' Wrapper for field$() to support multi-character delimiter fields function mfield$(s$, n, d$) local i, j, hit z$ = left$(d$, 1) r$ = "" hit = 0 for i = 1 to len(s$) c$ = mid$(s$, i, 1) for j = 1 to len(d$) if mid$(d$, j, 1) = c$ then if not hit then r$ = r$+c$ hit = 1 end if else hit = 0 end if next j if not hit then r$ = r$ + c$ next i f$ = field$(r$, n, d$) mfield$ = f$ end function -Bill |
||||
thwill![]() Guru ![]() Joined: 16/09/2019 Location: United KingdomPosts: 4311 |
Hey Bill, Two simple optimisations: - Use "INC r$, c$" instead of "r$ = r$ + c$" - if you prefer you can use CAT insted of INC, they are synonyms. - Don't include variable in NEXT commands, i.e. write "NEXT" instead of "NEXT i" or "NEXT j" Best wishes, Tom MMBasic for Linux, Game*Mite, CMM2 Welcome Tape, Creaky old text adventures |
||||
jirsoft![]() Guru ![]() Joined: 18/09/2020 Location: Czech RepublicPosts: 533 |
I'm using in my programs some simple function for remove duplicated of delimiter FUNCTION removeMulti(s AS STRING, d AS STRING) AS STRING LOCAL INTEGER p = 1 LOCAL STRING md = d + d removeMulti = s DO WHILE removeMulti<>"" AND p<>0 p = INSTR(removeMulti, md) IF p>0 THEN removeMulti = LEFT$(removeMulti, p-1) + MID$(removeMulti, p+1) ENDIF LOOP END FUNCTION Then you can on begin of your's first code snippet use string2$=removeMulti("A B C ", " ") and it should work... Jiri Napoleon Commander and SimplEd for CMM2 (GitHub), CMM2.fun |
||||
Mixtel90![]() Guru ![]() Joined: 05/10/2019 Location: United KingdomPosts: 7937 |
Thanks everyone. It's something else for me to have a look at. :) Mick Zilog Inside! nascom.info for Nascom & Gemini Preliminary MMBasic docs & my PCB designs |
||||
jirsoft![]() Guru ![]() Joined: 18/09/2020 Location: Czech RepublicPosts: 533 |
Tou can simply use "," as delimiter and then remove spaces on begin and end of every field... FUNCTION NCtrim(s AS STRING) AS STRING 'remove white chars from both end NCtrim = NClTrim(NCrTrim(s)) END FUNCTION FUNCTION NClTrim(s AS STRING) AS STRING 'left trim function (remove white chars from left) NClTrim = s DO WHILE NClTrim <> "" AND ASC(LEFT$(NClTrim,1)) < 33 NClTrim = MID$(NClTrim, 2) LOOP END FUNCTION FUNCTION NCrTrim(s AS STRING) AS STRING 'right trim function (removes white chars from right) NCrTrim = s DO WHILE NCrTrim <> "" AND ASC(RIGHT$(NCrTrim,1)) < 33 NCrTrim = LEFT$(NCrTrim, LEN(NCrTrim) - 1) LOOP END FUNCTION Jiri Napoleon Commander and SimplEd for CMM2 (GitHub), CMM2.fun |
||||
Mixtel90![]() Guru ![]() Joined: 05/10/2019 Location: United KingdomPosts: 7937 |
Trouble is you don't know which delimiter has been used. It could be a single space, single comma, or comma then space. Two spaces is possible, I suppose. Space then comma or two commas is unlikely. At the moment I just specify that you can use either a single comma or a single space. At least it works that way and it was easy. :) I use a single function that's called repeatedly, returning the next argument each time or a null string if there are none left. That's because the number of arguments for a command varies, sometimes varying for the same command. The delimiter at each stage can change. I have other problems to sort out yet though. Messing about with that bit can wait. lol Mick Zilog Inside! nascom.info for Nascom & Gemini Preliminary MMBasic docs & my PCB designs |
||||
jirsoft![]() Guru ![]() Joined: 18/09/2020 Location: Czech RepublicPosts: 533 |
I'm using something very similar: OPTION EXPLICIT DIM STRING dest(1) ? split(TIME$, ":", dest()) arrPrint(dest()) ? split(DATE$, "-", dest()) arrPrint(dest()) END FUNCTION split(s AS STRING, d AS STRING, ret() AS STRING) AS INTEGER LOCAL STRING hlp = s+d LOCAL INTEGER p = 1 split = 0 DO WHILE hlp <> "" AND p>0 p = INSTR(hlp, d) IF p>0 THEN INC split hlp = MID$(hlp, p+1) ENDIF LOOP ON ERROR SKIP ERASE dest() IF MM.ERRNO THEN split = -1 'error ELSE IF split>0 THEN DIM STRING dest(split) LOCAL INTEGER i hlp = s+d FOR i = 1 TO split p = INSTR(hlp, d) dest(i) = LEFT$(hlp, p-1) hlp = MID$(hlp, p+1) NEXT i ENDIF ENDIF END FUNCTION SUB arrPrint(a() AS STRING) LOCAL INTEGER i FOR i = 1 TO BOUND(a(), 1) ?"'"a(i)"'" NEXT i END SUB Jiri Napoleon Commander and SimplEd for CMM2 (GitHub), CMM2.fun |
||||
jirsoft![]() Guru ![]() Joined: 18/09/2020 Location: Czech RepublicPosts: 533 |
I would do it very simple: OPTION EXPLICIT DIM STRING test = "LOAD a, 5,7,q , 6" ? "'"test"'" ? "'"justOneDelimiter(test)"'" END FUNCTION justOneDelimiter(s AS STRING) AS STRING LOCAL INTEGER p = 1 justOneDelimiter = s DO WHILE justOneDelimiter<>"" AND p>0 p = INSTR(justOneDelimiter, ",") 'replace "," with SPACE IF p>0 THEN justOneDelimiter = LEFT$(justOneDelimiter, p-1) + " " + MID$(justOneDelimiter, p+1) ENDIF LOOP p = 1 DO WHILE justOneDelimiter<>"" AND p>0 p = INSTR(justOneDelimiter, " ") 'no more than 1 SPACE IF p>0 THEN justOneDelimiter = LEFT$(justOneDelimiter, p-1) + MID$(justOneDelimiter, p+1) ENDIF LOOP END FUNCTION Result is 'LOAD a, 5,7,q , 6' 'LOAD a 5 7 q 6 You can then use just SPACE as delimiter for your purpose... Jiri Napoleon Commander and SimplEd for CMM2 (GitHub), CMM2.fun |
||||
William Leue Guru ![]() Joined: 03/07/2020 Location: United StatesPosts: 405 |
Thanks everyone! This has been a productive discussion. -Bill |
||||
Mixtel90![]() Guru ![]() Joined: 05/10/2019 Location: United KingdomPosts: 7937 |
Thanks, Jiri - I hadn't even considered that approach. :) Mick Zilog Inside! nascom.info for Nascom & Gemini Preliminary MMBasic docs & my PCB designs |
||||
![]() |
![]() |
The Back Shed's forum code is written, and hosted, in Australia. | © JAQ Software 2025 |