Vydělávej až 160.000 Kč měsíčně! Akreditované rekvalifikační kurzy s garancí práce od 0 Kč. Více informací.
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

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

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 pokud programujeme nějakou simulaci (např. hru).

Dvourozměrné pole si můžeme v paměti představit jako tabulku a 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 obsazenostech sedadel v kinosálu. 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 - 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, takže si teď 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, můžeme se na to 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 2 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 opět provedeme pomocí cyklu, na 2d pole budeme potřebovat cykly 2 (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 může 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á přijímá jako parametr 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 řídící 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. S příkladem 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 samý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, jen již musíme zadat 3 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ů vlastně vícerozměrná pole nepodporuje, C# je spíše výjimkou. Můžeme si v nich ale stejně vytvořit kolika-rozměrné pole chceme, 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 (1. řádek) a každá buňka v tomto řádku v sobě bude obsahovat další pole, reprezentující 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 jak velké pole 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 navkládat sami (zatím si vložme všechny sloupečky o 5ti 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ěte si, že je nutné ptát se na počet sloupců, pokud je totiž 0, nemůžeme se dostat k 1. sloupci, abychom zjistili jeho délku (počet řádků ve sloupci).

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

kinosal[4][2] = 1; // Obsazujeme sedadlo v 5. sloupci a 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 bych rád dodal, že někteří lidé, kteří neumí správně používat objekty, využívají 2D polí 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 na 3D pole, ve skutečnosti se jedná o úlohu na obyčejné 1D pole (přesněji seznam) objektů typu Telefon. Pole si určitě ještě vyzkoušejte ještě v 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 425x (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í:
305 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