Przekazywanie dwuwymiarowej tablicy.

0

Cześć, mam bardzo krótkie pytanie. Programuje już od dłuższego czasu w C++, niestety nigdy nie natrafiłem na taki "problem", otóż:

mam tablicę: int tab[2][2] = {...};

oraz funkcję: print(int argTab[][]) {}

Moję pytanie, jak mogę przekazać tą tablicę do tej funkcji ? Wiem, że gdybym podał rozmiar drugiego wymiaru (lub po prostu liczbę większą) to by działało, ale jak to zrobić, przy założeniu, że nie znam wielkości tych wymiarów ?

0

Alokuj pamięć dynamicznie i przekaż int** razem z wymiarami jako argumenty funkcji?

1

Moję pytanie, jak mogę przekazać tą tablicę do tej funkcji ? Wiem, że gdybym podał rozmiar drugiego wymiaru (lub po prostu liczbę większą) to by działało, ale jak to zrobić, przy założeniu, że nie znam wielkości tych wymiarów ?

Prosto się nie da, jest to związane z tym jak kompilator traktuje statyczne tablice dwuwymiarowe:

A B C
D E F
G H I

rozmiar tablicy nie jest nigdzie przechowywany, dlatego ta tablica w pamięci wygląda po prostu tak:
A B C D E F G H I

Kiedy piszesz z = tab[x, y], kompilator generuje coś w rodzaju:

z = *(tab + x*width + y)

Czyli mnoży x razy logiczną szerokość tablicy, symulując jej dwuwymiarowość (na przykład dla powyższej - *(tab + 1*3 + 2) == *(tab + 5) == tab[5], czyli F - element w 3 kolumnie 2 wiersza.

Trick polega na tym, że szerokość jest hardcodowana w kodzie na podstawie typu tablicy. Czyli nie możesz przekazać tablicy dwuwymiarowej jako parametr, bo kompilator nie będzie wiedział przez co pomnożyć x.

Najprościej to obejść, przejmując na siebie obowiązki kompilatora:

int *tab = (int*)array;
z = *(tab + x*width + y); // z = tab[x, y]

Tak, to brzydkie rozwiązanie... Ładne rozwiązanie to przekazanie tablicy wskaźników, czyli int** - jak @Shalom proponuje.

3

jeśli rozmiary tablicy mają być stałe:

#include <iostream>
using namespace std;

void print(int (&argTab)[2][2])
{
  cout << argTab[0][0] << ' ' << argTab[0][1] << endl;
  cout << argTab[1][0] << ' ' << argTab[1][1] << endl;
}

int main()
{
  int tab[2][2] = {{2,3},{4,5}};
  print(tab);
}

Prosto się nie da
Nieprawda. Tylko rozmiar tablicy musi być znany w momencie kompilacji.

#include <iostream>
using namespace std;

template <int W, int H>
void print(int (&argTab)[W][H])
{
   for (int i=0; i<W; i++)
   {
       for (int j=0; j<H; j++)
          cout << argTab[i][j] << ' ';
       cout << endl;
   }
}

int main()
{
  int taba[2][2] = {{2,3},{4,5}};
  print(taba);
  int tabb[3][3] = {{2,3,0},{4,5,1},{6,7,8}};
  print(tabb);
}
0

Ok, dzięki wszystkim za szybką pomoc.

0

Jest jeszcze inny sposób. Umieścić tablicę w strukturze (klasie). Pozwala to przekazać tablicę nie tylko przez adres, ale i przez wartość.

0

Skoro nie ma wielowymiarowych tablic tylko są tablice tablic to ja bym skonstruował np wektor wektorów
std::vector<std::vector<int>> to też będzie tablica 2 wymiarowa z logicznego punktu widzenia. Potem bym po prostu przesłał to do funkcji jako obiekt.

0

Można jeszcze użyć boost::multi_array
http://www.boost.org/doc/libs/1_51_0/libs/multi_array/doc/user.html

Najprościej to będzie tak jak napisał Azarien.

0

Można jeszcze sobie zrobić funkcję-proxy coby kompilator nie generował osobnej instancji dla każdego użytego wymiaru tablicy, ale to już tylko jako ciekawostkę podaję:

/* proxy, do umieszczenia w pliku nagłówkowym */
template <size_t W, size_t H>
static inline void print(int (&argTab)[W][H])
{
    print((int*)&argTab, W, H);
}

/* funkcja właściwa, może być w .cpp */
void print(int *argTab, unsigned w, unsigned h)
{
   for (int i=0; i<w; i++)
   {
       for (int j=0; j<h; j++)
          cout << *argTab++ << ' ';
       cout << endl;
   }
}

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