简体   繁体   中英

Dynamic array in Turbo Pascal

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.

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.

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.

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, ie, 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM