use*_*472 6 arrays string forth
当我在Forth的堆栈上给出一个数字时,我试图实现一个从数组中生成字符串的单词.
我的第一次天真尝试是:
create myarray s" Alpha" , s" Beta" , s" Charlie" ,
Run Code Online (Sandbox Code Playgroud)
这被接受,但它没有按预期工作 - myarray @ type
产生不一致的输出(而不是我天真的期望它可能打印"Alpha").
在网上搜索时,我在Gforth文档中发现创建的字符串s"
具有有限的生命周期,这意味着我的ansatz必然会从一开始就失败.另一方面,根据Len的Forth Tutorial 中的Fours部分中的数组,即使是常规对象的数组似乎也没有标准化.
<Update>显然,这对Forth来说不是一个小问题.Web上有一些库实现了缺少的字符串功能:FFL(str模块)和Bernd Paysan的字符串函数.这是一个很好的起点,虽然它仍然需要工作从那里到一个字符串数组.</更新>
那么如何实现一个从给定数组返回字符串的单词呢?
要对代码的某些部分进行寻址,请在堆栈上s"
留下addr u
地址和字符串的长度。,
仅存储一个值,因此您不会以这种方式获得所需的结果。2,
可能会这样做,因为这将存储代表该字符串的两个堆栈项。完成后,您还需要取回两个值,所以2@
就是您想要的。
我的重写如下:
create myarray s" Alpha" 2, s" Beta" 2, s" Charlie" 2,
\ Test
myarray 2@ type Alpha **ok**
Run Code Online (Sandbox Code Playgroud)
获取数组的其他元素有点棘手。当您键入时,myarray
您将获得该字典条目中数据开始的地址,然后您可以使用 2@ 来获取前两个地址指向的内容(即“Alpha”的地址和长度)。如果你想要“Beta”,你需要下一对地址。所以你可以使用
myarray 2 cells + \ increment the address by two cells
Run Code Online (Sandbox Code Playgroud)
获取指向“Beta”的地址等等。因此,为了访问“Beta”,您需要输入
myarray 2 cells + 2@ type Beta **ok**
Run Code Online (Sandbox Code Playgroud)
我已经用 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**
Run Code Online (Sandbox Code Playgroud)
它定义了一个具有您选择的名称的单词(在本例中为“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
Run Code Online (Sandbox Code Playgroud)
为了好玩,我想我可以展示如果没有有用的格式,这毫无意义
: 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+ @ ;
Run Code Online (Sandbox Code Playgroud)