Prezentowane materiały są przeznaczone dla uczniów szkół ponadgimnazjalnych. Autor artykułu: mgr Jerzy Wałaszek, wersja1.0 |
©2013 mgr
Jerzy Wałaszek
|
We współczesnych językach programowania tablice są stosowane powszechnie do przechowywania danych podobnego rodzaju. Przy ich pomocy można zapisywać ciągi liczbowe, wyniki pomiarów różnych wielkości oraz tworzyć złożone bazy danych. Liczba zastosowań tablic jest w zasadzie ograniczona naszą wyobraźnią. Podstawową zaletą tablic jest prostota przetwarzania ich elementów. Dzięki dostępowi poprzez indeksy, elementy tablic daje się łatwo przetwarzać w pętlach iteracyjnych.
Deklarację tablicy umieszczamy w języku C++ na liście deklaracji zmiennych. Składnia jest następująca:
typ_danych | - | określa rodzaj informacji przechowywanych przez deklarowane zmienne |
nazwa_tablicy | - | tworzona jest wg zwykłych reguł tworzenia nazw zmiennych w języku C++ |
Liczba_elementów | - | określa, ile elementów danego typu przechowuje tablica |
Poniżej podajemy kilka przykładów deklaracji tablic w C++:
... int a[3]; // tablica zawierająca 3 elementy typu int double x[10]; // tablica przechowująca 10 liczb typu double char c[6]; // tablica przechowująca 6 wartości znakowych ...
W języku C++ indeksy tablic rozpoczynają się od 0. Ma to sens, ponieważ nazwa tablicy jest traktowana zawsze jak adres początku obszaru pamięci, w którym tablica przechowuje swoje elementy. Naturalne zatem jest, iż pierwszy element leży właśnie pod adresem tablicy. Stąd jego indeks wynosi 0, czyli nic nie musimy dodawać do adresu początku tablicy, aby uzyskać dostęp do jej pierwszego elementu.
W powyższym przykładzie zadeklarowano trzy tablice a, x oraz c. Posiadają one elementy o następujących indeksach:
Zwróć uwagę, iż tablica nie posiada elementu o indeksie równym ilości elementów. Zatem jeśli zadeklarujemy np. tablicę:
to jej ostatnim elementem jest Tlk[167], a nie Tlk[168]. Odwołanie się w programie do Tlk[168] jest błędem, którego kompilator zwykle nie zgłosi, zakładając, iż programista wie co robi. Niestety, język C++ nie był tworzony z myślą o początkujących.
Zwróć uwagę, iż nie musimy podawać liczby elementów. Kompilator utworzy tyle elementów, ile podamy dla nich wartości na liście inicjalizacyjnej. Poniższy przykład tworzy tablicę 10 liczb całkowitych i wypełnia ją kolejnymi liczbami Fibonacciego.
... int fib[ ] = (0,1,1,2,3,5,8,13,21,33); ...
W celu utworzenia w języku C++ tablicy dynamicznej, tworzymy zmienną wskaźnikową na typ danych, które mają być przechowywane w tablicy:
Zmienna wskaźnikowa (ang. pointer variable) nie przechowuje danych tylko adres obszaru pamięci komputera, w którym te dane się znajdują. Deklarację zmiennej wskaźnikowej zawsze poprzedzamy znakiem gwiazdki. W poniższym przykładzie tworzymy trzy wskaźniki a, b i c do danych typu double (czyli do obszaru pamięci, w którym będą przechowywane liczby zmiennoprzecinkowe o podwójnej precyzji):
Pamięć rezerwujemy operatorem new i adres zarezerwowanego obszaru umieszczamy w zmiennej wskaźnikowej:
Poniższy przykład tworzy trzy tablice dynamiczne, w których będzie można przechowywać odpowiednio 10, 100 i 1000 elementów typu double:
... a = new double[10]; // elementy od a[0] do a[9] b = new double[100]; // elementy od b[0] do b[99] c = new double[1000]; // elementy od c[0] do c[999] ...
Po tej operacji do elementów tablic a, b i c odwołujemy się w zwykły sposób za pomocą indeksów. Istnieje również alternatywna metoda, wykorzystująca fakt, iż zmienne a, b i c są wskaźnikami. W języku C++ dodanie do wskaźnika liczby całkowitej powoduje obliczenie adresu elementu o indeksie równym dodawanej liczbie. Zatem wynik takiej operacji jest również wskaźnikiem:
Tablica | Wskaźnik |
a[2] = 10.54; cout << a[2] << endl; |
* (a + 2) = 10.54; cout << * (a + 2) << endl; |
W rzeczywistości zapis a[i] kompilator i tak przekształca sobie na zapis * (a + i). Forma tablicowa jest tylko uproszczeniem zapisu wskaźnikowego.
Tablice dynamiczne nie są automatycznie usuwane z pamięci, jeśli utworzono je w funkcji. Dlatego po zakończeniu korzystania z tablicy program powinien zwolnić zajmowaną przez tablicę pamięć. Dokonujemy tego poleceniem delete w sposób następujący:
delete [ ] nazwa_tablicy_dynamicznej;
W poniższym przykładzie zwalniamy pamięć zarezerwowaną wcześniej na elementy tablic b i c.
... delete [ ] b; // usuwamy obszar wskazywany przez b delete [ ] c; // usuwamy obszar wskazywany przez c ...
Należy również wspomnieć, iż Code::Blocks dopuszcza konstrukcję:
co pozwala na tworzenie statycznych tablic o liczbie elementów podanej w zmiennej. Na przykład poniższa konstrukcja programowa tworzy statyczną tablicę a o liczbie elementów odczytanej ze strumienia wejściowego konsoli znakowej:
... int n; cin >> n; double a[n]; ...
Jednakże nie jest to zbyt standardowe rozwiązanie i może nie być przenośne na inne kompilatory C++, dlatego odradzam używania go - lepiej zastosować tablicę dynamiczną.
Poniżej podajemy sposoby odczytu zawartości tablicy z konsoli. Sposób ten jest bardzo ogólny. Wykorzystanie standardowego wejścia jako źródła danych daje nam kilka możliwości wprowadzania danych:
Na przykład nasz program nazywa się szukaj.exe,
a plik nosi nazwę dane.txt. Odpowiednie
polecenie odczytu danych z pliku przez nasz program wygląda
następująco:
To rozwiązanie umożliwia również zapis danych wynikowych nie na
ekran konsoli, lecz do pliku na dysku. W tym celu wystarczy wydać
polecenie:
Wejście i wyjście można przekierować w jednym poleceniu. Np.
nasz program
szukaj może odczytać dane wejściowe z pliku
dane.txt, a wyniki swojej pracy umieścić w
pliku
wyniki.txt. W tym celu wydajemy takie oto
polecenie:
Jeśli często korzystasz z takich opcji uruchamiania
programu, to zamiast wpisywać polecenie z klawiatury, można stworzyć
sobie prosty plik wsadowy
(ang. batch file), w którym umieszczamy
niezbędne polecenia. Plikowi można nadać prostą nazwę, np.
!.cmd. Wtedy w celu uruchomienia zawartych w
nim poleceń wystarczy wpisać !. Oczywiście
plik wsadowy należy umieścić w katalogu projektowym, ale to chyba
już wiesz. Poniżej podaję przykładową zawartość takiego pliku
wsadowego:
// Odczyt danych // (C)2013 mgr Jerzy Wałaszek //--------------------------- #include <iostream> using namespace std; int main() { int * T,n,i; cin >> n; T = new int[n]; for(i = 0; i < n; i++) cin >> T[i]; cout << endl; for(i = 0; i < n; i++) cout << T[i] << " "; cout << endl << endl; delete [] T; return 0; } |
Wynik |
6 12 34 28 65 121 83 12 34 28 65 121 83 |
W poniższych przykładach zakładamy, iż w programie zadeklarowano tablicę T o 100 elementach typu integer. Indeksy elementów tablicy T są w zakresie od 0 do 99.
... for(i = 0; i < 100; i++) T[i] = x; ... |
... for(i = 0; i < 100; i++) T[i] = (i + 1) << 1; ... |
... for(i = 0; i < 100; i++) T[i] = 1 + (i << 1); ... |
#include <cstdlib> #include <time.h> ... srand((unsigned)time(NULL)); ... for(i = 0; i < 100; i++) T[i] = a + rand() % (b - a + 1); ... |
I Liceum Ogólnokształcące |
Pytania proszę przesyłać na adres email: i-lo@eduinf.waw.pl
W artykułach serwisu są używane cookies. Jeśli nie chcesz ich otrzymywać,
zablokuj je w swojej przeglądarce.
Informacje dodatkowe