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