Podstawy programowania II

Slides:



Advertisements
Podobne prezentacje
Tablice 1. Deklaracja tablicy
Advertisements

C++ wykład 2 ( ) Klasy i obiekty.
C++ wykład 4 ( ) Przeciążanie operatorów.
Język C/C++ Funkcje.
Programowanie obiektowe
Deklaracje i definicje klas w C++ Składowe, pola, metody Konstruktory
Klasa listy jednokierunkowej Przekazywanie parametrów do funkcji
Programowanie obiektowe
Wskaźniki repetytorium Wskaźniki int Y = 1, X = 2; X = 5; int *p = &X; Y X p 4 4 p = &Y; *p = 4; 5.
Wzorce.
Prowadzący: mgr inż. Elżbieta Majka
Programowanie I Rekurencja.
Static, const, volatile.
PROGRAMOWANIE STRUKTURALNE
PROGRAMOWANIE STRUKTURALNE
formatowanie kodu źródłowego
Podstawy informatyki Wirtotechnologia – Wskaźniki i referencje
Podstawy informatyki Powtórka Grupa: 1A Prowadzący: Grzegorz Smyk
Wskaźniki. Definiowanie wskaźników Wskaźnik może wskazywać na obiekt dowolnego typu. int * w; char * Wsk_Znak; float * Wskaz_Real; Przykłady: Wskaźnik.
Struktury.
Tablice.
1 Dygresja: cztery płyty główne…. 2 Dygresja: osobliwości C /* cos o nieistniejacym typie Boolean */ /* oraz o operatorze przecinkowym */ #include int.
Biblioteki i przestrzenie nazw
C++ wykład 2 ( ) Klasy i obiekty.
Dynamiczne struktury danych 1
Wykład 1: Wskaźniki Podstawy programowania Programowanie w C
Zachodniopomorskie Centrum Edukacyjne Zadanie domowe.
Tablice tablica jest sekwencją elementów tego samego typu (prostego lub obiektowego) w Javie tablice są obiektami, a zmienne tablicowe przechowują referencję
Semafory według normy POSIX
Pamięć wspólna Opis własnego rozwiązania Marcin Kamiński, Michał Kotra Wydział EAIiE Katedra Automatyki Kraków, 2008.
Podstawy programowania
Podstawy programowania
Podstawy informatyki 2013/2014
Wskaźnik może wskazywać na obiekt dowolnego typu. int * w; char * Wsk_Znak; float * Wskaz_Float; Przykład: Wskaźnik przechowuje adres obiektu wskazanego.
Podstawy programowania
Podstawy programowania II
Informatyka I Wykład 10 WSKAŹNIKI I ADRESY Jerzy F. Kotowski.
Podstawy programowania II
Procedury i funkcje.
Podstawy programowania
Programowanie obiektowe III rok EiT
Prezentacja i szkolenie
Programowanie obiektowe III rok EiT dr inż. Jerzy Kotowski Wykład VIII.
Inicjalizacja i sprzątanie
Programowanie obiektowe Wykład 3 dr Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ 1/21 Dariusz Wardowski.
Programowanie obiektowe Wykład 6 dr Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ 1/14 Dariusz Wardowski.
Koncepcja procesu Zadanie i proces. Definicja procesu Process – to program w trakcie wykonywania; wykonanie procesu musi przebiegać w sposób sekwencyjny.
Przekazywanie parametrów do funkcji oraz zmienne globalne i lokalne
Programowanie obiektowe 2013/2014
Kurs języka C++ – wykład 3 ( )
Kurs języka C++ – wykład 4 ( )
Modele pamięci Tiny - mikroskopijny do 64 K zmienne inicjalizowane kod programu zmienne nie inicjalizowane HEAP (sterta) obszar wolny STACK (stos) Model.
Procesy, wątki Program a proces Proces: Przestrzeń adresowa, kod, dane, stos (część pamięci do przechowania zmiennych lokalnych i niektórych adresów) Otwarte.
Typy liczbowe, zmienne, operatory Zajęcia 4. Zmienne Zmienna – to w programowaniu element programu, który może mieć przypisaną pewną wartość (wartość.
Paweł Starzyk Obiektowe metody projektowania systemów
PO13-1 / 19 Wykład 13 Wyjątki i ich zgłaszanie Wyłapywanie wyjątków Obsługa wyjątków Wykorzystanie polimorfizmu Filtrowanie wyjątków Błędy w konstruktorach.
Seminarium Dyplomowe: Metodyka i Techniki Programowania Autor: Bartłomiej Fornal.
Podstawy informatyki Preprocesor Łukasz Sztangret Katedra Informatyki Stosowanej i Modelowania Prezentacja przygotowana w oparciu o materiały Danuty Szeligi.
1 Opisy funkcji Adres strony WWW : html (należy odszukać hyperlink Function Index) (
Łukasz Sztangret Katedra Informatyki Stosowanej i Modelowania Prezentacja przygotowana w oparciu o materiały Danuty Szeligi i Pawła Jerzego Matuszyka Podstawy.
Podstawy informatyki Mechanizm obsługi sytuacji wyjątkowych Łukasz Sztangret Katedra Informatyki Stosowanej i Modelowania Prezentacja przygotowana w oparciu.
K URS JĘZYKA C++ – WYKŁAD 3 ( ) Przenoszenie Składowe statyczne Funkcje wbudowane Argumenty domyślne.
C++ mgr inż. Tomasz Turba Politechnika Opolska 2016.
Zmienne typy danych w VBA. MS Excel – typy danych w języku programowania VBA.
C++ mgr inż. Tomasz Turba Politechnika Opolska 2016.
Programowanie Obiektowe – Wykład 2
Kurs języka C++ – wykład 4 ( )
nowe operatory & . (kropka) * operator rzutowy -> , (przecinek)
Język C++ Typy Łukasz Sztangret Katedra Informatyki Stosowanej i Modelowania Prezentacja przygotowana w oparciu o materiały Danuty Szeligi i Pawła Jerzego.
Zapis prezentacji:

Podstawy programowania II Zachodniopomorska Szkoła Biznesu Podstawy programowania II Wykład 4: Dynamiczna alokacja pamięci, referencje, rekurencja

Zapotrzebowanie na pamięć W wielu programach nie ma możliwości przewidzenia (na etapie projektowania) ilości przetwarzanych danych,np.: Baza danych - dowolna liczba rekordów, Obróbka grafiki i dźwięku - nieznane rozmiary pliku. Zapotrzebowanie na pamięć jest w wielu sytuacjach teoretycznie nieograniczone. Projektant lub programista musi jednak na etapie tworzenia programu poczynić pewne założenia. W przypadku wykorzystania statycznych struktur danych (np. zwykła tablica), niezbędne jest określenie maksymalnego rozmiaru danych już podczas kodowania. Deklaracja nadmiarowej tablicy powoduje, że pamięć nie jest wykorzystana w sposób efektywny. Podstawy programowania II - Dynamiczna alokacja pamięci, referencje, rekurencja

Przykład danych statycznych Program ma przetwarzać kwoty transakcji finansowych firmy z ostatniego roku. Deklaracja tablicy statycznej: #define MAX 1000 // wartość arbitralna! float kwoty[MAX]; Dobór wartości MAX bardzo rzadko okaże się trafny, w zależności od firmy i roku: Transakcji może być więcej niż MAX, np. 1005: - program przestaje spełniać swoje funkcje, - wyjście z błędem (przy braku zabezpieczenia) Transakcji może być dużo mniej niż MAX, np. 90: - niepotrzebnie zajęta pamięć. Nie ma przy tym znaczenia czy tablica jest globalna czy lokalna, ponieważ zawsze trzeba przy jej tworzeniu podać rozmiar. Podstawy programowania II - Dynamiczna alokacja pamięci, referencje, rekurencja

Co to jest alokacja pamięci? Każdy program potrzebuje pewnej ilości pamięci do przechowywania swojego kodu stosu wartości stałych (np. wypisywanych tekstów) wartości zmiennych (statycznych) Ilość ta jest znana w chwili ładowania programu, Następuje wtedy żądanie przydziału (alokacji) pamięci od systemu operacyjnego. Jeżeli brakuje pamięci, program się nie uruchamia. Program może również żądać przydziału dodatkowej pamięci od systemu operacyjnego (dynamiczna alokacja pamięci) Przydzielona pamięć powinna być zwolniona przez program przed jego zakończeniem Podstawy programowania II - Dynamiczna alokacja pamięci, referencje, rekurencja

Alokacja dynamiczna: operator new Operator jednoargumentowy (nie funkcja!) new wymaga podania typu danej, jaka ma być umieszczona w pamięci,np.: new typ (np. new int) Rozmiar przydzielonej pamięci zależy od podanego typu i jest określany automatycznie W odpowiedzi new generuje wskaźnik, którego wartość wskazuje otrzymane miejsce w pamięci, a typ wskaźnika odpowiada typowi podanemu jako operand, np.: int *wsk = new int; // wskaźnik na int Przydział pamięci może się nie powieść! Operator new zwraca w takim przypadku wskaźnik zerowy (NULL). Należy zawsze sprawdzić czy alokacja się powiodła. Zaniedbanie może prowadzić do katastrofalnych skutków. Podstawy programowania II - Dynamiczna alokacja pamięci, referencje, rekurencja

Cechy zmiennych dynamicznych Zmienna taka nie ma nazwy, dostępna jest tylko poprzez wskaźnik Zmienna istnieje od chwili alokacji do chwili zwolnienia pamięci Zakres dostępności zmiennej jest podobny do zmiennych statycznych (czyli wszędzie), pod warunkiem, że dostępny jest wskaźnik do tej zmiennej Zmienna nie jest inicjalizowana automatycznie, może zawierać "śmieci" Przydział pamięci odbywa się z tzw. sterty (ang. heap), której maksymalny rozmiar jest często jedną z opcji projektu w kompilatorze Podstawy programowania II - Dynamiczna alokacja pamięci, referencje, rekurencja

Rozmieszczenie danych w pamięci W przypadku danych tworzonych dynamicznie, w pamięci programu znajdują się wskaźniki, a właściwe dane - w pamięci przydzielonej od systemu operacyjnego. Zmienne przydzielone przez system w kolejnych alokacjach mogą fizycznie znajdować się w odległych miejscach pamięci Pamięć programu Pamięć przydzielana dynamicznie wskaźnik 1 zmienna 1 wskaźnik 2 zmienna 3 wskaźnik 3 zmienna 2 Podstawy programowania II - Dynamiczna alokacja pamięci, referencje, rekurencja

Zwolnienie pamięci: operator delete Pamięć pobrana dynamicznie powinna zostać zwolniona przed zakończeniem programu. Służy do tego operator (nie funkcja) jednoargumentowy delete, który wymaga podania wskaźnika na wcześniej zaalokowaną pamięć, np.: int *wsk = new int; // alokacja // tu korzystamy z danej *wsk delete wsk; // zwolnienie Operator delete nie zwraca żadnego wyniku (typ void) Podstawy programowania II - Dynamiczna alokacja pamięci, referencje, rekurencja

Zwolnienie pamięci - problemy Zaniechanie zwolnienia pamięci powoduje, że przydzielony jej fragment pozostaje niedostępny dla innych programów aż do restartu systemu operacyjnego Po zwolnieniu pamięci nie wolno już korzystać z danej zapisanej pod adresem zapisanym we wsk! Ten fragment pamięci już do nas nie należy! W szczególności nie wolno tej zmiennej powtórnie zwolnić. Jako argument dla delete wolno podać wyłącznie wartość wskaźnika, który wskazuje na pamięć przydzieloną dynamicznie. Zwolnienie pamięci jeżeli wskaźnik wynosi NULL (0) nie spowoduje katastrofy (system wykryje nieprawidłowość i nie wykona zwolnienia pamięci) Dobrym pomysłem może być więc ustawianie wskaźnika na wartość NULL natychmiast po zwolnieniu pamięci. Podstawy programowania II - Dynamiczna alokacja pamięci, referencje, rekurencja

Korzystanie z danych dynamicznych Ponieważ dostęp do pobranej pamięci istnieje poprzez wskaźnik, w celu dostępu do wartości zmiennej należy korzystać z operatora * lub [], np.: int *wsk = new int; if (wsk!=NULL) // czy przydzielono pamięć? { cin >> *wsk; cout << "Podana wartość: " << wsk[0]; cout << "Do kwadratu: " >> (*wsk) * (*wsk); delete wsk; // zwolnienie pamięci } else // alokacja nie powiodła się cout << "Brak pamięci!\n"; Podstawy programowania II - Dynamiczna alokacja pamięci, referencje, rekurencja

Utrata dostępu do danej Wskaźnik zwrócony przez operator new, jest jedynym łącznikiem z pobranym miejscem pamięci, a więc również z daną, która tam się znajduje. W przypadku zniszczenia wartości tego wskaźnika niemożliwe jest: korzystanie z tego fragmentu przydzielonej pamięci odczyt i zapis danej, która tam jest zapisana zwolnienie pobranej pamięci Przykład: int *wsk = new int; // pierwszy fragment pamięci *wsk=10; wsk = new int; // drugi fragment pamięci // utraciliśmy dostęp do fragmentu pierwszego *wsk=20; delete wsk; Podstawy programowania II - Dynamiczna alokacja pamięci, referencje, rekurencja

Inicjalizacja zmiennej dynamicznej Podczas tworzenia zmiennej dynamicznej można od razu podać jej wartość Składnia new typ(wartość) Przykład int *iw=new int(20); cout << *iw; // 20 float *fw=new float(-2.5); cout << *fw; // -2.5 Podstawy programowania II - Dynamiczna alokacja pamięci, referencje, rekurencja

Alokacja pamięci na strukturę W przypadku danych prostych (jak int lub float), sens dynamicznej alokacji jest wątpliwy: i tak trzeba tworzyć daną statyczną (wskaźnik) zużycie pamięci wzrasta (miejsce na wskaźnik i daną) Swoją wartość okazuje dynamiczna alokacja w przypadku danych złożonych, np.: struct Duza { //tu duża liczba pól - potrzeba sporo pamięci }; Duza * wsk = new Duza; W tym przypadku jedyną daną statyczną jest wskaźnik wsk, natomiast liczne dane znajdują się w pamięci przydzielonej dynamicznie Podstawy programowania II - Dynamiczna alokacja pamięci, referencje, rekurencja

Dostęp do składników struktury (1) Dostęp za pomocą operatora . struct Zespolona { float re, im; }; Zespolona * z = new Zespolona; if (z!=NULL) { // przydzielono pamięć (*z).re=10; // nawias konieczny! (*z).im=20; cout << (*z).re << "+"<< (*z).im << "i\n"; delete z; } else // alokacja nie powiodła się cout << "Brak pamięci!\n"; Podstawy programowania II - Dynamiczna alokacja pamięci, referencje, rekurencja

Dostęp do składników struktury (2) Dostęp za pomocą operatora -> struct Zespolona { float re, im; }; Zespolona * z = new Zespolona; if (z!=NULL) { // przydzielono pamięć z->re=10; z->im=20; cout << z->re << "+"<< z->im << "i\n"; delete z; } else // alokacja nie powiodła się cout << "Brak pamięci!\n"; Podstawy programowania II - Dynamiczna alokacja pamięci, referencje, rekurencja

Tablica zmiennych dynamicznych (1) Jeżeli trzeba utworzyć pewną liczbę zmiennych w sposób dynamiczny, można wykorzystać statyczną tablicę wskaźników Pamięć programu Pamięć systemu operacyjnego T[0] zmienna T[1] zmienna T[2] T[3] zmienna T[4] T[5] zmienna T[6] zmienna T[7] zmienna T - tablica wskaźników zmienna zmienna Podstawy programowania II - Dynamiczna alokacja pamięci, referencje, rekurencja

Tablica zmiennych dynamicznych (2) struct Zespolona { float re, im; }; Zespolona *z[10]; // tablica wskaźników int blad=0; // znacznik błędu for (int i=0; i<10; i++) { z[i]=new Zespolona; // utworzenie zmiennej i if (z[i]==NULL) blad=1; } if (!blad) { // tutaj można wykorzystać utworzone zmienne,np z1[5]->re=10; z1[5]->im=2; // liczba 10-2i cout << z1[5]->re << "+" << z1[5]->im << "i\n"; } else cout << "Brak pamięci!\n"); for (int i=0;i<10; i++) if (z[i]!=NULL) delete z[i]; Podstawy programowania II - Dynamiczna alokacja pamięci, referencje, rekurencja

Dynamiczna alokacja tablicy Dynamiczne utworzenie tablicy : wskaźnik=new typ[rozmiar]; Operator new generuje w tym przypadku również wskaźnik do typu typ, z tym że przydzielany jest obszar pamięci pozwalający zapisać rozmiar danych typu typ. Przykład int *tab=new int[10]; - tablica 10 int'ów Nie ma możliwości inicjalizacji takiej tablicy Programista musi być świadom czy wskaźnik wskazuje na jedną daną czy na pierwszą daną z tablicy (i pamiętać rozmiar) Ze wskaźnika można korzystać w identyczny sposób jak ze "zwykłej" tablicy - z użyciem operatora * lub [] Zwolnienie tablicy utworzonej dynamicznie odbywa się za pomocą konstrukcji: delete [] wskaźnik; Podstawy programowania II - Dynamiczna alokacja pamięci, referencje, rekurencja

Alokacja tablicy - przykłady int *wsk, *tab; wsk=new int; tab=new int[20]; // ten sam typ wskaźnika dla // zmiennej prostej i tablicy *wsk = 10; // wstawienie wartości *tab = 10; // zerowy element tablicy *(tab+1)=11; // pierwszy element tablicy wsk[0]=20; // poprawne ale mylące tab[0]=20; // zerowy element tablicy tab[1]=1; // pierwszy element tablicy tab[19]=100; // ostatni element tablicy wsk[1]=10; // Błąd! To nie nasza pamięć! delete wsk; delete [] tab; Podstawy programowania II - Dynamiczna alokacja pamięci, referencje, rekurencja

Alokacja tablicy - rozmieszczenie Struktury danych dla następujących zmiennych: int *T=new int[8]; Pamięć programu Pamięć systemu operacyjnego T T[0] T[1] wskaźnik na int T[2] T[3] T[4] T[5] T[6] T[7] tablica 8 zmiennych typu int Podstawy programowania II - Dynamiczna alokacja pamięci, referencje, rekurencja

Przykład alokacji tablicy int ile; cout << "Podaj liczbę danych: "; cin >> ile; float *tab=new float[ile]; // zmienny rozmiar!!! if (tab!=NULL) { for (int i=0; i<ile; i++) { cout << "Podaj wartość " << i << ": "; cin >> tab[i]; // wprowadzenie danych } // tu można korzystać z podanych liczb delete [] tab; } else cout << "Brak pamięci!\n"; Podstawy programowania II - Dynamiczna alokacja pamięci, referencje, rekurencja

Przykładowy program Program: Statystyka.cpp - wczytywanie tablicy z pliku tekstowego - dynamiczna alokacja tablicy Podstawy programowania II - Dynamiczna alokacja pamięci, referencje, rekurencja

Referencje Referencja jest typem pochodnym łączącym pewne cechy typu bazowego oraz wskaźnika (nie ma tylko analogii do tablicy!) Referencje nie występują w języku C, tylko w C++, C#, Javie Można ją rozumieć jako przezwisko (alias) pewnej już istniejącej zmiennej. Referencja zawiera w sobie adres i typ tej zmiennej ale nie wymaga stosowania operatora * (jak wskaźnik), "na oko" wygląda w programie jak zwykła zmienna Składnia deklaracji: typ & nazwa_referencji; Przykład void main() { int a=0,b=0; int &ref=a; ref=10; // ref=10 i a=10!!! ref=b; // ref=0, a=0 ref=20; // ref=20 i a=20 (b=0) } Podstawy programowania II - Dynamiczna alokacja pamięci, referencje, rekurencja

Referencje jako parametr funkcji Sens użycia referencji jako parametru jest podobny jak wskaźnika (poza przesyłaniem tablic), tyle że dostęp do zmiennej jest wygodniejszy (nie wymaga użycia operatorów *) Wywołując funkcję trzeba pamiętać, że może ona zmienić wartość zmiennej (w wywołaniu tego nie widać) Przykład: void plusminus(int *tab, int n, int &plus, int &minus) { plus=0, minus=0; // zerujemy referencje for (int i=0; i<n; i++) if (tab[i]>0) plus++; else minus++; } // plus i minus obliczone void main() { int tablica[20], ileplus, ileminus; plusminus(tablica, 20, ileplus, ileminus); } Podstawy programowania II - Dynamiczna alokacja pamięci, referencje, rekurencja

Referencje - uwagi Podobnie jak wskaźnik, referencja zawsze wskazuje na jakieś miejsce w pamięci, nawet nie została w programie zainicjowana. Użycie takiej referencji jest niebezpieczne. Należy pamiętać o tym, że referencja jest przezwiskiem jakiejś innej zmiennej i jej zmiana powoduje również zmiany tamtej zmiennej. Referencję należy zainicjować przypisując jej zmienną, później można podstawiać również zwykłe wyrażenia, np.: void plus5(int &liczba) { liczba+=5; // zwiększamy podaną zmienną o 5 } Wywołania: int a; plus5(a); // podajemy zmienną a plus5(a+1); // błąd, a+1 to nie zmienna plus5(10); // bład, 10 to nie zmienna Podstawy programowania II - Dynamiczna alokacja pamięci, referencje, rekurencja

Referencja na wskaźnik Skoro można utworzyć referencję do zwykłej zmiennej, to można i do wskaźnika: Składnia: typ * & nazwa_referencji; Przykład: void main() { int a,b, *wsk1; int *& refwsk=wsk1; wsk1=&a; // wsk1 i refwsk wskazują na a refwsk= &b; // wsk1 i refwsk wskazują na b } Podstawy programowania II - Dynamiczna alokacja pamięci, referencje, rekurencja

Rekurencja W niektórych zagadnieniach występuje potrzeba wywołania funkcji przez nią samą, np.: void odliczaj(int n) { cout << n <<endl; if (n>0) odliczaj(n-1); // rekurencja } Podczas każdego wywołania rekurencyjnego tworzony jest na stosie oddzielny zestaw zmiennych lokalnych (tutaj zmienna n) Należy zawsze pamiętać o zdefiniowaniu warunku zakończenia rekurencji, inaczej funkcja będzie wywoływać się w nieskończoność (w końcu zapychając pamięć) Podstawy programowania II - Dynamiczna alokacja pamięci, referencje, rekurencja

Rekurencja - silnia Wzór rekurencyjny: n! = n* (n-1)! , n>1; 0!=1!=1. long silnia(short n) { if (n>0) return n*silnia(n-1); else return 1; } Wzór iteracyjny: n! = n*(n-1)*...*2*1, n>1; 0!=1!=1. long silnia(short n) { long sil=1; for (;n>0;n--) sil*=n; return sil; } Podstawy programowania II - Dynamiczna alokacja pamięci, referencje, rekurencja

Rekurencja - ciąg Fibonacciego Wzór rekurencyjny na wyraz k ciągu Fibonacciego: Fib(k) = Fib(k-1) + Fib(k-2), k>2; Fib(1)=Fib(2)=1. Ciąg: 1 1 2 3 5 8 13 21 34 55 89 ... unsigned long Fib(unsigned short k) { if (k>2) return Fib(k-1)+Fib(k-2); else return 1; } Podstawy programowania II - Dynamiczna alokacja pamięci, referencje, rekurencja

Dziękuję