问题
I know, the question was often asked in the past and perhaps the information are given in previous Stack Overflow postings. But learning Forth is a very complicated task and repetition helps to understand the advantages of a concatenative programming language over alternative languages like C.
What I have learned from Forth tutorials is that Forth doesn't provide commands for creating a 2D array, but the user has to realize everything from scratch in the program. I've found two options in occupying memory in Forth. At first by creating a new word:
: namelist s” hello” s” world” ;
or secondly by the CREATE statement:
create temperature 10 allot
temperature 10 cells dump
So far so good; we have created an array of 10 cells in which integer variables can be stored. But what is, if I need to save float numbers? Do I have to convert float always to int or can they saved into the normal cells?
Another open problem is how to store string values in the array. As far as I know, a string contains a pointer plus a size. So in theory I can store only 5 strings in a 10 cell array and additionally I need memory somewhere else which holds the string itself. That doesn't make much sense.
Is there some kind of higher abstraction available to store values in arrays which can be used to write easy to read programs? I mean, if every programmer is using his own Forth method to store something in the memory, other programmers will find it hard to read the code.
回答1:
A generalised 2darray of elements. Takes the element size as a parameter
\ size is the per element multiplier
\ n size * is the per_row factor
\ m n size * * is the total space required
: 2darray \ create> m n size -- ; does> mix nix -- a
\ size is the number of bytes for one element
\
create 2dup * , \ multiplier to apply to m index
dup , \ multiplier to apply to n index
* * allot \ calculate total bytes and allot them
does> \ mix nix -- a
>r r@ cell+ @ * \ offset from n index
swap r@ @ * + \ offset with m index
r> + 2 cells+ \ 2 cells offset for the 'admin' cells
;
Examples
50 40 /float 2darray 50x40floats
50 40 2 cells 2darray 50x40stringpairs
even
20 constant /record
10 200 /record 2darray 2000records
回答2:
create creates a word that returns address of a buffer in the dictionary (data space); it is zero length initially, so you have to reserve required space for it right away.
allot reserves space that is measured in address units (usually bytes), so you have to calculate the required size in bytes.
For example:
create a 10 cells allot
create b 10 floats allot
It is just buffers, and you still need to deal with pointers arithmetic to get or set an item, e.g.:
0.35e 2 floats b + f! \ store the float number into third item (0-based indexing)
Example of a word that creates an array of floats in the dictionary:
: create-floats-array ( length "name" -- ) create floats allot does> swap 1- floats + ;
10 create-floats-array c
0.35e 3 c f! \ store the float number into third item (1-based indexing)
3 c f@ f. \ print float number form third item
If you need many arrays and many strings it is better to use appropriate libraries. For example, see Cell array module and Dynamic text string module from Forth Foundation Library.
回答3:
You're confused about strings. The string just goes into memory and memory at that address is allocated for that string, and it's there forever (unless you change that).
So if you wanted to store 5 ( c-addr u) strings in an allocated block of memory (calling it an array is a bit of a stretch), you can just store the c-addr in cell n and the length u in cell n+1.
If you're worried about 10 cells being a lot of space (it's really nothing to worry about) and only want to use 5 cells, you can store your strings as counted strings, using words like C"
- counted strings store the length in the first byte, every subsequent byte is a character.
Also, you can store things into the dictionary at the current dp
using the word ,
(comma).
来源:https://stackoverflow.com/questions/54108389/how-do-i-create-an-array-in-forth