Pobieranie prezentacji. Proszę czekać

Pobieranie prezentacji. Proszę czekać

Podstawy programowania PP – WYK5 Wojciech Pieprzyca.

Podobne prezentacje


Prezentacja na temat: "Podstawy programowania PP – WYK5 Wojciech Pieprzyca."— Zapis prezentacji:

1 Podstawy programowania PP – WYK5 Wojciech Pieprzyca

2 Tablice wielowymiarowe (1) Tablice wielowymiarowe w przypadku dwóch wymiarów można porównać do macierzy elementów, które znamy z matematyki albo do współrzędnych dwuwymiarowego układu kartezjańskiego XY. Tablica trójwymiarowa z kolei może być utożsamiona np. z punktem w przestrzeni 3D o współrzędnych (x,y,z). Tablice o więcej niż 3 wymiarach są raczej rzadkością, gdyż korzystanie z nich jest kłopotliwe. Deklaracja tablicy wielowymiarowej ma następującą składnię: typ nazwa[rozmiar_wymiaru_1][rozmiar_wymiaru_2]…[rozmiar_wymiaru_N]; Przykładowo: int tab[2][3] – macierz liczb 2x3, int tab[2][2][2] – trójwymiarowa przestrzeń liczbowa o rozmiarach 2x2x2.

3 Tablice wielowymiarowe (2) Dwuwymiarowa tablica liczb 2x3 (macierz 2x3) x11 x12 x13 x24 x25 x26 Do poszczególnych elementów możemy odwołać się w następujący sposób: tab[0][0] tab[0][1] tab[0][2] tab[1][0] tab[1][1] tab[1][2] Jak widać, pierwszy indeks wskazuje na wiersz w którym znajduje się dany element, a drugi indeks na kolumnę.

4 Tablice wielowymiarowe (3) Przykładowy program będzie wyświetlał zawartość tablicy dwuwymiarowej o rozmiarze 2x3. Wykorzystamy w tym celu zagnieżdżoną pętlę for. Pierwsza z pętli for operująca indeksem i porusza się po wszystkich wierszach (i=0,1). Druga pętla for wykorzystująca indeks j porusza się po wszystkich kolumnach (j=0,1,2). int tab[2][3] = { {1,2,3},{4,5,6} }; for (int i=0; i<2; i++) for (int j=0; j<3; i++) cout << Element [ << i << ][ << j << = << tab[i][j] << endl;

5 Wskaźniki (1) Wskaźnik jest adresem komórki pamięci operacyjnej od której rozpoczyna się obszar, w którym umieszczony jest określony obiekt (obiektem może być zmienna typu podstawowego np. int, zmienna typu złożonego np. typu strukturalnego a w szczególności wskaźnik może pokazywać na obszar pamięci w której znajduje się funkcja).

6 Wskaźniki (2) Do czego potrzebny jest nam wskaźnik ? Odpowiedź na to pytanie wiąże się z tzw. dynamicznym przydziałem pamięci. Często występuje sytuacja, gdy chcemy stworzyć obiekt np. tablicę o rozmiarach, które nie są narzucone z góry, ale wprowadzane dopiero w trakcie wywołania programu. Wskaźniki oraz dodatkowe operatory new i delete będą umożliwiały nam tworzenie takich dynamicznych obiektów.

7 Wskaźniki (3) Przykłady deklaracji wskaźników Deklaracja zmiennych wskaźnikowych podobna jest do deklaracji zwykłych zmiennych, z tą różnicą, że poprzedzamy nazwę zmiennej znakiem gwiazdki *, czyli: typ *nazwa; Przykłady: int *wsk_int; float *wsk_float; double *wsk_double; char *wsk_char;

8 Wskaźniki (4) Po deklaracji wskaźnik nie pokazuje na żadne konkretne miejsce w pamięci, a więc nie wskazuje na żaden obiekt. Aby tak się stało konieczne jest jawne przypisanie adresu obiektu do zmiennej wskaźnikowej. Załóżmy, że mamy zmienną typu całkowitoliczbowego a: int a=100; Następnie deklarujemy wskaźnik, który może pokazywać na tę liczbę: int *wsk_a; W kolejnym kroku przypisujemy do wskaźnika adres zmiennej a: wsk_a = &a; Za pomocą operatora & uzyskujemy adres zmiennej a.

9 Wskaźniki (5) Na poprzednim slajdzie pokazaliśmy jak zadeklarować i zdefiniować wskaźnik tak aby wskazywał na konkretny obiekt (zmienną). W ten sposób możemy uzyskać dostęp do zmiennej a na dwa sposoby: tradycyjny oraz poprzez wskaźnik. Sposób tradycyjny: cout << a << endl; Sposób z użyciem wskaźnika: cout << *wsk_a << endl; Dostęp do wartości na którą pokazuje wskaźnik możliwy jest poprzez użycie operatora wyłuskania *.

10 Wskaźniki (6) Całość programu wygląda jak poniżej: int a=100; int *wsk_a; wsk_a = &a; cout << a << endl; cout << *wsk_a << endl;

11 Wskaźniki do tablic (1) Specyficznym rodzajem wskaźników są wskaźniki do tablic. int tab[10]; int *wsk_tab; Istotne cechy wskaźników do tablic: 1) przypisanie do zmiennej wskaźnikowej nazwy tablicy ustawia wskaźnik na początku tablicy (jej pierwszym elemencie), czyli dwa poniższe przypisania są równoznaczne: wsk_tab = tab; wsk_tab = &tab[0];

12 Wskaźniki do tablic (2) 2) Aby wskaźnik pokazywał na element tablicy o indeksie k wystarczy napisać poniższą instrukcję: wsk_tab = &tab[k]; 3) Poruszanie się po tablicy możemy zrealizować poprzez inkrementację wskaźnika. Co ważne wskaźnik ten będzie automatycznie inkrementowany o taką wartość, aby wskazywał na następny element tablicy, a więc np. w przypadku tablicy znakowej o 1 bajt, a w przypadku tablicy liczb całkowitych o 4 bajty, itp. wsk_tab++;

13 Wskaźniki do tablic (3) 4) Wyświetlenie wszystkich elementów tablicy przy użyciu wskaźników mogłoby się odbyć przykładowo w następujący sposób: int tab[5] = {1,2,3,4,5}; int *wsk_tab; wsk_tab = tab; for (int i=0; i<5; i++) cout << *(wsk_tab++) << endl; W każdej iteracji pętli najpierw wyświetlany jest element na który pokazuje wskaźnik wsk_tab, a następnie wskaźnik ten jest inkrementowany o 4 bajty (rozmiar zmiennej int).

14 Operatory new i delete (1) Operatory new i delete służą do dynamicznego tworzenia obiektów np. tablic. Rozpoczniemy od prostego przykładu deklaracji wskaźnika na zmienną całkowitoliczbową. Przy czym należy zauważyć, że wcześniej nie będziemy deklarować samej zmiennej, a tylko za pomocą operatora new zarezerwujemy sobie odpowiedni obszar pamięci, gdzie ta liczba będzie przechowywana. int *wsk; wsk = new int; Do tak utworzonego obszaru pamięci dla liczby możemy odwołać się jedynie poprzez wskaźnik wsk. Nie ma bowiem deklaracji żadnej zmiennej dla tej liczby.

15 Operatory new i delete (2) Należy zwrócić szczególnie baczną uwagę na to, aby zwalniać zarezerwowane wcześniej miejsce w pamięci operacyjnej, które nie jest już wykorzystywane. Służy do tego operator delete. Na przykład przy jego użyciu możemy zwolnić miejsce w pamięci, której wcześniej zarezerwowaliśmy do przechowywania liczby. delete wsk; Po takiej operacji nie możemy już używać wskaźnika wsk, dopóki nie przypiszemy do niego jakiegoś nowego obszaru. Przestajemy również mieć dostęp do liczby, która była tam przechowywana.

16 Tablice dynamiczne (1) Nie zawsze jesteśmy w stanie z góry określić rozmiaru tablicy, która będzie potrzebna. Częstokroć dopiero w trakcie wykonywania programu możemy w sposób dokładny określić liczbę elementów, która ma być przechowywana w tablicy. W tradycyjnym podejściu nie ma jednak możliwości zadeklarowania zmiennej tablicowej o dynamicznym rozmiarze. Z pomocą przychodzą jednak wskaźniki oraz operatory new i delete.

17 Tablice dynamiczne (2) Do dynamicznego utworzenia tablicy potrzebny będzie nam wskaźnik do elementu typu takiego samego jak elementy przechowywane w tablicy. Dla przykładu załóżmy, że w tablicy chcemy przechowywać liczby rzeczywiste typu double. Za pomocą operatora new możemy zarezerwować nie tylko pamięć dla jednego obiektu, ale także dla większej ich liczby. Ta cecha operatora new świetnie współgra z potrzebami dotyczącymi tablic, które zawierają wiele elementów. double *tab = new double[10]; Po takiej deklaracji wskaźnik tab pokazuje na początek obszaru (pierwszy element) w którym przechowywane będzie 10 liczb rzeczywistych typu double.

18 Tablice dynamiczne (3) Posiadając dotychczasowe informacje możemy napisać program, który będzie pytał użytkownika o liczbę elementów, a następnie dynamicznie tworzył tablicę o odpowiednim rozmiarze. int n; cout << Podaj liczbe elementów: ; cin >> n; double *tab = new double[n]; //pobranie danych od użytkownika for (int i=0; i<n; i++) { cout << Podaj element << i << = ; cin >> tab[i];//lub tab[i] }

19 Tablice dynamiczne (4) //wyświetlenie danych na ekranie for (int i=0; i<n; i++) { cout << Element tablicy << i << = << tab[i] << endl; } Zwróćmy uwagę na to, że odwołując się do elementów tablicy możemy korzystać z notacji tradycyjnej (tab[i]) zamiast wskaźnikowej (*tab) co znacznie upraszcza proces przetwarzania tych elementów.

20 Wskaźniki do funkcji (1) Wskaźniki mogą w szczególności pokazywać także na funkcje. Typ wskaźnika musi się w takim przypadku zgadzać z typem funkcji. Na przykład mając funkcję o następującym nagłówku: float oblicz (char,int) możemy zadeklarować wskaźnik do tej funkcji: float (*wsk) (char, int); Przypisanie funkcji do wskaźnika ma postać: wsk = oblicz; Teraz alternatywnie możemy wywołać funkcję oblicz na dwa sposoby: oblicz(znak,liczba); wsk(znak,liczba);

21 Wskaźniki do funkcji (2) Prosty przykład funkcji obliczającej pole okręgu lub kuli w zależności od podanego parametru znakowego: o – okrąg, k - kula: float oblicz(char typ, int r) { if (typ==o) return 3.14*r*r; else if (typ==k) return 4/3*3.14*r*r*r; else return -1; } float (*wsk) (char, int) = oblicz; Przykłady wywołań: oblicz(o,4); oblicz(k,4); wsk(o,4); wsk(k,4);


Pobierz ppt "Podstawy programowania PP – WYK5 Wojciech Pieprzyca."

Podobne prezentacje


Reklamy Google