Both sides previous revision
Poprzednia wersja
Nowa wersja
|
Poprzednia wersja
|
pl:dydaktyka:jimp2:2017:labs:pamiec-i-pliki [2017/03/03 15:22] mwp [Ćwiczenia] |
pl:dydaktyka:jimp2:2017:labs:pamiec-i-pliki [2019/06/27 15:50] (aktualna) |
}</code> | }</code> |
| |
| Niestety należy pamiętać o tym by zwolnić pamięć przydzieloną inaczej uzyskujemy wyciek pamięci i program w trakcie działania zaczyna zużywać coraz więcej pamięci operacyjnej mimo, że już jej i tak nigdy nie użyje! Sprawa też nie jest taka prosta, bo nie zawsze wiadomo, czy pewne elementy nie są już na pewno przez nikogo używane. |
| |
| === Brak wartości === |
| |
| W C%%++%%11 nie używamy już makra **NULL** zostało dodane specjalne słowo kluczowe reprezentujące pusty wskaźnik **nullptr** |
| |
| <code cpp> |
| int *v = nullptr; |
| delete v; |
| </code> |
| |
| |
| =====Ale jest nadzieja - zautomatyzowane zarządzanie pamięcią część pierwsza===== |
| |
| Jedną z możliwości automatycznego zarządzania pamięcią jest oddelegowanie tego zadania do kontenerów zdefiniowanych w bibliotece standardowej, |
| które automatycznie zwolnią pamięć jeśli przestanie ona być używana. |
| ==== Vector ==== |
| |
| Jednym z takich kontenerów jest tablica rozszerzalna [[http://en.cppreference.com/w/cpp/container/vector|vector]], zapoznać się z dokumentacją |
| uruchomić przykłady podane w dokumentacji przez **run code** i przyglądnąć się dokumentacji funkcji: |
| * emplace_back |
| * pop_back |
| * clear |
| Przenalizować poniższy kod: |
| <code cpp> |
| #include <iostream> |
| #include <vector> |
| |
| using std::cout; |
| using std::endl; |
| using std::vector; |
| |
| void PrintVector(const vector<int> &v) { |
| bool first = true; |
| for(auto n : v) { |
| if (!first) { |
| cout<< ", "; |
| } else { |
| first = false; |
| } |
| cout << n; |
| |
| } |
| cout<<endl; |
| } |
| |
| int main() |
| { |
| // Create a vector containing integers |
| vector<int> v = {7, 5, 16, 8}; |
| |
| cout << "initilized with 4 numbers"<<endl; |
| PrintVector(v); |
| |
| // Add two more integers to vector |
| v.emplace_back(25); |
| v.emplace_back(13); |
| cout << "after 2 more inserted"<<endl; |
| PrintVector(v); |
| |
| //copy of the value inside vector |
| for (auto n : v) { |
| ++n; |
| } |
| |
| cout << "BUT: after incrementation"<<endl; |
| PrintVector(v); |
| |
| //reference to the value inside vector, therefore one can change the value |
| for (auto &n : v) { |
| ++n; |
| } |
| cout << "and again... can you spot the difference?"<<endl; |
| PrintVector(v); |
| } |
| </code> |
| [[http://coliru.stacked-crooked.com/a/056089e192222291|Run code]] |
| |
| ==== Map ==== |
| |
| [[http://en.cppreference.com/w/cpp/container/map|Tablica asocjacyjna]], która pozwala zaadresować dowolny element innym typem, niekoniecznie tylko liczbą naturalną. |
| |
| <code cpp> |
| #include <iostream> |
| #include <map> |
| |
| using std::cout; |
| using std::endl; |
| using std::map; |
| |
| void PrintMap(const map<char,int> &v) { |
| bool first = true; |
| for(const auto &n : v) { |
| if (!first) { |
| cout<< ", "; |
| } else { |
| first = false; |
| } |
| cout << n.first << " -> " << n.second; |
| |
| } |
| cout<<endl; |
| } |
| |
| int main() |
| { |
| // Create a vector containing integers |
| map<char, int> v = {{'a',17}, {'c',-2}, {'g',67}, {'z',13}}; |
| |
| cout << "initilized with 4 numbers"<<endl; |
| PrintMap(v); |
| |
| // Add two more integers to vector |
| v.emplace('h',25); |
| v.emplace('$',13); |
| cout << "after 2 more inserted"<<endl; |
| PrintMap(v); |
| |
| //copy of the value inside vector |
| for (const auto &n : v) { |
| //Compilation error |
| //++n.second; |
| } |
| |
| cout << "BUT: after incrementation"<<endl; |
| PrintMap(v); |
| |
| //reference to the value inside vector, therefore one can change the value |
| for (auto &n : v) { |
| ++n.second; |
| } |
| cout << "and again... can you spot the difference?"<<endl; |
| PrintMap(v); |
| } |
| </code> |
| |
| [[http://coliru.stacked-crooked.com/a/4d32653f8fae33c3|Run code]] |
===== Operacje na plikach ===== | ===== Operacje na plikach ===== |
Operacje na plikach wykonywane są w C++ przy użyciu strumieni - analogicznie jak operacja czytania z klawiatury i wypisywania na ekran. | Operacje na plikach wykonywane są w C++ przy użyciu strumieni - analogicznie jak operacja czytania z klawiatury i wypisywania na ekran. |
====== Ćwiczenia ====== | ====== Ćwiczenia ====== |
- Zrefaktoryzować kod metod //factorial//, //reverse// i //is_palindrome// tak, żeby nawiązywały do konwencji, że nazwa funkcji jest pisana jako //NazwaFunkcjiCamelCase//, skorzystać z narzędzia do refaktoryzacji wbudowanego w CLion: najechać na metodę kursorem wybrać z menu Refactor->Rename... (SHIFT+F6). | - Zrefaktoryzować kod metod //factorial//, //reverse// i //is_palindrome// tak, żeby nawiązywały do konwencji, że nazwa funkcji jest pisana jako //NazwaFunkcjiCamelCase//, skorzystać z narzędzia do refaktoryzacji wbudowanego w CLion: najechać na metodę kursorem wybrać z menu Refactor->Rename... (SHIFT+F6). |
- [1 plus] W sekcji [[#wskazniki_i_alokacja_pamieci|Wskaźniki i alokacja pamięci]] zostało powiedziane, że **nie można** utworzyć tablicy wielowymiarowej prostym poleceniem //int * *tab = new int[10][10]//. Przeanalizuj rysunek poniżej i zastanów się dlaczego tak jest. Następnie napisz program który będzie pobierał od użytkownika wymiary tablicy i dynamicznie alokował pamięć dla niej. Napisz funkcję która będzie uzupełniała tablicę iloczynami wierszy i kolumn i osobną funkcję do wyświetlania tablicy. Czy można do tego wykorzystać funkcje napisane na poprzednich laboratoriach nie modyfikując ich? Pamiętaj o **poprawnym** zwolnieniu pamięci! {{.:pointers2pointers.png|Tablica wskaźników}}. Zadanie zostało podzielone na kroki: (step1,step2,...). Ukończenie pierwszego i drugiego kroku jest wymagane do zaliczenia ćwiczenia. | - [1 plus] W sekcji [[#wskazniki_i_alokacja_pamieci|Wskaźniki i alokacja pamięci]] zostało powiedziane, że **nie można** utworzyć tablicy wielowymiarowej prostym poleceniem //int * *tab = new int[10][10]//. Przeanalizuj rysunek poniżej i zastanów się dlaczego tak jest. Następnie napisz program który będzie pobierał od użytkownika wymiary tablicy i dynamicznie alokował pamięć dla niej. Napisz funkcję która będzie uzupełniała tablicę kolejnymi liczbami całkowitymi (tak jak na rysunku) i osobną funkcję do wyświetlania tablicy. Czy można do tego wykorzystać funkcje napisane na poprzednich laboratoriach nie modyfikując ich? Pamiętaj o **poprawnym** zwolnieniu pamięci! {{.:pointers2pointers.png|Tablica wskaźników}}. Zadanie zostało podzielone na kroki: (step1,step2,...). Ukończenie pierwszego i drugiego kroku jest wymagane do zaliczenia ćwiczenia. |
* Moduł: **array2d** | * Moduł: **array2d** |
* Pliki z implementacją: **Array2d.h/cpp** | * Pliki z implementacją: **Array2D.h/cpp** |
* Sygnatura metody: <code cpp>int **Array2D(int n_rows, int n_columns); | * Sygnatura metody: <code cpp>int **Array2D(int n_rows, int n_columns); |
void DeleteArray2D(int **array, int n_rows, int n_columns);</code> | void DeleteArray2D(int **array, int n_rows, int n_columns);</code> |
std::string PolybiusDecrypt(std::string crypted);</code> | std::string PolybiusDecrypt(std::string crypted);</code> |
* Pliki nagłówkowe: <code cpp>#include <string></code> | * Pliki nagłówkowe: <code cpp>#include <string></code> |
- [2 plusy] Wykorzystując strukturę danych (struct) znaną jeszcze z języka C, należy zaimplementować listę jednokierunkową zdolną przechowywać liczby całkowite w swoich węzłach. **UWAGA: jest to ćwiczenie tylko techniczne, w standardowej bibliotece istnieje [[http://en.cppreference.com/w/cpp/container/forward_list|forward_list]] zdolna przechowywać dowolny typ. | - [2 plusy] Wykorzystując strukturę danych (struct) znaną jeszcze z języka C, należy zaimplementować listę jednokierunkową zdolną przechowywać liczby całkowite w swoich węzłach. **UWAGA**: jest to ćwiczenie tylko techniczne, w standardowej bibliotece istnieje [[http://en.cppreference.com/w/cpp/container/forward_list|forward_list]] zdolna przechowywać dowolny typ. |
* Moduł: **simpleforwardlist** | * Moduł: **simpleforwardlist** |
* Pliki z implementacją: **ForwardList.h/cpp** | * Pliki z implementacją: **SimpleForwardList.h/cpp** |
* Sygnatury metod: <code cpp>ForwardList *CreateNode(int value); | * Sygnatury metod: <code cpp>ForwardList *CreateNode(int value); |
void DestroyList(ForwardList *list);</code> | void DestroyList(ForwardList *list);</code> |
* Pliki nagłówkowe: <code cpp>#include <string> | * Pliki nagłówkowe: <code cpp>#include <string> |
#include <vector></code> | #include <vector></code> |
| * Wskazówki: <code cpp>#include <algorithm> |
| using std::find; |
| using std::vector; |
| using std::string; |
| |
| vector<string> dictionary {"the","of"}; |
| |
| //THERE ARE BETTER WAYS TO LOOK FOR A WORD BUT IT WORKS |
| if (find(dictionary.begin(),dictionary.end(),"of") != dictionary.end()) { |
| //FOUND! |
| } |
| |
| </code> |