NOVINKA - Online rekvalifikační kurz Python programátor. Oblíbená a studenty ověřená rekvalifikace - nyní i online.
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

Lekce 4 - Vícerozměrná pole v C# .NET

V minulé lekci, Spojový seznam v C#, jsme se věnovali spojovým seznamům.

Dnešní díl C# .NET tutoriálu pojednává o tzv. vícerozměrných polích.

Jednorozměrné pole

S jednorozměrným polem, které si můžeme představit jako řádku přihrádek v paměti počítače, již pracovat umíme.

Struktura pole - Kolekce a LINQ v C# .NET

(Na obrázku je vidět pole osmi čísel)

Dvourozměrné pole

Ačkoli to není tak časté, v programování se občas setkáváme i s vícerozměrnými poli, a to zejména tehdy, pokud programujeme nějakou simulaci (např. hru).

Dvourozměrné pole si můžeme v paměti představit jako tabulku. Mohli bychom takto reprezentovat např. rozehranou partii piškvorek. Pokud bychom se chtěli držet reálných aplikací, které budete později v zaměstnání tvořit, můžeme si představit, že do 2D pole budeme ukládat informace o obsazenosti sedadel v kinosále. Situaci bychom si mohli graficky znázornit např. takto:

Struktura dvourozměrného pole - Kolekce a LINQ v C# .NET

(Na obrázku je vidět 2D pole reprezentující obsazenost kinosálu)

Kinosál by byl v praxi samozřejmě větší, ale jako ukázka nám toto pole postačí. 0 znamená volno, 1 obsazeno. Později bychom mohli doplnit i 2 jako rezervováno a podobně. Pro tyto stavy by bylo správnější vytvořit si vlastní datový typ, tzv. výčet, ale s ním se setkáme až později, proto si nyní musíme vystačit pouze s čísly.

2D pole deklarujeme v C# .NET následujícím způsobem:

int[,] kinosal = new int [5, 5];

První číslice udává počet sloupců, druhá počet řádků (samozřejmě si to můžeme určit i obráceně, např. matice v matematice se zapisují opačně).

Všechna číselná pole v C# .NET jsou po deklaraci automaticky inicializována samými nulami, na což se můžeme spolehnout. Vytvořili jsme si tedy v paměti tabulku plnou nul.

Naplnění daty

Nyní kinosál naplníme jedničkami tak, jak je vidět na obrázku výše. Protože budeme jako správní programátoři líní, využijeme k vytvoření řádku jedniček for cykly :) Pro přístup k prvku 2D pole musíme samozřejmě zadat dvě souřadnice.

kinosal[2, 2] = 1; // Prostředek
for (int i = 1; i < 4; i++) // 4. řádek
{
    kinosal[i, 3] = 1;
}
for (int i = 0; i < 5; i++) // Poslední řádek
{
    kinosal[i, 4] = 1;
}

Výpis

Výpis pole provedeme opět pomocí cyklu, na 2D pole budeme potřebovat cykly dva (jeden nám proiteruje sloupce a druhý řádky). Jako správní programátoři nevložíme počet řádků a sloupců do cyklů napevno, jelikož se údaje mohou změnit. C# .NET poskytuje na 2D poli vlastnost Length, jako tomu bylo u 1D pole, ale ta vrací celkový počet prvků v poli, v našem případě tedy 25. Nás bude zajímat metoda GetLength(), která jako parametr přijímá dimenzi (0 pro sloupce, 1 pro řádky) a vrátí nám počet prvků v této dimenzi. První dimenzí je počet sloupců, druhou počet řádků.

Cykly zanoříme do sebe tak, aby nám vnější cyklus projížděl řádky a vnitřní sloupce v aktuálním řádku. Po výpisu řádku je nutné odřádkovat. Oba cykly musí mít samozřejmě jinou řídicí proměnnou:

for (int j = 0; j < kinosal.GetLength(1); j++)
{
    for (int i = 0; i < kinosal.GetLength(0); i++)
    {
        Console.Write(kinosal[i, j]);
    }
    Console.WriteLine();
}

Výsledek:

Konzolová aplikace
00000
00000
00100
01110
11111

N-rozměrná pole

Někdy může být příhodné vytvořit si pole o ještě více dimenzích. My všichni si jistě dokážeme představit minimálně 3D pole. V příkladu s kinosálem se nabízí případ užití, kdy má budova více pater (nebo obecně více kinosálů). Vizualizace by vypadala asi nějak takto:

3D pole v C# .NET - Kolekce a LINQ v C# .NET

3D pole můžeme vytvořit týmž způsobem jako 2D pole:

int[, ,] kinosaly = new int [4, 4, 3];

Kód výše vytvoří 3D pole jako na obrázku. Přistupovat k němu budeme opět přes indexer (hranaté závorky) jako předtím, jenom musíme zadat tři souřadnice:

kinosaly[3, 2, 1] = 1; // Druhý kinosál, třetí řada, čtvrtý sloupec

Pokud metodě GetLength() zadáme parametr s hodnotou 2, získáváme počet „pater“ (kinosálů).

Pole polí

Mnoho programovacích jazyků vícerozměrná pole nepodporuje, C# je spíše výjimkou. I v ostatních jazycích si však přesto můžeme vytvořit pole s tolika rozměry, s kolika potřebujeme, jelikož 2D pole není vnitřně nic jiného než pole polí. Situaci si můžeme představit tak, že si vytvoříme pole o pěti prvcích (první řádek) a každá buňka v tomto řádku bude v sobě obsahovat další pole, jež reprezentuje sloupeček.

Takové 2D pole deklarujeme následujícím způsobem:

int[][] kinosal = new int[5][];

Výhodou takto deklarovaného 2D pole je fakt, že si do každého řádku/sloupce můžeme uložit tak velké pole, jak chceme. V některých případech tedy nemusíme plýtvat pamětí na celou tabulku a můžeme pole vytvořit „zubaté“ (anglicky jagged):

Pole polí v C# .NET - Kolekce a LINQ v C# .NET

Nevýhodou tohoto přístupu je, že musíme pole nepříjemně inicializovat sami. Původní řádek s pěti buňkami sice existuje, ale jednotlivé sloupečky si do něj musíme vložit sami (zatím si vložme všechny sloupečky o pěti prvcích):

for (int i = 0; i < kinosal.Length; i++)
{
    kinosal[i] = new int[5];
}

C# rovněž dále neposkytuje žádný komfort ve formě získání počtu sloupců a řádků polí polí. Velikost pole musíme získat takto:

int sloupcu = kinosal.Length;
int radku = 0;
if (sloupcu != 0)
    radku = kinosal[0].Length;

Všimněme si, že je nutné ptát se na počet sloupců. Je-li totiž počet 0, nemůžeme se dostat k prvnímu sloupci, abychom zjistili jeho délku (počet řádků ve sloupci).

K hodnotám v poli poté přistupujeme pomocí dvou indexerů:

kinosal[4][2] = 1; // Obsazujeme sedadlo v 5. sloupci a ve 3. řadě

Použití jediného indexeru nám vrátí celý sloupeček na daném indexu.

Zkrácená inicializace vícerozměrných polí

Ještě si ukážeme, že i vícerozměrná pole je možné rovnou inicializovat hodnotami (kód vytvoří rovnou zaplněný kinosál jako na obrázku):

int[,] kinosal = new int[,] {
    { 0, 0, 0, 0, 1 },
    { 0, 0, 0, 1, 1 },
    { 0, 0, 1, 1, 1 },
    { 0, 0, 0, 1, 1 },
    { 0, 0, 0, 0, 1 }
};

(Pole je v tomto zápisu otočené, jelikož definujeme sloupce, které zde zapisujeme jako řádky.)

Podobnou inicializaci můžeme použít dokonce i u polí zubatých (kód níže vytvoří zubaté pole jako na obrázku):

int[][] zubatePole = new int[][] {
    new int[] {15, 2, 8, 5, 3},
    new int[] {3, 3, 7},
    new int[] {9, 1, 16, 13},
    new int[] {},
    new int[] {5}
};

Na závěr bychom rádi dodali, že někteří lidé, kteří neumějí správně používat objekty, využívají 2D pole k ukládání více údajů o jediné entitě. Např. budeme chtít uložit výšku, šířku a délku pěti mobilních telefonů. Ačkoli se vám nyní může zdát, že se jedná o úlohu pro 3D pole, ve skutečnosti se jedná o úlohu pro obyčejné 1D pole (přesněji seznam) objektů typu Telefon. Pole si určitě ještě vyzkoušejte ve cvičení v tomto kurzu.

V následujícím kvízu, Kvíz - Genericita, List, N-rozměrné pole v C# .NET Kolekce, si vyzkoušíme nabyté zkušenosti z předchozích lekcí.


 

Měl jsi s čímkoli problém? Stáhni si vzorovou aplikaci níže a porovnej ji se svým projektem, chybu tak snadno najdeš.

Stáhnout

Stažením následujícího souboru souhlasíš s licenčními podmínkami

Staženo 463x (32.73 kB)
Aplikace je včetně zdrojových kódů v jazyce C#

 

Předchozí článek
Spojový seznam v C#
Všechny články v sekci
Kolekce a LINQ v C# .NET
Přeskočit článek
(nedoporučujeme)
Kvíz - Genericita, List, N-rozměrné pole v C# .NET Kolekce
Článek pro vás napsal David Hartinger
Avatar
Uživatelské hodnocení:
389 hlasů
David je zakladatelem ITnetwork a programování se profesionálně věnuje 15 let. Má rád Nirvanu, nemovitosti a svobodu podnikání.
Unicorn university David se informační technologie naučil na Unicorn University - prestižní soukromé vysoké škole IT a ekonomie.
Aktivity