Nowa wersja
|
Poprzednia wersja
|
pl:dydaktyka:jimp2:2017:labs:wprowadzenie [2017/02/25 12:56] 127.0.0.1 edycja zewnętrzna |
pl:dydaktyka:jimp2:2017:labs:wprowadzenie [2019/06/27 15:50] (aktualna) |
====== Wprowadzenie do programowania w C++ ====== | ====== Wprowadzenie do programowania w C++ ====== |
| |
//How C%%++%% is like teenage sex:// | ===== IDE ===== |
- //It is on everyone's mind all the time.// | |
- //Everyone talks about it all the time.// | |
- //Everyone thinks everyone else is doing it.// | |
- //Almost no one is really doing it.// | |
- //The few who are doing it are: **A.** Doing it poorly. **B.** Sure it will be better next time. **C.** Not practising it safely.// | |
| |
| Na zajęciach kod programów będzie pisany przy użyciu CLion IDE. IDE oprócz dostarczania podstawowego kolorowania składni i możliwości uruchamiania kodu, |
| dostarcza szereg przydatnych narzędzi, które znacznie potrafią przyspieszyć pisanie kodu. Są to między innymi: |
| * podpowiadanie składni (CTRL+SPACE) |
| * zautomatyzowanie nawigacji po projekcie (CTRL+B, CTRL+SHIFT+BACKSPACE, CTRL+ALT+HOME, CTRL+N, itd...) |
| * [[https://www.jetbrains.com/help/clion/2016.3/adding-deleting-and-moving-code-elements.html|łatwiejsze zarządzanie liniami kodu]] (TAB, SHIFT+TAB, CTRL+/, ALT+D, CTRL+Z, CTRL+Y, CTRL+D, CTRL+DEL, CTRL+BACKSPACE itd...) |
| * automatyczna generacja części kodu (ALT+INSERT, CTRL+SHIFT+D, ...) |
| * narzędzie do automatycznego formatowania kodu (CTRL+ALT+L) |
| * integracja z debuggerem |
| * integracja z systemem kontroli wersji git, |
| * integracja z narzędziem do automatycznego budowania kodu CMake |
| * integracja z frameworkiem do testów jednostkowych Google Test |
| * narzędzia do refaktoryzacji kodu, czyli poprawiania czytelności i jakości kodu bez modyfikacji jego zachowania |
| * i wiele innych |
| |
==Ciekawostka== | W celu zmaksymalizowania produktywności należy zainstalować plugin [[https://plugins.jetbrains.com/clion/plugin/4455-key-promoter|Key promoter]] i wydrukować sobie [[https://resources.jetbrains.com/assets/products/clion/CLion_ReferenceCard.pdf|Clion Reference Card]]. |
| Również należy zainstalować sobie wersję CLiona na domowym sprzęcie należy skorzystać z darmowej [[https://www.jetbrains.com/student/|licencji studenckiej]]. |
| |
Nieco przewrotny [[http://home.agh.edu.pl/~wojnicki/interview.html|Wywiad z twórcą C++]] ;-) | ===== CMake ===== |
| |
| Na zajęciach będziemy korzystać z systemu budującego CMake. W celu ułatwienia pracy |
| należy zapoznać się z elementami znajdującymi się w dokumencie [[https://www.jetbrains.com/help/clion/2016.3/quick-cmake-tutorial.html|CMake]], |
| w szczególności, |
| * jak ma nazywać się plik ze specyfikacją projektu w CMake :?: |
| * jak zdefiniować zmienną przechowującą nazwy plików cpp (z kodem źródłowym) |
| * jak dodać nowy cel (target) w postaci pliku wykonywalnego :?: |
| * jak dodać nowy cel (target) w postaci biblioteki :?: |
| * jak zdefiniować żeby stworzona wyżej biblioteka eksportowała pliki h (nagłówkowe) :?: |
| * jak w hierarchii projektu dołączyć podprojekt (podkatalog) z innym plikiem CMakeLists.txt :?: |
| * jak dołączyć bibliotekę do celu w postaci innego pliku wykonywalnego lub biblioteki :?: |
| Zagadnienia te będą obowiązywać na kolokwium :!: |
| |
| ===== Git i automatyczne sprawdzanie zadań ===== |
| |
| Na zajęciach będziemy wykorzystywali system kontroli wersji git. |
| Pod [[https://gitlab.com/agh-jimp2/exercises|linkiem]] znajduje się adres repozytorium, gdzie zdefiniowane są testy do zadań |
| do laboratoriów. Każde laboratorium ma swój osobny katalog np. lab1, lab2, itd... w każdym laboratorium znajdują się podfoldery |
| dla każdego zadania, przykładowy factorial do pierwszego zadania z silnią już znajduje się repozytorium. Należy sklonować repozytorium |
| i zaimportować projekt do CLiona. |
| |
| Należy zapoznać się z plikami CMakeLists.txt w folderze lab1 i lab1/factorial. Polecenie **add_subdirectory_if_exists(reversestring)** nie jest |
| wbudowane w CMake, ale jest zdefiniowane w tym projekcie jako wariant **add_subdirectory**, ale nie powodujący błędu jeśli podkatalog |
| nie istnieje. Żeby rozwiązywać kolejne zadania należy nawiązać do konwencji nazwniczej użytej w projekcie tzn. kolejne foldery muszą się |
| nazywać tak samo jak to jest przedstawione w kolejnych deklaracjach add_subdirectory_if_exists. W przeciwnym wypadku podprojekt nie |
| będzie widoczny :!: |
| |
| W celu sklonowania repozytorium do lokalnego folderu wystarczy wpisać w linii komed polecenie (jako opcjonalny można podać ostatni argument |
| z nazwą folderu do którego ma zostać skolnowany projekt |
| <code bash> |
| git clone https://gitlab.com/agh-jimp2/exercises.git |
| </code> |
| |
| Należy sobie odświeżyć wiedzę na temat gita, w szczególności: |
| * git diff, |
| * git commit, |
| * git status, |
| * git add, |
| * git push, |
| * git pull, |
| * git log, |
| * git checkout |
| |
| Dostępny projekt jest wyposażony w automatyczne testy jednostkowe weryfikujące poprawność napisanego kodu. Same testy zostaną omówione pod koniec laboratoriów, |
| jednak teraz wystarczy wiedzieć, że są to mini programiki, których celem jest uruchomienie małego fragmentu kodu i sprawdzenie, czy zachowuje się on zgodnie z naszymi oczekiwaniami |
| i zaraportowanie użytkownikowi sytuacji gdy jest przeciwnie. |
| |
| Projekt został tak pomyślany, że każde zadania ma swoje osobne testy. Ogólna struktura kodu wygląda tak, że zdefiniowana jest biblioteka z kodem rozwiązania, która jest linkowana zarówno |
| do programu zdefiniowanego przez Ciebie, jak i mini programiku z testami. Stąd po naciśnięciu CTRL+F9 (Build) zostanie zbudowany projekt. Następnie można nacisnąć kombinację CTRL+ALT+F10 |
| żeby zobaczyć listę dostępnych celów (targets) zdefiniowanych w całym projekcie. Wśród nich powinny znajdować się następujące cele: |
| * factorial |
| * libfactorial |
| * lab1_factorial_tests |
| * lab1_all_tests |
| * i wiele innych |
| Cele zdefiniowane ze słowem tests powinny znajdować się w niższej sekcji i posiadać ikonę z czerwonym elementem. Są to zadania, które zostały rozpoznane przez IDE jako testy. |
| Wybranie zadania factorial uruchomi program z funkcją main zdefiniowaną w **lab1/factorial/main.cpp**. Natomiast uruchomienie zadania lab1_factorial_tests uruchomi testy jednostkowe |
| dotyczące zadania z silnią. Zadanie lab1_all_tests uruchamia wszystkie testy zdefiniowane dla laboratorium numer 1. W tym momencie jednak to zadanie nie powinno się dać skompilować |
| ponieważ brakuje kodu realizującego kolejne zadania. Uruchomienie libfactorial nie jest możliwe, dlatego, że jest to bilblioteka z kodem i nie ma punktu wejścia z funkcją main tak jak cały program. |
| |
| Uruchomienie zadania lab1_factorial_tests powinno zakończyć się jednak częściowym powodzeniem, tzn. część testów powinno przejść, a część nie. |
| {{ unit-test.png?600 |}} |
| Uzyskujemy informację, że z 16 testów wykonanych 12 zawiodło. Testy zostały zorganizowane w dwie grupy factorial_test i FactorialDataDriveTests, każdej z tych grup można się przyglądnąć osobno. |
| Wynik testu informuje nas, że na przykład uruchomienie factorial(5) powinno dać nam w rezultacie 120, ale otrzymany wynik to 0 :!: |
| W innym wypadku napisane jest, że oczekiwano p.second równego 1, ale uzyskany wynik factorial(p.first) był również równy 0 :!: |
| |
| Jeśli przeniesiemy się do definicji funkcji factorial (CTRL+SHIFT+ALT+N i wpisać początek nazwy factorial), a następnie naciśniemy (CTRL+B) by przeskoczyć do definicji funkcji wszystko będzie |
| jasne defnicja funkcji factorial jest następująca: |
| <code cpp> |
| int factorial(int value) { |
| return 0; |
| } |
| </code> |
| Nic dziwnego, że zawsze zwraca 0. |
===== Typy ===== | ===== Typy ===== |
Lista typów wbudowanych w standard C%%++%% | Lista typów wbudowanych w standard C%%++%% |
| |
^Nazwa^Opis^Rozmiar^ | ^Nazwa^Opis^ |
|char |Znak, albo mała liczba całkowita| 1 bajt | | |char |Znak, albo mała liczba całkowita | |
|short int \\ (short) |Mała liczba całkowita | 2 bajty | | |short int \\ (short) |Mała liczba całkowita | |
|int |Liczba całkowita | 4 bajty | | |int |Liczba całkowita | |
|long int \\ (long)|Długa liczba całkowita | 4 bajty | | |long int \\ (long)|Długa liczba całkowita | |
|bool |Wartość **true** albo **false** | 1 bajt | | |bool |Wartość **true** albo **false** | |
|float | Liczba zmiennoprzecinkowa | 4 bajty | | |float | Liczba zmiennoprzecinkowa | |
|double |Liczba zmiennoprzecinkowa podwójnej precyzji |8 bajtów| | |double |Liczba zmiennoprzecinkowa podwójnej precyzji | |
|long double |Duża liczba zmiennoprzecinkowa podwójnej precyzji | 12 bajtów | | |long double |Duża liczba zmiennoprzecinkowa podwójnej precyzji | |
|void | Pusty typ danych | -- | | |void | Pusty typ danych | |
| |
Typy //char, short, int, long int// posiadają warianty **signed** i **unsigned**. | Typy //char, short, int, long int// posiadają warianty **signed** i **unsigned**. |
| Standard nie gwarantuje rozmiaru typu i rozmiary podstawowych typów zmieniają |
| się w zależności dla jakiej architekturze jest kompilowany kod. |
| |
| Jeśli stawiamy pewne wymagania, np. chcemy przynajmniej 8 bajtową liczbę typu integer lepiej |
| skorzystać z typów zdefniowane w [[http://en.cppreference.com/w/cpp/header/cstdint|cstdint]]. |
| |
| Oprócz typów prymitywnych w C%%++%% można zdefiniować znacznie bogatszy system typów niż w C |
| w oparciu o klasy. Temat ten będzie zgłębiony na dalszych laboratoriach jednak w ćwiczeniach przyda się |
| znajomość klasy [[http://en.cppreference.com/w/cpp/string/basic_string|std::string]], przyglądnąć się jak |
| w dokumentacji przedstawione są metody znajdujące się w klasie string (własciwie to basic_string), np. |
| * c_str() |
| * length()/size() |
| * substr() |
| * find_first_of() |
| * replace() |
===== Instrukcje sterujące ===== | ===== Instrukcje sterujące ===== |
W C%%++%% dostępne są następujące instrukcje sterujace: | W C%%++%% dostępne są następujące instrukcje sterujace: |
| |
| |
===== Prosty program w C++ ===== | ===== Prosty program ===== |
==== Przykład ==== | ==== Przykład ==== |
Program ma za zadanie wczytanie imienia i wyświetlenie powitania na ekranie. | Program ma za zadanie wczytanie imienia i wyświetlenie powitania na ekranie. |
====== Ćwiczenia ====== | ====== Ćwiczenia ====== |
- Skompiluj i uruchom przykład z sekcji [[#prosty_program_w_c|Prosty program w C++]] | - Skompiluj i uruchom przykład z sekcji [[#prosty_program_w_c|Prosty program w C++]] |
- [1 plus] Napisz program obliczający silnię. Silnia powinna być obliczana przez funkcję <code cpp>int silnia(int);</code>Wykonaj dwie wersje funkcji: | - [1 plus] Napisz program obliczający silnię. Silnia powinna być obliczana przez funkcję <code cpp>int factorial(int);</code> Zdefiniowaną w katalogu factorial. Wykonaj dwie wersje funkcji: |
* rekurencyjną | * rekurencyjną |
* iteracyjną | * iteracyjną |
- [2 plusy] Wyświetlanie napisu wspak. Napisz funkcję która jako parametr będzie przyjmowała tablicę znaków i wyświetlała ją wspak. Funkcja powinna być rekurencyjna! Podpowiedź: przerwij rekurencję po napotkaniu zerowego znaku końcowego //\0//. | - [2 plusy] Wyświetlanie napisu wspak. Napisz funkcję która jako parametr będzie przyjmowała tablicę znaków i wyświetlała ją wspak. Funkcja powinna być rekurencyjna! Podpowiedź: przerwij rekurencję po napotkaniu zerowego znaku końcowego //\0//. |
- **[2 punkty] Napisz funkcję palindrom, sprawdzającą czy podany jako parametr napis jest palindromem. Funkcja powinna zwracać **//true//** gdy napis jest palindromem, a **//false//** gdy nie jest. \\ Napisz proste menu posiadające dwie opcje: //Wyjście// i //Sprawdź palindrom//. Po wybraniu //Sprawdź palindrom// program powinien poprosić o wpisanie słowa a następnie sprawdzić i wyświetlić na ekranie czy podane słowo jest palindromem. Po wybraniu //Wyjście// program powinien kończyć działanie.** | * Moduł: **reversestring** |
| * Pliki z implementacją: **ReverseString.h/cpp** |
| * Sygnatura metody: <code cpp>std::string reverse(std::string str)</code> |
| * Pliki nagłówkowe: <code cpp>#include <string></code> |
| * Wskazówki: <code cpp>const char *characters = str.c_str(); //uzyskanie z obiektu string wskaźnika na poszczególne znaki |
| size_t size = str.size(); //uzyskanie z obiektu string ilości znaków |
| //utworzenie nowego obiektu string na podstawie innego char*, char[], itp.. |
| return std::string(reversed_characters)</code> |
| * uruchomienie testów: ALT+SHIFT+F10 -> lab1_reverse_string_tests |
| - **[2 punkty]** Napisz funkcję palindrom, sprawdzającą czy podany jako parametr napis jest palindromem. Funkcja powinna zwracać **//true//** gdy napis jest palindromem, a **//false//** gdy nie jest. \\ Napisz proste menu posiadające dwie opcje: //Wyjście// i //Sprawdź palindrom//. Po wybraniu //Sprawdź palindrom// program powinien poprosić o wpisanie słowa a następnie sprawdzić i wyświetlić na ekranie czy podane słowo jest palindromem. Po wybraniu //Wyjście// program powinien kończyć działanie. |
| * Moduł: **palindrome** |
| * Pliki z implementacją: **Palindrome.h/cpp** |
| * Sygnatura metody: <code cpp>bool is_palindrome(std::string str);</code> |
| * Pliki nagłówkowe: <code cpp>#include <string></code> |
| * uruchomienie testów: ALT+SHIFT+F10 -> lab1_palindrome_tests |
- [2 plusy] Napisz funkcję która będzie przyjmować tablicę dwuwymiarową o rozmiarach 10 na 10 i będzie uzupełniać ją iloczynami wierszy i kolumn, tworząc //tabliczkę mnożenia//. Napisz osobną funkcję do wyświetlania tej tablicy. | - [2 plusy] Napisz funkcję która będzie przyjmować tablicę dwuwymiarową o rozmiarach 10 na 10 i będzie uzupełniać ją iloczynami wierszy i kolumn, tworząc //tabliczkę mnożenia//. Napisz osobną funkcję do wyświetlania tej tablicy. |
- [3 plusy] [[http://projecteuler.net/index.php?section=problems&id=36|Palindromy liczbowe]] | * Moduł: **multiplicationtable** |
- **[3 punkty] Zadanie 4.24 do pobrania {{.:przypadek_skoczka.pdf|tutaj}}. Zadanie znajduje się w książce Arkana C%%++%%.** | * Pliki z implementacją: **MultiplicationTable.h/cpp** |
| * Sygnatura metody: <code cpp>void MultiplicationTable(int tab[][10]);</code> |
| * uruchomienie testów: ALT+SHIFT+F10 -> lab1_multiplication_table_tests |
| - **[3 punkty]** [[http://projecteuler.net/index.php?section=problems&id=36|Palindromy liczbowe]] |
| * Moduł: **doublebasepalindromes** |
| * Pliki z implementacją: **DoubleBasePalindromes.h/cpp** |
| * Sygnatura metody: <code cpp>uint64_t DoubleBasePalindromes(int max_vaule_exculsive);</code> |
| * Pliki nagłówkowe: <code cpp>#include <cstdint></code> |
| * uruchomienie testów: ALT+SHIFT+F10 -> lab1_double_base_palindrome_tests |
| |