V1ctor:
I see you are implementing PRINT USING after saying in the first version yo would never do it. I understand you.. I once coded a PRINT USING as an external library for RapidQ. What a mess!
Could you add a STRING USING keyword, a sort of sprintf?
QBasic never had it, so I used a hack in Ethan Winer's book using the NUL: device and FIELD, but you reused FIELD, so you killed that hack...
STRING USING (or VB's FORMAT) would be useful to preformat things before sending them to GUI, not all output is to console or to file..
While I was testing the PRINT USING statement, I tried to write a function to convert floating point numbers to strings.
Here are some preliminary results:
Code:
FUNCTION DStr (X AS DOUBLE) AS STRING
' Alternative STR$ function. Output is in fixed point format (no exponent).
IF X = 0 THEN DStr = " 0": EXIT FUNCTION
CONST InvLn10 = 0.43429448190325# ' 1/ Ln(10)
DIM Y AS DOUBLE
DIM E AS INTEGER, D AS INTEGER, L AS INTEGER
DIM A AS STRING
Y = ABS(X)
' Get exponent
E = INT(LOG(Y) * InvLn10)
' Convert mantissa to string
A = LTRIM$(STR$(Y / 10 ^ E))
' Remove decimal point (if any)
IF INSTR(A, ".") > 0 THEN
A = LEFT$(A, 1) + RIGHT$(A, LEN(A) - 2)
END IF
IF E >= 0 THEN ' Case |X| >=1
L = LEN(A)
D = E + 1 ' Position of decimal point
IF D > L THEN
' Pad with trailing zero's
A = A + STRING$(D - L, "0")
ELSEIF D < L THEN
' Restore decimal point at its right place
A = LEFT$(A, D) + "." + RIGHT$(A, L - D)
END IF
ELSE ' Case |X| < 1
' Pad with leading zero's
IF E < -1 THEN A = STRING$(-E - 1, "0") + A
A = "0." + A
END IF
' Add blank or negative sign
IF X >= 0 THEN A = " " + A ELSE A = "-" + A
DStr = A
END FUNCTION
FUNCTION FloatToStr (X AS DOUBLE, Ntot AS INTEGER, Ndec AS INTEGER) AS STRING
' Converts the floating point number X to a string
' Ntot = total length of string
' Ndec = number of decimal places
CONST MachEp = 2.22D-16
DIM P AS DOUBLE, Y AS DOUBLE
DIM D AS INTEGER, K AS INTEGER, L AS INTEGER
DIM S AS STRING, S1 AS STRING, S2 AS STRING
P = 10 ^ Ndec
Y = INT(ABS(X) * P + .5) / P ' Round X to Ndec decimal places
Y = (1 + MachEp) * Y ' Necessary to prevent negative roundoff error
IF X < 0 THEN Y = -Y
S = DStr(Y)
L = LEN(S)
K = INSTR(S, ".")
IF K > 0 THEN
D = L - K
IF D > Ndec THEN
' Remove unnecessary digits
S = LEFT$(S, K - 1) + "." + MID$(S, K + 1, Ndec)
ELSEIF D < Ndec THEN
' Pad with trailing zero's
S = S + STRING$(Ndec - D, "0")
END IF
END IF
L = LEN(S)
' Remove decimal point if it's the last character
IF RIGHT$(S, 1) = "." THEN S = LEFT$(S, L - 1)
' Add leading spaces if necessary
IF L < Ntot THEN S = SPACE$(Ntot - L) + S
FloatToStr = S
END FUNCTION
Quite insufficient of course... But maybe a starting point ?
Jean Debord
Thanks, Jean.
Perhaps I could also dig out my PRINT USING library for RapidQ
:
It would be of no use in FB, as it does'nt allow variable parameters lists. Speed has its constraints...EDITED: As a curiosity: it's here
http://www.basicguru.com/rapidq/contrib/using.bas
END OF EDIT.
I'm asking v1ctor for STRING USING (or whatever syntax he prefers) because he's probably building PRINT USING's output on a string, and it would be easy to give the user access to that string, it's not a brand new function to implement.
Well, I guess you could go the veeery long way around it and trap the console output.