Next: , Previous: , Up: Other I/O   [Contents][Index]


6.20.2 Formatted numeric output

Forth は伝統的に、 整数の書式設定された出力に「表示数値出力」(pictured numeric Output) と呼ばれる手法を使用しています。 この手法では、 数値から数字桁(digits)が抽出され(base で定義された現在の出力基数を使用 see Number Conversion)、 ASCII コードに変換され、 メモリのスクラッチパッド領域(see Implementation-defined options)に構築される文字列の先頭に付加されます。 抽出プロセス中に、 文字列の先頭に任意の文字を追加できます。 完成した文字列はアドレスと長さによって指定され、 プログラム制御の下で操作(TYPE や、 コピーや、 変更)できます。

前のセクションで説明したすべての整数出力ワード (see Simple numeric output) は、 Gforth では表示数値出力(pictured numeric output)を使用して実装されています。

表示数値出力(pictured numeric output)について覚えておくべき 3 つの重要な点:

標準 Forth は、 <# で空にして初期化し、 #> で結果文字列を取得する単一の出力バッファー(別名ホールド領域;hold area)をサポートします。

Gforth はさらに、 このバッファーの入れ子になった使用をサポートしており、 たとえば、 ホールド領域を処理するコード内でデバッグ・トレーサー ~~ からの出力を入れ子にすることができます。 <<# は新しい入れ子を開始し、 #> は結果文字列を生成し、 #>> は入れ子を解除します。 入れ子のホールド領域が再利用され、#> は次に外側の入れ子の文字列を生成します。 Gforth の高レベルの数値出力ワードはすべて <<# ... #> ... #>> を使用し、 ホールド領域の他のユーザー内に入れ子にできます。

<# ( ) core “less-number-sign”

表示数値出力文字列を 初期化/クリア します(訳注: 表示数値出力用のポインタをホールド領域の末尾(初期値)に戻すだけ。 中身は消さない。)

<<# ( ) gforth-0.5 “less-less-number-sign”

#>> で終わるホールド領域を開始します。 相互に入れ子にすることも、 <# で入れ子にすることもできます。 注: <<##>> を一致させないと、 最終的にホールド領域が不足します。 <# を使用してホールド領域を空にリセットできます。

# ( ud1 – ud2  ) core “number-sign”

<<##> の間で使用されます。 ud1 の最下位桁(base による)を、 表示数値出力文字列の先頭に追加します。 ud2ud1/base、 つまり残りの桁を表す数値です。

#s ( ud – 0 0  ) core “number-sign-s”

<<##> の間で使用されます。 ud のすべての数字を表示数値出力文字列の先頭に追加します。 #s は少なくとも 1 つの数字を変換します。 したがって、 ud が 0 の場合、 #s は表示数値出力文字列の先頭に ‘0‘ を追加します。

hold ( char –  ) core “hold”

<<##> の間で使用されます。 表示数値出力文字列の前に文字 char を追加します。

holds ( addr u –  ) core-ext “holds”

<<##> の間で使用されます。 表示数値出力文字列の前に文字列 addr u を追加します。

sign ( n –  ) core “sign”

<<##> の間で使用されます。 n (1倍長整数) が負の場合、 表示数値出力文字列の先頭に - を追加します。

#> ( xd – addr u  ) core “number-sign-greater”

変換対象(変換残りの)数値 xd を破棄し、 フォーマットされた文字列のアドレスと長さを示す addr u を返すことで、 表示数値出力文字列を完成させます。 標準のプログラムでは、 文字列内の文字を変更する場合があります。 ホールド領域は解放されません。 #>> を使用して <<# で始まるホールド領域を解放するか、 <# を使用してすべてのホールド領域を解放します。

#>> ( ) gforth-0.5 “number-sign-greater-greater”

<<# で始まるホールド領域を解放します。

以下に、 表示数値出力の使用例をいくつか示します:

: my-u. ( u -- )
  \ PNS(Pictured Number String)の最も単純な使用法。標準の u. のように振る舞います。
  0              \ 上記 u を 2倍長にする
  <<#            \ 変換開始
  #s             \ 全桁を変換
  #>             \ 変換終了
  TYPE SPACE     \ 表示、続けて空白1つ
  #>> ;          \ ホールド領域を開放

: cents-only ( u -- )
  0              \ 上記 u を 2倍長整数に変換
  <<#            \ 変換開始
  # #            \ 最下位と最下位からの次の 2 桁のみ変換
  #>             \ 変換完了。他の桁は破棄
  TYPE SPACE     \ 表示、続けて空白1つ
  #>> ;          \ ホールド領域を開放

: dollars-and-cents ( u -- )
  0              \ 上記 u を符号無し2倍長整数に変換
  <<#            \ 変換開始
  # #            \ 下位2桁を変換
  '.' hold       \ 小数点を打つ
  #s             \ 残りの桁を変換
  '$' hold       \ 通貨記号を打つ
  #>             \ 変換完了
  TYPE SPACE     \ 表示、続けて空白1つ
  #>> ;          \ ホールド領域を開放

: my-. ( n -- )
  \ 負数も処理する標準の . のように振る舞う
  s>d            \ 符号付き2倍長整数に変換
  swap over dabs \ 符号バイトを別途保存して数値は符号無し2倍長に
  <<#            \ 変換開始
  #s             \ 全桁を変換
  rot sign       \ 符号チェック。必要なら "-" 付加
  #>             \ 変換完了
  TYPE SPACE     \ 表示、続けて空白1つ
  #>> ;          \ ホールド領域を開放

: account. ( n -- )
  \ (会計風出力)会計士はマイナス記号が嫌いで、
  \ 負の数には括弧を使用します
  s>d            \ 符号付き2倍長整数に変換
  swap over dabs \ 符号バイトを別途保存して数値は符号無し2倍長に
  <<#            \ 変換開始
  2 pick         \ 符号バイトのコピーを得る
  0< IF ')' hold THEN \ これが(あれば)出力の右端の文字
  #s             \ 全桁を変換
  rot            \ 符号バイトを得る
  0< IF '(' hold THEN
  #>             \ 変換完了
  TYPE SPACE     \ 表示、続けて空白1つ
  #>> ;          \ ホールド領域を開放

これらのワードの利用例をいくつか示します:

1 my-u. 1  ok
hex -1 my-u. decimal FFFFFFFFFFFFFFFF  ok
1 cents-only 01  ok
1234 cents-only 34  ok
2 dollars-and-cents  $0.02  ok
1234 dollars-and-cents  $12.34  ok
123 my-. 123  ok
-123 my-. -123  ok
123 account. 123  ok
-456 account. (456)  ok


Next: Floating-point output, Previous: Simple numeric output, Up: Other I/O   [Contents][Index]