C++ mgr inż. Tomasz Turba Politechnika Opolska 2016
Z2++ brzmiało: Napisz kompleksowy program który będzie zawierał: 1. Funkcja potęguje dwie wprowadzone liczby A i B i wyświetla wynik na ekranie 2. Funkcja pobiera od użytkownika Imię i wyświetla na ekranie „Witaj $imię!” 3. Funkcja która po wprowadzeniu przez użytkownika liczby całkowitej wykona silnię tej liczby. 4. Funkcja która wypełni tablicę N-elementową liczbami losowymi, wyświetli je, a następnie je przesortuje metodą QuickSort i wyświetli przesortowane. 5. Program po uruchomieniu powinien posiadać menu wyboru (po każdym wyborze i wykonaniu operacji program ma wracać do menu, kończy się dopiero po wyborze opcji 5. Zakończ): 1. Potęguj 2. Przywitaj 3. Silnia 4. Sortuj 5. Zakończ
Zajęcia [ ] Pętla WHILE Rekurencja Wskaźnik Referencja Zadanie domowe
Pętla WHILE while( /* warunek kończący pętlę */ ) { instrukcja1; instrukcja2; zmiana_wartości_warunku; }
#include void odliczanie(int iStart) { while(iStart>=0) { std::cout << iStart << ", "; --iStart; std::system("pause"); } //while std::cout << "LUBUDUBU!" << std::endl; } int main() { odliczanie(5); return 0; }
Rekurencja Rekurencja (rekursja) – wywołanie samej siebie Stosuje się często przy potrzebie ponownego wywołania funkcji operującej na tym samym stosie danych (struktury drzewiaste, vide XML). Stabilizuje przejrzystość kodu, ułatwia implementację rozwiązań Przykład (w zadaniu domowym: silnia)
#include using namespace std; long sumuj(int n) { if(n<1) return 0; return n+sumuj(n-1); } int main() { int n; cout << "Podaj liczbe: "; cin >> n; cout << "Suma " << n <<" kolejnych liczb naturalnych wynosi " << sumuj(n) << endl; system("pause"); return 0; }
Stos Pamięć komputera jest podzielona na bajty, a każdy bajt ma swój adres. Dla przykładu: W 1KB pamięci jest 1024 bajtów i każdy z nich ma adres (0-1023).
Po co stosować wskaźniki/referencje? Za każdym razem gdy programista zadeklaruje zmienną, kompilator umieszcza ją _gdzieś_ w pamięci. Mając wiedzę _gdzie_ w pamięci jest wartość zmiennej – można się do niej odwoływać. Uproszczenie kodu Głębsze zrozumienie obsługi pamięci komputera (optymalizacja działnia kodu) Bezpieczeństwo (memleak, buffer overflow)
Wskaźniki „Zmienne w komputerze są przechowywane w pamięci. To wie każdy programista, a dobry programista potrafi kontrolować zachowanie komputera w przydzielaniu i obsłudze pamięci dla zmiennych. W tym celu pomocne są wskaźniki.” © Wikipedia int main() { int zmienna = 5; cout << &zmienna; //dereferencja (odwołanie do adresu) system(pause); return 0; } Co pojawiło się na ekranie?
Wskaźniki – deklaracja
#include using namespace std; int main() { int *pc, c; c = 5; cout << "Adres zmiennej c (&c): \t\t\t" << &c << endl; cout << "Wartosc zmiennej (c): \t\t\t" << c << endl << endl; pc = &c; //wskaźnik trzyma adres pamięci zmiennej c cout << "Adres ktory jest we wskazniku (pc): \t" << pc << endl; cout << "Zawartosc wskaznika (*pc): \t\t" << *pc << endl << endl; c = 11; //zawartość wewnątrz adresu &c jest zmieniona z 5 na 11 cout << "Adres ktory jest we wskazniku (pc): \t" << pc << endl; cout << "Zawartosc wskaznika (*pc): \t\t" << *pc << endl << endl; *pc = 2; cout << "Adres zmiennej c (&c): \t\t\t" << &c << endl; cout << "Wartosc zmiennej c (c): \t\t" << c <<endl << endl; return 0; }
Referencja Referencja to: przypisanie adresu zmiennej do innej zmiennej Referencja to także: przekazanie argumentu do funkcji Operacje wykonane na zmiennej referencyjnej zostaną odzwierciedlone na zmiennej z której pobrano adres. W odróżnieniu od wskaźnika adres może być przypisany tylko jeden raz, a następnie operacje wykonywane są jak na zwykłej zmiennej Analiza dwóch programów (zmienne, funkcje) – przeanalizuj i odpowiedz na pytanie: jakie wartości otrzymano w przypadku zmiennych, a jakie w przypadku wywołania funkcji?
#include using namespace std; int main() { int i = 5; int &ref_i = i; //referencja musi być zadeklarowana w momencie inicjalizacji cout << i << endl; cout << ref_i << endl; ref_i = 1; cout << i << endl; cout << ref_i; return 0; }
#include using namespace std; void update_nie(int liczba) { ++liczba; } void update_tak(int & liczba) //nie musi być zadeklarowana w momencie inicjalizacji { ++liczba; } int main() { int wartosc=0; cout << "Podaj wartosc: "; cin >> wartosc; update_nie(wartosc); cout << "Wynik funkcji update_nie: " << wartosc; update_tak(wartosc); cout << "\nWynik funkcji update_tak: " << wartosc; return 0; }
Zadanie domowe (5pkt) 1. Napisz program który: A) funkcją poprosi o podanie wartości int trzech kolejnych zmiennych X, Y, Z B) wypisze wartości i adresy zmiennych X, Y, Z za pomocą wskaźników C) zamieni wartości wskazanych dwóch zmiennych za pomocą wskaźników D) zamieni wartości wskazanych dwóch zmiennych za pomocą referencji (!) E) Po wypisaniu A, B, C, D program czeka na ruch użytkownika: Wpisanie słowa „exit” [enter] -> koniec programu Wpisanie słowa „run” [enter] -> wyświetlenie na ekranie 1000 liczb od 1 do 1000, następny [enter] -> koniec programu Wykorzystaj wiedzę nt. operacji we/wy, funkcji, stringów, pętli oraz alokacji w pamięci (punkt E może być realizowany bez wsk/ref), podpowiedź: wykorzystaj zmienne pomocnicze, ostrożnie z mieszaniem wskaźników i referencji
Przykład Podaj X: Podaj Y: Podaj Z: Wartosc X=Adres X= Wartosc Y=Adres Y= Wartosc Z=Adres Z= Podaj zmienne do zamiany wskaźnikowej: Z, Y Wartosc X=Adres X= Wartosc Y=Adres Y= Wartosc Z=Adres Z= Podaj zmienne do zamiany referencyjnej: X, Y Wartosc X=Adres X= Wartosc Y=Adres Y= Wartosc Z=Adres Z= Co mam robić, mój Panie? [exit/run] run 1, 2, 3, 4, 5, … 1000 exit