Kurs C++
Transkrypt
Kurs C++
Kurs C++ TI 312[01] Kurs C++ Spis treści 1. Wielkie i małe litery........................................................................................................ 4 Przykład 1.1 .................................................................................................................... 4 2. Komentarze .................................................................................................................... 4 Przykład 2.1 .................................................................................................................... 4 3. Słowa kluczowe .............................................................................................................. 4 Tabela 3.1. Słowa kluczowe ............................................................................................ 5 Tabela 3.2. Leksemy alternatywne.................................................................................. 5 4. Funkcja return................................................................................................................ 6 Przykład 4.1 .................................................................................................................... 6 5. Dyrektywa #include ....................................................................................................... 6 6. Deklaracja stałych .......................................................................................................... 6 Przykład 6.1 .................................................................................................................... 6 Przykład 6.2 .................................................................................................................... 7 7. Deklaracja zmiennych .................................................................................................... 7 Tabela 7.1. Podstawowe typy zmiennych ........................................................................ 7 Przykład 7.1 .................................................................................................................... 7 Tabela 7.2. Podstawowe manipulatory............................................................................ 8 8. Operatory ....................................................................................................................... 8 a) Operatory arytmetyczne ............................................................................................. 8 Tabela 8.1. Operatory arytmetyczne ............................................................................ 8 Przykład 8.1................................................................................................................. 8 b) Operatory relacyjne .................................................................................................... 8 Tabela 8.2. Operatory relacyjne................................................................................... 9 Przykład 8.2................................................................................................................. 9 c) Operatory logiczne...................................................................................................... 9 Tabela 8.3. Operatory logiczne .................................................................................... 9 Przykład 8.3................................................................................................................. 9 d) Bitowe operatory logiczne ........................................................................................ 10 Tabela 8.4. Bitowe operatory logiczne ....................................................................... 10 Przykład 8.4............................................................................................................... 10 9. Funkcje......................................................................................................................... 12 Przykład 9.1. Mnożenie dwóch liczb .............................................................................. 12 Przykład 9.2 Mnożenie dwóch liczb (typ void) ............................................................... 13 10. Instrukcje warunkowe ............................................................................................... 13 a) instrukcja niepełna (wybór niepełny): ................................................................ 13 b) instrukcja pełna (wybór pełny) ........................................................................... 13 Przykład 10.2 Zagnieżdżanie instrukcji warunkwych .................................................... 14 11. Instrukcja switch......................................................................................................... 14 Przykład 11.1. Kalkulator .............................................................................................. 15 Przykład 11.2. Sprawdzanie ile wynosi reszta z dzielenia wprowadzonej liczby przez 4. ..................................................................................................................................... 16 12. Pętla while i do while ................................................................................................... 16 a) Pętla while .......................................................................................................... 16 Przykład 12.1. Sumowanie liczb naturalnych od 1 do n.............................................. 16 b) Pętla do while ...................................................................................................... 17 Przykład 12.2. Sumowanie liczb naturalnych od 1 do n (ze sprawdzaniem czy n jest większe od 1) ............................................................................................................ 17 13. Pętla for ..................................................................................................................... 17 Przykład 13.1. Program wypisujący liczby naturalne od 1 do n ..................................... 18 Przykład 13.2. Program sprawdzający, czy liczba jest pierwsza.................................... 18 14. Typ tablicowy ............................................................................................................. 19 a) Tablice jednowymiarowe .......................................................................................... 19 Przykład 14.1. Wypełnianie i wypisywanie elementów tablicy za pomocą pętli ......... 19 Przykład 14.2. Wypisanie elementów zadeklarowanej (wypełnionej) tablicy. ........... 19 2 Kurs C++ Przykład 14.3............................................................................................................. 20 b) Tablice wielowymiarowe........................................................................................... 20 Przykład 14.4 Wprowadzanie imion i nazwisk do bazy (za pomocą pętli) i szukanie osób w bazie o podanym nazwisku. ........................................................................... 20 15. Struktury danych........................................................................................................ 21 Przykład 15.1. Struktura ............................................................................................... 22 Przykład 15.2. Tablica struktur (tablica typu strukturalnego)....................................... 22 Przykład 15.2. Baza danych - tablica struktur (tablica typu strukturalnego)................. 22 16. Klasy .......................................................................................................................... 26 Przykład 16.1. Program „Przedstaw się”....................................................................... 27 Przykład 16.2. Tablica klas– baza danych „Osoby”........................................................ 27 Przykład 16.3. Tablica klas– baza danych „Osoby 2”..................................................... 28 17. Hermetyzacja ............................................................................................................. 30 Przykład 17.1. Program „Bankomat”............................................................................. 30 18. Konstruktor i destruktor............................................................................................. 31 Przykład 18.1. Nadawanie wartości początkowych tworzonemu obiektowi za pomocą konstruktora ................................................................................................................. 31 Przykład 18.2. Nadawanie wartości początkowych tworzonemu obiektowi za pomocą konstruktora i informowanie za pomocą destruktora o usunięciu obiektu po skończeniu programu ...................................................................................................................... 32 19. Zagnieżdżona definicja klasy ...................................................................................... 33 Przykład 19.1. Konstruktory zagnieżdżonych klas......................................................... 34 20. Przeciążenie funkcji.................................................................................................... 35 Przykład 20.1. Przeciążenie funkcji............................................................................... 35 21. Przeciążenie operatorów ............................................................................................ 35 Tabela 20.1. Lista operatorów, które mogą być przeładowane...................................... 36 Przykład 20.1. Przeciążenie operatorów ....................................................................... 36 21. Zapis i odczyt pliku ..................................................................................................... 37 Przykład 21.1. Zapis do pliku tekstowego ..................................................................... 37 Przykład 21.2. Odczyt z pliku tekstowego ..................................................................... 37 Tabela 21.1. Tryby klasy ios.......................................................................................... 38 22. Dziedziczenie.............................................................................................................. 38 Przykład 22.1. Dziedziczenie składowej klasy podstawowej przez klasę pochodną....... 38 23 Polimorfizm ................................................................................................................. 39 24. Unie............................................................................................................................ 39 Przykład 24.1 ................................................................................................................ 39 25. Pola bitowe................................................................................................................. 40 Przykład 25.1 ................................................................................................................ 40 26. Wskaźniki ................................................................................................................... 40 Przykład 26.1 ................................................................................................................ 40 Przykład 26.2. Manipulowanie danymi za pomocą wskaźników .................................... 42 a) Zarządzanie pamięcią ............................................................................................... 42 Przykład 26.3. Rezerwacja i zwalnianie pamięci ........................................................... 43 3 Kurs C++ 1. Wielkie i małe litery C++ rozróżnia wielkie i małe litery (ważne przy deklaracji zmiennych!) , polecenia C++ piszemy zawsze małymi literami. Przykład 1.1 #include <iostream> using namespace std; int main() { int zmienna, ZMIENNA, Zmienna; zmienna=1; ZMIENNA=2; Zmienna=3; cout << „Zmienne to: ” << endl; cout << zmienna << „\n” << ZMIENNA << „\n” << Zmienna << „\n” << Zmienna << „\n”; } 2. Komentarze Komentarz składający się z jednej linii rozpoczynamy //. Komentarz składający się z kilku linijek rozpoczynamy /* i kończymy */. Przykład 2.1 #include <iostream> using namespace std; int main() { // Komentarz zajmujacy jedną linijke cout << „Bla bla bla”; /* Komentarz zajmujący wiecej niz jedna linijke */ cout << „bla bla bla”; } 3. Słowa kluczowe Słowo kluczowe to identyfikator w C++ zarezerwowany dla określonych zadań. Deklarowana zmienna nie może być słowem kluczowym. 4 Kurs C++ Tabela 3.1. Słowa kluczowe Słowo kluczowe asm auto bool break case catch char class const const_cast continue default delete Znaczenie Słowo kluczowe new operator private protected przerwij „jeśli” w wyborze wielokrotnym public register reinterpret_cast return short signed sizeof static static_cast zmienna znakowa do wykonuj w pętli „dowhile” struct double zmienna rzeczywista switch dynamic_cast else enum explicit extern false float for friend goto if inline int long mutable namespace Znaczenie zwróć testuj zmienną (w wyborze wielokrotnym) template w pozostałym przypadku this throw true try typedef typeid typename union unsigned fałsz zmienna rzeczywista identyfikator pętli identyfikator instrukcji warunkowej prawda using virtual void volatile wchar_t while zmienna całkowita Tabela 3.2. Leksemy alternatywne Leksem and and_eq bitand bitor compl not not_eq or Znaczenie && &= & | ~ ! != || 5 identyfikator pętli Kurs C++ or_eq xor xor_eq |= ^ ^= 4. Funkcja return Funkcja return zwraca wartość zdefiniowaną w funkcji. Przykład 4.1 #include <iostream> using namespace std; int dodawanie(int x, int y) { return x+y; } int main() { int x, y; cout << „Podaj 1 liczbe: “; cin >> x; cout << „Podaj 2 liczbe: “; cin >> y; cout << „Wynik dodawania liczb ” << x << „ i ” << y << „ to ” << dodawanie(x,y); } 5. Dyrektywa #include Dyrektywa służy do włączania do pliku źródłowego bibliotek standardowych (np. iostream) lub innych plików nagłówkowych (tworzonych przez użytkownika). Nawiasy <> służą do dołączania bibliotek standardowych, natomiast „” do dołączania własnych plików nagłówkowych. 6. Deklaracja stałych Z chwilą deklarowania zmiennych możemy od razu przypisać im konkretne wartości. Przykład 6.1 #include <iostream> using namespace std; int main() { int x=5; cout << x; } 6 Kurs C++ Deklarowana wartość może być w każdym miejscu skryptu zmieniona (może osiągnąć inną wartość). Jeśli zachodzi konieczność aby zmienna zachowała w obrębie całego programu tą samą wartość (aby nie można jej było zmienić), to wykorzystujemy w tym celu słowo kluczowe const. Przykład 6.2 #include <iostream> using namespace std; int main() { const int x=5; cout << x; } 7. Deklaracja zmiennych Zmienna musi zostać zadeklarowana zanim zaczniemy jej używać. Deklaracja zmiennej powoduje rezerwację miejsca w pamięci. Tabela 7.1. Podstawowe typy zmiennych Zmienna bool unsigned short int short int unsigned long int long int int unsigned int char float double Opis zmiennej Zmienna boole’owska (true/false) Liczba całkowita krótka (dodatnia) Liczba całkowita krótka Liczba całkowita długa (dodatnia) Liczba całkowita długa Liczba całkowita Liczba całkowita (dodatnia) Zmienna znakowa Liczba rzeczywista (do 7 miejsc po przecinku) Liczba rzeczywista (do 15 miejsc po przecinku) Zakres wartości (pamięć) 0 lub 1 (1b) 0÷65535 (2B) -32768÷32767 (2B) 0 ÷ 4294967295 (4B) -2147483648 ÷ 2147483647 (4B) -2147483648 ÷ 2147483647 (4B) 0 ÷ 4294967295 (4B) -128 ÷ 127 (1B) 1,2x10-38 ÷ 3,4x1038 (4B) 2,2x10-308 ÷ 1,8x10308 (8B) Aby sprawdzić ile miejsca (w bajtach) w pamięci rezerwuje każdy typ zmiennej używamy funkcji sizeof() Przykład 7.1 #include <iostream> using namespace std; int main() { cout << “Zmienna int zajmuje w pamieci “ << sizeof(int) << “ bajtow”; } 7 Kurs C++ Tabela 7.2. Podstawowe manipulatory Manipulator \a \n \b \r \’ \\ \t \” Znaczenie Dzwonek (Bell) Nowa linia Powrót o 1 znak Powrót na początek linii Apostrof Backslash Tabulator Cudzysłów 8. Operatory Operand – zmienna lub wartość liczbowa sąsiadująca z operatorem a) Operatory arytmetyczne Tabela 8.1. Operatory arytmetyczne Operator + * / Przykład x+y x-y x*y x/y % x%y Zastosowanie Suma x i y Róznica x i y Iloczyn x i y Iloraz x i y Reszta z dzielenia x przez y (tylko dla typów int, short int, long int) Przykład 8.1 #include <iostream> using namespace std; int main() { int x,y,z,w; cout << „podaj 1 liczbe: ”; cin >> x; cout << „podaj 2 liczbe: ”; cin >> y; z=x+y; w=x-y; cout << “Suma wprowadzonych liczb wynosi “ << z << “, a roznica ” << w; } b) Operatory relacyjne Operatory relacyjne zwracają wartość true (gdy sprawdzany warunek jest prawdziwy) lub false (gdy sprawdzany warunek jest fałszywy). 8 Kurs C++ Tabela 8.2. Operatory relacyjne Operator < <= > >= != == Przykład x<y x<=y x>y x>=y x!=y x==y Zastosowanie x mniejsze od y x mniejsze lub równe y x większe od y x większe lub równe y x różne od y x równe y Przykład 8.2 #include <iostream> using namespace std; int main() { int x; cout << „podaj liczbe: ”; cin >> x; if (x>10) { cout << “Wprowadzona liczba jest wieksza od 10”; } else { cout << “Wprowadzona liczba jest mniejsza lub rowna 10”; } } c) Operatory logiczne Tabela 8.3. Operatory logiczne Operator && || ! Znaczenie and - część wspólna (iloczyn logiczny) or – suma logiczna not - negacja Przykład 8.3 #include <iostream> using namespace std; int main() { int x; cout << „podaj liczbe: ”; cin >> x; if ((x>10)&&(x<=15)) 9 Kurs C++ { cout << “Wprowadzona liczba nalezy do przedzialu (10,15>”; } else { cout << “Wprowadzona liczba jest mniejsza rowna 10 lub wieksza od 15”; } } d) Bitowe operatory logiczne Tabela 8.4. Bitowe operatory logiczne Operator | & ^ << >> ~ Przykład x|y x&y x^y x<<y x>>y ~x Nazwa Alternatywa bitowa Koniunkcja bitowa Bitowa różnica symetryczna Bitowe przesunięcie w lewo Bitowe przesunięcie w prawo Negacja bitowa Przykład 8.4 #include <iostream> using namespace std; int main() { unsigned int x,y; cout << „podaj 1 liczbe: ”; cin >> x; cout << „podaj 2 liczbe: ”; cin >> y; cout << “1. Bitowa alternatywa liczb “ << x << „ i ” << y << „ wynosi „ << (x|y) << endl; cout << “2. Bitowa koniunkcja liczb “ << x << „ i ” << y << „ wynosi „ << (x&y) << endl; cout << “3. Bitowa roznica symetryczna liczb “ << x << „ i ” << y << „ wynosi „ << (x^y) << endl; cout << “4. Bitowa negacja liczby “ << x << „ wynosi „ << (~x) << endl; cout << “5. Bitowe przesuniecie w lewo liczby “ << x << „ o liczbe ” << y << „ wynosi „ << (x<<y) << endl; cout << “6. Bitowe przesuniecie w prawo liczby “ << x << „ o liczbe ” << y << „ wynosi „ << (x>>y) << endl; } Dla licz x=50 i y=4 dostajemy: 1. Bitowa alternatywa liczb 50 i 6 wynosi 54 10 Kurs C++ 2. 3. 4. 5. 6. Bitowa Bitowa Bitowa Bitowe Bitowe koniunkcja liczb 50 i 6 wynosi 2 roznica symetryczna liczb 50 i 6 wynosi 52 negacja liczby 50 wynosi 4294967245 przesuniecie w lewo liczby 50 o liczbe 6 wynosi 3200 przesuniecie w prawo liczby 50 o liczbe 6 wynosi 0 Zapisując liczby 50 i 6 w systemie otrzymujemy: (50)10=(110010)2 i (6)10=(110)2 Ad. 1 Zapisujemy liczby 50 i 6 w systemie binarnym jedną pod drugą (uzupełniając krótszą liczbę zerami z lewej strony aby dwie liczby miały tą samą długość) 50 6 50|6 1 0 ↓ 1 1 0 ↓ 1 0 0 ↓ 0 0 1 ↓ 1 1 1 ↓ 1 0 0 ↓ 0 Jeśli na tych samych pozycjach jednej i drugiej liczby mamy co najmniej jedną jedynkę to alternatywa binarna liczb będzie miała na tej samej pozycji jedynkę binarną. W pozostałych przypadkach mamy 0 binarne. Dostajemy zatem liczbę 110110, co po przeliczeniu na system dziesiętny daje liczbę 54 Ad. 2 50 6 50&6 1 0 ↓ 0 1 0 ↓ 0 0 0 ↓ 0 0 1 ↓ 0 1 1 ↓ 1 0 0 ↓ 0 Jeśli na tych samych pozycjach jednej i drugiej liczby mamy dwie jedynki to koniunkcja binarna liczb będzie miała na tej samej pozycji jedynkę binarną. W pozostałych przypadkach mamy 0 binarne. Dostajemy zatem liczbę 000010, co po przeliczeniu na system dziesiętny daje liczbę 2 Ad. 3 50 6 50^6 1 0 ↓ 1 1 0 ↓ 1 0 0 ↓ 0 0 1 ↓ 1 1 1 ↓ 0 0 0 ↓ 0 Jeśli na tych samych pozycjach jednej i drugiej liczby mamy tylko jedną jedynkę to binarna różnica symetryczna liczb będzie miała na tej samej pozycji jedynkę binarną. W pozostałych przypadkach mamy 0 binarne. Dostajemy zatem liczbę 110100, co po przeliczeniu na system dziesiętny daje liczbę 52 Ad. 4 Zmienna typu unsigned int zajmuje w pamięci 4B=32 bity. Uzupełniamy liczbę x=6 (110) zerami z lewej strony aby miała długość 32 bity. 11 Kurs C++ 50 ~ 50 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 1 0 ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 1 1 0 1 Jeśli na tych samych pozycjach jednej i drugiej liczby mamy tylko jedną jedynkę to binarna różnica symetryczna liczb będzie miała na tej samej pozycji jedynkę binarną. W pozostałych przypadkach mamy 0 binarne. Dostajemy zatem liczbę 11111111111111111111111111001101, co po przeliczeniu na system dziesiętny daje liczbę 4294967245 Ad. 5 50 50<<6 1 1 0 0 1 0 1 0 1 0 0 0 0 0 1 0 0 0 Bitowe przesunięcie o liczbę 6 w lewo polega na dopisaniu 6 zer z prawej strony liczby przesuwanej. Dostajemy zatem liczbę 110010000000, co po przeliczeniu na system dziesiętny daje liczbę 3200 Ad. 6 50 50>>6 1 0 1 0 0 0 0 0 1 0 0 0 Bitowe przesunięcie o liczbę 6 w prawo polega na usunięciu z prawej strony 6 cyfr liczby przesuwanej. Dostajemy zatem liczbę 000000, co po przeliczeniu na system dziesiętny daje liczbę 0. 9. Funkcje Funkcja to podprogram, który jest realizowany w chwili wywołania. Po zakończeniu wykonywania funkcji sterowanie jest przekazane do kolejnej linii kodu programu (po linii w której następuje wywołanie funkcji). Konstrukcja funkcji: typ_danych nazwa_fun(typ_zmiennej_1 zmienna_1, typ_zmiennej_2 zmienna_2,…) Przykład 9.1. Mnożenie dwóch liczb #include <iostream> using namespace std; float mnozenie(float x, float y) { return x*y; } int main() { float x, y; cout << „Podaj 1 liczbe: “; cin >> x; 12 Kurs C++ cout << „Podaj 2 liczbe: “; cin >> y; cout << „Iloczyn liczb ” << x << „ i ” << y << „ to ” << mnozenie(x,y); } Przykład 9.2 Mnożenie dwóch liczb (typ void) #include <iostream> using namespace std; void mnozenie(float x, float y) { cout << "Iloczyn liczb " << x << " i " << y << " to " << x*y; } int main() { float x, y; cout << "Podaj 1 liczbe: "; cin >> x; cout << "Podaj 2 liczbe: "; cin >> y; mnozenie(x,y); } Typ void oznacza, że funkcja nie zwraca wartości (jak ma to miejsce w funkcjach typu całkowitego lub rzeczywistego). 10. Instrukcje warunkowe Występują dwa typy funkcji warunkowej: a) instrukcja niepełna (wybór niepełny): if(warunek) { lista_instrukcji; } b) instrukcja pełna (wybór pełny) if(warunek) { lista_instrukcji; } else { lista_instrukcji_2; } Instrukcje warunkowe można zagnieżdżać. 13 Kurs C++ Przykład 10.1 Sprawdzanie, czy liczba jest parzysta #include <iostream> using namespace std; int main() { int x; cout << "Podaj liczbe: "; cin >> x; if(x%2==0) { cout << „Liczba ” << x << “ jest parzysta”; } else { cout << „Liczba ” << x << “ nie jest parzysta”; } } Przykład 10.2 Zagnieżdżanie instrukcji warunkwych #include <iostream> using namespace std; int main() { int x; cout << "Podaj liczbe: "; cin >> x; if(x==1) { cout << „Wpisano jedynke”; } else { if(x==2) { cout << „Wpisano liczbe dwa”; } else { cout << „Wpisano inna liczbe niz jeden i dwa”; } } } 11. Instrukcja switch Instrukcja swich pozwala przetestować i wybrać (w przypadku spełnienia warunku) spośród wielu dostępnych wartości. Konstrukcja switch: 14 Kurs C++ switch(zmienna) { case 1_wartosc_zmiennej: lista_instrukcji_1; break; case 2_wartosc_zmiennej: lista_instrukcji_2; break; ... case n_wartosc_zmiennej: lista_instrukcji_n; break; default: inna_lista_instrukcji; } Przykład 11.1. Kalkulator #include <iostream> using namespace std; int main() { float x,y; char dzialanie; cout << "Podaj 1 liczbe: "; cin >> x; cout << "Podaj 2 liczbe: "; cin >> y; cout << "Podaj rodzaj dzialania (+,-,*,/): "; cin >> dzialanie; switch(dzialanie) { case ‘+’: cout << „Suma liczb wynosi „ << x+y; break; case ‘-’: cout << „Roznica liczb wynosi „ << x-y; break; case ‘*’: cout << „Iloczyn liczb wynosi „ << x*y; break; case ‘/’: cout << „Iloraz liczb wynosi „ << x/y; break; default: cout << „Dzialanie zle okreslone „ ; } } 15 Kurs C++ Przykład 11.2. Sprawdzanie ile wynosi reszta z dzielenia wprowadzonej liczby przez 4. #include <iostream> using namespace std; int main() { int x,y; cout << "Podaj liczbe naturalna: "; cin >> x; y=x%4; cout << „Reszta z dzielenia liczby „ << x << „ przez 4 wynosi „; switch(y) { case 1: cout << „jeden”; break; case 2: cout << „dwa”; break; case 3: cout << „trzy”; break; default: cout << „zero”; } } 12. Pętla while i do while a) Pętla while Pętla while jest pętlą 0-∞-krotną, tzn. może nie być wykonana ani razu (przy odpowiednim warunku). Lista instrukcji jest wykonywana tylko w przypadku spełnienia określonego warunku (lub warunków) zdefiniowanego na początku pętli. Konstrukcja: while (warunek) { lista instrukcji; } Przykład 12.1. Sumowanie liczb naturalnych od 1 do n #include <iostream> using namespace std; int main() { unsigned int n,i,s; cout << „Podaj liczbe naturalna wieksza od 1: „; cin >> n; i=1; 16 Kurs C++ s=0; while(i<=n) { s=s+i; i=i+1; } cout << „Suma liczb naturalnych od 1 do „ << n << „ wynosi „ << s; } b) Pętla do while Pętla do while jest pętlą 1-∞-krotną, tzn. musi być wykonana co najmniej raz. Przy pierwszym obiegu pętli najpierw jest wykonywana lista instrukcji, a dopiero potem jest sprawdzany warunek. Jeśli warunek jest spełniony, to następuje drugi obieg pętli, itd. Konstrukcja: do { lista instrukcji; } while (warunek); Przykład 12.2. Sumowanie liczb naturalnych od 1 do n (ze sprawdzaniem czy n jest większe od 1) #include <iostream> using namespace std; int main() { int n,i,s; do { cout << „Podaj liczbe naturalna wieksza od 1: „; cin >> n; } while (n<=1); i=1; s=0; while(i<=n) { s=s+i; i=i+1; } cout << „Suma liczb naturalnych od 1 do „ << n << „ wynosi „ << s; } 13. Pętla for Pętla for jest pętlą iteracyjną (krokową). Konstrukcja: 17 Kurs C++ for(instrukcja_poczatkowa; warunek; instrukcja_krokowa) { lista_instrukcji; } instrukcja_poczatkowa polega z reguły na przypisaniu wartości początkowej pewnej zmiennej z opcjonalnym określeniem typu zmiennej; warunek określa sprawdzany na początku, a potem w trakcie pętli warunek decydujący o ponownym wykonaniu (lub pierwszym wykonaniu) instrukcji zawartych w pętli; instrukcja_krokowa określa krok pętli (rosnący lub malejący); Przykład 13.1. Program wypisujący liczby naturalne od 1 do n #include <iostream> using namespace std; int main() { unsigned int n,i; cout << „Podaj liczbe naturalna wieksza od 1: „; cin >> n; for(i=1;i<=n;i++) { cout << i << ”,”; } } Przykład 13.2. Program sprawdzający, czy liczba jest pierwsza. #include <iostream> using namespace std; int main() { unsigned int n,i,t; cout << „Podaj liczbe naturalna wieksza od 1: „; cin >> n; t=0; for(i=2;i<n;i++) { if(n%i!=0) { t=t+1; } } if(t==n-2) { cout << „Liczba „ << n << „ jest pierwsza”; } else { 18 Kurs C++ cout << „Liczba „ << n << „ nie jest pierwsza”; } } 14. Typ tablicowy a) Tablice jednowymiarowe Aby zadeklarować tablicę należy podać jej typ (typ danych zawartych w tablicy), nazwę (identyfikator) i rozmiar. Elementy w tablicy są numerowane od zera. Deklaracja tablicy: typ nazwa_tablicy[ilosc_elementow]; Np. deklaracja int tab[4] oznacza tablicę składającą się z 4 elementów całkowitych mających postać: tab[0], tab[1], tab[2], tab[3]. Przykład 14.1. Wypełnianie i wypisywanie elementów tablicy za pomocą pętli #include <iostream> using namespace std; int main() { int i; int tab[5]; for(i=0;i<=4;i++) { cout << “Podaj “ << i+1 << “ element tablicy: “; cin >> tab[i]; } for(i=0;i<=4;i++) { cout << i+1 << „ element tablicy jest rowny “ << tab[i] << “\n“; } } Jeśli chcemy zadeklarować tablicę z wypełnionymi wartościami, to używamy zapisu: typ nazwa_tablicy[]={element_1, element_2, ..., element_n}; W tym wypadku nie musimy podawać wymiaru tablicy. Przykład 14.2. Wypisanie elementów zadeklarowanej (wypełnionej) tablicy. #include <iostream> using namespace std; int main() { int i; int tab[]={2,3,5,6,7}; 19 Kurs C++ for(i=0;i<=4;i++) { cout << i+1 << „ element tablicy jest rowny “ << tab[i] << “\n“; } } Przykład 14.3 #include <iostream> using namespace std; int main() { int i; char decyzja; char tab[]={‘a’,’b’,’c’,’d’,’e’,’f’,’g’,’h’,’i’,’j’,’k’,’l’,’m’,’n’,’o’,’p’, ’q’,’r’,’s’,’t’,’u’,’v’,’w’,’x’,’y’,’z’}; do { do { cout << “Podaj liczbe od 1 do 26: “; cin >> i; } while((i<1)||(i>26)); cout << i << „ litera alfabetu to „ << tab[i-1] << „\n”; cout << „Jesli chcesz sprawdzic kolejna litere wcisnij \”t\”: „; cin >> decyzja; } while(decyzja==’t’); } b) Tablice wielowymiarowe Tablica wielowymiarowa jest zbiorem tablic jednowymiarowych, tzn. elementami tablicy są tablice. Deklaracja tablicy wielowymiarowej: typ nazwa_tablicy[wymiar_1][wymiar_2]; Np. zapis int tab[3][2] oznacza deklarację tablicy składającej się z 3 tablic, z których każda zawiera 2 elementy. Jej elementami są: tab[1][1], tab[1][2], tab[2][1], tab[2][2], tab[3][1], tab[3][2]. Przykład 14.4 Wprowadzanie imion i nazwisk do bazy (za pomocą pętli) i szukanie osób w bazie o podanym nazwisku. #include <iostream> using namespace std; 20 Kurs C++ int main() { int i,j,s; string tab[5][2]; string nazw; for(i=0;i<=4;i++) { for(j=0;j<=1;j++) { if (j==0) { cout << “Podaj “ << i+1 << “ imie ”; } else { cout << “Podaj “ << i+1 << “ nazwisko ”; } cin >> tab[i][j]; } } cout << „Podaj nazwisko: „; cin >> nazw; s=0; for(i=0;i<=4;i++) { if (tab[i][1]==nazw) { cout << tab[i][0] << „\n”; s=s+1; } } if(s==0) { cout << „Nie ma osob o podanym nazwisku”; } } 15. Struktury danych Struktura służy do operowania zbiorami danych różnych typów (tekst, liczba). Jeśli chcemy przechować dane różnych typów używamy struktury definiując z osobna jej poszczególne elementy. Deklaracja struktury: struct nazwa_struktury { typ_1 element_1; typ_2 element_2; ... typ_n element_n; }; 21 Kurs C++ Przykład 15.1. Struktura #include <iostream> using namespace std; struct sam { string marka_model; int rok_prod; }; int main() { sam peugeot={“Peugeot 106”,2000}; sam skoda={“Skoda Octavia”,2010}; cout << peugeot.marka_model << “\n”; cout << peugeot.rok_prod << “\n”; } Przykład 15.2. Tablica struktur (tablica typu strukturalnego) #include <iostream> using namespace std; struct sam { string marka_model; int rok_prod; }; int main() { int i; sam tab[3]={{“Peugeot 106”,2000}, {“Skoda Octavia”,2010}, {“Honda Civic”,2003}}; cout << „Dostepne sa samochody: “ << “\n”; for(i=0;i<=2;i++) { cout << tab[i].marka_model << „\n”; } } Przykład 15.2. Baza danych - tablica struktur (tablica typu strukturalnego) #include <iostream> using namespace std; struct sam { string marka; string model; 22 Kurs C++ int int int int rok; poj; przebieg; cena; }; int main() { int i,k,pmax,pmin,szukanie,rmin,rmax,prmin,prmax,cmin,cmax; string szukanamarka, szukanymodel; char decyzja; sam tab[20]={ {"Peugeot", "106",2000,1000,115000,5000}, {"Opel", "Astra",1995, 1600, 104000, 4000}, {"Fiat","Cinquecento",1993, 700, 105000, 3000}, {"Audi", "80", 1990, 1600, 340000, 2500}, {"Opel", "Astra", 1998, 1600, 198000, 10500}, {"Fiat", "Panda", 2004, 1100, 40000, 10000}, {"Toyota", "Yaris", 2010, 1400, 10000, 40000}, {"Renault", "Megane", 1998, 1400, 140500, 5000}, {"Opel", "Astra", 1996, 1600, 235000, 3000}, {"VW", "Golf II", 1992, 1800, 210000, 2500}, {"Skoda", "Fabia", 2009, 1600, 20000, 35000}, {"Mercedes", "A170", 2005, 1600, 90000, 25000}, {"Mitsubishi", "Lancer", 2009, 1800, 30000, 40000}, {"Subaru","Impreza", 2010, 2500, 1000, 50000}, {"Mazda", "RX-8", 2008, 1300, 45000, 60000}, {"Bugatti", "Veyron", 2009, 8000, 10000,3500000}, {"Porsche", "911", 2009, 4500, 6000, 150000}, {"Fiat", "125p", 1985, 1300, 150000, 1500}, {"BMW", "M3", 2010, 4000, 20000, 200000}, {"Ford", "Fusion", 2010, 1600, 1000, 45000} }; do { system("cls"); cout << "Podaj kryterium wyszukiwania \n 1-marka \n 2-model \n 3rok produkcji \n 4-pojemnosc \n 5-przebieg \n 6-cena \n Wybieram: "; cin >> szukanie; switch(szukanie) { case 1: { cout << "Podaj marke samochodu: "; cin >> szukanamarka; k=0; for (i=0;i<=19;i++) { if (tab[i].marka==szukanamarka) { 23 Kurs C++ cout << tab[i].marka << " " << tab[i].model << ", rok produkcji: " << tab[i].rok << "r" << ", pojemnosc: " << tab[i].poj << " cm3" << ", przebieg: " << tab[i].przebieg << " km" << ", cena: " << tab[i].cena << " zl" << "\n"; k=k+1; } } if (k==0) cout << "Nic nie znaleziono" << "\n"; break; } case 2: { cout << "Podaj model samochodu: "; cin >> szukanymodel; k=0; for (i=0;i<=19;i++) { if (tab[i].model==szukanymodel) { cout << tab[i].marka << " " << tab[i].model << ", rok produkcji: " << tab[i].rok << "r" << ", pojemnosc: " << tab[i].poj << " cm3" << ", przebieg: " << tab[i].przebieg << " km" << ", cena: " << tab[i].cena << " zl" << "\n"; k=k+1; } } if (k==0) cout << "Nic nie znaleziono" << "\n"; break; } case 3: { cout << "Podaj rok produkcji min: "; cin >> rmin; cout << "Podaj rok produkcji max: "; cin >> rmax; k=0; for (i=0;i<=19;i++) { if ((tab[i].rok>=rmin) && (tab[i].rok<=rmax)) { cout << tab[i].marka << " " << tab[i].model << ", rok produkcji: " << tab[i].rok << "r" << ", pojemnosc: " << tab[i].poj << " cm3" << ", przebieg: " << tab[i].przebieg << " km" << ", cena: " << tab[i].cena << " zl" << "\n"; k=k+1; } 24 Kurs C++ } if (k==0) cout << "Nic nie znaleziono" << "\n"; break; } case 4: { cout << "Podaj pojemnosc min: "; cin >> pmin; cout << "Podaj pojemnosc max: "; cin >> pmax; k=0; for (i=0;i<=19;i++) { if ((tab[i].poj>=pmin) && (tab[i].poj<=pmax)) { cout << tab[i].marka << " " << tab[i].model << ", rok produkcji: " << tab[i].rok << "r" << ", pojemnosc: " << tab[i].poj << " cm3" << ", przebieg: " << tab[i].przebieg << " km" << ", cena: " << tab[i].cena << " zl" << "\n"; k=k+1; } } if (k==0) cout << "Nic nie znaleziono" << "\n"; break; } case 5: { cout << "Podaj przebieg min: "; cin >> prmin; cout << "Podaj przebieg max: "; cin >> prmax; k=0; for (i=0;i<=19;i++) { if ((tab[i].przebieg>=prmin) && (tab[i].przebieg<=prmax)) { cout << tab[i].marka << " " << tab[i].model << ", rok produkcji: " << tab[i].rok << "r" << ", pojemnosc: " << tab[i].poj << " cm3" << ", przebieg: " << tab[i].przebieg << " km" << ", cena: " << tab[i].cena << " zl" << "\n"; k=k+1; } } if (k==0) cout << "Nic nie znaleziono" << "\n"; break; 25 Kurs C++ } case 6: { cout << "Podaj cene min: "; cin >> cmin; cout << "Podaj cene max: "; cin >> cmax; k=0; for (i=0;i<=19;i++) { if ((tab[i].cena>=cmin) && (tab[i].cena<=cmax)) { cout << tab[i].marka << " " << tab[i].model << ", rok produkcji: " << tab[i].rok << "r" << ", pojemnosc: " << tab[i].poj << " cm3" << ", przebieg: " << tab[i].przebieg << " km" << ", cena: " << tab[i].cena << " zl" << "\n"; k=k+1; } } if (k==0) cout << "Nic nie znaleziono" << "\n"; break; } default: cout << "Zle kryterium wyszukiwania"; } cout << "\n" << "Jesli chcesz wyszukac ponownie wciscij \"t\": "; cin >> decyzja; } while(decyzja=='t'); } 16. Klasy Klasa służy do operowania zbiorami danych różnych typów (składowe klasy) przydzielając im różne uprawnienia (etykiety): public, private, protected oraz zezwala na implementowanie funkcji składowych operujących na składowych tej klasy. Deklaracja klasy: class nazwa_klasy { private: typy_składowych_1 lista_składowych_1; funkcje_1; public: typy_składowych_2 lista_składowych_2; funkcje_2; }; Obiekt – grupa składowych klasy wraz z funkcjami odnoszącymi się do tych składowych Funkcja składowa – funkcja wchodząca w skład klasy 26 Kurs C++ Przykład 16.1. Program „Przedstaw się”. #include<iostream> using namespace std; //deklaracja klasy class osoba { //deklaracja składowych wraz z atrybutami public: string imie; string nazwisko; int wiek; void przedstawsie(); }; //definiowanie składowej funkcyjnej void osoba::przedstawsie() { cout << "Nazywam sie " << imie << " " << nazwisko << endl; cout << "Mam " << wiek << " lat." << endl; } int main() { //tworzenie obiektów osoba czlowiek1; osoba czlowiek2={"Adam","Nowak",30}; czlowiek1.imie="Jan"; czlowiek1.nazwisko="Kowalski"; czlowiek1.wiek = 40; //wywołanie funkcji czlowiek1.przedstawsie(); czlowiek2.przedstawsie(); system("Pause"); } Przykład 16.2. Tablica klas– baza danych „Osoby” #include<iostream> using namespace std; class osoba { public: string imie; string nazwisko; int wiek; void dane(); }; void osoba::dane() { cout << imie << ", " << nazwisko << ", " << wiek << " lat" << endl; } 27 Kurs C++ int main() { int s; // tworzenie tablicy obiektów klasy osoba // każdy obiekt klasy będzie miał postać czlowiek[i] osoba czlowiek[5]={ {"Jan", "Kowalski" ,30}, {"Adam", "Nowak", 40}, {"Marcin", "Krol", 27}, {"Pawel", "Brodziak", 19}, {"Dariusz", "Sukiennik", 19} }; cout << "Ktora osobe chcesz wyszukac? "; cin >> s; cout << s << " osoba w bazie to " ; // wywołanie funkcji czlowiek[s-1].dane(); system("Pause"); } Przykład 16.3. Tablica klas– baza danych „Osoby 2” #include<iostream> using namespace std; class osoba { public: string imie; string nazwisko; int wiek; void dane(); }; void osoba::dane() { cout << imie << ", " << nazwisko << ", " << wiek << " lat" << endl; } int main() { string szukane; int wybor, wiekmin, wiekmax; osoba czlowiek[15]={ {"Jan", "Kowalski" ,30}, {"Adam", "Nowak", 40}, {"Marcin", "Krol", 27}, {"Pawel", "Brodziak", 19}, {"Adam", "Mickiewicz", 52}, {"Rychu", "Peja", 30}, {"Arnold", "Boczek", 55}, {"Ferdek", "Kiepski", 54}, 28 Kurs C++ {"Marian", "Pazdzioch", 60}, {"John", "Rambo", 40}, {"Dzoana", "Krupa", 31}, {"Kuba", "Gminny", 45}, {"Adam", "Kurc", 35}, {"Turbo", "Dymomen", 25}, {"Super", "S", 40}, }; cout << "Podaj kryterium wyszukiwania (1-imie, 2-nazwisko, 3-wiek):" ; cin >> wybor; switch(wybor) { case 1: { cout << "Podaj imie: "; cin >> szukane; int k=0; for(int i=0;i<15;i++) { if(czlowiek[i].imie==szukane) { czlowiek[i].dane(); k++; } } if (k==0) cout << "Nie ma osoby o podanym imieniu \n"; } break; case 2: { cout << "Podaj nazwisko: "; cin >> szukane; int k=0; for(int i=0;i<15;i++) { if(czlowiek[i].nazwisko==szukane) { czlowiek[i].dane(); k++; } } if (k==0) cout << "Nie ma osoby o podanym nazwisku \n"; } break; case 3: { cout << "Podaj wiek min: "; 29 Kurs C++ cin >> wiekmin; cout << "Podaj wiek max: "; cin >> wiekmax; int k=0; for(int i=0;i<15;i++) { if((czlowiek[i].wiek>=wiekmin)&&(czlowiek[i].wiek<=wiek max)) { czlowiek[i].dane(); k++; } } if (k==0) cout << "Nie ma osoby o podanym wieku \n"; } break; default: cout << "Zle kryterium wyszukiwania \n"; } system("Pause"); } 17. Hermetyzacja Hermetyzacja (kapsułkowanie) - ukrywaniu pewnych danych składowych lub funkcji składowych danej klasy tak, aby były one dostępne tylko funkcjom z nią zaprzyjaźnionym. O hermetyzacji mówimy, gdy wszystkie pola w klasie znajdują się w sekcji prywatnej. Przykład 17.1. Program „Bankomat” #include<iostream> using namespace std; class bankomat { private: int pin; int saldo; public: int uwierzytelnij(int pinnew); int zapamietaj(int pinnew, int saldonew); }; int bankomat::zapamietaj(int pinnew, int saldonew) { pin=pinnew; saldo=saldonew; }; 30 Kurs C++ int bankomat:: uwierzytelnij(int pinnew) { if (pinnew==pin) { cout << "Twoje saldo wynosi " << saldo; } } int main() { int pinnew,i,k; bankomat klient[100]; klient[0].zapamietaj(11,1000); klient[1].zapamietaj(12,2000); cout << "Podaj pin: "; cin >> pinnew; for (i=0;i<=1;i++) { klient[i].uwierzytelnij(pinnew); } system("Pause"); } 18. Konstruktor i destruktor Konstruktor i destruktor to funkcje składowe klasy. Konstruktor ma taką samą nazwę jak nazwa klasy, a jego zadaniem jest budowanie obiektów swojej klasy. Takie budowanie obiektu powoduje, że komputer przydziela obiektowi pamięć i przypisuje wartości do niestatycznych zmiennych składowych. Jeśli w klasie nie zadeklarowano konstruktora to zostaną one stworzone automatycznie przez kompilator i użyte w chwili tworzenia obiektu. W ciele konstruktora możemy nadać tworzonemu obiektowi wartości początkowe. Obiekt podczas tworzenia za pomocą domyślnego konstruktora nie ma przypisanych wartości początkowych dla swoich składowych. Destruktor to funkcja, która ma nazwę taką samą jak klasa, której dotyczy i jest poprzedzona znakiem ~. Destruktor nie ma parametrów. Jest wywoływany zawsze automatycznie, gdy obiekt jest usuwany. Zadaniem destruktora jest zwalnianie rezerwowanej dynamicznie podczas tworzenia obiektów pamięci (dodatkowej pamięci zarezerwowanej podczas tworzenia obiektu). Destruktor ma za zadanie wykonać czynności składające się na usunięcie obiektu (np. poinformowanie o usuwaniu obiektu) ale sam nie usuwa obiektu i nie zwalnia miejsca w pamięci po usunięciu obiektu. Przykład 18.1. Nadawanie wartości początkowych tworzonemu obiektowi za pomocą konstruktora #include<iostream> using namespace std; class samochod { private: string rok; string marka; public: string model; 31 Kurs C++ string przebieg; samochod(); }; samochod::samochod() { cout << "Do tej pory nasz obiekt ma dane: \n"; cout << "\n Marka: " << marka; cout << "\n Rocznik: " << rok; cout << "\n Przebieg: " << przebieg; cout << "\n Model: " << model; cout << "\n \n Teraz konstruktor nadaje poczatkowe wartosci danemu obiektowi: \n"; marka="Peugeot"; model="106"; rok="2000"; przebieg="120000"; cout << "\n Konstruktor nadal wartosci: \n"; cout << "\n Marka: " << marka; cout << "\n Model: " << model; cout << "\n Rocznik: " << rok; cout << "\n Przebieg: " << przebieg; } int main() { samochod PEUGEOT; cout << "\n-----------------------------"; cout << "\n Przypisanie nowej wartosci do skladowej model i przebieg \n"; PEUGEOT.model="206"; PEUGEOT.przebieg="65000"; cout << "\n Teraz model to: " << PEUGEOT.model << " i przebieg to: " << PEUGEOT.przebieg << "\n\n"; system("pause"); } Przykład 18.2. Nadawanie wartości początkowych tworzonemu obiektowi za pomocą konstruktora i informowanie za pomocą destruktora o usunięciu obiektu po skończeniu programu #include<iostream> using namespace std; class samochod { private: string rok; string marka; public: string model; string przebieg; samochod(); ~samochod(); 32 Kurs C++ }; samochod::samochod() { cout << "Do tej pory nasz obiekt ma dane: \n"; cout << "\n Marka: " << marka; cout << "\n Rocznik: " << rok; cout << "\n Przebieg: " << przebieg; cout << "\n Model: " << model; cout << "\n \n Teraz konstruktor nadaje poczatkowe wartosci danemu obiektowi: \n"; marka="Peugeot"; model="106"; rok="2000"; przebieg="120000"; cout << "\n Konstruktor nadal wartosci: \n"; cout << "\n Marka: " << marka; cout << "\n Model: " << model; cout << "\n Rocznik: " << rok; cout << "\n Przebieg: " << przebieg; } samochod::~samochod() { cout << “\n Obiekt PEUGEOT zostal zniszczony \n”; } int main() { samochod PEUGEOT; cout << "\n-----------------------------"; cout << "\n Przypisanie nowej wartosci do skladowej model i przebieg \n"; PEUGEOT.model="206"; PEUGEOT.przebieg="65000"; cout << "\n Teraz model to: " << PEUGEOT.model << " i przebieg to: " << PEUGEOT.przebieg << "\n\n"; PEUGEOT.~samochod(); system("pause"); } 19. Zagnieżdżona definicja klasy Z zagnieżdżoną definicją klasy mamy do czynienia, gdy wewnątrz jednej klasy definiujemy inną klasę (klasa w klasie). Konstrukcja: class klasa_1 { private: skladowe_klasy_1; public: skladowe_klasy_1; class klasa_2 33 Kurs C++ { private: skladowe_klasy_2; public: skladowe_klasy_2 }; }; Przykład 19.1. Konstruktory zagnieżdżonych klas #include<iostream> using namespace std; class motocykl { public: int rok; string producent; string model; motocykl(); class kierowca { public: int wiek; string imie; kierowca(); }; }; motocykl::motocykl() { producent="Romet"; model="Komar"; rok=1965; cout << "\n Konstruktor nadal wartosci poczatkowe: \n"; cout << "\n Producent: " << producent; cout << "\n Model: " << model; cout << "\n Rok produkcji: " << rok; } motocykl::kierowca::kierowca() { wiek=60; imie="Rajmund"; cout << "\n Imie kierowcy: " << imie; cout << "\n Wiek kierowcy: " << wiek << " lat"; } int main() { 34 Kurs C++ motocykl MOTOR1; motocykl::kierowca KIEROWCA1; cout << "\n -----------------------------"; cout << "\n Motocyklem " << MOTOR1.producent << ", "; cout << "\n model: " << MOTOR1.model << ", "; cout << "\n rok: " << MOTOR1.rok << ", "; cout << "\n jedzie kierowca o imieniu " << KIEROWCA1.imie; cout << "\n i ma on " << KIEROWCA1.wiek << " lat \n \n"; system("Pause"); } 20. Przeciążenie funkcji W języku C++ możliwe jest utworzenie wielu funkcji mających tą samą nazwę. W tym wypadku identyfikator funkcji określamy jako przeciążony. Podczas wywołania funkcji wykonana jest ta funkcja do której „pasują” parametry (typy zmiennych) i ilość parametrów. Przykład 20.1. Przeciążenie funkcji #include<iostream> using namespace std; int funkcja_przeciazona(int x, int y, int z) { return x*y*z; } void funkcja_przeciazona(string imie, int wiek) { cout << „Mam na imie „ << imie << „ i mam „ << wiek << „ lat.”; } int main() { cout << funkcja_przeciazona(3,4,5) << „\n”; funkcja_przeciazona(„Marcin”,27); } 21. Przeciążenie operatorów Przeciążenie operatorów (przeładowanie operatorów) ma miejsce, gdy operatorom nadajemy nowe funkcje. Konstrukcja: typ_zwracany operator@(argumenty) { cialo_funkcji } gdzie @ oznacza odpowiedni operator. 35 Kurs C++ Tabela 20.1. Lista operatorów, które mogą być przeładowane + * / $ ^ & | ~ ! = < > += -= *= /= %= ^= &= |= >> << >>= <<= == != >= <= && || ++ -- ->* -> new delete () [] , Przeładowanie może nadać operatorowi dowolne znaczenie. Nie można zmienić argumentowości operatorów (np / musi być zawsze operatorem dwuargumentowym). Przynajmniej jeden z argumentów funkcji operatora musi być typu zdefiniowanego przez użytkownika. Przykład 20.1. Przeciążenie operatorów #include<iostream> using namespace std; class liczba { public: int a; int b; liczba(int wartosc=0); liczba operator+(int); }; liczba::liczba(int wartosc) { a=wartosc; b=wartosc; } liczba liczba::operator+(int zmiana) { liczba rezultat; rezultat.a=a+zmiana; rezultat.b=b+2*zmiana; return rezultat; } int main() { liczba pierwszaliczba(1); liczba drugaliczba; drugaliczba=pierwszaliczba+100; cout << "Pierwsza skladowa pierwszej liczby ma wartosc " << pierwszaliczba.a << endl; cout << "Druga skladowa pierwszej liczby ma wartosc " << pierwszaliczba.b << endl; cout << "------------------------------------------------------\n"; cout << "Pierwsza skladowa drugiej liczby ma wartosc " << drugaliczba.a << endl; cout << "Druga skladowa drugiej liczby ma wartosc " << drugaliczba.b << endl; cout << "------------------------------------------------------\n"; 36 Kurs C++ drugaliczba=drugaliczba+200; cout << "A teraz pierwsza skladowa drugiej liczby ma wartosc " << drugaliczba.a << endl; cout << "Druga skladowa drugiej liczby ma wartosc " << drugaliczba.b << endl; } 21. Zapis i odczyt pliku Przykład 21.1. Zapis do pliku tekstowego #include<iostream> #include<fstream> using namespace std; int main() { ofstream zapisywanie; //tworzenie obiektu ‘zapisywanie’ //należącego do klasy fstream cout << "Zapisuje do pliku \n"; zapisywanie.open("plik.txt",ios::out);//skojarzenie obiektu //‘zapisywanie’ z plikiem //‘plik.txt’, plik nie musi //istniec (zostanie utworzony, gdy //nie istnieje lub zostanie //nadpisany, gdy istnieje) zapisywanie << "Test zapisu do pliku"; //zapisanie tekstu do pliku zapisywanie.close(); //zamkniecie polaczenia z plikiem ‘plik.txt’ cout << "Zapisalem \n"; system("pause"); } Przykład 21.2. Odczyt z pliku tekstowego #include<iostream> #include<fstream> using namespace std; int main() { char notatka; ifstream czytanie; //tworzenie obiektu ‘czytanie’ należącego //do klasy fstream cout << "Odczytuje z pliku \n"; czytanie.open("plik.txt", ios::in); //skojarzenie obiektu ‘czytanie’ //z plikiem ‘plik.txt’ czytanie >> noskipws >> notatka; //wczytanie pierwszego znaku //z obiektu ‘czytanie’ do zmiennej //notatka (manipulator ‘noskipws’ //„nakazuje” pobierac spacje) while (!czytanie.eof()) //petla sprawdzajaca, czy osiagnelismy 37 Kurs C++ //koniec pliku (funcja eof()), zamiast //‘(!czytanie.eof()’ mozna uzyc zapisu //‘(czytanie.good()’ { cout << notatka; czytanie >> noskipws >> notatka; }; czytanie.close(); //zamkniecie polaczenia z plikiem ‘plik.txt’ cout << "\n Przeczytalem \n"; system("pause"); } Kojarzenie obiektu klasy fstream z plikiem przebiega według schematu: fstream obiekt; obiekt.open(polozenie_i_nazwa_pliku,ios::tryb); W przypadku nie podania trybu dla obiektu klasy ifstream domyślnym trybem jest in (czytanie istniejącego pliku), a dla obiektu klasy ofstream – out (tworzenie lub nadpisanie pliku) Tabela 21.1. Tryby klasy ios Tryb ios::in ios::out ios::ate ios::app Funkcja czytanie istniejącego pliku tworzenie nowego pliku lub nadpisanie istniejącego ustawienie wskaźnika na koniec pliku dopisanie do pliku 22. Dziedziczenie Przykład 22.1. Dziedziczenie składowej klasy podstawowej przez klasę pochodną #include<iostream> using namespace std; class samochod { public: string producent; samochod(); ~samochod(); }; class autobus:public samochod { public: autobus(); ~autobus(); }; samochod::samochod() { producent="Peugeot"; 38 Kurs C++ } autobus::autobus() { producent="Jelcz"; } samochod::~samochod() { cout << "Peugeot zostal skasowany"; } autobus::~autobus() { cout << "Jelcz zostal skasowany"; } int main() { autobus nowy; cout << nowy.producent; system("pause"); } 23 Polimorfizm Polimorfizm to różnorodność zachowania się metody (funkcji) w zależności od obiektu dla którego zostaje wykonana (obiektu klasy podstawowej lub pochodnej). 24. Unie Unia to typ danych pozwalający przechowywać zmienne różnego typu, ale tylko jedną wartość w danej chwili. Deklaracja unii: union nazwa_unii { skladowe_unii; }; Przykład 24.1 #include<iostream> #include<string> using namespace std; union rower { int numer_pasazera; char imie_pasazera; }; int main() { rower BMX, Salto; 39 Kurs C++ BMX.numer_pasazera=1; Salto.numer_pasazera=2; cout << "Rowerami jada pasazerowie o numerach " << BMX.numer_pasazera; cout << " i " << Salto.numer_pasazera; BMX.imie_pasazera='M'; Salto.imie_pasazera='A'; cout << "\n Teraz rowerami jada " << BMX.imie_pasazera; cout << " i " << Salto.imie_pasazera; cout << "\n Rowerem Salto dalej jedzie " << Salto.numer_pasazera; system("pause"); } 25. Pola bitowe Pola bitowe wykorzystujemy, gdy chcemy ograniczyć pamięć (zajmowane miejsce w pamięci) deklarowanych typów zmiennych. Konstrukcja: typ_zmiennej nazwa_zmiennej : ilosc_bitow; Przykład 25.1 #include<iostream> using namespace std; struct test_pola_bitowego { unsigned int obwod1 :4; int obwod2 : 4; }; int main() { test_pola_bitowego kwadrat={15,15}; cout << "\n Dla unsigned int obwod wynosi " << kwadrat.obwod1; cout << "\n Dla int obwod wynosi " << kwadrat.obwod2; system("pause"); } 26. Wskaźniki Wskaźniki to zmienne nie przechowujące danych, a jedynie ich adresy w pamięci komputera (wskazuje początek zmiennej w pamięci). Aby określić adres zmiennej należy posłużyć się operatorem adresu &. Przykład 26.1 #include<iostream> using namespace std; int main() { unsigned int zmienna1=8; cout << “Adres zmiennej w pamieci komputera to “ << &zmienna1 << endl; 40 Kurs C++ cout << „Wartosc zmiennej to „ << zmienna << endl; } Do wskaźnika można przypisać adres konkretnego typu zmiennej. Aby zadeklarować wskaźnik do przechowywani adresu zmiennej korzystamy z zapisu: typ_zmiennej *nazwa_wskaznika=0; Wskaźnik, którego wartość jest równa 0 określany jest jako null, tzn. nie wskazuje na żaden obiekt. aby przypisać do wskaźnika adres konkretnej zmiennej należy posłużyć się zapisem: typ_zmiennej=wartosc; typ_zmiennej *nazwa_wskaznika=0; nazwa_wskznika=&wartosc; np. unsigned int wiek=27; unsigned int *wwiek=0; wwiek=&wiek; //deklaracja zmiennej ‘wiek’ z wartoscia 27 //deklaracja zmiennej wskaznikowej ‘wwiek’ //z wartoscia null //przypisanie do wskaznika ‘wwiek’ adresu //zmiennej ‘wiek’ Operator dostępu pośredniego * może służyć do odczytywania i zmieniania wartości zmiennej przechowywanej pod adresem przechowywanym we wskaźniku, np. unsigned int wiek=27; unsigned int *wwiek=&wiek; unsigned int nowy_wiek; nowy_wiek=*wwiek; //deklaracja zmiennej ‘wiek’ z wartoscia 27 //deklaracja zmiennej wskaznikowej ‘wwiek’ //i przypisanie jej adresu zmiennej ‘wiek’ //deklaracja zmiennej ‘nowy_wiek’; //przypisanie zmiennej ‘nowy_wiek’ wartosci //zmiennej ‘wiek’ za pomoca operatora dostepu //posredniego * zmiennej wskaznikowej wwiek //(*zmienna_wskaznikowa oznacza wartosc //przechowywana pod adresem zmiennej //‘zmienna_wskaxnikowa’ Operator dostępu pośredniego jest wykorzystywany zatem w dwóch wariantach przy deklaracji zmiennej wskaźnikowej typ_zmiennej *nazwa_wskaznika=0; przy odczytywaniu lub zmianie wartości zmiennej nowa_zmienna=*stara_zmienna //przypisanie do zmiennej ‘nowa_zmienna’ //wartości przechowywanej pod adresem ///‘*stara_zmienna’ lub *stara_zmienna=nowa_zmienna //przypisanie wartosci ‘nowa_zmienna’ do //zmiennej wskazywanej przez wskaznik //‘stara_zmienna’ 41 Kurs C++ Przykład 26.2. Manipulowanie danymi za pomocą wskaźników #include<iostream> using namespace std; int main() { int mojwiek; //deklaracja zmiennej ‘mojwiek’; int *wwiek=0; //deklaracja zmiennej wskaznikowej ‘wwiek’ mojwiek=5; cout << “mojwiek: “ << mojwiek << “\n”; wwiek=&mojwiek; //przypisanie adresu zmiennej ‘mojwiek’ //do wskaznika ‘wwiek’ cout << „*wwiek: ” << *wwiek << „\n\n”; //wypisanie wartosci zmiennej //mojwiek za pomoca wartosci //wskaznika ‘wwiek’ *wwiek=7; //przypisanie wartosci zmiennej ‘mojwiek’ za pomoca //wskaznika ‘wwiek’ cout << „*wwiek: ” << *wwiek << „\n”; cout << „mojwiek: ” << mojwiek << „\n\n”; mojwiek=9; cout << „mojwiek: ” << mojwiek << „\n”; cout << „*wwiek: ” << *wwiek << „\n”; system(„pause”); } a) Zarządzanie pamięcią new Do rezerwacji pamięci służy słowo kluczowe new. Następuje po nim nazwa typu obiektu dla którego rezerwujemy pamięć. Dzięki temu kompilator wie, ile pamięci ma zarezerwować. Na przykład new unsigned short int; zarezerwuje 2 bajty na stercie (sterta – wolna pamięć programu nie przeznaczona na zmienne lokalne, kod programu, zmienne globalne, rejestry). Wartością zwracaną przez new jest adres w pamięci. Musi on być przypisany do wskaźnika. Aby stworzyć na stercie miejsce dla konkretnej zmiennej możemy użyć zapisu: typ_zmiennej *nazwawskaznika; wskaznik=new typ_zmiennej; np. unsigned short int *wskaznik; //deklaracja zmiennej wskaznikowej ‘wskaznik’ wskaznik=new unsigned short int; //przypisanie do zmiennej wskaznikowej //‘wskaznik’ nowego adresu w stercie //i zarezerwowanie odpowiedniego obszaru //pamieci lub zapisu skróconego 42 Kurs C++ unsigned short int *wskaznik = new unsigned short int; Zaletą sterty jest fakt, że pamięć w niej zarezerwowana jest dostępna tak długo, aż jej bezpośrednio nie zwolnimy (w przeciwieństwie do zmiennych lokalnych, które są automatycznie czyszczone z pamięci). delete Aby zwolnić pamięć na stercie należy użyć słowa kluczowego delete. Np. delete nazwa_wskaznika; Usuwając wskaźnik kasujemy pamięć wskazywaną przez ten wskaźnik. Taka pamięć będzie mogła być zarezerwowana przez kolejną instrukcję new. sam wskaźnik nadal istnieje i będzie mu można przypisać nowy adres. Przykład 26.3. Rezerwacja i zwalnianie pamięci #include<iostream> using namespace std; int main() { int zmiennalokalna=5; int *wzmiennalokalna=&zmiennalokalna; //deklaracja zmiennej wskaznikowej //’wzmiennalokalna’ i przypisanie //jej adresu zmiennej //‘zmiennalokalna’ int *wsterta=new int; //deklaracja zmiennej wskaznikowej ‘wstarta’ //i przypisanie dla niej nowego adresu //w stercie wraz z rezerwacja pamieci *wsterta=7; // przypisanie wartosci 7 do zmiennej wskazywanej przez //wskaznik ‘wsterta’ cout << „zmiennalokalna: ” << zmiennalokalna << „\n”; cout << „*wzmiennalokalna: ” << *wzmiennalokalna << „\n”; cout << „*wsterta: ” << *wsterta << „\n”; delete wsterta; //zwolnienie miejsca w pamieci dla wskaznika ‘wsterta’ wsterta=new int; //rezerwacja i przypisanie nowego obszaru //w pamieci dla wskaznika ‘wsterta’ *wsterta=9; cout << „*wsterta: ” << *wsterta << „\n”; delete wsterta; system(„pause”); } Aby nie tracić obszarów na stercie należy pamiętać o zwolnieniu obszaru zajmowanego (wskazywanego) przez wskaźnik po zakończeniu pracy ze wskaźnikiem. 43