如何在Forth中输入数字

  • 本文关键字:数字 Forth forth
  • 更新时间 :
  • 英文 :


在Basic中有类似input的内容,在Forth中有类似C中的scanf("%d")的内容吗?

可能会是这样的:

200 buffer: buf
: input ( -- n ) buf 200 accept 
some-magic-filter
buf swap evaluate ;

上面代码中的问题是,如何定义一个只传递数字而不传递任何单词、定义等的过滤器?

标准仅指定一个低级别的>NUMBER字来解释整数。OTOH使用EVALUATE将字符串转换为数字是一种快速而肮脏的方法。要么在没有检查的情况下使用它(在可信输入的情况下(,要么根本不使用它。尝试在EVALUATE之前过滤字符串是个坏主意:它有>NUMBER单词本身的成本和低重用因子。

注意:>NUMBEREVALUATE都未检测到数字溢出。

在任何情况下,输入单单元格整数的单词都可以定义为:

: accept-number ( -- n )
PAD DUP 80 ACCEPT ( addr u ) StoN ( n )
;

在可信输入的情况下,您可以像一样定义StoN

: StoN ( addr u -- x )
STATE @ ABORT" This naive StoN should not be used in compilation state"
DEPTH 2- >R
EVALUATE
DEPTH 1- R> <> IF -24 THROW THEN
 check depth to accept the single-cell numbers only
;

否则(在不可信输入的情况下(,您有两种选择:依赖特定Forth系统的特定单词,或者使用一些(也许是您自己的(库。

我使用以下词典来定义StoN:

 ---
 The words from Substring Matching library
 (where length is counted in address units)
: MATCH-HEAD ( a u a-key u-key -- a-right u-right true | a u false ) 
2 PICK OVER U< IF  2DROP FALSE EXIT THEN 
DUP >R
3 PICK R@ COMPARE IF  RDROP FALSE EXIT THEN 
SWAP R@ + SWAP R> - TRUE
; 
 ---
 The words from Literals interpreting library
 (where prefix 'I-' is shortcut for Interpret)
: I-DLIT ( a u -- x x true | a u false ) 
2DUP S" -"  MATCH-HEAD >R
DUP 0= IF  NIP RDROP EXIT THEN 
0 0 2SWAP >NUMBER NIP IF  RDROP 2DROP FALSE EXIT THEN 
R> IF  DNEGATE THEN  2SWAP 2DROP TRUE
; 
: I-LIT ( a u -- x true | a u false ) 
I-DLIT IF  D>S TRUE EXIT THEN  FALSE
;

之后StoN可以定义为:

: StoN ( a u -- x ) I-LIT IF EXIT THEN -24 THROW ;

上述库可以在GitHub:上找到

  • 子字符串匹配函数库
  • 解析程序示例(用于各种词法(

Rosetta Code建议使用GForth 0.6.2来确定输入字符串是否为数字:

: is-numeric ( addr len -- )
2dup snumber? ?dup if
0< if
-rot type ."  as integer = " .
else
2swap type ."  as double = " <# #s #> type
then
else 2dup >float if
type ."  as float = " f.
else
type ."  isn't numeric in base " base @ dec.
then then ;

我为Camel Forth构建了一个类似BASIC的#INPUT单词,为BASIC用户提供了更熟悉的东西。这比人们想象的要多得多。它以$ACCEPT开头,它可以用来喜欢带有字符串变量或内存块的输入。

NUMBER的定义?这里只针对单个int,但它是在GForth上编译的。如果转换不好,则输出true;SNUMBER的反面?

DECIMAL
: NUMBER?  ( addr len -- n ?)       ?=0 is good conversion
(          -- addr len)  bad conversion
OVER C@ [CHAR] - = DUP >R      save flag for later
IF 1 /STRING THEN              remove minus sign
0 0  2SWAP >NUMBER NIP NIP     convert the number
R> IF SWAP NEGATE SWAP THEN    negate if needed
;
: $ACCEPT ( $addr -- ) CR ." ?  "  DUP  1+ 80 ACCEPT  SWAP C!  ;

: #INPUT  ( variable -- )    made to look/work like TI-BASIC
BEGIN
PAD $ACCEPT         $ACCEPT text into temp buffer PAD
PAD COUNT NUMBER?   convert the number in PAD
WHILE                 while the conversion is bad do this
CR ." Input error "
CR DROP
REPEAT
SWAP ! ;            store the number in the variable
 USAGE:  VARIABLE X  
         X #INPUT      

相关内容

  • 没有找到相关文章