Dynamiczna tablica wielowymiarowa jako parametr funkcji

0

Jak w temacie.

Muszę napisać procedurę/funkcję, która będzie wykonywała operacje na wielowymiarowych tablicach dynamicznych.

Gdy składam coś takiego:

function Tab(Tablica:array of string):String;
begin

end;

to niby działa (kompiluje się). To jednak jest parametr w postaci tablicy jednowymiarowej, a ja mam tablice wielowymiarowe.

Zmieniam więc na:

function Tab(Tablica:array of array of string):String;
begin

end;

i wychodzi klops. Kompilator wypluwa:

"Identifier expected but "ARRAY" found".

Jest to dla mnie o tyle dziwne, że deklarowanie w ten sposób tablic jako zmiennych działa poprawnie. Np.:

var
Tablica: array of array of string;

Ponadto nie wiem czemu, ale nie mogę zmieniać długości takiej tablicy z parametru za pomocą SetLength. Wychodzi "Incompatibile Types"... Również jest mi to potrzebne, bo moja funkcja zakłada trwałe modyfikowanie tych tablic (dodawanie i wywalanie rekordów).

Szukałem na forum, czytałem art z kompendium na temat tablic, ale odpowiedzi nie znalazłem.

0

sprobuj takie cos

type
  TXYKolor = array of array of integer;
  
  
 procedure Wyswietl(const xPoczatek, yPoczatek: integer; const xyKolor: TXYKolor);

a co do SetLength

  for x := 0 to Length(xyKolor) - 1 do
    for y := 0 to Length(xyKolor[0]) - 1 do

powinno pomoc

0

@Crow - Ty używasz w deklaracji funkcji otwartej tablicy (tzw. open array); Więc jeżeli potrzebujesz użyć wielowymiarowej tablicy jako parametru, to musisz zadeklarować najpierw jej typ, np.:

type
  TMyArray = array of array of Integer;

a następnie użyć jej w deklaracji funkcji:

function Foo(AArray: TMyArray): String;
{...}

Wymiary tak przekazanej macierzy możesz pobierać wewnątrz funkcji za pomocą funkcji Length.

0

Oczywiście działa, dzięki, ale - tak by poszerzyć swoją wiedzę - czemu taka dwuwymiarowa tablica musi najpierw zostać zadeklarowana jako typ? Czemu nie można użyć jej bezpośrednio jak każdego innego parametru (czy choćby nawet jednowymiarowych tablic)?

0

Ponieważ przy tym:

function Tab(Tablica:array of array of string):String;

trzeba wywoływać tak:

Tab([['aaa','bbb','ccc'],['11','22']]);
0

Czemu nie można użyć jej bezpośrednio jak każdego innego parametru (czy choćby nawet jednowymiarowych tablic)?

Bo deklarujesz wtedy open array, które może i jest podobne do zwykłej tablicy, ale ma zupełnie inne zastosowanie.

1
Crow napisał(a)

Czemu nie można użyć jej bezpośrednio jak każdego innego parametru (czy choćby nawet jednowymiarowych tablic)?

Z prostej przyczyny - kompilator nie pozwala, uznając to za błąd składniowy języka;

Napisałem Ci wcześniej, że Ty próbujesz użyć open array, które nie mogą być wielowymiarowe; Chodzi o to, że mając np. poniższą procedurę:

procedure Foo(const AItems: array of Integer);

Możesz podać do niej dowolną macierz jednowymiarową, indeksowaną dowolnie, byle typ elementów się zgadzał; Np.:

type
  TItemsArr = array [0 .. 4] of Integer;
var
  arrItems: TItemsArr = (0, 1, 2, 3, 4);
begin
  Foo(arrItems);
end.

Ta indeksowana jest od 0 do 4; Możesz też podać macierz inaczej indeksowaną:

type
  TItemsArr = array [5 .. 9] of Integer;
var
  arrItems: TItemsArr = (5, 6, 7, 8, 9);
begin
  Foo(arrItems);
end.

ale ważne jest to, że open array zawsze indeksowany jest od 0, czyli wewnątrz procedury Foo; Dlatego też wewnątrz procedury Foo początkowy i końcowy indeks macierzy musisz pobierać za pomocą instrukcji Low i High, ewentualnie od 0 do Length - 1:

procedure Foo(const AItems: array of Integer);
var
  intLoop: Integer;
begin
  for intLoop := Low(AItems) to High(AItems) do
//for intLoop := 0 to Length(AItems) - 1 do
    WriteLn(AItems[intLoop]);
end;

type
  TItemsArr = array [5 .. 9] of Integer;
var
  arrItems: TItemsArr = (5, 6, 7, 8, 9);
  intLoop: Integer;
begin
  Foo(arrItems);
  ReadLn;
end.

Jeżeli użyjesz indeksowania od 5 do 9 - wyjedziesz poza rozmiar tablicy, nawet jeśli macierz indeksowana jest od 5 do 9:

procedure Foo(const AItems: array of Integer);
var
  intLoop: Integer;
begin
  for intLoop := 5 to 9 do // wyjechanie poza rozmiar tablicy
    WriteLn(AItems[intLoop]);
end;

Taki jest sens używania otwartych macierzy, że indeksowanie podawanych macierzy jest sprowadzane do uniwersalnej postaci, czyli od indeksowania od 0.

1 użytkowników online, w tym zalogowanych: 0, gości: 1