Qbasicnews.com

Full Version: STRING USING?
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
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... Big Grin

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 Big Grin:
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.