Po co wprowadzono tablice
Praktycznie zawsze w programach mamy potrzebę zorganizowania naszych danych w jakiś wygodny sposób do późniejszego ich przetwarzania. Tablice dobrze się nadaja do takich zastosowań, przyjrzyjmy się im bliżej.
Tablice jednowymiarowe
Tablica jest to nic innego jak
zwykła zmienna. Różnica polega na tym, iż przy tworzeniu tablicy zmiennych należy pamiętać o trzech elementach:
Ważnym aspektem jest to, iż
LiczbaElementów musi być
wartością stałą całkowitą, lub stałą
const. Czyli:
const STALA = 10;
int Tablica[ STALA ];
int Tablica_P[ 10 ];
int Tablica_A[ 2.5 ];
Inną różnicą jest fakt, że tablica zajmuje więcej miejsca w pamięci.
Odczytywanie i zapisywanie danych do zmiennej z tablicy odbywa się tak samo jak dla zwykłych zmiennych. Jedyną istotną różnicą jest podanie
numeru indeksu, do którego dane mają zostać zapisane. Tak więc zapis:
nazwa_tablicy[ 10 ] = 33;
Należy tu wyraźnie podkreślić, że numerowanie tablic w C++ zaczyna się
zawsze od zera !!!
#include <iostream>
#include <conio.h>
const short WIELKOSC_TAB = 5;
int main()
{
using namespace std;
int tab1[ WIELKOSC_TAB ];
char tab4[ 2 ];
tab1[ 0 ] = 1;
tab1[ 1 ] = 2;
tab1[ 2 ] = 3;
tab1[ 3 ] = 4;
tab1[ 4 ] = 5;
tab1[ 5 ] = 6;
char tab2[ WIELKOSC_TAB ] = { 'N', 'u', 'm', 'e', 'r' };
int tab3[ 4 ] = { 7, 8 };
cout << "Oto dane zawarte w tab1:\n"
<< "pierwszy element - " << tab1[ 0 ]
<< "\ndrugi element - " << tab1[ 1 ]
<< "\ntrzeci element - " << tab1[ 2 ]
<< "\nczwarty element - " << tab1[ 3 ]
<< "\npiaty element - " << tab1[ 4 ]
<< "\nA tak wyglada nieprawidlow element szosty - "
<< tab1[ 5 ] << endl << endl;
cout << "Nalezy pamietac, by nie przekroczyc "
<< tab2[ 0 ] << tab2[ 1 ] << tab2[ 2 ] << tab2[ 3 ]
<< tab2[ 4 ] << " indeksu tabeli." << endl;
tab4[ 0 ] = tab2[ 0 ];
tab4[ 1 ] = tab2[ 4 ];
cout << "Jezeli tabela ma miec 5 elementow "
"to jej ostatni element ma " << tab4[ 0 ]
<< tab4[ 1 ] << " indeksu rowny " << tab1[ 3 ]
<< "!" << endl << endl;
cout << "tab3 zawiera takie dane:\n"
<< "1- " << tab3[ 0 ] << endl
<< "2- " << tab3[ 1 ] << endl
<< "3- " << tab3[ 2 ] << endl
<< "4- " << tab3[ 3 ] << endl;
getch();
return 0;
}
Tablice wielowymiarowe
Do tej pory operowaliśmy na tablicach jedno wymiarowych, przyjrzyjmy się jak tworzy i stosuje tablice wielowymiarowe. Załóżmy, że chcemy napisać program, która będzie przechowywać wyniki Eliminacje MŚ w piłce nożnej
grupy polskiej.
#include <iostream>
#include <conio.h>
const short LICZBA_DRUZYN = 6;
const short MAX_ZNAKOW = 12;
int main()
{
using namespace std;
char tab1[ LICZBA_DRUZYN ][ MAX_ZNAKOW ] = {
{ 'S', 'l', 'o', 'w', 'a', 'c', 'j', 'a' },
{ 'I', 'r', 'l', 'a', 'n', 'd', 'i', 'a', ' ', 'P' },
{ 'C', 'z', 'e', 'c', 'h', 'y' },
{ 'P', 'o', 'l', 's', 'k', 'a' },
{ 'S', 'l', 'o', 'w', 'e', 'n', 'i', 'a' },
{ 'S', 'a', 'n', ' ', 'M', 'a', 'r', '.' },
};
short tab2[ LICZBA_DRUZYN ] = {
9, 7, 7, 7, 7, 0 };
short tab3[] = { 1, 2, 3, 4, 5, 6 };
cout << "Tabela eliminacji mistrzostw swiata 2010"
<< endl << "Grupa Polska\n\n"
<< " Lp." << "|" << " Druzyna " << "|"
<< " pkt. " << endl
<< "-------------------------\n"
<< " " << tab3[ 0 ] << " "
<< "| " << tab1[ 0 ] << " | " << tab2[ 0 ]
<< "\n " << tab3[ 1 ] << " "
<< "| " << tab1[ 1 ] << " | " << tab2[ 1 ]
<< "\n " << tab3[ 2 ] << " "
<< "| " << tab1[ 2 ] << " | " << tab2[ 2 ]
<< "\n " << tab3[ 3 ] << " "
<< "| " << tab1[ 3 ] << " | " << tab2[ 3 ]
<< "\n " << tab3[ 4 ] << " "
<< "| " << tab1[ 4 ] << " | " << tab2[ 4 ]
<< "\n " << tab3[ 5 ] << " "
<< "| " << tab1[ 5 ] << " | " << tab2[ 5 ];
getch();
return 0;
}
W programie użyto tablic dwuwymiarowych, jednak C++ umożliwia również tworzenie tablic więcej wielowymiarowych. Ich zapis jest bardzo prosty i wygodny w użyciu np.
int mapa[ 10 ][ 20 ][ 30 ];
utworzy tablicę trójwymiarową, w której będziemy mogli przechowywać liczby typu int. Zapis danych do takiej tablicy jak nie trudno się domyślić będzie wyglądał tak:
mapa[ 9 ][ 3 ][ 1 ] = 13;
Przeanalizujmy kod programu, skupmy się na tabelach. Pierwszą tabelę
tab1 od razu deklarujemy:
char tab1[ LICZBA_DRUZYN ][ MAX_ZNAKOW ] = {
{ 'S', 'l', 'o', 'w', 'a', 'c', 'j', 'a' },
{ 'I', 'r', 'l', 'a', 'n', 'd', 'i', 'a', ' ', 'P' },
{ 'C', 'z', 'e', 'c', 'h', 'y' },
{ 'P', 'o', 'l', 's', 'k', 'a' },
{ 'S', 'l', 'o', 'w', 'e', 'n', 'i', 'a' },
{ 'S', 'a', 'n', ' ', 'M', 'a', 'r', '.' },
};
Po pierwsze tworzymy tablicę o wymiarach [6][12]. Następnie od razu ją wypełniamy o czym świadczy
klamra ( { } ). Jakbyśmy chcieli wypełnić tą tabele na piechotę podczas działania programu należało by zrobić to tak:
char tab1[ LICZBA_DRUZYN ][ MAX_ZNAKOW ];
tab1[ 0 ][ 0 ] = 'S';
tab1[ 0 ][ 1 ] = 'l';
tab1[ 0 ][ 2 ] = 'o';
tab1[ 0 ][ 3 ] = 'w';
tab1[ 0 ][ 4 ] = 'a';
tab1[ 0 ][ 5 ] = 'c';
tab1[ 0 ][ 6 ] = 'j';
tab1[ 0 ][ 7 ] = 'a';
};
Więc podkreślę to jeszcze raz, jeśli znasz dana, które mają znajdować się w tabeli to wprowadź je od razu, zaoszczędzisz czas. Jak to się dzieje, iż kompilator wie w jakie indeks wprowadzić dane?
char tab1[ LICZBA_DRUZYN ][ MAX_ZNAKOW ] = {
----[ 0 ][ 1 ][ 2 ][ 3 ][ 4 ][ 5 ][ 6 ][ 7 ]
[ 0 ] { 'S', 'l', 'o', 'w', 'a', 'c', 'j', 'a' },
----[ 0 ][ 1 ][ 2 ][ 3 ][ 4 ][ 5 ][ 6 ][ 7 ][ 8 ][ 9 ]
[ 1 ] { 'I', 'r', 'l', 'a', 'n', 'd', 'i', 'a', ' ', 'P' },
----[ 0 ][ 1 ][ 2 ][ 3 ][ 4 ][ 5 ]
[ 2 ] { 'C', 'z', 'e', 'c', 'h', 'y' },
----[ 0 ][ 1 ][ 2 ][ 3 ][ 4 ][ 5 ]
[ 3 ] { 'P', 'o', 'l', 's', 'k', 'a' },
----[ 0 ][ 1 ][ 2 ][ 3 ][ 4 ][ 5 ][ 6 ][ 7 ]
[ 4 ] { 'S', 'l', 'o', 'w', 'e', 'n', 'i', 'a' },
----[ 0 ][ 1 ][ 2 ][ 3 ][ 4 ][ 5 ][ 6 ][ 7 ]
[ 5 ] { 'S', 'a', 'n', ' ', 'M', 'a', 'r', '.' },
};
Ponieważ sam numeruje sobie indeksy tak jak jest to pokazane wyżej. A co jeśli chcielibyśmy usunąć pierwszy wpis(index tabeli[0])
Slowacja?
char tab1[ LICZBA_DRUZYN ][ MAX_ZNAKOW ] = {
[ 0 ] { 'I', 'r', 'l', 'a', 'n', 'd', 'i', 'a', ' ', 'P' },
[ 1 ] { 'C', 'z', 'e', 'c', 'h', 'y' },
[ 2 ] { 'P', 'o', 'l', 's', 'k', 'a' },
[ 3 ] { 'S', 'l', 'o', 'w', 'e', 'n', 'i', 'a' },
[ 4 ] { 'S', 'a', 'n', ' ', 'M', 'a', 'r', '.' },
};
Dla kompilatora nie będzie to miało znaczenia, ponieważ co również podkreślę
nie trzeba wypełniać całej tabeli danymi, a indeksy się tylko przesuną. Jednak w tabeli, która nie jest całkowicie wypełniona mogą znajdować się przypadkowe dane(podobnie jak jest to ze zmiennym gdy ich od razu nie zadeklarujemy).
Przyjrzyjmy się teraz
tab3, składnia:
short tab3[] = { 1, 2, 3, 4, 5, 6 };
informuje kompilator o tym by sam policzył ile jest elementów(sam wstawia indeksy) tabeli. Taki rodzaj tabeli od razu musi zawierać wszystkie dane, w przeciwnym wypadku kompilator nie wie jak duża ma być tabela.
Nie objaśnię zasady wyświetlania danych, ponieważ Sam już powinieneś ją znać i mieć opanowaną z wcześniejszych kursów.
Tablice i inne zmienne, a zużycie pamięci
Tworząc tablice należy pamiętać o zasobach pamięci, jakie tablica nam pochłonie. Tablica jednowymiarowa zabierze nam:
sizeof(typ_zmiennej)*ilość_elementów; bajtów pamięci, a tablica
int mapa[10][20][30]; pochłonie 4*10*20*30 bajtów pamięci, co daje prawie 24KB zarezerwowanej pamięci.
#include <iostream>
#include <conio.h>
int main()
{
using namespace std;
int liczba_calkowita;
double liczba_zmiennoprzecinkowa;
char znak;
int tab_jedenwymiar_liczba[ 10 ];
char tab_jedenwymiar_znak[ 5 ];
int tab_wielowymiar_liczba[ 10 ][ 20 ][ 30 ];
char tab_wielowymiar_znak[ 10 ][ 20 ][ 30 ];
cout << "Pokaz ile zajmuja uzyte zmienne:\n"
<< " int ma " << sizeof( int ) << endl
<< " Liczba calkowita ma " << sizeof liczba_calkowita
<< endl << endl
<< "Natomiast char ma " << sizeof( char )
<< " , a jego zmienna znak ma "
<< sizeof( znak ) << endl << endl;
cout << "Natomiast pozostale rozmiary to:\n"
<< "Tabela jednowymiarowa liczb "
<< sizeof tab_jedenwymiar_liczba << "\n"
<< "Tabela jednowymiarowa znak "
<< sizeof tab_jedenwymiar_znak << "\n"
<< "Tabela wielowymiar liczb "
<< sizeof tab_wielowymiar_liczba << "\n"
<< "Tabela wielowymiar znak "
<< sizeof tab_wielowymiar_znak << "\n"
<< "Oraz rodzynek na sam koniec liczba"
" zmiennoprzecinkowa "
<< sizeof liczba_zmiennoprzecinkowa;
cout << "\n\n Wszystkie wartosci podane"
" sa w bajtach!!!";
getch();
return 0;
}
Kilka słów o programie, operator
sizeof zwraca nam wartości typów(zmiennych) w bajtach. Nazwy typów muszą być podane w nawiasach
(int). Dla nazw zmiennych nie jest to konieczne.
Ćwiczenia
1. Napisz program, który wykona poniższe zadania:
Wyniki zapisz do tabeli, a następnie wyświetl je na ekranie.
2. Używając tabeli z pierwszego zadania napisz program, który wyniki z pierwszego zadania przekaże do drugiej tabeli następnie wykona dodatkowe obliczenia odpowiednio:
Najlepiej napisać program do pierwszego zadania a potem rozszerzyć go by wykonywał podane przykład.
3. Napisz program, który pobierze od użytkownika dwie liczby i wykona na nich działania:
dodawanie, odejmowanie, mnożenie i dzielenie. Wynik ma być wyświetlony w takiej formie:
Użytkownik podał następujące liczby
Liczba 1 = 20
Liczba 2 = 10
Wynik dodawania
20 + 10 = 30
Wynik odejmowania
20 - 10 = 10
Wynik mnożenia
20 * 10 = 200
Wynik dzielenia
20 : 10 = 2
Użyj dwóch tablic jedną na wyniki drugą na dwie liczby które poda użytkownik. Następnie spróbuj użyć tylko jednej tablicy.