Board index » delphi » Two dimensional dynamic arrays (more help please).

Two dimensional dynamic arrays (more help please).

I have a two dimensional dynamic array declared as follows:

     ResultsArray = Array[0..0, 0..0] of Double;
     ResultsPointer = ^ResultsArray;

but I am getting some funny results from it which I think are
from incorrectly dereferencing an array. For example, the following
code should set up a 10 by 10 (zero based) array with the number 7
all along row 7 like this :

0 0 0 0 0 0 0 0 0       {row 0}
0 0 0 0 0 0 0 0 0       {row 1}
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
7 7 7 7 7 7 7 7 7       {row 7}
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0       {row 9}

but instead I get this:

0 0 0 0 0 0 7 7 7       {row 0}
0 0 0 0 0 7 7 7 7       {row 1}
0 0 0 0 7 7 7 7 7
0 0 0 7 7 7 7 7 7
0 0 7 7 7 7 7 7 7
0 7 7 7 7 7 7 7 7
7 7 7 7 7 7 7 7 7
7 7 7 7 7 7 7 7 7       {row 7}
7 7 7 7 7 7 7 7 0
7 7 7 7 7 7 7 0 0       {row 9}

here is the code:

procedure TMyProject.TestRunResults;
var
  Test : ResultsPointer;
  a, b : Integer;
begin
  getmem(Test,9*9*sizeof(Double)); { allocate the memory for a 10 by 10 array of double }

  for a := 0 to 9 do            { initialise it to 0 }
     for b := 0 to 9 do
        Test^[a,b] := 0;

  for a := 0 to 9 do            { fill row 7 with '7' }
     for b := 0 to 9 do
        if a = 7 then Test^[a,b] := a;

  for a := 0 to 9 do            { display the result }
     for b := 0 to 9 do
        DisplayResult(Self,a, b,Test^[a,b]); { displays result in
                a grid in row a, col b }
  freemem(Test,9*9*sizeof(Double)); { free the memory }
end;

I don't understand how the '[]' referencing (eg Test^[a,b]) works
when it is allocated in the manner above, but I'm fairly sure that
it is not how I'm trying to use it.

Does anyone have any ideas? Please help.

Thanks.

Phil.

--
/----------------------------------------------------------------\
| Phillip Middlemiss            | 2 wrongs don't make a right... |
| NZ Forest Research Institute  |                                |
| phill...@tawa.fri.cri.nz      |   .....but three lefts do      |
\----------------------------------------------------------------/

 

Re:Two dimensional dynamic arrays (more help please).


In article <308EA051.5...@fri.cri.nz>
           phill...@fri.cri.nz "Phillip Middlemiss" writes:

Quote
> I have a two dimensional dynamic array declared as follows:

>      ResultsArray = Array[0..0, 0..0] of Double;

I think you want Array[0..9, 0..9] of Double

Quote
>      ResultsPointer = ^ResultsArray;

> but I am getting some funny results from it which I think are
> from incorrectly dereferencing an array. For example, the following
> code should set up a 10 by 10 (zero based) array with the number 7
> all along row 7 like this :

> 0 0 0 0 0 0 0 0 0       {row 0}
> 0 0 0 0 0 0 0 0 0       {row 1}
> 0 0 0 0 0 0 0 0 0
> 0 0 0 0 0 0 0 0 0
> 0 0 0 0 0 0 0 0 0
> 0 0 0 0 0 0 0 0 0
> 0 0 0 0 0 0 0 0 0
> 7 7 7 7 7 7 7 7 7       {row 7}
> 0 0 0 0 0 0 0 0 0
> 0 0 0 0 0 0 0 0 0       {row 9}

> but instead I get this:

> 0 0 0 0 0 0 7 7 7       {row 0}
> 0 0 0 0 0 7 7 7 7       {row 1}
> 0 0 0 0 7 7 7 7 7
> 0 0 0 7 7 7 7 7 7
> 0 0 7 7 7 7 7 7 7
> 0 7 7 7 7 7 7 7 7
> 7 7 7 7 7 7 7 7 7
> 7 7 7 7 7 7 7 7 7       {row 7}
> 7 7 7 7 7 7 7 7 0
> 7 7 7 7 7 7 7 0 0       {row 9}

> here is the code:

> procedure TMyProject.TestRunResults;
> var
>   Test : ResultsPointer;
>   a, b : Integer;
> begin
>   getmem(Test,9*9*sizeof(Double)); { allocate the memory for a 10 by 10 array
>  of double }

and this should be getmem(Test,10*10*sizeof(Double));

(the last element may be 9, but you still need to allocate memory for 10*10)

Possibly won't make any difference - until the last 19 spaces are actually
being used by something else at which point you will get either a GPF or
some very weird results!

Quote

>   for a := 0 to 9 do            { initialise it to 0 }
>      for b := 0 to 9 do
>         Test^[a,b] := 0;

>   for a := 0 to 9 do            { fill row 7 with '7' }
>      for b := 0 to 9 do
>         if a = 7 then Test^[a,b] := a;

>   for a := 0 to 9 do            { display the result }
>      for b := 0 to 9 do
>         DisplayResult(Self,a, b,Test^[a,b]); { displays result in
>                 a grid in row a, col b }
>   freemem(Test,9*9*sizeof(Double)); { free the memory }

again, you need 10s rather than 9s.

Quote
> end;

> I don't understand how the '[]' referencing (eg Test^[a,b]) works
> when it is allocated in the manner above, but I'm fairly sure that
> it is not how I'm trying to use it.

> Does anyone have any ideas? Please help.

> Thanks.

> Phil.

The rest of your code looks fine to me - my suspicion is that the weird
triangular structure is a side-effect of the 0..0 declaration.

If this doesn't fix it, let me know & I'll have another look.

yours,

Catherine.

Quote

> --
> /----------------------------------------------------------------\
> | Phillip Middlemiss            | 2 wrongs don't make a right... |
> | NZ Forest Research Institute  |                                |
> | phill...@tawa.fri.cri.nz      |   .....but three lefts do      |
> \----------------------------------------------------------------/

--
Catherine Rees-Lay                 Cathe...@polyhdrn.demon.co.uk

Polyhedron Software Ltd.        
Programs for Programmers - QA, Compilers, Graphics

************ Visit our Web site on http://www.polyhedron.co.uk/ ************

Re:Two dimensional dynamic arrays (more help please).


Quote
Phillip Middlemiss <phill...@fri.cri.nz> wrote:
>I have a two dimensional dynamic array declared as follows:
>     ResultsArray = Array[0..0, 0..0] of Double;
>     ResultsPointer = ^ResultsArray;

You mean Array[0..9,0..9], right?

Quote
>but I am getting some funny results from it which I think are
>from incorrectly dereferencing an array. For example, the following
>code should set up a 10 by 10 (zero based) array
(snip)
>here is the code:
>procedure TMyProject.TestRunResults;
>var
>  Test : ResultsPointer;
>  a, b : Integer;
>begin
>  getmem(Test,9*9*sizeof(Double)); { allocate the memory for a 10 by 10 array of double }

You need to allocate 10*10*SizeOf(Double), since you need 100 doubles,
not 81.  Or, you could use New(Test), which automatically allocates
the right amount of memory for the data structure pointed to by the
given parameter (in this case, the array pointed to by Test)

Quote
>  for a := 0 to 9 do                { initialise it to 0 }
>     for b := 0 to 9 do
>        Test^[a,b] := 0;

Okay.

Quote
>  for a := 0 to 9 do                { fill row 7 with '7' }
>     for b := 0 to 9 do
>        if a = 7 then Test^[a,b] := a;

Why not just the following (at least for testing purposes):

    For b := 0 to 9 do
       Test^[7,b] := 7;

Quote
>  for a := 0 to 9 do                { display the result }
>     for b := 0 to 9 do
>        DisplayResult(Self,a, b,Test^[a,b]); { displays result in
>            a grid in row a, col b }

I don't know how your DisplayResult proccedure works, but the above
code should give you a row of 7's.  If not, it may be the
DisplayResults procedure, not the contents of the array, that are at
fault.

Quote
>  freemem(Test,9*9*sizeof(Double)); { free the memory }
>end;

Free up 10*10*Sizeof(double).  Or if you use New(Test), use
Dispose(Test) to de-allocate the memory.

Quote
>I don't understand how the '[]' referencing (eg Test^[a,b]) works
>when it is allocated in the manner above

Same as if it was a static array, e.g.

Var  Test : array[0..9,0..9] of double;
        .
        .
        .
     Test[a,b] := x;

You can pass the dereferenced array to another procedure, modify the
contents, or whatever.

Hope this helps!
Warren Sande

Re:Two dimensional dynamic arrays (more help please).


Quote
m...@setanta.demon.co.uk (Matt Francomb) wrote:
>In article <814629738...@polyhdrn.demon.co.uk> Catherine Rees-Lay <Cather...@polyhdrn.demon.co.uk> writes:
>-------------------------------------------------------------------------------------
>   In article <308EA051.5...@fri.cri.nz>
>          phill...@fri.cri.nz "Phillip Middlemiss" writes:

>   > I have a two dimensional dynamic array declared as follows:

>   >      ResultsArray = Array[0..0, 0..0] of Double;

>   I think you want Array[0..9, 0..9] of Double
>Yes, he does, but he wants to set the size dynamically.
>   >      ResultsPointer = ^ResultsArray;
[Snip]
>The problem here is that although you have allocated the memory
>correctly, and have declared two subscripts instead of
>one, you _cannot_ have both dimensions dynamic, even if you
>switch range-checking off.
>I repeat _cannot_.
>The compiler needs to know how many entries there are in each
>row in order to be able to access the rows correctly.

[Snip]
>You'll just have to do the multiplication and stuff yourself.
>And you might as well give the dummy declaration for the array
>as single-dimensional, because you'll just confuse yourself
>further otherwise.

Another alternative that I have used is to create a dynamic array of
pointers to dynamic arrays.  This means that you can have something
that looks similar to a two-dimentional array, and it can be very very
big - maximum of (64k / SizeOf(pointer)) rows, each of which can be
(64k / sizeof(element)) in size.

Here is the code I am using.  This is part of a real-nifty mandelbrot
set program I am working on every now and then - hence the type names.
(Note that this would be better defined in a standalone class... some
time soon.  Also it has no error handling as yet. )

Types defined :

  FracPix = record
     n : Integer;   { note : value 0 indicates not yet processed }
    {rest of record details not really relevant }
  end;

  FPa = array[0..0] of FracPix;
  PFPa = ^FPa;
  TFracArray = array[0..0] of PFPa;  { array of array pointers }
  TPFracArray = ^TFracArray;  { pointer to that array }

On creating the array :
var
  pFracArray : TPFracArray;
  i, fWidth, fHeight : Integer;
begin
    getmem(pFracArray, fwidth * sizeof(PFPa));
    for i := 0 to fwidth - 1 do
      begin
        getmem(pFracArray^[i], fheight * sizeof(FracPix));
        ap := pFracArray^[i];
        for j := 0 to fheight - 1 do
          ap^[j].n := 0;  { flag - not yet calculated }
      end;
end;

On destroying the array :
  if pFracArray <> nil
  then begin
    for i := 0 to fwidth - 1 do
      freemem(pFracArray^[i], fheight * sizeof(FracPix));
    freemem(pFracArray, fwidth * sizeof(PFPa));
    pFracArray := nil;
  end;

To access an element in the array, use
  pFracArray^[x]^[y];

You do have to pay a large performance penalty here - every array
access involves two or three pointer dereferences - but it works for
now - it will do until Delphi32 comes out!

Hope this helps.

 - Korny
-------------------------------------------------------------------
  Kornelis Sietsma | ko...@zikzak.net | http://zikzak.net/~korny

Other Threads