我正在尝试编写一个程序,为我求和数组,但是当我尝试运行单词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
如果我理解正确的话,问题是:
- 将堆栈中的所有数字存储到数组中。
- 将存储在数组中的所有数字求和。
我会这样做:
: 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 ALLOT
。ALLOT
在当前字典或数据空间指针上分配内存,不一定是在LIST
返回的地址上。ALLOT
不消耗堆栈中的起始地址。实际上,上面代码片段中LIST返回的地址稍后由!
在数组填充循环中使用。这是第一个数组单元格的数据。因此,您的地址类似SUM
返回的数字。
最好是保持CREATE
和ALLOT
在一起。在创建LIST和执行ALLOT之间发生了一些字典添加。您的数组单元格可能不在LIST所指向的位置。
一般情况下,变量不消耗堆栈中的数字。大多数情况下,它们被自动初始化为0
。所以0 VARIABLE CUMSUM
将在堆栈上留下零。如果您一次运行或键入代码,这对DEPTH
和LENGTH
都有影响。尽量避免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 ;