7. cvičení

Reprezentace matice v paměti počítače

Matice je dvourozměrný objekt, kdežto paměť počítače funguje jednorozměrně, takže prvky matice musíme vhodně uspořádat, aby se s nimi v paměti počítače dobře pracovalo. V jazyce C++ se typicky používá uložení po řádcích (viz obrázek ze cvičení).

Pro vytvoření matice v jazyce C++ lze použít tzv. dvourozměrné pole, které usnadňuje indexování pomocí dvojice hranatých závorek (první je index řádku, druhý index sloupce):

// pocet radku a sloupcu
int R = 3;
int S = 4;

// definice matice
double matice[R][S];

// zapis prvku na 2. radek a 1. sloupec
matice[2][1] = 8;

Nevýhoda tohoto přístupu je, že v jazyce C++ neexistuje způsob, jak takovéto dvourozměrné pole předat jako parametr nějaké funkci. V jazyce C by však bylo možné definovat funkci tímto způsobem:

void vypis_matici(int r, int s, double a[r][s])
{
    // ...
}

V jazyce C++ je potřeba použít alternativní přístup, kde vytvoříme jednorozměrné pole pro \(R \times S\) prvků a sami budeme převádět dvojici indexů na jeden index pro přístup do tohoto pole: \(r,s\)-tý prvek matice bude odpovídat prvku pole s indexem \(r \cdot S + s\). Jednorozměrné pole pak můžeme předávat jako parametr funkcím stejným způsobem jako v případě vektorů.

#include <iostream>
using namespace std;

void vypis_matici(int R, int S, double* a)
{
    for (int i = 0; i < R; i++) {
        for (int j = 0; j < S; j++) {
            //cout << a[i][j] << " ";
            cout << a[i*S + j] << " ";
        }
        cout << endl;
    }
}

int main()
{
    int R = 3;
    int S = 4;

    double matice[R*S];

    // inicializace
    for (int i = 0; i < R*S; i++) {
        matice[i] = 0;
    }

    int r = 2;  // index radku
    int s = 1;  // index sloupce
    matice[r*S + s] = 8;

    vypis_matici(R, S, matice);

    return 0;
}

Vytvoření vlastní struktury

Struktury v jazyce C++ slouží k vytváření vlastních typů, které mohou kombinovat předem definované typy (nebo i struktury). Typické použití struktur je pro reprezentaci komplikovanějších objektů, jejichž stav je určen několika provázanými parametry.

Např. pro reprezentaci bodu v rovině pomocí kartézských souřadnic můžeme definovat následující strukturu obsahující atributy pro souřadnice \(x\) a \(y\):

struct Point2D
{
    // atributy nasi struktury (muzeme nastavit pocatecni hodnoty)
    double x = 0;
    double y = 0;
};

Název struktury Point2D představuje nový typ, se kterým můžeme pracovat stejně jako se základními typy. Můžeme např. vytvořit proměnnou tohoto typu:

Point2D a;

Jelikož v definici struktury máme specifikované počáteční hodnoty všech atributů, dojde při definici proměnné a k inicializaci souřadnic x a y (jinak by v atributech zůstaly neinicializované hodnoty stejně jako v případě základních typů).

Dále můžeme přepsat souřadnice na jiné hodnoty. K atributům objektu se dostaneme pomocí operátoru . (tečka):

a.x = 1;
a.y = 2;
cout << "a = [" << a.x << ", " << a.y << "]" << endl;

Alternativně můžeme při vytváření proměnné specifikovat jiné počáteční hodnoty pomocí složených závorek (pořadí hodnot v závorkách odpovídá pořadí atributů v definici struktury, tj. x dostane hodnotu 3 a y dostane hodnotu 4):

Point2D b = {3, 4};

Alternativně můžeme proměnnou vytvořit jako kopii jiného objektu, přičemž se kopírování provede „po složkách“:

Point2D c = b;

Stejně funguje i přiřazovací operátor pro již existující proměnné:

a = b;