|
Wil Baden 1999-02-20
Elizabeth D Rather comp.lang.forthMany implementations provide "hooks" for the application, ... e.g., retaining the "discarded" high-order part of the last number converted in a place the appl can find it, and providing a way to know how many "decimal places" in a just-converted number.
Unfortunately, ANS Forth doesn't go very far in this direction, because when we studied this situation we found the specific approaches differed so much we were unable to derive a good synthesis.
However, handling user input is normally in a part of the application that is highly platform-dependent (e.g., using a Winxx dialog box, keypad on an embedded system, etc.) so you're already outside the normal scope of the Standard and you may as well make use of whatever your implementation provides in this line.
In SwiftForth, for example, there are two application-layer words for input number conversions:
NUMBER ( c-addr u -- n | d )
NUMBER? ( c-addr u -- 0 | n 1 | d 2 )
TEXTBoth words use
DPLto indicate the number of digits to the right of the rightmost punctuation (if any) . It's negative if there was no punctuation. So you can check it to find out whether you got a single or a double, and in the latter case use it for scaling if desired. If it was a single and you are concerned about possible overflow, the discarded high-order part may be found inNH.
Coded by Wil Baden from Elizabeth D. Rather's description.
NUMBER? is used to check if a string is numeric, so "bad"
punctuation is rejected.
DPL ( -- addr )
NH ( -- addr )
Is-Num-Punct ( c -- flag )
NUMBER? ( str len -- 0 | num 1 | num . 2 )
'NUMBER ( -- addr )
NUMBER ( str len -- n | n . )
'NUMBER. Error when string is not a number.
(NUMBER) ( str len -- n | n . )
NUMBER routine.
VARIABLE DPL
VARIABLE NH
\ Numeric Punctuation : + , - . / test.
: Is-Num-Punct ( c -- flag )
DUP [CHAR] : = SWAP [CHAR] + - 5 U< OR ;
\ Check that string is a number.
: NUMBER? ( str len -- 0 | num 1 | num . 2 )
-1 DPL !
\ Reject empty string.
DUP 0= IF 2DROP 0 EXIT THEN
OVER C@ [CHAR] - = DUP NH ! 1 AND /STRING
\ Reject lone minus sign.
DUP 0= IF 2DROP 0 EXIT THEN
\ Reject double minus sign.
OVER C@ [CHAR] - = IF 2DROP 0 EXIT THEN
\ Reject lone punctuation.
DUP 1 = IF OVER C@ Is-Num-Punct
IF 2DROP 0 EXIT THEN
THEN
0 0 2SWAP ( num . str len)
BEGIN >NUMBER DUP WHILE
OVER C@ Is-Num-Punct
\ Reject successive punctuations.
OVER DPL @ <> AND
WHILE 1 /STRING DUP DPL !
REPEAT THEN ( num . str len)
?DUP AND IF ( num . str)
C@ BL - IF 2DROP 0 EXIT THEN
THEN ( num .)
NH @ IF DNEGATE THEN
DPL @ 0< IF NH ! 1 ELSE 2 THEN ;
VARIABLE 'NUMBER
: NUMBER 'NUMBER @ EXECUTE ;
: (NUMBER) NUMBER? 0= ABORT" ? " ;
' (NUMBER) 'NUMBER !