TABLICE W JĘZYKU C/C++
Tablica jest reprezentacją umożliwiającą zgrupowanie kilku danych tego samego typu i odwoływanie się do nich za pomocą wspólnej nazwy. Jest to jeden z najczęściej wykorzystywanych typów danych.
Ogólna postać definicji tablicy:
typ_elementu nazwa_tablicy[liczba_elementów];
Na przykład:
float dane_liczbowe[5];//5-cio elementowa tablica liczb rzeczywistych
int tab[10]; //10-cio elementowa tablica liczb całkowitych
char tekst[255]; //255-cio elementowa tablica znaków
double (*funkcje[20])(double,double);//tab. 20 wskaźników na funkcje
Uwagi o tablicach:
Ważną cechą tablic jest reprezentacja w postaci spójnego obszaru pamięci oraz równomierne rozmieszczenie kolejnych elementów bezpośrednio jeden po drugim. Dzięki takiej reprezentacji możliwe jest szybkie wyliczanie położenia zadanego elementu w pamięci operacyjnej (na podstawie jego numeru porządkowego - indeksu) oraz znaczne skrócenie kodu przetwarzającego duże tablice poprzez zastosowanie instrukcji pętlowych.
Elementy tablicy są indeksowane od zera!
W języku C i C++ nie jest sprawdzana poprawność (zakres) indeksów! Często jest to przyczyną trudnych do wykrycia błędów. Na przykład przy definicji:
float dane_liczbowe[5];
instrukcja:
dane_liczbowe[5]=10.5;
niszczy (zamazuje) zawartość pamięci zaraz po ostatnim elemencie tej tablicy.
Nazwa tablicy jest jednocześnie adresem pierwszego elementu tej tablicy, tzn.
nazwa_tablicy == &nazwa_tablicy[0]
Zwykła tablica nie przechowuje informacji o liczbie swoich elementów.
Uwaga! Polecenie: sizeof( ) nie zwraca rozmiaru w sensie liczby elementów.
Definicja tablicy wielowymiarowej:
typ_elementu nazwa_tablicy [wymiar_1][wymiar_2][wymiar_3]...;
np.
char kostka_Rubika [3][3][3];
float macierz [5][2]; //dwuwymiarowa tablica: 5 wierszy po 2 kolumny
Definicję tablicy można połączyć z inicjalizacją jej zawartości:
int tab[10]; //sama definicja bez inicjalizacji
int tab_inicjalizowana[10] = {20,-3,12,1,0,7,-5,100,2,5};
char tab_znakow[5] = {'a', 'B', '\n', '1', '\0'};
float macierz_A[3][2] = { {1,1}, {3.5,7.0}, {-15,100} };
float macierz_B[3][2] = { 1, 1, 3.5, 7.0, -15, 100 };
Kolejne „inicjalizatory” zawsze wstawiane są do kolejnych „komórek” tablicy (w związku z tym można pominąć wewnętrzne nawiasy klamrowe).
Jeżeli lista inicjalizatorów jest krótsza niż ilość elementów tablicy to pozostałe elementy są uzupełniane zerami lub wskaźnikami NULL
np. definicja:
int tab[10] = { 20, -3, 12, 1 };
jest równoważna:
int tab[10] = { 20, -3, 12, 1, 0, 0, 0, 0, 0, 0 };
a definicja:
float macierz[3][2] = { {1}, {3.5,7.0} };
jest równoważna:
float macierz[3][2] = { {1,0}, {3.5,7.0}, {0,0} };
lub:
float macierz[3][2] = { 1, 0, 3.5, 7.0, 0, 0 };
Wykorzystanie stałych do definiowania ilości elementów tablicy:
int tablica [100] ; //rozmiar zadany bezpośrednio
#define ROZMIAR 100 //definicja stałej w stylu języka C
int tablica [ROZMIAR] ;
const ROZMIAR_2 = 100 ; //definicja stałej w stylu języka C++
int tablica_2 [ROZMIAR_2] ;
W języku C inicjalizatorami muszą być stałe, natomiast w języku C++ inicjalizatorami mogą być zarówno stałe jak i zmienne.
Specjalnym rodzajem tablic są tablice do przechowywania znaków (np. liter).
char zdanie[80];
Ta definicja określa, że zdanie jest tablicą 80 elementów będących znakami. W tablicy tej można umieścić tekst, dzięki temu, że każdy z jej elementów nadaje się do przechowywania reprezentacji liczbowej znaków alfanumerycznych. Na przykład - znaków zakodowanych kodem ASCII. Teksty w tablicach znakowych zwykło się przechowywać tak, że po ciągu liter (a właściwie ich kodów liczbowych) następuje znak o kodzie 0. Ten znak zwany jest NULL. Znak ten jest po to, by oznaczyć gdzie kończy się ciąg liter. Na taki ciąg liter zakończony znakiem NULL mówimy string.
Naszą tablicę zdanie można już w trakcie definicji zainicjalizować:
char zdanie[80] = { "lot" };
W rezultacie w poszczególnych komórkach tablicy zdanie znajdą się następujące znaki
l | o | t | null | ||||||
0 | 1 | 2 | 3 | 4 | 5 | … | … | 78 | 79 |
Nie wymienione elementy inicjalizuje się do końca zerami. Znak NULL został automatycznie dopisany po ostatniej literze t dzięki temu, że inicjalizowaliśmy tablicę ciągiem znaków ograniczonym cudzysłowem. W językach C i C++ wszelkie funkcje biblioteczne pracujące na stringach opierają się na założeniu, że koniec stringu oznaczony jest znakiem NULL.
Na przykład:
Jeśli chcemy jakiś string wypisać na ekran, to wywołujemy standardową funkcję biblioteczną (puts - od put string) i jako argument przekazujemy jej adres początku stringu. Funkcja ta będzie sukcesywnie wypisywała na ekran znaki zawarte w kolejnych komórkach pamięci począwszy od adresu podanego jako początek stringu. Akcja zakończy się dopiero po natknięciu się na komórkę ze znakiem NULL, czyli inaczej mówiąc z zapisanym tam bajtem 0.
Jest też inny sposób inicjalizacji tablicy znaków:
char zdanie[80] = { 'l', 'o', 't' };
Zauważ, że w klamrze pojawiły się pojedyncze litery ograniczone apostrofami. Zapis taki jest równoważny trzem instrukcjom:
zdanie[0] = 'l'
zdanie[1] = 'o'
zdanie[2] = 't'
Ponieważ nie było tu cudzysłowu, więc kompilator nie dokończył tego znakiem NULL umieszczanym poprzednio w elemencie zdanie[3]. Zatem sprawa wydaje się ryzykowna - po ciągu liter nie nastąpił znak kończący string.
Jeśli wartości początkowych jest mniej niż elementów tablicy, to reszta jest inicjalizowana zerami. Czyli pozostałe elementy tablicy zdanie, aż do elementu o indeksie 79 zostaną inicjalizowane zerami. W szczególności w elemencie zdanie[3] też znajdzie się zero. Znak NULL ma przecież też wartość 0 - zatem nie musimy się martwić, string w tablicy zdanie jest poprawnie zakończony.
Jeśli nie podamy rozmiaru tablicy:
char zdanie[] = { '1', 'o', 't' };
to kompilator przeliczy sobie liczbę inicjalizatorów i taką zarezerwuje tablicę. W naszym przykładzie doliczy się trzech elementów. Zostanie więc zarezerwowana tablica 3 elementowa. W poszczególnych jej elementach znajdą się znaki 'l' 'o' 't', ale znaku NULL tam nie będzie. Nie było cudzysłowu, więc kompilator nie sądził, że te znaki mają się składać na string. Dopisania reszty zerami nie będzie, bo żadnej reszty nie ma. Tablica ma tylko trzy elementy. Należy jednak podkreślić - nie jest to błąd. Możliwe, że litery te nie mają być używane jak ciąg znaków (czyli string), lecz po prostu są to luźne litery, do innych celów. Traktować jako string ich jednak nie można.
Zwróćmy uwagę na deklarację:
char zadnie[] = { "lot" };
Tutaj kompilator obliczając ile elementów ma zarezerwować na tablicę doliczy się trzech liter, ale z faktu, że są one ujęte w cudzysłów wywnioskuje, że mają one być używane jako string, więc zarezerwuje jeszcze jeden dodatkowy element na znak NULL.
Uruchom poniższy program, uzasadnij wynik jego działania.
main()
{
char napis1[]={"Nocny lot"};
char napis2[]={'N','o','c','n','y',' ','l','o','t'};
cout << "rozmiar tablicy pierwszej :"
<< sizeof(napis1) << endl;
cout « "rozmiar tablicy drugiej:"
<< sizeof(napis2) << endl;
}
Czy poniższe deklaracje są poprawne?
char tl[1] = { "a" };
char t2[1] = { 'a' };
char zdanie [80];
float numer [9];
Napisz program, który wczytuje do tablicy cztery znaki (z klawiatury) i wyświetla je.
Poniższy program wczytuje i sumuje elementy tablicy jednowymiarowej n-elementowej.
int main()
{
int n;
cout<<"Podaj n=";
cin>>n;
int tab[n];
int i,s;
s=0;
for (i=0; i<n; i++)
{
cout<<"Podaj element "<<i;
cin>>tab[i];
s = s + tab[i];
}
cout<<"suma="<<s;
}
Uruchom i przeanalizuj działanie powyższego programu.
Zmodyfikuj ten program tak, aby wczytywał i sumował elementy tablicy dwuwymiarowej Amxn.
Narysuj schemat blokowy algorytmu i napisz program, który wczytuje tablicę jednowymiarową wyświetla ją następnie zamienia pierwszy element tablicy z ostatnim i ponownie wyświetla tablicę.
Narysuj schemat blokowy algorytmu i napisz program, który tworzy tablicę trójwymiarową 3x3x3 i wpisuje wartość jeden (1) do komórek znajdujących się na przekątnej sześcianu oraz zero (0) do pozostałych komórek.
Napisz program który wyznaczy liczbę elementów ujemnych, dodatnich i zer w tablicy.
Napisz program szukający wartości największej w tablicy liczb całkowitych, Zadanie rozwiąż w dwóch wariantach:
Zapamiętywana jest liczba zapisana w komórce tablicy
Zapamiętywany jest indeks elementu w tablicy.