Home
JAQForum Ver 24.01
Log In or Join  
Active Topics
Local Time 10:36 01 Aug 2025 Privacy Policy
Jump to

Notice. New forum software under development. It's going to miss a few functions and look a bit ugly for a while, but I'm working on it full time now as the old forum was too unstable. Couple days, all good. If you notice any issues, please contact me.

Forum Index : Microcontroller and PC projects : Question on field$() function

Author Message
William Leue
Guru

Joined: 03/07/2020
Location: United States
Posts: 405
Posted: 02:50pm 11 Aug 2021
Copy link to clipboard 
Print this post

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 Kingdom
Posts: 7937
Posted: 03:37pm 11 Aug 2021
Copy link to clipboard 
Print this post

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 Kingdom
Posts: 2170
Posted: 04:10pm 11 Aug 2021
Copy link to clipboard 
Print this post

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 States
Posts: 405
Posted: 05:34pm 11 Aug 2021
Copy link to clipboard 
Print this post

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 Kingdom
Posts: 4311
Posted: 06:27pm 11 Aug 2021
Copy link to clipboard 
Print this post

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 Republic
Posts: 533
Posted: 11:31am 12 Aug 2021
Copy link to clipboard 
Print this post

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 Kingdom
Posts: 7937
Posted: 11:35am 12 Aug 2021
Copy link to clipboard 
Print this post

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 Republic
Posts: 533
Posted: 11:43am 12 Aug 2021
Copy link to clipboard 
Print this post

  Mixtel90 said  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".

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 Kingdom
Posts: 7937
Posted: 12:05pm 12 Aug 2021
Copy link to clipboard 
Print this post

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 Republic
Posts: 533
Posted: 12:25pm 12 Aug 2021
Copy link to clipboard 
Print this post

  CaptainBoing said  this does. VB-work-a-like Split() function .

returns the number of elements and populates a global array with them
.

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 Republic
Posts: 533
Posted: 12:43pm 12 Aug 2021
Copy link to clipboard 
Print this post

  Mixtel90 said  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

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 States
Posts: 405
Posted: 01:14pm 12 Aug 2021
Copy link to clipboard 
Print this post

Thanks everyone! This has been a productive discussion.

-Bill
 
Mixtel90

Guru

Joined: 05/10/2019
Location: United Kingdom
Posts: 7937
Posted: 01:33pm 12 Aug 2021
Copy link to clipboard 
Print this post

Thanks, Jiri - I hadn't even considered that approach. :)
Mick

Zilog Inside! nascom.info for Nascom & Gemini
Preliminary MMBasic docs & my PCB designs
 
Print this page


To reply to this topic, you need to log in.

The Back Shed's forum code is written, and hosted, in Australia.
© JAQ Software 2025