Colobot Wiki
Advertisement

Definicja[]

Tablica to zestaw obiektów określonego typu. W języku CBOT tablica może mieć nieskończenie wiele wymiarów, ale jeden wymiar może mieć maksymalnie 9999 elementów. Operatorem służącym do definiowania i używania tablicy są nawiasy kwadratowe [ ]. Elementy są liczone od zera, to znaczy że jeśli stworzymy tablicę z 9999 elementami, to pierwszy element ma nr 0, drugi 1, trzeci 3-1, czwarty n-1, ostatni 9998 itd.

W rzeczywistości nazwa tablicy jest nazwąwskaźnika (adresu) do jej zerowego (pierwszego) elementu. W momencie deklaracji tablicy nie jest rezerwowane miejsce w pamięci, staje się to dopiero w chwili utworzenia elementu. Za każdym razem, gdy się odwołujemy do któregoś jej elementu, przy pomocy adresu do elementu zerowego jest obliczany adres elementu, do którego się chcemy odwołać. W zależności od rodzaju i wielkości typu to obliczanie wygląda inaczej.

Użycie[]

Tablice przydają się w sytuacji, gdy potrzebujemy dużą liczbę obiektów tego samego typu i służącym w podobnym celu. Dzięki temu zamiast definiować każdą zmienną osobno, podaje się liczbę elementów, w zależności od tego, ile ich potrzebujemy.

Do pracy z tablicami wręcz stworzona została pętla for.

Deklaracja tablicy[]

Zanim będziemy mogli używać tablicy, trzeba ją zadeklarować. Robi się to taką instrukcją:

typ nazwa[liczba_elementów];
  1. Typ informuje, jakiego typu obiekty tablica ma przechowywać. Może być to zarówno typ fundamentalny jak i zdefiniowany przez użytkownika.
  2. Tablica musi mieć nazwę.
  3. Liczba elementów określa, ile obiektów ma przechowywać tablica.

Przykład:[]

int tab[5];

Czytamy: obiekt tab jest tablicą pięciu elementów typu int.

Odwoływanie się do elementów tablicy[]

Aby odwołać się do konkretnego elementu tablicy używa się takiego samego operatora, jak przy deklaracji (czyli nawiasów kwadratowych):

nazwa[nr_elementu]

Takiej konstrukcji używa się w wyrażeniach. Należy pamiętać, że pierwszy element tablicy ma numer 0.

Przykład:[]

tab[0] = 10;

Czytamy: do obiektu tab[0] wpisujemy wartość 10.

Inicjalizacja tablicy[]

Można w jednej linijce od razu zarezerwować pamięć i utworzyć możliwe do odczytania elementy. Inicjalizacja może wyglądać inaczej w zależności od typu elementów, czasami może nie być w ogóle możliwa.

Przykład:[]

int tab[5] = (1, 2, 3, 4, 5);

Czytamy: obiekt tab jest tablicą pięciu elementów typu int, które mają w tej chwili wartości: 1, 2, 3, 4 i 5.

Typ tablicy[]

W rzeczywistości typ podany przy deklaracji oznacza jakiego typu są elementy przechowywane przez tablicę.

UWAGA, PRZECZYTAJ: TYP STRING[]

W CBOT istnieje błąd, który nie pozwala na definicję tablicy z elementami typu string. Innymi słowy, taka linijka:

string s[3]; // BLAD!!! Brak srednika na koncu wiersza?

Wywoła błąd kompilatora. Po nazwie s oczekuje on średnika, ale znajduje tam nawias kwadratowy, więc nie pozwala się skompilować. Ciekawostką jest to, że taką tablicę da się zdefiniować wewnątrz klasy.

public class MojaKlasa
{
string s[3]; // DZIALA!!!
}

void f()
{
string s[3]; // BLAD!!!
}

extern void object::f()
{
string s[3]; // BLAD!!!
}

Więc jeśli chce się mieć tablicę typu string trzeba się posłużyć obiektem klasy.

Nazwa tablicy[]

Dzięki nazwie tablicy możemy się odwoływać do jej elementów - to oczywiste. Jednak to tylko przebranie, bo w rzeczywistości tablica działa nieco inaczej.

Czym jest tak naprawdę nazwa tablicy?[]

Nazwa tablicy jest tak naprawdę nazwą jednego obiektu! Tym obiektem jest stały (nieruchomy) wskaźnik. To znaczy, że nie możemy zmieniać jego wartości. Inaczej mówiąc - nazwa tablicy jest adresem do jej elementu nr 0. Matematycznie:

tab[0] = tab

Co nie znaczy, że możemy używać tych konstrukcji zamiennie. Po prostu warto to wiedzieć, aby uniknąć błędów.

Elementy tablicy[]

Liczba elementów podana w nawiasach kwadratowych ogranicza wielkość naszej tablicy, dzięki temu w trakcie działania programu jest sprawdzane, czy przypadkiem nie próbujemy odwołać się do nieistniejącego elementu.

int tab[2];

tab[2] = 1; // BLAD!!! Element nie istnieje.

Należy pamiętać, że:[]

  1. poszczególne elementy tablicy są liczone od zera (bądź ostrożny, zwłaszcza na początku często możesz "pomylić się o jedynkę"!) - tzn. że jeśli mamy dwuelementową tablicę tab to zawiera ona elementy [0] i [1].
  2. deklaracja tablicy nie rezerwuje pamięci na obiekty, to znaczy że żaden z elementów jeszcze nie istnieje!
  3. tablica może mieć maksymalnie 9999 elementów - czyli liczba elementów powinna być z zakresu 1 - 9999, odwołać się natomiast można do elementu [0]-[9998].

Dygresja na temat punktu 2[]

To znaczy, że żadnego elementu nie można jeszcze odczytać po samej deklaracji.

int tab[2];
message(tab[0]); // BLAD!!! Nie ma czego odczytac

Przed odczytaniem jakiegokolwiek elementu musi on zostać zinicjalizowany (musi być wpisana jakaś wartość).

int tab[2];
tab[0] = 1;
message(tab[0]); // w porzadku. Jest co odczytac

Ciekawostka: W momencie deklaracji tablicy w rzeczywistości żaden z elementów nie istnieje. Dopiero, gdy któryś z nich zainicjalizujemy, są tworzone obiekty i pamięć jest zajmowana. W dodatku wszystkie poprzednie elementy także są w tym momencie tworzone, chociaż nie możemy z nich korzystać. Udowadnia to funkcja sizeof:

int tab[3];
tab[1] = 1;

// message(tab[0]); // BLAD!!! Nie ma co odczytac - element jest pusty!
message(tab[1]); // w porzadku
// message(tab[2]); // BLAD!!! Element nie istnieje!
// message(tab[3]); // BLAD!!! Element nawet nie mial istniec :P

message(sizeof(tab)); // Dowod, ze istnieja 2 elementy.

Sama deklaracja tablicy nawet nie rezerwuje pamięci. Pamięć jest rezerwowana dopiero w momencie utworzenia obiektu. Wspaniała oszczędność, nieprawdaż?


Dygresja na temat punktu 3[]

"...liczba elementów POWINNA być z zakresu 1 - 9999" - powinna, ale być wcale nie musi! W rzeczywistości ta liczba jest w rzeczywistości ograniczeniem tablicy do określonej liczby elementów, nawet nie musimy jej podawać! Wtedy taka tablica pozwala na zamieszczenie 9999 obiektów, ale nie zajmuje tyle pamięci, dopóki nie utworzymy elementu (patrz: dygresja na temat punktu 2).

int tab[]; // jeszcze nie zajmuje ani troche pamieci

tab[9998] = 1; // tablica teraz zajmuje 9999 * sizeof(int) pamięci

Jeśli jakimś cudem jako liczbę elementów wpiszesz liczbę 0, ujemną bądź zmiennoprzecinkową to będzie to traktowane tak, jakbyś tam nic nie wpisał. Czyli tak samo, jak w przykładzie wyżej.

Przekazywanie tablicy do funkcji[]

Nie ma możliwości przekazania tablicy do funkcji. Można jedynie przekazać zerowy element podając nazwę tablicy w argumencie.

Advertisement