Sorting 按Forth排序字符串数组

Sorting 按Forth排序字符串数组,sorting,forth,gforth,Sorting,Forth,Gforth,我曾经创建过一个字符串数组: create mystringarray s" This" , s" is" , s" a", s" list" , 我想按升序排序。我在网上找到了一些汇编语言教程,但我想在Forth中完成。最佳实践方法是什么?您需要首先确保数据表示准确 Forth中的文字字符串是使用单词s“获得的,因此您可以编写,例如: s" This" ok s" This" 0 myString compare .s <1> 0 ok 输入后,如果执行.s,将看到两个值

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

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

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

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

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

s" This"  ok
s" This" 0 myString compare .s <1> 0  ok
输入后,如果执行
.s
,将看到两个值:

.s <2> 7791776 4  ok
现在您知道需要两个单元格来表示由
s“
获得的字符串。您的
创建
需要考虑到这一点,并使用
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@ ;
分解这一点,您需要获取数组变量的基,
mystringaray
,并将正确的偏移量添加到所需的字符串地址/计数中。该偏移量是数组项(2个单元格)的大小乘以索引(位于数据堆栈上)。因此表达式,
myStringArray交换2个单元格*+
。然后是
2@
,检索该位置的双字(地址和计数)

投入使用

3 myString type array ok
0 myString type This ok
等等

既然您已经了解了对数组进行索引的基本知识,那么排序的“最佳实践”将遵循为您希望排序的数组类型选择排序算法的常规最佳实践。在这种情况下,冒泡排序可能适用于非常小的字符串数组。例如:

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

结果是
0
表示字符串相等。

对数组排序的最佳实践方法是使用一些现有库。如果现有图书馆不符合您的需要,或者您的主要目的是学习- 然后实现您自己的库是有意义的

使用图书馆

例如,从第四个基础库()可以用来排序任何项的数组。

代码示例 输出

This
is
a
list

This
a
is
list
赤裸裸地使用 如果你需要一个简单的解决方案只是为了学习,看看

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

冒泡排序从数字的变量调整为字符串的变量,只需替换比较项的单词。请注意,word返回顶部最低地址的值

代码示例
\一些辅助词
:交换+上的边界(addr1 u1--addr1 addr2);
:lt cstring(a1a2--标志)>r count r>count compare-1=;
\创建一个计数字符串数组
:noname(--addr cnt)
在这里
c“这个”,c“是”,c“a”,c“列表”,
这边->牢房
; 执行常量cnt常量arr
\从数组中转储字符串
:转储arr(--)cnt 0?i单元arr+@计数型cr环路;
\气泡排序
:排序arr(--)
cnt 2 u<如果退出,则
cnt 1是否正确
arr-cnt-i-细胞边界
I2@(a2 a1)lt cstring如果I2@交换I2!假然后
细胞+环
如果你离开的话
环
;
\测试排序
卸载arr cr
排序arr
卸载arr cr
\输出与以前相同

我认为这个答案应该包括某种排序实现,它可以对数组进行实际排序(在它被接受之前),但我给了它一个向上的投票,因为它是FORTH中的一个贡献,这本身就很棒。你的回答一般来说都很棒,我希望你留下来。@EvanCarroll我的目的不是要完全完成OP的所有工作,而是要澄清他们一直存在的问题,这些问题阻碍了他们完成工作。任何进一步的阐述都将是对一些众所周知的常见排序算法的翻译。此外,还有许多方法,这些方法的选择取决于OP的特定排序方案,但尚未描述。这是一个非常普遍的问题,它表明,与排序本身相比,更缺乏必要的第四个先决条件。@lower,需要考虑以下问题:“由于一个实现可能选择只为解释字符串提供一个缓冲区,因此解释字符串可能会被下一次执行的S”在解释状态下覆盖“@ruvim是的,你是对的。谢谢你的关注。当我有更多的时间时,我会更新我的答案。解决临时缓冲区问题的简单方法是将字符串包装为
:noname s“This”2,s“is”2;执行
有趣的事实:另一个问题也有同样的问题-您没有字符串数组。在Forth中,没有一个数组抽象可以堆在字符串抽象之上。给我打印第三个字符串的代码,你就明白我的意思了
\ 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