如何实现字符串数组?

时间:2012-01-01 13:37:46

标签: arrays string forth

我尝试实现一个单词,当在Forth的堆栈中给出一个数字时,它会从数组中生成一个字符串。

我的第一次天真尝试是:

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

这已被接受,但它没有按预期工作 - myarray @ type产生不一致的输出(而不是我天真的期望它可能打印“Alpha”)。

在搜索网页时,我在Gforth documentation中发现使用s"创建的字符串的生命周期有限,这意味着我的ansatz必然会从一开始就失败。另一方面,根据Len的Forth Tutorial中的Arrays in Forth部分,甚至常规对象的数组似乎也没有标准化。

< Update> 显然,这对Forth来说不是一个小问题。 Web上有一些库实现了缺少的字符串功能:FFLstr module)和String Functions by Bernd Paysan。这是一个很好的起点,虽然它仍然需要工作从那里到一个字符串数组。的< /更新>

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

1 个答案:

答案 0 :(得分:2)

为了解决部分代码问题,s"在堆栈上留下addr u,地址和字符串的长度。 ,只存储一个值,因此您无法获得所需的结果。 2,可能会这样做,因为它会存储表示字符串的两个堆栈项。完成后,您需要同时获取两个值,因此2@就是您想要的。

我的重写看起来像这样:

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

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

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

myarray 2 cells + \ increment the address by two cells

获取指向" Beta"的地址等等。所以为了获得" Beta"你会输入

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

我用gforth对此进行了测试,看起来一切正常,但我不确定如何严格测试持久性。

你的话需要能够根据堆栈上的内容开始增加地址。您可能想要了解更多create does>内容。我可以提供一些建议,但我不想破坏发现的乐趣。

如果我跳过太多关于这实际意味着什么的详细信息,我会再试一次。


也许这太粗糙了,但我还是选择了#34;字符串类型"不久之前。

: 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**

它定义了一个单词,其中包含您选择的名称(在本例中为#34;单词"),它将推送字符串的长度和起始地址(在本例中为#34;某些单词")当它被解释。据我所知,当字符串处于这样的定义时,它是持久的。

这并没有完全回答你的问题,但它可能有所帮助。


我还有一个持久字符串,这个字典条目中的allot内存绝对是唯一的,只要该字存在,它就是安全的。字符串"键入"之前只存储了s"创建的地址和长度,这只有任何好处,直到其他内容写入该内存区域。现在,这会将s"创建它的字符串复制到名为" 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+ @ ;