Lazarus

Free Pascal => General => Topic started by: Neville on December 08, 2021, 11:07:17 am

Title: Dynamic Arrays
Post by: Neville on December 08, 2021, 11:07:17 am
I'm getting grief with a rectangular array which I need to resize dynamically during a process (almost always an increase of either rows or columns.  Is there an approved way of doing this?
Title: Re: Dynamic Arrays
Post by: JernejL on December 08, 2021, 11:43:26 am
I would suggest you use a 1-dimensional array, and use a custom row-column lookup method.
 
Title: Re: Dynamic Arrays
Post by: Neville on December 08, 2021, 12:03:31 pm
Thanks, I'll experiment with that.
Title: Re: Dynamic Arrays
Post by: marcov on December 08, 2021, 12:16:19 pm
Dynamic arrays can be ragged, iow each second level of the array can have varying sizes.
Title: Re: Dynamic Arrays
Post by: Neville on December 08, 2021, 12:54:54 pm
Yes, but I've taken great care to ensure that all rows have the same length, and new elements are zeroed.  I'm still geting spurious entries after a resize.
Title: Re: Dynamic Arrays
Post by: MarkMLl on December 08, 2021, 01:06:22 pm
Yes, but I've taken great care to ensure that all rows have the same length, and new elements are zeroed.  I'm still geting spurious entries after a resize.

Are you enforcing that using assertions where appropriate?

MarkMLl
Title: Re: Dynamic Arrays
Post by: Kays on December 08, 2021, 01:15:08 pm
Show us some code. Here’s a quick demo I’ve drawn up:
Code: Pascal  [Select][+][-]
  1. program matrixDemo(input, output, stdErr);
  2.  
  3. type
  4.         integerList = array of integer;
  5.         integerLists = array of integerList;
  6.  
  7. procedure print(const data: integerLists);
  8. var
  9.         x, y: integer;
  10. begin
  11.         for x := 0 to high(data) do
  12.         begin
  13.                 for y := 0 to high(data[x]) do
  14.                 begin
  15.                         write(data[x, y]:8);
  16.                 end;
  17.                 writeLn;
  18.         end;
  19. end;
  20.  
  21. var
  22.         data: integerLists;
  23. begin
  24.         data := integerLists.create(
  25.                         integerList.create(1, 2),
  26.                         integerList.create(3, 4)
  27.                 );
  28.         print(data);
  29.         writeLn;
  30.        
  31.         setLength(data, length(data), length(data[0]) + 1);
  32.         data[0, 2] := 5;
  33.         data[1, 2] := 6;
  34.         print(data);
  35.         writeLn;
  36.        
  37.         setLength(data, length(data) + 1, length(data[0]));
  38.         print(data);
  39. end.

Yes, but I've taken great care to ensure that all rows have the same length, and new elements are zeroed.  I'm still geting spurious entries after a resize.
This should not be necessary: SetLength (https://www.freepascal.org/docs-html/rtl/system/setlength.html) already zeroes out any additional fields. See also the demo.
Title: Re: Dynamic Arrays
Post by: BobDog on December 11, 2021, 04:04:18 pm
You could do this pedantically, without any memory overlap problems, just using the array elements.
Code: Pascal  [Select][+][-]
  1. program resizearrays;
  2.  
  3.  
  4. {$rangeChecks on}  // optional
  5.  
  6. type MyArray=array of array  of int32;
  7.  
  8. procedure resize(var a:MyArray;d1:int32;d2:int32);
  9. var
  10. copy:MyArray;
  11. x,y:int32;
  12. begin
  13. SetLength(copy,d1,d2);
  14.     For x :=0 to d1-1 do
  15.     begin
  16.         For y :=0 to d2-1 do
  17.         begin
  18.             If ((x<=high(a)) and (y<=high(a[0]))) then  copy[x,y]:=a[x,y];    
  19.       end;
  20.     end;
  21.     setlength(a,0,0);
  22.     setlength(a,d1,d2);
  23.     For x := 0 to d1 -1 do
  24.     begin
  25.         For y :=0 to d2 -1 do
  26.         begin
  27.             a[x,y]:=copy[x,y];
  28.        end;
  29.    end;
  30. End;
  31.  
  32. procedure fill(var a:myArray);
  33. var
  34. x,y:int32;
  35. begin
  36.  For x := 0 to high(a) do
  37.     begin
  38.         For y :=0 to high(a[0]) do
  39.         begin
  40.             a[x,y]:=1+random(9);
  41.        end;
  42.    end;
  43. end;
  44.  
  45. procedure show(var a:MyArray);
  46. var
  47. x,y:int32;
  48. begin
  49.  For x := 0 to high(a) do
  50.     begin
  51.         For y :=0 to high(a[0]) do
  52.         begin
  53.             write(a[x,y],' ');
  54.        end;
  55.        writeln;
  56.    end;
  57. end;
  58.  
  59. var
  60. a1:MyArray;
  61.  
  62.  
  63. begin
  64. setlength(a1,7,9);
  65. writeln('lengths ',high(a1),' x ',high(a1[0]),' (filled with random digits)');
  66. fill(a1);
  67. show(a1);
  68. resize(a1,9,13);
  69. writeln('lengths ',high(a1),' x ',high(a1[0]));
  70. show(a1);
  71. resize(a1,6,6);
  72. writeln('lengths ',high(a1),' x ',high(a1[0]));
  73. show(a1);
  74. writeln('Press return to end . . .');
  75. readln;
  76. end.
  77.  
I use integer array, but other array types are OK if defined as MyArray, or you could maybe template for a generic type.
Title: Re: Dynamic Arrays
Post by: SymbolicFrank on December 13, 2021, 10:05:39 am
As the array gets copied, it is more efficient to double the size than to increase it by 1.
TinyPortal © 2005-2018