如何实现字符串数组



我尝试在Forth中实现一个word,当在堆栈中给定一个数字时,它会从数组中产生一个字符串。

我第一次天真的尝试是:

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

这是可以接受的,但它没有像预期的那样工作- myarray @ type产生不一致的输出(而不是我天真的期望它可能会打印"Alpha")。

当搜索web时,我在Gforth文档中发现用s"创建的字符串具有有限的生命周期,这意味着我的ansatz从一开始就注定会失败。另一方面,即使是常规对象的数组似乎也没有根据Len's Forth教程中的Forth部分进行标准化。

显然,这不是Forth的一个小问题。网络上有一些库实现了缺失的字符串功能:FFL (str模块)和Bernd Paysan的string Functions。这是一个很好的起点,尽管从这里到字符串数组仍然需要一些工作。 & lt;/更新>

那么我如何实现一个从给定数组返回字符串的单词呢?

为了处理部分代码,s"在堆栈上留下addr u,地址和字符串的长度。,只存储一个值,所以你不会得到想要的结果。2,可以这样做,因为它将存储表示字符串的两个堆栈项。一旦你完成了,你需要得到两个值回来,所以2@是你想要的。

我的重写看起来像这样:

create myarray s" Alpha" 2, s" Beta" 2, s" Charlie" 2,
 Test
myarray 2@ type Alpha **ok**

获取数组的其他元素有点棘手。当您输入myarray时,您将获得该字典条目中数据开始的地址,然后您可以使用2@来获得前两个地址指向的内容(即"Alpha"的地址和长度)。如果你想要"Beta",你需要下一对地址。所以你可以使用

myarray 2 cells +  increment the address by two cells

获取指向"Beta"的地址,等等。所以要访问"Beta"你需要输入

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的内存,只要这个词存在,它就是安全的。在字符串"type"之前,只存储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+ @ ;

首先。必须为字符串分配永久存储空间。在ciforth(我的Forth)中,有一个单词$,它在字典空间中执行此操作。

S" aap" $,

留下一个带有一个单元格计数的地址,后面跟着字符。没有类似的标准词,你必须自己写。这是假设ALLOCATE不可用的。使用这种方法,下面的代码将字符串指针临时保存到堆栈中:

0 s" Alpha" $, s" Beta" $, s" Charlie" $,

则必须将这些指针存储在数组中,因此使用哨兵0,代价是增加一个辅助字:

: ttt  BEGIN DUP WHILE , REPEAT DROP ;

( CREATE string-array) ttt
HERE CONSTANT ttt-end

现在您可以按如下方式处理字符串:

tt-end 2 CELLS -  ( @+ TYPE )

你可能需要添加助词。

相关内容

  • 没有找到相关文章