Tablice

darek963

Poniższa publikacja zawiera podstawowe informacje wraz z przykładami, które pozwalają na wykorzystanie tablic w języku C#. Artykuł nie wyczerpuje tematu.

Tablica to najprościej rzecz ujmując zestaw zaindeksowanych zmiennych tego samego typu. Początkujący programista może zapytać po co tablice skoro są zmienne? Taka struktura danych znajduje szerokie zastosowanie. Np jeśli chcemy w pamięci przechowywać nazwy dni tygodnia dużo wygodniej jest skorzystać z tablic zamiast ze zmiennych. Będą one przetrzymywane w strukturze o tej samej nazwie i będziemy mogli się do nich odwoływać po indeksie, który będzie reprezentował ich kolejność w kalendarzu.

1 Tablice jednowymiarowe
2 Tablice wielowymiarowe
3 Tablice postrzępione (jagged arrays)

Tablice jednowymiarowe

Deklaracja tablicy w języku C# wygląda następująco:

typ_danych[] nazwa_tablicy; 

przykład:

string[] dniTygodnia; 

Ten przykład zadeklarował nam tablicę, której elementy są typu string. Samo zadeklarowanie tablicy nie powoduje, że jest ona już gotowa do użycia (tak jak to bywa w niektórych językach). Należy ją teraz zainicjalizować:

nazwa_tablicy = new typ_danych[liczba_elementów]; 

przykład:

dniTygodnia = new string[7]; 

Mamy już gotową tablicę, w której możemy zapisywać wartości:

nazwa_tablicy[indeks] = wartosc; 

przykład:

dniTygodnia[0] = "poniedziałek";
dniTygodnia[1] = "wtorek";
dniTygodnia[2] = "środa";
dniTygodnia[3] = "czwartek";
dniTygodnia[4] = "piątek";
dniTygodnia[5] = "sobota";
dniTygodnia[6] = "niedziela"; 

Teraz ktoś może zapytać - a skąd to zero? Programując w C# należy pamiętać, że w tym środowisku wszystkie indeksy są tworzone od zera a nie od 1. Czyli deklarując tablicę dniTygodnia w powyższy sposób stworzyliśmy strukturę, której pierwszy element posiada indeks 0 a ostatni 6.

Deklarację i inicjalizację można połączyć i zapisać w jednej linii.

string[] dniTygodnia = new string[7]; 

Kolejny sposób zapisu w jednej linii to deklaracja tablicy i przypisanie wartości. Tutaj nie trzeba jawnie zapisywać inicjalizacji:

string[] dniTygodnia = { "poniedziałek", "wtorek", "śr", "cz", "pi", "so", "ni" }; 

Umiemy już deklarować i inicjalizować tablicę oraz zapisywać w niej wartości. Teraz czas pokazać jak odczytywać z niej dane. Poniższy kod tworzy zmienną i tablicę typu string oraz przypisuje do zmiennej pierwszą wartość z tablicy (o indeksie 0):

string zmienna;
string[] dniTygodnia = { "poniedziałek", "wtorek", "śr", "cz", "pi", "so", "ni" };
zmienna = dniTygodnia[0]; 

W języku C# tablica to nie tylko struktura danych ale również obiekt, przez co posiada własne metody oraz właściwości. Dzięki temu korzystanie z tablic staje się jeszcze łatwiejsze. Np. żeby odczytać długość tablicy (liczbę elementów) możemy skorzystać z właściwości Length:

int dlugoscTablicy;
dlugoscTablicy = dniTygodnia.Length; 

Podczas odczytywania lub zapisywania wartości w tablicach w nawiasach kwadratowych zamiast jawnej liczby można podać nazwę zmiennej, która będzie tego samego typu. Dzięki temu w łatwy sposób możemy np. odczytać interesujące nas elementy tablicy:

pierwsze 5:

for (int indeks = 0; indeks < 5; indeks++)
{
Console.WriteLine( dniTygodnia[indeks] );
} 

wszystkie:

for (int indeks = 0; indeks < dniTygodnia.Length; indeks++)
{
Console.WriteLine( dniTygodnia[indeks] );
} 

Operując na wszystkich elementach tablicy warto skorzystać z pętli FOREACH. Daje nam ona możliwość krótszego zapisu niż pętla FOR:

foreach(string element in dniTygodnia)
{
Console.WriteLine(element);
} 

W powyższym przypadku pętla FOREACH wykona się tyle razy ile jest elementów w tablicy dniTygodnia. Podczas każdej iteracji pętli do zmiennej element będzie przypisany kolejny element tablicy.

Tablice wielowymiarowe

Tablice w języku C# mogą posiadać więcej niż jeden wymiar. Tzn. że każdy element może być reprezentowany przez więcej niż jeden indeks.

Wizualizacja tablicy jednowymiarowej:

0123456
poniedzialekwtorekśrczpisoni

Wizualizacja tablicy dwuwymiarowej:

0123456
0poniedzialekwtorekśrczpisoni
1mondaytuesdaywethfrsasu
2montagdienstagmidofrsaso

Deklaracja i inicjalizacja tablicy dwuwymiarowej, która będzie przechowywać nazwy dwóch pierwszych dni tygodnia w trzech językach:

string[,] dniTygodnia;
dniTygodnia = new string[2, 3]; 

to samo można zapisać w jednej linii:

string[,] dniTygodnia = new string[2, 3]; 

Przypisanie wartości do elementów tablicy dwuwymiarowej:

dniTygodnia[0, 0] = "poniedzialek";
dniTygodnia[1, 0] = "wtorek";
dniTygodnia[0, 1] = "monday";
dniTygodnia[1, 1] = "tuesday";
dniTygodnia[0, 2] = "montag";
dniTygodnia[1, 2] = "dienstag"; 

Odczytywanie wartości elementu tablicy dwuwymiarowej:

string zmienna;
zmienna = dniTygodnia[1, 1]; 

Wyświetlenie w konsoli nazw drugiego dnia tygodnia (indeks = 1) we wszystkich językach:

for (int i = 0; i < 3; i++)
{
Console.WriteLine(dniTygodnia[1,i]);
} 

Wyświetlenie wszystkich elementów tablicy używając pętli FOREACH:

foreach (string element in dniTygodnia) 
{ 
Console.WriteLine(element); 
} 

Aby sprawdzić ile wymiarów ma tablica należy posłużyć się właściwością Rank:

int[,,] ary = new int[2, 4, 3];
Console.WriteLine(ary.Rank); // 3

Deklaracja tablicy typu prostego może wyglądać tak:

int[] tab = new tab[10];

a jej użycie tak:

tab[0]=20;

Jeżeli zechcemy użyć własną klasę:

sigma
{
    int value;
    public void SETvalue(int a)
    {
        value = a;
    }
}

i zbudować tablicę wielowymiarową klas, to deklaracja:

sigma[,] si = new sigma[2,5];

nie wystarczy. Trzeba jeszcze dla każdego pola tablicy utworzyć instancje klasy np. tak:

si[0,0] = new sigma();

Dopiero wtedy można odwołać się do pola tablicy:

si[0,0].SETvalue(5);

Tablice postrzępione (jagged arrays)

Elementami tablicy postrzępionej (ang. jagged array) są tablice. Przykład deklaracji takiej tablicy:
int[][] ary = new int[3][];

ary[0] = new int[2];
ary[1] = new int[4];
ary[2] = new int[3];

ary[0][0] = 1;
ary[0][1] = 2;

ary[1][0] = 3;
ary[1][1] = 4;
ary[1][2] = 5;
ary[1][3] = 6;

ary[2][0] = 7;
ary[2][1] = 8;
ary[2][2] = 9;

Jak widzimy elementami tej tablicy są tablice, które zawierają po kolei 2, 4 i 3-elementy. Powyższy kod można zapisać krócej - od razu inicjalizując elementy, dzięki czemu nie trzeba podawać wymiaru tablicy:

int[][] ary = new int[][]
{
    new int[2],
    new int[4],
    new int[3]
};
ary[0][0] = 1;
ary[0][1] = 2;

ary[1][0] = 3;
ary[1][1] = 4;
ary[1][2] = 5;
ary[1][3] = 6;

ary[2][0] = 7;
ary[2][1] = 8;
ary[2][2] = 9;

lub jeszcze prościej:

int[][] ary =           // lub: int ary[][] = new int[][]
{
    new int[] {1,2},
    new int[] {3,4,5,6},
    new int[] {7,8,9}
};

Należy pamiętać, iż typy "podrzędnych" tablic muszą być takie same jak typ tablicy "głównej", przez co niemożliwy jest zapis np.:

int[][] ary =
{
    new double[] {1.99, 2.88}, // <-- błąd konwersji int[] -> double[]
    new int[] {3,4,5,6},
    new int[] {7,8,9}
};

Jest to oczywiste, bo w końcu chodzi nam o tablicę intów.

Dostęp do tablic postrzępionych realizowany jest w postaci tablica[x][y], gdzie x to indeks elementu tablicy "głównej", a y - indeks tablicy, która znajduje się pod elementem x tablicy "głównej". Przykład dla zadeklarowanej wyżej tablicy ary:

Console.Write(ary[1][2]); // 5

ponieważ:

1 2 // ary[0]
3 4 5 6 // ary[1]
7 8 9 // ary[2]

1 2
3 4 5 6</b> // ary[1][2]
7 8 9

Jeśli chodzi o właściwość Length, to:

Console.Write("{0}; {1} {2}", ary.Length, ary[0].Length, ary[1].Length); // 3; 2 4

Oczywiście można też tworzyć bardziej zagnieżdżone wymiary:

int[][][] ary =
{
    new int[][]
    {
        new int[] {1,2},
        new int[] {3,4,5}
    }
};
Console.Write(ary[0][1][2]); // 5

Również nic nie stoi na przeszkodzie, aby zadeklarować tablice wielowymiarowe:

int[][,] ary =
{
    new int[,] { {1,2}, {3,4} },
    new int[,] { {5,6,7}, {8,9,10} }
};
Console.WriteLine(ary[1][0, 2]); // 7

Tablice postrzępione przydają się, kiedy różne wymiary mają mieć różną ilość elementów i/lub trzeba się do nich dostać nie znając wymiarów tablicy. Oto przykład:

int[,] ary = new int[2, 3] { {1,2,3}, {4,5,6} };
for (int i = 0; i < 2; i++)
{
    for (int j = 0; j < 3; j++)
        Console.Write(" {0}", ary[i, j]);
    Console.WriteLine();
}

Wynik będzie następujący:

1 2 3
4 5 6

a co, jeśli chcielibyśby wyświetlić:

1 2 3
4 5

Tablicami wielowymiarowymi to już się tak prosto nie da, jedynym wyjściem będzie warunek w środku pętli, ale to bez sensu. Do tego możemy właśnie użyć jagged array:

int[][] ary =
{
    new int[] {1,2,3},
    new int[] {4,5},
};
for(int i = 0; i < ary.Length; i++)
{
    for(int j = 0; j < ary[i].Length; j++)
        Console.Write("{0} ", ary[i][j]);
    Console.WriteLine();
}

5 komentarzy

Witam. Koledzy potrzebuje utworzyć tablicę 63 wiersze i 12 kolumn i wpisywać do niej dane w formie {1,2,3,4,5,6,7,8,9,10,11,12}. Tablicę zadeklarowałem jako:
int[,] tablicaA;
tablicaA = new int [63,12];
chyba dobrze ale nie jej wypełnić w formie podanej wyżej. Co robię źle?

Brakuje jeszcze opisu jak wyświetlić tablice dwuwymiarowe w Windows Forms.

Już nie brakuje ;]

"Teraz ktoś może zapytać - a skąd to zero? Programując w C# należy pamiętać, że w tym środowisku wszystkie indeksy są tworzone od zera a nie od 1." Trochę niefortunne stwierdzenie, bo w większości (jeśli nie we wszystkich) języków tak jest.

BTW. Dobry tekst

Artykuł OK, choć brakuje opisu tablic postrzępionych (jagged array). A i dodaj artykuł też do podręcznika.
Pozdrawiam.