Procvičení neobjektových vlastností jazyka C++



Pro lepší kontrolu manipulace s pamětí použijte knihovnu Checker .
Funkce pro omezení počtu alokací – viz checker.h.



Práce se složeným datovým typem - struct

1) Nadefinujte strukturu TVector, která bude obsahovat proměnné:
- iData pro uložení dynamického pole (tj. pole s proměnnou délkou) typu int.
- iSize pro uložení naalokované délky,
- iLen, ve které bude uložena hodnota aktuálně využitých prvků (od počátku bez mezer).

2) Ve funkci main vytvořte proměnnou vec typu TVector (proměnnou, ne ukazatel). Inicializujte její prvky na "nulové" hodnoty.

Alokace paměti pomocí new, mechanizmus výjimek

v C++ slouží pro alokování mechanizmus spojený s klíčovým slovem new. Za něj se uvede datový typ, pro který chceme místo v paměti alokovat. Podobně se alokuje i pole pomocí new[] (alokaci jednoho prvku a pole je nutné odlišovat z důvodu různých odalokací).
V případě neúspěchu (na rozdíl od C nevrací NULL, ale) vyvolá výjimku datového typu (std::)bad_alloc.
int *i1 = new int; // alokace paměti pro jeden prvek int
int *i10 = new int[10]; // alokace paměti pro deset prvků int
int **pi1; pi1 = new int * ; // alokace paměti pro jeden prvek ukazatel na int
int **pi10; pi10 = new int * [10]; // alokace paměti pro deset prvků ukazatel na int



3) Naalokujte v proměnné vec do iData pole o délce 10 prvků (int – viz bod 1). Alokaci proveďte pomocí operátoru new.
Pro zjištění úspěšnosti alokace využijte mechanizmus výjimek. (Pro ověření zkuste naalokovat "větší" množství paměti - tak aby se objevila standardní výjimka).
V případě, že při alokaci došlo k chybě (tj. v případě výjimky) vypište chybové hlášení a program ukončete.
Chybové hlášení vytiskněte pomocí mechanizmů c++ (proměnná cout, endl, prostor std, knihovna iostream).
Tisk se v C++ provádí pomocí streamu (realizován proměnnou cout). Díky vlastnostem C++ není při tisku nutné uvádět datový typ proměnné, správný tisk pro daný typ vybere překladač ze znalosti typu proměnné. Tisk se realizuje pomocí operátoru << (který je možný zřetězit). Pro přechod na nový řádek je možné použít znak ´\n´ nebo endl.
double d=2; int i=5; char txt[]=“vysledek“;
std::cout << txt << d << “pro index “ << i << std::endl;



Odalokování paměti pomocí delete

v C++ se uvolnění paměti provádí pomocí mechanizmu spojeného s klíčovým slovem delete pro prvek a delete[] pro pole prvků. Mezi těmito dvěmi je nutno rozlišovat aby bylo dodrženo párování new → delete a new[] → delete[].

Pro alokace uvedené výše bude uvolnění paměti následující:
delete i1; // uvolnění jednoho prvku – alokace pomocí new Typ
delete[] i10; // uvolnění pole prvků – alokace pomocí new Typ [počet]
delete pi1; // uvolnění jednoho prvku – alokace pomocí new Typ
delete[] pi10;// uvolnění pole prvků – alokace pomocí new Typ [počet]

4) Před koncem funkce main korektně ukončete "život" vytvořených proměnných typu TVector (odalokujte paměť pomocí operátoru delete, nebo delete[] (?).
Po odalokaci "vynulujte" proměnné struktury (signalizující, že proměnná nemá platná data). V tomto případě to není nutné, ale pokud by se v budoucnu přidával kód je dobré vědět, že proměnná neobsahuje platná data).


Práce se strukturou

5) Po inicializaci proměnné vec naplňte pvky v poli iData hodnotami indexů (tj. 0,1...9). Nastavte zbylé proměnné struktury tak, aby odpovídaly realitě. Funkci zavolejte a ověřte její činnost.

Struktura jako parametr při volání funkce

6) Alokaci pole (tj inicializaci proměnných struktury hodnotami) přesuňte do funkce AllocVector(TVector *uk,int delka).

Pokud funkce dostane v parametru délka nulu, nebo záporné číslo, hodí výjimku typu int s hodnotou stejnou jako je v proměnné delka. V main se výjimka odchytne a vypíše text “spatne zadana delka“ a uvede se požadovaná hodnota (získaná z mechanizmu výjimky).
Pokud předaný parametr uk bude již ukazovat na platnou adresu, hodí se výjimka s textem “nealokuji – pamet je jiz alokovana“. Tato vyjimka se odchytí v main a vyslaný řetězec se vytiskne.

Promyslete:
Stačí proměnnou pole předávat pomocí ukazatele, když do ní chceme zapsat?
Nebo musíme předávat adresu na které proměnná leží pomocí TVector**?
Vysvětlete, která varianta je vhodná pro splnění zadání.
Popište rozdíly mezi jednotlivými předáními.

Pole struktur

7) Ve funkci main vytvořte proměnnou fp , která bude ukazatelem na pole struktur TVector.

8) Napište funkci AllocMatrix, která naalokuje pole struktur TVector o požadovaném počtu prvků, jednotlivé prvky inicializuje stejně jako ve funkci AllocVector (můžete s výhodou využít přímo AllocVector – je nutné ošetřit výjimky z AllocVector).
Možná hlavička (aSloupcu říká jak dlouhé bude pole v jednotlivých proměnných TVector, proměnná aRadku říká, kolik řádků (řádek je tvořen jednou proměnnou TVector) bude mít proměnná aMatrix)
AllocMatrix(TVector ** aMatrix, size_t aRadku, size_t aSloupcu,XX aInicializacniHodnota).

9) Na konci funkce main odalokuje pole struktur (tj. odalokujte naalokovanou paměť uvnitř všech prvků a potom celé pole).
DU – napište pro odalokování pole ve struktuře funkci DeAllocVector a dále napište pro odalokování pole struktur (včetně pole uvnitř) funkce DAllocMatrix. Z „bezpečnostních důvodů“ po odalokování nastavte ukazatele na nullptr (aby v příštím použití bylo jasno, že data nejsou platná).

Reference

10) (Po probrání reference) napište funkci vykonávající stejnou činnost jako AllocVector(TVector*, int), ale pro předání proměnné struktury použijte reference AllocVector(TVector &, int). Nechte v programu obě funkce. Ověřte, že je to možné, a že obě fungují. Vysvětlete rozdíly.





DU – viz. sekce DU/projekt ve čtvrtém týdnu rozvrhu cvičení:

Na základě zadání 1 vytvořte program, který bude plnit požadované - jedná se o verzi v jazyce C.

Na základě zadání 2 přepište tento program tak aby využíval možností jazyka C++.

Oba programy (projekty) budou ve stejném řešení (solution) v prostředí Visual Studio.









Poslední úpravy 2018-09-30