7

Forthのスタックに数値が与えられたときに、配列から文字列を生成する単語を実装しようとしました。

私の最初の素朴な試みは:

create myarray s" Alpha" , s" Beta" , s" Charlie" ,

これは受け入れられましたが、期待どおりに機能しませんでした—myarray @ type一貫性のない出力が生成されます(「Alpha」が出力される可能性があるという私の素朴な期待の代わりに)。

Webを検索したところ、Gforthのドキュメントで、で作成された文字列s"の有効期間が限られていることがわかりました。これは、私の仮説が最初から失敗することを意味します。一方、通常のオブジェクトの配列でさえ、LenのForthチュートリアルのForthセクションの配列に従って標準化されていないようです。

<更新>どうやら、これはForthの些細な問題ではありません。不足している文字列機能を実装するライブラリがWeb上にあります:FFLstr module)およびBerndPaysanによる文字列関数。これは良い出発点ですが、そこから文字列の配列に移動するにはまだ作業が必要です。</更新>

では、特定の配列から文字列を返す単語をどのように実装できますか?

4

2 に答える 2

2

コードの一部をアドレス指定するには、アドレスと文字列の長さをスタックにs"残します。1 つの値しか格納しないため、目的の結果が得られません。文字列を表す両方のスタック項目を格納するようにそれを行うかもしれません。それが完了したら、両方の値も取得する必要があるので、それが必要です。addr u,2,2@

私の書き直しは次のようになります。

create myarray s" Alpha" 2, s" Beta" 2, s" Charlie" 2,

\ Test
myarray 2@ type Alpha **ok**

配列の他の要素を取得するのは少しトリッキーです。入力myarrayすると、その辞書エントリのデータの開始アドレスが取得され、2@ を使用して、最初の 2 つのアドレスが指すもの ("Alpha" のアドレスと長さ) を取得できます。「ベータ版が必要な場合は、次のアドレスのペアが必要です。したがって、使用できます

myarray 2 cells + \ increment the address by two cells

「ベータ」などを指すアドレスを取得します。「ベータ版」にアクセスするには、次のように入力します

myarray 2 cells + 2@ type Beta **ok**

私はこれを gforth でテストしましたが、永続性を厳密にテストする方法はわかりませんが、すべてうまくいくようです。

あなたの言葉は、最初にスタックにあるものに基づいてアドレスをインクリメントできる必要があります。あなたはもっと何かに入りたいと思うかもしれませんcreate does>。いくつかのヒントを与えることはできますが、発見の楽しさを台無しにしたくありません.

これが実際に意味することの詳細をスキップしすぎている場合は、ただ言ってください。もう一度やり直します.


これは大雑把すぎるかもしれませんが、少し前に「文字列型」のようなものを作ってみました。

: string                                    ( addr u "name" -- )
    create 2,                               \ add address and length to dict entry "name"
    does> dup cell+ @ swap @ ;              \ push addr u

\ Example
s" Some Words" string words **ok**
words type Some Words **ok**

選択した名前 (この場合は「words」) を持つ単語を定義し、解釈時に文字列の長さと開始アドレス (この場合は「some words」) をプッシュします。文字列がこのような定義にあるとき、私が知る限り、それは永続的です。

これはあなたの質問に完全には答えませんが、役立つかもしれません。


私は永続的な文字列をもう一度試しました。これは間違いなくallot辞書エントリ内のメモリであり、その単語が存在する限り安全です。文字列「タイプ」が作成される前は、s"作成されたアドレスと長さのみが格納されていましたが、これは、他の何かがメモリのその領域を上書きするまで有効です。これにより、s"作成元の文字列が「name」と呼ばれる辞書項目にコピーされ、「name」自体と同じくらい続くことが保証されます。

: string                                    ( addr u "name" -- )
    create                                  \ create dict entry called "name"
    dup >r here >r                          \ keep copies of string length and start of "name"'s memory
    dup 2 cells + allot                     \ allot memory for the number of chars/bytes of the string plus 2
                                            \ for the new addr u
    r@ 2 cells +                            \ Get the address two cells from the start the space for "name"
    swap cmove                              \ copy the string at addr u into the alloted space for "name"

    \ Now "name" looks like this: "name" -blank1- -blank2- "the text of the string at addr u"
    \ blank1 should be the address of the start of the the text = addr2 and blank2 should be u

    r@ dup 2 cells + swap !                 \ get the address of blank1, copy it, increment by 2 to get addr2
                                            \ and then store that in blank1
    r> cell+ r> swap !                      \ get address of blank1, increment to get address of blank2, then get u and
                                            \ store it in blank2

    \ Now "name" looks like this: "name" addr2 u "the text of the string at addr u"

    does> dup @ swap cell+ @ ;              \ push addr2 u

娯楽として、役に立つ書式設定なしでは、これがどれほど意味がないかを示すことができると思いました。

: string-no-comments         ( addr u "name" -- )
    create dup >r here >r dup 2 cells + allot r@
    2 cells + swap cmove r@ dup 2 cells + swap !
    r> cell+ r> swap ! does> dup @ swap cell+ @ ;
于 2012-01-05T19:01:09.643 に答える