代码之家  ›  专栏  ›  技术社区  ›  ivand58

如何在Forth中输入数字

  •  7
  • ivand58  · 技术社区  · 6 年前

    有什么像 input 基本或 scanf("%d") 进C进F?

    可能是这样的:

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

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

    2 回复  |  直到 6 年前
        1
  •  6
  •   ruvim José Nobile    6 年前

    标准只规定了一个低水平 >NUMBER 用于解释整数的单词。 耳鸣 EVALUATE 把字符串转换成数字是一种快速而肮脏的方法。要么不用检查就使用它(在可信输入的情况下),要么根本不用它。尝试在之前筛选字符串 评价 是个坏主意:它有成本 >数字 词本身和低重用因子。

    注: 也不 >数字 也不是 评价 检测数值溢出。

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

    : 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系统的特定单词,或者使用某些(可能是您自己的)库。

    我用下面的词典来定义 斯通 :

    \ ---
    \ 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 ( a u -- x ) I-LIT IF EXIT THEN -24 THROW ;
    

    在GitHub上可以找到提到的库:

        2
  •  1
  •   luigif    6 年前

    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 ;
    
    推荐文章