4

我曾经CREATE创建一个字符串数组:

create mystringarray s" This" , s" is" , s" a", s" list" ,

我想按升序排序。我在网上找到了一些汇编语言教程,但我想在 Forth 中完成。最佳实践方法是什么?

4

2 回答 2

7

您需要首先确保您的数据表示是准确的。

Forth 中的文字字符串是使用单词获得的s",因此您可以编写,例如:

s" This"  ok

输入后,如果您这样做.s,您将看到两个值:

.s <2> 7791776 4  ok

这是一个指向实际字符串(字符数组)的指针,以及字符串中字符数的计数。Forth 中的某些词理解这种字符串表示。type是其中之一。如果您现在输入type,您将在显示屏上输入字符串:

type This ok

所以现在您知道您需要两个单元格来表示由s". 您create需要考虑到这一点,并使用这个2,词来存储每个条目 2 个单元格,而不是,只存储一个单元格:

create myStringArray
    s" This" 2,
    s" is" 2,
    s" an" 2,
    s" array" 2,
    s" of" 2,
    s" strings" 2,

这是字符串的地址/计数对数组。如果您想访问其中之一,您可以执行以下操作:

: myString ( u1 -- caddr u1 )  \ given the index, get the string address/count
    \ fetch 2 cells from myStringArray + (sizeof 2 cells)*index
    myStringArray swap 2 cells * + 2@ ;

打破这一点,您需要获取数组变量的基数,myStringArray并将正确的偏移量添加到您想要的字符串地址/计数中。该偏移量是数组条目(2 个单元格)的大小乘以索引(位于数据堆栈上)。因此表达式,myStringArray swap 2 cells * +。接下来是2@检索该位置的双字(地址和计数)。

投入使用...

3 myString type array ok
0 myString type This ok

ETC...

既然您了解了索引数组的基础知识,那么排序的“最佳实践”将遵循为您希望排序的数组类型选择排序算法的正常最佳实践。在这种情况下,冒泡排序可能适用于非常小的字符串数组。您将使用compare该词来比较两个字符串。例如:

s" This" 0 myString compare .s <1> 0  ok

结果0意味着字符串相等。

于 2018-04-02T15:09:22.163 回答
4

对数组进行排序的最佳实践方法是使用一些现有的库。如果现有的库不能满足你的需求,或者你的主要目的是学习——那么实现你自己的库是有意义的。

使用库

例如,来自 The Forth Foundation Library ( FFL ) 的单元格数组模块可用于对任何项目的数组进行排序。

代码示例

include ffl/car.fs
include ffl/str.fs

0 car-new value arr  \ new array in the heap

\ shortcut to keep -- add string into our 'arr' array
: k ( a1 u1 -- ) str-new dup arr car-push str-set ;

\ set compare method
:noname ( a1 a2 -- n ) >r str-get r> str-get compare ; arr car-compare!

\ dump strings from the array
: dump-arr ( -- ) arr car-length@ 0 ?do i arr car-get str-get type cr loop ;

\ populate the array
s" This" k s" is" k s" a" k s" list" k

\ test sorting
dump-arr cr
arr car-sort 
dump-arr cr

输出

This
is
a
list

This
a
is
list

使用裸 Forth

如果您需要一个仅用于学习的 Forth 解决方案,请查看冒泡排序示例

字符串数组应仅包含字符串地址。琴弦本身应该放在另一个地方。在这种情况下使用计数字符串格式很有用——因此,我们使用c"word 表示字符串文字。为了保留字符串本身,我们将初始化代码放入定义中(:noname在本例中)——它将字符串保留在字典空间中。

冒泡排序从数字的变体改编为字符串的变体,只需替换比较项的单词即可。请注意,2@word 返回顶部最低地址的值。

代码示例

\ some helper words
: bounds ( addr1 u1 -- addr1 addr2 ) over + swap ;
: lt-cstring ( a1 a2 -- flag ) >r count r> count compare -1 = ;

\ create an array of counted strings
:noname ( -- addr cnt )
  here
    c" This" , c" is" , c" a" , c" list" ,
  here over - >cells
; execute constant cnt constant arr

\ dump strings from the array  
: dump-arr ( -- ) cnt 0 ?do i cells arr + @ count type cr loop ;

\ bubble sort
: sort-arr ( -- )
  cnt 2 u< if exit then
  cnt 1 do true
    arr cnt i - cells bounds do
      i 2@ ( a2 a1 ) lt-cstring if i 2@ swap i 2! false and then
    cell +loop
    if leave then
  loop
;

\ test sorting
dump-arr cr
sort-arr
dump-arr cr

\ the output is the same as before
于 2018-04-14T10:07:09.877 回答