Namespace: PSU_ Machine Code Ext.s - psu_ S(uper)BASIC PROCedures/FuNctions
(PSU: Peter Sulzer Utilities)

PSU_FPARSE%(initialised_float_var, expression_convertible_to_string)
(parameter 2 maybe a variable like string$, '1.2', a float or integer variable
or even any expression that can be converted to a string like 3<4(!). But it's
recommended that you pass a string expression. The function result is the
the number of characters which could be converted to a float or a negative
error number (e.g. -17 for error in expression). Be careful if your number
ends with 'e' or 'E', this cannot be converted. After 'e' a digit MUST
follow(!). This is IMHO a fault of CN.DTOF as a number ending with a dot
is okay. So e.g. '9eleven' should IMO be converted to 9 (result=1).

Examples

a=99:rslt%=PSU_FPARSE(a,'1'):REMark Now rslt%=1, a=1
a=99:rslt%=PSU_FPARSE(a,'1.'):REMark Now rslt%=2, a=1
a=99:rslt%=PSU_FPARSE(a,'1.23'):REMark Now rslt%=4, a=1.23
a=99:rslt%=PSU_FPARSE(a,'1.23 2 3 4'):REMark Now rslt%=4, a=1.23
a=99:rslt%=PSU_FPARSE(a,'1.Rest_of_string'):REMark Now rslt%=2, a=1
a=99:rslt%=PSU_FPARSE(a,'1e'):REMark Now rslt%=-17, a=99(!)
a=99:rslt%=PSU_FPARSE(a,'1eRest_of_string'):REMark Now rslt%=-17, a=99(!)
a=99:rslt%=PSU_FPARSE(a,'1e0Rest_of_string'):REMark Now rslt%=3, a=1
a=99:rslt%=PSU_FPARSE(a,3.6):REMark Now rslt=1, a=3.6
a=99:rslt%=PSU_FPARSE(a,'3+4'):REMark Now rslt=1, a=3
a=99:rslt%=PSU_FPARSE(a,3+4):REMark Now rslt=1, a=7
CLEAR:a=99:rslt%=PSU_FPARSE(a,s$):REMark Now rslt=-17, a=99
a=99:rslt%=PSU_FPARSE(a):REMark ERROR bad parameter
DIM arr(3):a=99:rslt%=PSU_FPARSE(a,arr):REMark ERROR bad parameter
REMark ... For more examples see the unit tests "fparsUtest_bas" and
remark ... "fparsUtest2_bas" (latter requires VALIDI_bin from knoware.no)

E.g. use it like this:

DEFAULT_VALUE='-1.6158502672999e616'
a=99:if NOT PSU_FPARSE(a,var$):a=DEFAULT_VALUE:END IF
REMark a is now value of var$ (if convertable to float) or the DEFAULT_VALUE.
REMark THE FIRST PARAMETER (variable which is assigned) MUST BE INITIALISED (at
REMARK least on none SMSQ/E sytems)!

After implementing it (with CN.DTOF) I realised tha CN.DTOF returns the position
of the next character which has not been converted. So PSU_FPARSE() returns NOT
0 (or 1) if the conversion was successful, but the number of characters from the
second parameter, which have been converted successfully.

This allows (finally) array initialisation (currently only 1 dimensional
arrays/array slices). See my example program
"fpars_arrini1_bas". It does initialise a floating point array, e.g.
DIM a(3,3):rslt=psu_farray_init1%(arr(2),'1 2 3 4.5e3)')
PRINT a(2)
REMark Outputs 1 2 3 4500 (replace spaces with linefeeds)

The example program also includes FuNction psu_eat_spc%(string$,pos) which
returns the first position in string$, starting from string$(pos), which is
no space.

I wanted to write a similar function to initialise multidimensional arrays. This
is unfortunately much more complex, than I have thought, so this has been left
open as an exercise for the user <GRIN>. You can use psu_farray_init1%() with array
slices as the above example shows.

However the main reason why I wrote psu_fparse%() is that, together with
the VALID%() funtion from knoware.no
(https://www.knoware.no/htm/toolkits.htm), it makes it possible to detect
implicitly omitted parameters or convert parameters passed as strings
into floats without the program crashing with an error. See the tests in
the unit test program "fparsUtest2_bas", which call the function
test_paraf(). Here a simple example:

100 DEFine FuNction indent$(s_$,flt_$)
110   REMark for flt_$ a number (float/integer) should be passed(!)
120   LOCal typ,indent%,flt,rslt%,slen%
130   indent%=2:flt=0
140   typ=VALID%(-1,flt_$)
150   SELect ON typ
160   =513
170     REMark Omitted or passed as string
180     slen%=LEN(s_$)
190     rslt%=PSU_FPARSE%(flt,flt_$)
200     IF rslt%>=0
210       IF flt>=0AND flt<=32765-slen%:indent%=INT(flt):END IF
220      END IF
230   =514
240     REMark Passed as float
250     slen%=LEN(s_$)
260     IF flt_$>=0AND flt_$<=32765-slen%:indent%=INT(flt_$):END IF
270   =515
280     REMark Passed as integer
290     indent%=flt_$
300   END SELect
310   RETurn FILL$(' ',indent%)&s_$
320 END DEFine

PRINT#0,indent$('Test')
  Test
PRINT#0,indent$('Test','Not convertable to a float')
  Test
PRINT#0,indent$('Test','4.3rest of convertable string')
    Test
PRINT#0,indent$('Test',4.7)
    Test
PRINT#0,indent$('Test',-1):REMark or ...,'-1')
  Test
PRINT#0,indent$('Test',32761):REMark or ...,'32761')
[LOT OF EMPTY LINES...]
 Test
PRINT#0,indent$('Test',32762):REMark or ...,'32762')
  Test
inum%=3:PRINT#0,indent$('Test',inum%)
   Test
dim arr(3):PRINT#0,indent$('Test',arr)
  Test
