4
votes

I am working on my school project and I would like to use Dynamic (not static) array. I worked with ObjectPascal, so I am used to some syntax. But now I am programming in the old TurboPascal (I am using Turbo Pascal 7 for Windows).

It doesn't seem to know the ObjectPascal, so I thought, that you Turbo Pascal doesn't know dynamic arrays.

Could anyone tell me, if my theory is right or not? I tried to google, but I was not succesfull. Basicly I am asking "how is it with dynamic arrays in Turbo Pascal 7" ? Thank you for all reactions.

3
You can achieve a "dynamic array" with pointers. Google for it.darkl
TP7 did not have dynamic arrays like ObjectPascal in Delphi does. However, one trick in those days was to declare an array as say array[0..0] of integer, then use GetMem to allocate space for an array of whatever size you like and access it via a pointer. That may be what @darkl is thinking of.MartynA
Yes, I found dynamic array with pointers, but I didn't like it at all, I was looking for more "elegant" way to do so. Thank you for you quick help.Palindrom
Are you required to use TP7?lurker
@MartynA not sure why they wouldn't use Free Pascal. Or does the FPC license restrict educational use?lurker

3 Answers

7
votes

As MartynA says, there is no dynamic array type in Turbo Pascal. You need to manually allocate memory using pointers, and be careful if you use rangechecks.

Typically you define an array type

TYPE
  TArrayT = array[0.. ((65535-spillbytes) div sizeof(T))-1] of T;

where spillbytes is a constant for a small deduction because you can't use the whole 64k, see what the compiler accepts. (Probably this deduction is for heapmanager structures inside the 64k block)

Then you define a pointer

  PArrayT= ^TArrayT;

and a variable to it

  var 
     P : PArrayT;
      

and you allocate nrelement elements using getmem;

 getmem(P,SizeOf(T) * nrelements);

and optionally fill them with zero to initialize them:

 fillchar(p^,SizeOf(T) * nrelements,#0);

You can access elements using

 p^[index]

to free them, use freemem using the exact opposite of the getmem line.

 freemem(P,Sizeof(T)*nrelements);

Which means you have to save the allocated number of elements somewhere. This was fixed/solved in Delphi and FPC.

Also keep in mind that you can't find bugs with rangechecking anymore.

If you want arrays larger than 64k, that is possible, but only with constraints, and it matters more which exact TP target (dos, dos-protected or Windows you use) I advise you to search for the online SWAG archive that has many examples. And of course I would recommend to go to FreePascal/Lazarus too where you can simply do:

 var x : array of t;
 begin
    setlength(x,1000000);

and be done with it without additional lines and forget about all of this nonsense.

2
votes

I'm using Turbo Pascal 5.5 and to create a dynamic array, perhaps the trick is to declare an array with zero dimension as follows:

dArray = array [0..0] of integer;

And then declare a pointer to that array:

pArray = ^dArray ;

And finally, create a pointer variable:

ArrayPtr : pArray;

You can now reference the pointer variable ArrayPtr as follows:

ArrayPtr^[i]; { The index 'i' is of type integer}

See the complete example below:

{
  Title: dynarr.pas

  A simple Pascal program demonstrating dynamic array.

  Compiled and tested with Turbo Pascal 5.5.
}

program dynamic_array;


{Main Program starts here}
type
  dArray = array [0..0] of integer;
  pArray = ^dArray ;
var
  i : integer;
  ArrayPtr : pArray;
begin

  for i := 0 to 9 do { In this case, array index starts at 0 instead of 1. }
    ArrayPtr^[i] := i + 1;

  writeln('The Dynamic Array now contains the following:');
  writeln;

  for i := 0 to 9 do
    writeln(ArrayPtr^[i]);

end.

In this example, we have declared the array as:

array[0..0] of integer;

Therefore, the index starts at 0 and if we have n elements, the last element is at index n-1 which is similar to array indexing in C/C++.

Regular Pascal arrays start at 1 but for this case, it starts at 0.

0
votes
unit Vector;

interface

const MaxVector = 8000;
  // 64 k div SizeOf(float); number of float-values that fit in 64 K of stack
  VectorError: boolean = False;
// toggle if error occurs. Calling routine can handle or abort


type
  VectorStruc = record
    Length: word;
    Data: array [1..MaxVector] of float;
  end;
  VectorTyp = ^VectorStruc;

procedure CreateVector(var Vec: VectorTyp; Length: word; Value: float);
{ Generates a vector of length Length and sets all elements to Value }

procedure DestroyVector(var Vec: VectorTyp);
{ release memory occupied by vector }

procedure SetVectorElement(var Vec: VectorTyp; n: word; c: float);

function GetVectorElement(const Vec: VectorTyp; n: word): float;

implementation

var ch: char;

function WriteErrorMessage(Text: string): char;

begin
  Write(Text);
  Read(WriteErrorMessage);
  VectorError := True;         // toggle the error marker
end;

procedure CreateVector(var Vec: VectorTyp; Length: word; Value: float);

var
  i: word;

begin
  try
    GetMem(Vec, Length * SizeOf(float) + SizeOf(word) + 6);
  except
    ch := WriteErrorMessage(' Not enough memory to create vector');
    exit;
  end;
  Vec^.Length := Length;
  for i := 1 to Length do
    Vec^.Data[i] := Value;
end;

procedure DestroyVector(var Vec: VectorTyp);

var
  x: word;

begin
  x := Vec^.Length * SizeOf(float) + SizeOf(word) + 6;
  FreeMem(Vec, x);
end;

function VectorLength(const Vec: VectorTyp): word;

begin
  VectorLength := Vec^.Length;
end;

function GetVectorElement(const Vec: VectorTyp; n: word): float;

var
  s1, s2: string;

begin
  if (n <= VectorLength(Vec))  then
    GetVectorElement := Vec^.Data[n]
  else
  begin
    Str(n: 4, s1);
    Str(VectorLength(Vec): 4, s2);
    ch := WriteErrorMessage(' Attempt to read non-existent vector element No ' +
      s1 + ' of ' + s2);
  end;
end;


procedure SetVectorElement(var Vec: VectorTyp; n: word; C: float);

begin
  if (n <= VectorLength(Vec))  then
    Vec^.Data[n] := C
  else
    ch := WriteErrorMessage(' Attempt to write to non-existent vector element');
end;

end.  

As long as your data fit on the stack, i.e., are smaller than 64 kB, the task is relatively simple. The only thing I don't know is where the 6 bit of extra size go, they are required, however.