Link to home
Start Free TrialLog in
Avatar of rfwoolf
rfwoolfFlag for South Africa

asked on

Setting the length of a multidimentional array

I'm getting an access violation so I'm going to need some help...

First I have my array
var
  multiarray : array of array of array of string;

The first dimension will be 1 to 15 (there are 15 departments)
The second dimension will be from 1 up to the number of jobs in that department. Here's an example:
DEPARTMENT 1: 10 Jobs
DEPARTMENT 2: 12 Jobs
DEPARTMENT 3: 7 Jobs
...
DEPARTMENT 15: 9 Jobs
This information is stored in
var
  departmentcounts : array[1..15] of integer;
 
Then...
The third dimension will be for each job! There will be strings from 1 to 14.

Can you give me some examples of setlength that can accomplish this.
I'm sure I'm doing it wrong!

  for k := 1 to 15 do
  begin
    for i := 1 to departmentcounts[k] do
    setlength(multiarray[k], departmentcounts[i], 14);
  end;
end;
Avatar of Lukasz Zielinski
Lukasz Zielinski
Flag of Poland image

so first dimension is array[1..15] of Integer or is it array of array... ?

ziolko.
Avatar of rfwoolf

ASKER

Ziolko - as far as I'm concerned it's an array.
Here's a reword:
There are 15 departments,
each departments has X jobs,
each job has 14 variables.

The number of jobs in each department is already stored in array called "departmentcounts" which is an array[1..15] of integer
So to get the number of jobs in Department one, call departmentcounts[1];
To get the number of jobs in Department two, call departmentscounts[2];

Create a multi-dimensional array to represent this information.
Set the size of each dimension, using setlength for the second dimension.
procedure TForm1.Button1Click(Sender: TObject);
var multiarray: array of array of array of string;
    cnt, cnt2: Integer;
begin
  SetLength(multiarray, 15);//first dimension - 15 departments
  for cnt := 0 to 14 do begin
    SetLength(multiarray[cnt], cnt + 2); //second dimension - sample lengths: 1 dep = 3 jobs, 2 dep - 4 jobs...
    for cnt2 := 0 to Length(multiarray[cnt]) - 1 do
      SetLength(multiarray[cnt][cnt2], 14); //third dimension - fixed length = 14
  end;
  multiarray[0][0][0] := 'job';
end;

ziolko.
including array[1..15] of integer with jobs count

procedure TForm1.Button1Click(Sender: TObject);
var multiarray: array of array of array of string;
    jobscount: array[1..15] of Integer;
    cnt, cnt2: Integer;
begin
  // fill jobscount here with random values
  Randomize;
  for cnt := 1 to 15 do
    jobscount[cnt] := Random(20);
  //
  SetLength(multiarray, 15);//first dimension - 15 departments
  for cnt := 0 to 14 do begin
    SetLength(multiarray[cnt], jobscount[cnt + 1]); //second dimension - taken from jobscount
    for cnt2 := 0 to Length(multiarray[cnt]) - 1 do
      SetLength(multiarray[cnt][cnt2], 14); //third dimension - fixed length = 14
  end;
  multiarray[0][0][0] := 'job';
end;


ziolko.
and if you always have 15 departments and each job will have always 14 variables you cen mix open and fixed array:

procedure TForm1.Button1Click(Sender: TObject);
var multiarray: array[1..15] of array of array[1..14] of string;
    jobscount: array[1..15] of Integer;
    cnt: Integer;
begin
  // fill jobscount here with random values
  Randomize;
  for cnt := 1 to 15 do
    jobscount[cnt] := Random(20);
  //
  for cnt := 1 to 15 do begin
    SetLength(multiarray[cnt], jobscount[cnt]); //second dimension - taken from jobscount
  end;
  multiarray[1][0][1] := 'job';
end;

just remember that 1st and 3rd dimensions are indexed from 1 and second dimension is indexed from 0

ziolko.
Avatar of rfwoolf

ASKER

Hmmm looks great, I've adapted it a bit and am getting an access violation. Not sure why.
I'm going to go try it in the actual application.

This whole setlength thing is what has been confusing me - the help files and online examples all suck :)

var
  multiarray: array of array of array of string;
  departmentcounts : array[1..15] of integer;
  cnt, cnt2: Integer;
begin
  SetLength(multiarray, 15);//first dimension - 15 departments
  for cnt := 1 to 15 do begin
    SetLength(multiarray[cnt], departmentcounts[cnt]); //second dimension - sample lengths: 1 dep = 3 jobs, 2 dep - 4 jobs...
    for cnt2 := 1 to departmentcounts[cnt] do
     SetLength(multiarray[cnt][cnt2], 14); //third dimension - fixed length = 14
  end;
  multiarray[0][0][0] := 'job';
end; 

Open in new window

Avatar of rfwoolf

ASKER

Just saw your 2nd answer - I'll try it :)
Avatar of rfwoolf

ASKER

"just remember that 1st and 3rd dimensions are indexed from 1 and second dimension is indexed from 0"
ahhh that's probably what's doing it :)
here:
SetLength(multiarray, 15);//first dimension - 15 departments
  for cnt := 1 to 15 do begin

if you keep multiarray an open array it's indexed from 0 not from 1 so you HAVE to make a loop
for cnt := 0 to 14 NOT for cnt := 1 to 15

same here:
for cnt2 := 1 to departmentcounts[cnt] do
     SetLength(multiarray[cnt][cnt2], 14); //third dimension - fixed length = 14

should be:
for cnt2 := 0 to departmentcounts[cnt] - 1

again it's open array so it's 0-indexed

ziolko.
>>"just remember that 1st and 3rd dimensions are indexed from 1 and second dimension is indexed from 0"

>>ahhh that's probably what's doing it :)

that's true for declaration like this:
multiarray: array[1..15] of array of array[1..14] of string;

if you stick to open arrays
multiarray: array of array of array of string;
all 3 dimensions are 0-indexed

ziolko.

you can do quick test on simple one dimensional array.

1.
var a: array of string;

SetLength(a, 2);

for cnt := 0 to 1 do //this wll work
  a[cnt] := 'aaa';

for cnt := 1 to 2 do // this will fail with access violation
  a[cnt] := 'aaa';

2.
var a: array[1..2] of string;

for cnt := 1 to 2 do // this will work
  a[cnt] := 'aaa';

for cnt := 0 to 1 do // this will not compile (out of bounds)
  a[cnt] := 'aaa';

ziolko.
Avatar of rfwoolf

ASKER

That last code I pasted..
...when I adapted it for 0-indexing and it worked - it took forever and I ran out of memory. Now Delphi's crashing when I run it.
Have to reboot, then will try your code. Thanks :)
>>it took forever and I ran out of memory

look here:
for cnt := 0 to 14 do begin
    SetLength(multiarray[cnt], departmentcounts[cnt + 1]);

if multiarray is open array it's 0-indexed but departmentcounts is fixed array[1..15] of Integer
in this situation you have 0-indexed and 1-indexed array
so you have to do it like this:
    SetLength(multiarray[cnt], departmentcounts[cnt + 1]);if you do it like this
    SetLength(multiarray[cnt], departmentcounts[cnt]);
results might be unpredictible

ziolko.
I think it would be easier if you decide if you want to use

multiarray: array of array of array of string;
or
multiarray: array[1..15] of array of array[1..14] of string;

:)

ziolko.
Avatar of rfwoolf

ASKER

Oh crap. ... Today I updated to Internet Explorer 8 beta 2 and delphi was working fine, but since the memory crash, when I reset the layout to "Classic Undocked" it gives error "Access Violation at address blahblah in module 'ieframe.dll'
ieframe.dll <--- internet explorer?

I guess I may have to uninstall IE 8 :p
Anyways, I'll stay in debug mode and try your code.
ASKER CERTIFIED SOLUTION
Avatar of Lukasz Zielinski
Lukasz Zielinski
Flag of Poland image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of rfwoolf

ASKER

Thank you so much for the excellent help Ziolko.
At one point I was using Setlength to set the length of each dimension all in one go, e.g.
setlength(ArrayName, Dimension1, Dimension2, Dimension3) etc.

and the 0-based vs. 1-based index thing is very important here.
Thanks! :)
Avatar of rfwoolf

ASKER

A very worthy expert!
glad I could help:)

ziolko.