Dotąd poznane typy danych pozwalały przechowywać pojedyncze elementy. Tablice pozwalają gromadzić ich wiele w jednym miejscu.
Przykładowo, gdy dokonywaliśmy obliczeń np. pola trójkąta podawaliśmy dwie liczby określające podstawę i wysokość, które przypisywaliśmy do zmiennych np. a, h.
W innym ćwiczeniu licząc sumę kolejnych liczb korzystaliśmy z instrukcji suma = suma + a. Nie musieliśmy zapamiętać kolejnych wprowadzanych liczb i przypisywać ich do różnych zmiennych, gdyż wszystkie liczby wprowadzane były kolejno do zmiennej a i przechowywane jako wynik ich dodawania w zmiennej suma.
Nieraz zachodzi jednak konieczność przechowywania wszystkich danych np. wyniki pomiarów. Moglibyśmy każdemu pomiarowi przypisać zmienną, ale gdyby było ich 1000, pojawiłby się problem z ich nazwaniem (zabrakłoby liter w alfabecie), a do tego pomiary te przypisane do różnych zmiennych nie byłyby ze sobą powiązane, co utrudniałoby wykonanie wielu operacji. Wygodniej zastosować tablice.
wszystkie elementy tablicy umieszczane są w pamięci naszego komputera razem w jednym miejscu,
elementy tablicy są ponumerowane; numer elementu to indeks; indeksy w C++ rozpoczynają się od wartości 0,
do każdego z tych elementów możemy się odwołać, posługując się nazwą tablicy i indeksem określającym numer danego elementu,
nazwa tablicy jest równocześnie adresem jej zerowego elementu,
możemy tworzyć tablice dowolnego typu wbudowanego w strukturę C++ oraz tablice własnych typów takich jak struktury czy klasy.
Prostą tablicę, można zobrazować wyobrażając ją sobie jako karton z takimi samymi pudełkami (dane tego samego typu).
Liczby poniżej kratek (pudełek), to indeksy kolejnych elementów tablicy, których, wartości można wpisać w kratki.
Elementy tablicy numerowane są od 0. Tak więc w zadeklarowanej przez nas tablicy sześcioelementowej kolejne elementy są ponumerowane od 0 do 5. Indeks 0 odnosi się do pierwszego elementu, indeks 1 do drugiego i tak dalej, aż do indeksu 5, który reprezentuje szósty (ostatni) element tablicy.
Tablica jest zmienną złożoną stąd przed pierwszym użyciem, podobnie jak inne zmienne, musi zostać zadeklarowana - po jej nazwie w nawiasach kwadratowych wpisujemy rozmiar tablicy (liczbę elementów). Nawiasy kwadratowe są informacją dla kompilatora, że ma do czynienia z tablicą.
Deklaracja umieszczona na liście deklaracji zmiennych ma postać:
typ_elementów nazwa_tablicy[liczba_elementów];
typ_elementów – nazwa typu danych przechowywanych przez deklarowane zmienne np. double, int
nazwa_tablicy - tworzona wg zasad tworzenia nazw zmiennych
liczba_elementów - określa, ile elementów danego typu przechowuje tablica (inaczej: rozmiar tablicy); rozmiar możemy określić zmienną, ale nie da się rozmiaru podać z klawiatury (cin) i dopiero utworzyć tablicę o wczytanym rozmiarze, gdyż rozmiar tablicy musi być znany w momencie kompilacji
Przykłady deklaracji tablic:
int a[6]; // tablica o nazwie a przechowuje 6 elementów typu int
char tab[10]; // tablica o nazwie tab przechowuje 10 wartości znakowych
double x[1000]; // tablica o nazwie x przechowuje 1000 liczb typu double
string napisy[10]; // tablica o nazwie napisy - przechowuje 10 napisów
int a[6]; polecenie tworzy tablicę o 6 elementach o indeksach:
a[0] a[1] a[2] a[3] a[4] a[5]
Zwróć uwagę, że ostatnim elementem tablicy int a[6] jest a[5]. Tablica nie posiada elementu o indeksie równym ilości elementów, gdyż indeksy tablic rozpoczynają się od 0. Stąd błędem (którego kompilator zwykle nie wykryje) byłoby odwołanie się w programie do a[6], czyli elementu o wartości wyższej niż ostatni element tablicy – mogłoby to spowodować nadpisanie obszaru pamięci poza tablicą, należącego do innej zmiennej.
Uwaga. Odwołując się do ostatniej komórki tablicy n-elementowej, jej indeks jest równy n-1
Odwołanie się do danego elementu tablicy następuje przez zmienną indeksowaną:
zmienna_indeksowana[numer_elementu]
a[1]
Danemu elementowi możemy przypisać wartość (za pomocą instrukcji przypisania)
zmienna_indeksowana [numer_elementu] = wartość;
a[1] = 10; //przypisanie elementowi a[1] wartości 10
Przypisaną wartość możemy przypisać innej zmiennej np.
b = a[1]; //przypisanie zmiennej b wartości elementu a[1]
Dla elementów tablicy można stosować wszystkie instrukcje modyfikacji np.:
a[3]++; //zwiększenie o 1 wartości przypisanej do komórki a[3]
a[4] += 10; // zwiększenie wartości przypisanej do komórki a[4] o 10
Do wprowadzania (wczytywania) wartości elementów tablicy może być stosowana:
instrukcja pętli (pętle mogą wczytywać wartości tablicy i wyprowadzać je na ekran; iterator pełni funkcje indeksu - i w nawiasie [i] - tj. w każdej iteracji podawany jest indeks szufladki/elementu)
inicjacja tablicy – podczas deklaracji tablicy w nawiasach klamrowych umieszczamy wartości kolejnych elementów tablicy oddzielone od siebie przecinkami: int a[6] = {4, 2, 5, 6, 1};
Jeżeli przy deklaracji inicjujemy tablicę, nie musimy podawać jej rozmiaru - kompilator ustali go na podstawie danych inicjujących np. int a[ ] = {4, 2, 6, 5, 1};
Przykład
Przeanalizuj przykład i odpowiedz na pytania, a następnie uruchom program.
W jaki sposób zostały wprowadzone warości elementów tablicy?
Jaki wymiar ma ta tablica?
Jaką wartość ma element tablicy o indeksie [3]?
#include <cstdlib>
#include <iostream>
using namespace std;
int main()
{
int tablica[]={7,6,5,4,3,2,1,0};
cout << tablica [3];
cout << endl << endl;
system("PAUSE");
return 0;
}
Przykład. Zmienna tablicowa o nazwie oceny przechowującą 6 elementów typu całkowitoliczbowego.
#include <cstdlib>
#include <iostream>
using namespace std;
int main()
{
int oceny[6];
oceny[0] = 4;
oceny[1] = 5;
oceny[2] = 4;
oceny[3] = 3;
oceny[4] = 2;
oceny[5] = 6;
for (int i=0; i<6; i++)
{
cout << "Indeks nr " << i;
cout << " - ocena: " << oceny[i];
cout << endl;
}
cout << endl;
system("PAUSE");
return 0;
}
Ćwiczenie. Na podstawie przykładu, stwórz zmienną tablicową o nazwie oceny, przechowującą wprowadzone przez ciebie - z użyciem pętli - oceny z sześciu przedmiotów o nazwach przedmiot0 ... przedmiot5.
Oprócz tablic jednowymiarowych, można również deklarować tablice wielowymiarowe. Przykładowo tablicę dwuwymiarową można graficznie zobrazować jako tabelę z wierszami i kolumnami.
Tablicę dwuwymiarową deklarujemy podając jej rozmiar, który stanową liczba wierszy i liczba kolumn, podane w nawiasach kwadratowych (czyli o jeden nawias kwadratowy więcej niż w tablicy jednowymiarowej).
Powyższa tablica ma wymiar 4 wiersze na 5 kolumn, czyli tak ją zadeklarujemy:
int tablica[4] [5];
#include <cstdlib>
#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
int tablica[4][5];
int liczba=1;
for (int i=0; i<4; i++)
{
for (int j=0; j<5; j++)
{
tablica[i][j]=liczba;
liczba++;
}
}
for (int i=0; i<4; i++)
{
for (int j=0; j<5; j++)
{
cout << "tablica[" << i << "][" << j << "]";
cout << "=" << tablica[i][j] << endl;
liczba++;
}
}
cout << endl;
system("PAUSE");
return EXIT_SUCCESS;
}
Komentarz:
w podwójnej pętli wprowadzane są do tablicy kolejne cyfry;
pierwsza pętla będzie przechodziła przez kolejne wiersze tablicy, a zagnieżdżona w niej druga pętla przechodzi przez kolejne kolumny tablicy w ramach danego wiersza;
do tablicy wpisujemy wartość zmiennej liczba, która jest w każdym przebiegu pętli zwiększona o 1;
Tablicę wielowymiarową też możemy zainicjować, wpisując w nawiasach klamrowych kolejne wartości oddzielone przecinkami lub dodatkowo zwiększyć czytelność zapisu obejmując wartości kolejnych wierszy dodatkowymi klamrami.
int tablica[4][5] = {{1,2,3,4,5} {6,7,8,9,10} {11,12,13,14,15} {16,17,18, 19, 10}};
W przypadku inicjacji tablic wielowymiarowych bez wymiaru możemy pozostawić tylko jeden – pierwszy wymiar tablicy (kompilator sam go ustali na podstawie wczytanych danych) np.
int tablica[ ][5] = {{1,2,3,4,5} {6,7,8,9,10} {11,12,13,14,15} {16,17,18, 19, 10}};
Tablica typu znakowego umożliwia przechowywanie ciągów znakowych (łańcuchów) czyli napisów.
Przy deklaracji zmiennych typu łańcuchowego podajemy o jedną komórkę więcej do rozmiaru tablicy, gdyż ciąg znaków musi być zakończony specjalnym znakiem null zapisywanym jako '\0' (kod ASCII = 0), dzięki któremu program wie kiedy zakończyć wypisywanie tekstu.
Deklaracja zmiennych typu tekstowego:
char lancuch[n+1];
czyli
char lancuch[7]; - deklaracja łańcucha o długości 6 znaków
Deklarowana długość łańcucha to jego maksymalny rozmiar, stąd tekst może posiadać mniejszą ilość znaków. Odwołanie się do znaków nieistniejących będzie błędem.
Do pojedynczego znaku łańcucha odwołujemy się tak samo jak do elementu tablicy:
lancuch[i];
Inicjalizacja tablicy – wypełnienie tablicy zawartością w momencie jej tworzenia
pojedyncze znaki umieszczamy w apostrofach
ciąg znaków (łańcuch) umieszczamy w cudzysłowach
1. Podczas deklaracji tablicy w nawiasach klamrowych umieszczamy pojedyncze kolejne znaki (inicjalizacja):
char tab[7] = {'l', 'e', 'k', 'c', 'j', 'a', '\0'};
lub
char tab1[] = {'t', 'e', 'm', 'a', 't', '\0'}; //program sam dopasuje rozmiar
2. Poprzez przypisanie wartości zmiennej w momencie jej deklarowania (inicjalizacja):
char tab2[] = "lekcja tablice";
//podajemy ciąg znaków pamiętając o podwójnym cudzysłowie; nie określamy liczby elementów tablicy - kompilator ustali rozmiar na podstawie dostarczonego tekstu (wszystkie znaki tekstu oraz kończący je znak NUL).
3. Poprzez wprowadzanie znaków z klawiatury za pomocą obiektu cin (dane zostaną zredukowane do jednego wyrazu; obiekt cin wczytuje dane do napotkania pierwszej spacji lub znaku końca linii):
char tab3[40];
cin>>tab3;
4. Przez wprowadzenie danych w pętli po zadeklarowaniu zmiennej jako tablicy znaków:
char tab4[10];
for (i=0; i<10; i++) cin >> tab4[i];
Ważne by nie mylić omówionych sposobów wypełniania tablicy (inicjalizacja, pętle, cin) ze zwykłym operatorem przypisania. W przypadku tablic wykonywane są operacje złożone (np. sprawdzenie pojemności, ilości znaków do przekopiowania) i nie można w poniższy sposób przypisywać danych.
Błędem byłoby:
char tab5[20]; //tworzenie tablicy 20 znaków
tab5 = "informatyka";
cout << tab5;