循环到sum数组返回地址,如读取而不是正确的答案。为什么?

时间:2015-06-04 09:29:36

标签: forth gforth

我试图制作一个程序,为我总结一个数组,但是当我尝试运行单词sum时,它会继续给我一个类似地址的长数字。我尝试将它拆开并在终端中的字之外逐行运行并手动循环工作正常,但是当我真正使其工作时它完全失败。我做错了什么?

UIWindow

上传就像魅力一样,但我会在

之后使用这个词
variable length \ length var declared
create list \ space for my list made
0 variable cumsum  \ sum value initialized to zero

: upload     ( n1 n2 n3 --) \ loops thru and stuffs data into array
depth        ( n1 n2 n3 -- n1 n2 n3 depth) \ get depth
length !     ( n1 n2 n3 depth -- n1 n2 n3) \ array length stored
list         ( n1 n2 n3 -- n1 n2 n3 addr)
length @     ( n1 n2 n3 addr -- n1 n2 n3 addr nlength)
cells allot  ( n1 n2 n3 addr nlength -- n1 n2 n3) 
length @ 1+  ( n1 n2 n3 -- n1 n2 n3 nlength) \ consume all entries
0            ( n1 n2 n3 nl -- n1 n2 n3 nl 0) \ lower loop parameter..
do           ( n1 n2 n3 nl 0 -- n1 n2 n3) \ loop begins
list         ( n1 n2 n3 -- n1 n2 n3 addr)
I            ( n1 n2 n3 addr -- n1 n2 n3 addr I) \ calculating address
cells        ( n1 n2 n3 addr I -- n1 n2 n3 addr Ibytes)
+            ( n1 n2 n3 addr Ibytes -- n1 n2 n3 addr1+)
!            ( n1 n2 n3 addr1+ -- n1 n2) \ storing into calculated address
loop
;

它返回一个看起来像地址的非常长的数字,而不是我为测试它而添加的一些小数字列表的总和。

: sum ( n1 n2 n3 -- nsum)
upload \ initiates the array
length @  \ invokes upper limit of loop
0        \ lower limit of loop
do
list          ( -- addr)        \ addr invoked
I cells +     ( addr -- addr+)  \ offset calculated and added
@             ( addr+ -- nl)    \ registered value at address fetched
cumsum @      ( nl -- nl ncs)   \ cum sum value fetched to stack
+             ( nl ncs -- nsum) \ summation
cumsum !      ( nsum --)        \ new sum written to cumsum
loop
cumsum ?      ( -- cumsum)      \ show sum
;

3 个答案:

答案 0 :(得分:2)

因此,如果我理解正确,问题是:

  1. 将堆叠中的所有数字存储到一个数组中。
  2. 汇总存储在数组中的所有数字。
  3. 我会做这样的事情:

    : upload ( ... "name" -- ) create depth dup ,  0 ?do , loop ;
    : sum ( a -- n ) 0 swap @+ 0 ?do @+ rot + swap loop drop ;
    

    像这样使用:

    1 2 3 4 upload array
    array sum .
    

答案 1 :(得分:1)

UPLOAD中执行LIST LENGTH @ CELLS ALLOTALLOT在当前字典或数据空间指针处分配内存,而不必在LIST返回的地址处分配内存。 ALLOT不使用堆栈中的起始地址。实际上,上面代码片段中LIST返回的地址稍后会在数组填充循环中由!使用。它是第一个阵列单元的数据。因此,您的地址就像SUM返回的地址一样。

最好将CREATEALLOT放在一起。在创建LIST和执行ALLOT之间发生了一些字典添加。您的阵列单元格可能不在LIST指向的位置。

通常,变量不会消耗堆栈中的数字。大多数情况下,它们会自动初始化为0。所以0 VARIABLE CUMSUM将在堆栈上留下零。 如果你一次运行或输入代码,这会产生DEPTHLENGTH的后果。 尽量避免DEPTH,最好是明确告诉数组定义单词您想要多少项,例如:
CREATE LIST 3 CELLS ALLOT

BTW在SwiftForth中运行您的代码,我在SUM的字典主菜之后分配了一个4单元格数组。我在LENGTH @ 1+之后的字典中存储了5个项目UPLOAD LIST),覆盖了CUMSUM字典主菜的部分...

Lars Brinkhoff展示了一个不错的选择,除了DEPTH之外; - )

答案 2 :(得分:0)

主要问题是@roelf解释。我只想添加两个兴趣点。

1)你怎么知道有什么事情发生了?遇到这样的问题时,请检查内存 - 执行十六进制转储!

1 2 3 sum -1223205794  ok
list 32 dump 
B7175C58: 58 5C 17 B7  03 00 00 00 - 02 00 00 00  01 00 00 00  X\..............
B7175C68: 00 00 00 00  00 00 00 00 - 5E 5C 17 B7  58 5C 17 B7  ........^\..X\..
 ok

你可以看到列表的第一个单元格是垃圾。所以也许upload毕竟不是很好!

2)请注意,如果您只想在堆栈中添加所有值,则不需要使用变量来混淆命名空间:

: sum depth 1 do + loop ;