循环求和数组返回像读取一样的地址,而不是正确的答案.为什么



我正在尝试编写一个程序,为我求和数组,但是当我尝试运行单词sum时,它一直给我一个非常长的数字,类似于地址。我试着把它拆开,在终端的单词外逐行运行,手动循环工作得很好,但当我真正让它工作时,它完全失败了。我做错了什么?

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
;

upload效果很好,但是我要在

后面加上这个词
: 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
;

,它返回一个很长的数字,看起来像一个地址,而不是我用来测试它的一些小数的和。

1  ok
2  ok
3  ok
sum 140313777201982  ok

如果我理解正确的话,问题是:

  1. 将堆栈中的所有数字存储到数组中。
  2. 将存储在数组中的所有数字求和。

我会这样做:

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

UPLOAD执行LIST LENGTH @ CELLS ALLOTALLOT在当前字典或数据空间指针上分配内存,不一定是在LIST返回的地址上。ALLOT不消耗堆栈中的起始地址。实际上,上面代码片段中LIST返回的地址稍后由!在数组填充循环中使用。这是第一个数组单元格的数据。因此,您的地址类似SUM返回的数字。

最好是保持CREATEALLOT在一起。在创建LIST和执行ALLOT之间发生了一些字典添加。您的数组单元格可能不在LIST所指向的位置。

一般情况下,变量不消耗堆栈中的数字。大多数情况下,它们被自动初始化为0。所以0 VARIABLE CUMSUM将在堆栈上留下零。如果您一次运行或键入代码,这对DEPTHLENGTH都有影响。尽量避免DEPTH,最好是显式地告诉数组定义词你想要多少项,例如:
CREATE LIST 3 CELLS ALLOT

顺便说一句,在SwiftForth中运行您的代码,我在SUM的字典条目之后分配了一个4单元数组。我在LIST之后的字典中存储了5个条目(LENGTH @ 1+UPLOAD中),覆盖了CUMSUM的部分字典条目…

Lars Brinkhoff展示了一个很好的替代方案,除了DEPTH,那就是;-)

主要问题是@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

可以看到list的第一个单元格是垃圾。所以也许upload并没有很好地工作!

请注意,如果您只是想在堆栈中添加所有值,则不需要使用变量来使名称空间混乱:
: sum depth 1 do + loop ;

相关内容

  • 没有找到相关文章

最新更新