Práce s ukazateli – dvourozměrné pole – úpravy 1



Procvičování práce s pamětí a vícerozměrnými proměnnými. Úpravy na C++ mechanizmy.



Zadání

Upravte program pro práci s dvourozměrným polem z minulého cvičení pomocí C++ mechanizmů:





Postup práce:

  1. Vytvořte nový prázdný projekt.

  2. Do adresáře projektu vložte kopie souborů z minulého cvičení main2D.c, funkce2d.c, funkce2d.h a vložte je do projektu. U zdrojových souborů přejmenujte koncovku na .cpp, u hlavičkového na .hpp. Zkuste přeložit a opravte případné chyby plynoucí z rozdílu mezi jazyky C a C++.

  3. Do projektu vložte i knihovnu check.

  4. Pro tisk používá C++ koncepci streamů, která nahrazuje tisk pomocí funkcí typu printf.
    Místo tisku pomocí printf použijte v tomto projektu tisk pomocí streamu cout. Vyměňte všechny printf (pouze v souboru funkce2d.cpp) za cout a zkuste přeložit. Ke správné funkci musíte naincludovat knihovnu iostream. Dále je nutné si uvědomit, že proměnné cout, cerr (standardní výstup a standardní chybový výstup) a manipulátor endl (odřádkuje a vytiskne výstupní text na konzolu) jsou v prostoru std. Proto je nutné je „zpřístupnit“ pomocí direktivy using. Zpřístupněte je jednotlivě (using pro každou z proměnných cout, cerr, endl). Přeložte a zkontrolujte zda je tisk v pořádku.

  5. Vyměňte obsah souboru main2d.cpp za přiložený zdrojový text. V následujících krocích se postupně snažte upravit své soubory (funkce2d.h a funkce2d.cpp) tak, aby fungovaly s přiloženým zdrojovým textem pro main2d.cpp. Odlaďujte postupně, tím že budete odstraňovat komentáře.
    Jelikož chyby jsou signalizovány pomocí typu enum, vložte do souborů funkce2D (rozhodněte co do hlavičkového a co do zdrojového) projektu následující kód:
    extern const char *MatrixErrorStr[];
    #define TOSTR(a) (#a)
    const char *MatrixErrorStr[] = { TOSTR(EOk), TOSTR(EWrongSize), TOSTR(ENoMemory), TOSTR(ENotAllocated), TOSTR(EAlreadyAllocated) };

  6. Pomocí klíčového slova typedef můžeme vytvořit nový datový typ z již stávajícího.
    Vyměňte definici MUJTYP z minulého cvičení za příkaz typedef double TType;. Všechny výskyty MUJTYP přejmenujte na TType.

  7. Při práci v týmu, nebo na větších projektech je výhodné oddělit funkce (na základě autorů nebo společné činnosti) pomocí jmenných prostorů.
    Vytvořte jmenný prostor pro funkce ze souboru funkce2D se jménem Matrix. Nejprve vložte do jmenného prostoru deklarace nacházející se v hlavičkovém souboru a přeložte (= nadefinujte v hlavičkovém souboru jmenný prostor daného jména a do jeho těla vložte obsah původního hlavičkového souboru (mimo ošetření vícenásobného načtení)).
    Následně přiřaďte do jmenného prostoru Matrix i zdrojové funkce v souboru funkce2D.cpp. Funkci transpose_matrix přiřaďte do jmenného prostoru Matrix pomocí operátoru příslušnosti a jména prostoru, ostatní funkce vložte pomocí namespace {} (stejně jako v hlavičkovém souboru).
    Přístup k proměnným v modulu main je plným názvem Prostor::jmeno.
    Zapněte část programu, vyřazenou pomocí podmíněného překladu tak, že vyměníte #if 0 za #if 1.

  8. Jazyk C++ používá k práci s pamětí klíčová slova new a delete, které nahrazují původní funkce typu malloc a free.
    Nahraďte alokaci a odalokaci novými mechanizmy – new a delete. Pro pole je nutné použít „polní“ operátory new [] a delete [].

  9. Pro ošetření chyb se v jazyce C++ kromě návratových hodnot funkcí používá mechanizmus výjimek.
    Přepracujte předávání chyb na mechanizmus výjimek.
    Všechny funkce z modulu funkce2D (mimo „lokálních“ static funkcí) budou vracet chyby pomocí výjimek. Jelikož výjimky „jdou mimo“ parametrů funkcí, budou nyní funkce vracet typ void – přepište prototypy funkcí tak, aby vracely void.
    Tímto krokem „přestanou fungovat“ returny (nepůjdou přeložit). Místo returnů nyní musíme vygenerovat chybu typu výjimka. Pro výjimku využijeme stávající návratové hodnoty (a jejich typ). Výjimku vygenerujeme pomocí klíčového slova throw (kterým nahradíme stávající return).

  10. Výjimky jsou generovány i při použití operátoru new při alokaci.
    Kód pro alokaci s ošetřením chyb pomocí výjimek může vypadat například tak jak je uvedeno níže.
    Pokud generujeme výjimku, je nutné označit blok, ve kterém se má ošetřit – tento blok začíná klíčovým slovem try a za blokem následuje sekce bloků uvozených příkazem catch. Operátor new generuje standardní výjimku bad_alloc (knihovna <new>). Pro výjimky vašeho programu budou použit typ enum.
    Všimněte si, že kód pro výjimky byl v modulu main2d již přítomen, aniž bychom výjimky generovali.
    V modulu main zkuste zda mechanizmus výjimek funguje.
    try

{

mat = new TType*[aY];

for(y = 0; y < aY; ++y)

mat[y] = new TType[aX];

}


catch(std::bad _alloc)

{

if(mat)

deallocate(mat, y - 1);

throw(ENoMemory);

}

  1. „Přesuňte“ matici do struktury – vytvořte (v hlavičkovém souboru) definici struktury TMatrix. Struktura TMatrix bude mít dvě proměnné typu unsigned: iRadku a iSloupcu a proměnnou typu TType** iData pro uložení dat (+další proměnné, které budete potřebovat pro správný chod programu).
    Přepište program tak, aby všechny matice, které se skládaly ze tří proměnných (data, rozměry), byly nahrazeny daty v této struktuře. Funkce allocate a deallocate neměňte (slouží obecně pro práci s 2D polem bez návaznosti na strukturu, která je „vyšší“ proměnnou).
    Program odlaďte – zakomentujte funkci main a postupně odkomentovávejte jednotlivé řádky a za současné změny příslušných funkcí na parametr typu struktura TMatrix.
    Strukturu je vhodné předávat pomocí ukazatele nebo struktury (byla-li probrána volte tuto možnost).









Poslední změna 2016-10-21