Różnice

Różnice między wybraną wersją a wersją aktualną.

Odnośnik do tego porównania

pl:dydaktyka:jimp2:2016:labs:pamiec-i-pliki [2016/02/17 11:28]
127.0.0.1 edycja zewnętrzna
pl:dydaktyka:jimp2:2016:labs:pamiec-i-pliki [2017/07/17 10:08]
Linia 1: Linia 1:
-======Dynamiczne zarządzanie pamięcią i operacje na plikach====== 
  
-//Writing in C or C%%++%% is like running a chain saw with all the safety guards removed// 
- 
-<WRAP center round info 60%> 
-Do ukończenia tego laboratorium wymagana jest znajomość wskaźników i referencji z C. Jeżeli ktoś nie czuje się w tym temacie na siłach, w laboratorium [[.:​wskazniki|Wskaźniki i referencje]] przygotowane zostało krótkie przypomnienie najważniejszych informacji. 
-</​WRAP>​ 
- 
- 
-===== Dynamiczne zarządzanie pamięcią ===== 
-Często zdarza się, że nie jesteśmy w stanie z góry przewidzieć ile pamięci będzie potrzebował nasz program do poprawnego działania. Na przykład w prostym kalkulatorze macierzowym nie można z góry ustalić wymiarów tablicy przechowującej macierz ani z góry ustalić ile takich tablic-macierzy będzie występować w równaniu! 
- 
-Jedynym rozwiązaniem jest tworzenie nowych macierzy o ustalonych wymiarach podczas działania programu. 
- 
-====Wskaźniki i alokacja pamięci==== 
-Wraz z dynamiczną alokacją pamięci idą w parze wskaźniki. Pamięć zawsze alokowana jest pod jakimś adresem. A zmienne przechowujące adres i pozwalające się dostać do danych w niej przechowywanych,​ to właśnie wskaźniki. 
-===Operator new === 
-Operator **new** jest ekwiwalentem znanej z C funkcji //malloc// ale dużo potężniejszym. Wynikiem zwracanym przez operator **new** jest wskaźnik do zaalokowanej pamięci 
- 
-Przykład dynamicznego tworzenia zmiennych:<​code cpp>#​include <​iostream>​ 
-using namespace std; 
- 
-int main(void){ 
-   char* ptr = new char;    //Stworzy zmienną typu char 
-   int* tab = new int[10]; ​ //Stworzy tablicę typu int o rozmiarze 10 
- 
-   // NIEPOPRAWNIE!!! 
-   int** tab2d = new int[10][10];​ 
-}</​code>​ 
-===Operator delete === 
-Operator **delete** działa podobnie jak funkcja //free// znana z C. Pamięć w momencie kiedy nie jest już wykorzystywana przez program powinna być zwolniona. 
-Przykład dynamicznego tworzenia i usuwania zmiennych:<​code cpp>#​include <​iostream>​ 
-using namespace std; 
- 
-int main(void){ 
-   char* ptr = new char;    //Stworzy zmienną typu char 
-   int* tab = new int[10]; ​ //Stworzy tablicę typu int o rozmiarze 10 
- 
-   // Tutaj znajdują się operacje na zmiennych 
- 
-   ​delete ptr; 
-   ​delete [] tab; 
- 
-   // NIEPOPRAWNIE!! 
-   // Jeśli tab2d jest poprawnie zaalokowaną tablica dwuwymiarową 
-   // nie można zwolnić pamięci w następujący sposób 
-   ​delete [][] tab2d; 
-}</​code>​ 
- 
-===== Operacje na plikach ===== 
-Operacje na plikach wykonywane są w C++ przy użyciu strumieni - analogicznie jak operacja czytania z klawiatury i wypisywania na ekran. 
- 
-Należy pamiętać o tym, że każdy plik, który został otwarty, powinien zostać również zamknięty, kiedy korzystanie z niego nie jest już potrzebne. 
-====Biblioteka fstream==== 
-Obiekty strumieni służące do odczytu i zapisu do pliku znajdują się w pliku nagłówkowym //<​fstream>//​. Biblioteka ta zawiera dwa obiekty strumieni analogiczne do obiektów //cin// i //​cout//: ​ 
-  * //​ifstream//​ - służący do odczytu z pliku (//​input-file-stream//​) 
-  * //​ofstream//​ - służący do zapisu do pliku (//​output-file-stream//​). 
-====Czytanie z pliku==== 
-Przykład wczytywania pliku wyraz po wyrazie:<​code cpp> 
-#include <​iostream>​ 
-#include <​fstream>​ 
-using namespace std; 
- 
-int main(void){ 
-  ifstream myfile("​file.txt"​);​ 
-  char word[64]; 
- 
-  if(!myfile) 
-    cout << "Nie można otworzyć pliku!"​ << endl; 
- 
-  while(myfile >> word) 
-    cout << word; 
-  ​ 
-  myfile.close();​ 
-  return 0; 
-} 
-</​code>​ 
-Przykład wczytywania pliku linia po linii:<​code cpp> 
-#include <​iostream>​ 
-#include <​fstream>​ 
-using namespace std; 
- 
-int main(void){ 
-  ifstream myfile("​file.txt"​);​ 
-  char line[256]; 
- 
-  if(!myfile) 
-    cout << "Nie można otworzyć pliku!"​ << endl; 
- 
-  while(!myfile.eof()){ 
-    myfile.getline(line,​256);​ 
-    cout << line; 
-  } 
-  ​ 
-  myfile.close();​ 
-  return 0; 
-} 
-</​code>​ 
- 
-====Zapisywanie do pliku==== 
-Przykład **dopisywania** do pliku:<​code cpp>#​include <​iostream>​ 
-#include <​fstream>​ 
-using namespace std; 
- 
-int main () { 
- 
-  // Aby zrozumieć zapis: ios_base::​in | ios_base::​app 
-  // Zobacz kolejny podrozdział 
-  ofstream myfile ("​file.txt",​ ios_base::​in | ios_base::​app);​ 
- 
-  if(!myfile) 
-    cout << "Nie można otworzyć pliku!"​ << endl; 
- 
-  myfile << "Tekst zapisany w pliku" << endl; 
- 
-  myfile.close();​ 
- 
-  return 0; 
-} 
-</​code>​ 
- 
- 
-====Otwieranie pliku w różnych trybach==== 
-Plik można otworzyć w 6 różnych trybach; kombinacje trybów też są możliwe. 
- 
-^Wartość flagi^Znaczenie^ 
-|ios_base::​app|(append) Ustawia wskaźnik pozycji strumienia na samym końcu strumienia. Służy do dopisywania do pliku.| 
-|ios_base::​ate|(at end) Ustawia wskaźnik pozycji strumienia na samym końcu pliku.| 
-|ios_base::​binary|(binary) Traktuje strumień jako strumień binarny a nie tekstowy| 
-|ios_base::​in|(input) Umożliwia zapis do pliku| 
-|ios_base::​out|(output) Umożliwia odczyt z liku| 
-|ios_base::​trunc|(truncate) Jeśli otwierany pli posiadał jakąś zawartość,​ jest ona pomijana i wskaźnik pozycji w strumieniu jest ustawiany na początku pliku.| 
- 
-Otwieranie strumienia //​ifstream//​ z opcją //​ios_base::​out//​ mija się z celem. Do strumieni, które mają służyć zarówno zapisowi jak i odczytowi, stosuje się ogólną postać strumienia o nazwie //​fstream//​. 
-<code cpp> 
-  fstream file("​file.txt",​ ios_base::​in | ios_base::​out | ios_base:​app);​ 
-</​code>​ 
-====== Ć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ę 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}} 
-  - **[2 punkty] Napisz program, który będzie implementować algorytm szyfrujący [[http://​pl.wikipedia.org/​wiki/​Szachownica_Polibiusza|Polibiusza]]. Program powinien przyjmować trzy parametry: nazwę pliku wejściowego,​ nazwę pliku wyjściowego oraz 1 w przypadku gdy plik wejściowy ma zostać zaszyfrowany lub 0, gdy ma zostać odszyfrowany. Wynik szyfrowania/​deszyfrowania powinien znaleźć się w pliku wyjściowym podanym jako parametr.\\ Przykład uruchomienia programu:​**<​code>​./​program plik-tekst.txt plik-szyfr.txt 1</​code>​ 
-  - [2 plusy] Napisz program, który w pierwszej kolejności wczyta od użytkownika rozmiar tablicy, stworzy dynamicznie tablicę o podanych wymiarach, następnie uzupełni ją losowymi liczbami całkowitymi i znajdzie te liczby w tablicy, których iloczyn da największą liczbę. **Uwaga** - Program ma mieć złożoność obliczeniową //O(n)// - innymi słowy, przegląda tablicę tylko raz - od początku do końca i zwraca wynik!  ​ 
-  - [3 plusy] [[http://​projecteuler.net/​index.php?​section=problems&​id=59|Łamanie hasła]] 
-  - **[3 punkty] Minimalne drzewo rozpinające:​** 
- 
-  * Zadanie bazuje na problemie ze strony [[http://​projecteuler.net/​index.php?​section=problems&​id=107|Project Euler]], na której można sprawdzić poprawność rozwiązania wpisując w formularz wynik. 
-  * Rozwiąż problem wyszukiwania [[http://​pl.wikipedia.org/​wiki/​Minimalne_drzewo_rozpinaj%C4%85ce|minimalnego drzewa rozpinającego]] wykorzystując wybrany z poniższych algorytmów:​ 
-    * [[http://​pl.wikipedia.org/​wiki/​Algorytm_Kruskala|Algorytm Kruskala]] 
-    * [[http://​pl.wikipedia.org/​wiki/​Algorytm_Bor%C5%AFvki|Algorytm Borůvki]] 
- 
-  * Poniższy nieskierowany graf ważony składa się z siedmiu wierzchołków i dwunastu krawędzi o całkowitej wadze równej 243. Wagą całkowitą grafu określana jest suma wag wszystkich krawędzi tego grafu. \\ {{.:​graf.gif|Źródło:​ http://​projecteuler.net}} 
-  * Graf z rysunku powyżej może zostać opisany za pomocą dwuwymiarowej tablicy: 
- 
-^ ^   ​ A ^B ^C ^D ^E ^F ^G^ 
-^A| -| 16| 12| 21| -| -| -| 
-^B| 16| -| -| 17| 20| -| -| 
-^C| 12| -| -| 28| -| 31| -| 
-^D| 21| 17| 28| -| 18| 19| 23| 
-^E| -| 20| -| 18| -| -| 11| 
-^F| -| -| 31| 19| -| -| 27| 
-^G| -| -| -| 23| 11| 27| -| 
- 
-  * Możliwe jest zoptymalizowanie grafu poprzez usunięcie niektórych krawędzi w taki sposób, aby wszystkie wierzchołki w danym grafie nadal pozowały połączone. Graf, który można uzyskać w ten sposób nazywany jest minimalnym drzewem rozpinającym:​ \\ {{.:​spanning-tree.gif|Źródło:​ http://​projecteuler.net}} 
- 
-  * Wykorzystując {{.:​network.txt|plik}} z tablicową reprezentacją pewnego grafu. Napisz program, który znajdzie minimalne drzewo rozpinające grafu, o najmniejszej możliwej wadze całkowitej. 
- 
- 
-  * Modyfikacje w stosunku do oryginalnego zadania z http://​projecteuler.net 
-    - Załóż, że w pliku wejściowym pierwsza linijka to zawsze liczba określająca ilość wierzchołków grafu. 
-    - Program powinien wyświetlać w konsoli oraz zapisywać do pliku minimalne drzewo rozpinające danego grafu w analogicznej konwencji jak w przypadku danych wejściowych 
-    - Program powinien zwracać do systemu wartość oszczędności jaką osiągnięto (w zadaniu określanej jako //maximum saving//) 
- 
-====== Do przygotowania na kolejne zajęcia====== 
-Zapoznać się z materiałem o [[http://​home.agh.edu.pl/​~gjn/​dydaktyka/​UGLX/​node10.html | Makefile]]. ​ 
pl/dydaktyka/jimp2/2016/labs/pamiec-i-pliki.txt · ostatnio zmienione: 2019/06/27 15:50 (edycja zewnętrzna)
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0