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 8 - Pole v C# .NET

V minulé lekci kurzu, Ošetření uživatelských vstupů v C# .NET, jsme si ukázali ošetření uživatelských vstupů.

Dnes si v C# .NET tutoriálu představíme datovou strukturu pole a vyzkoušíme si, co všechno umí.

Pole

Představme si, že si chceme uložit nějaké údaje o více prvcích. Např. chceme v paměti uchovávat 10 čísel, hrací pole šachovnice nebo jména 50 uživatelů. Asi nám dojde, že v programování bude nějaká lepší cesta než začít bušit proměnné uzivatel1, uzivatel2 až např. uzivatel50. Nehledě na to, že jich může být třeba 1000. Jak by se pak navíc v takovém systému hledalo? Brrr, takto ne :)

Potřebujeme-li uchovávat větší množství proměnných stejného typu, tento problém nám řeší pole. Pole si můžeme představit jako řadu přihrádek, kdy v každé máme uložený jeden prvek. Přihrádky jsou očíslované tzv. indexy, přičemž první přihrádka má index 0.

Struktura pole - Základní konstrukce jazyka C# .NET

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

Programovací jazyky se velmi liší v tom, jak s polem pracují. V některých jazycích (zejména starších, kompilovaných) nebylo možné za běhu programu vytvořit pole s dynamickou velikostí (např. mu dát velikost dle nějaké proměnné). Pole se muselo deklarovat s konstantní velikostí přímo ve zdrojovém kódu. Toto se obcházelo tzv. pointery a vlastními datovými strukturami, což často vedlo k chybám při manuální správě paměti a k nestabilitě programu (např. v C++). Naopak některé interpretované jazyky umožňují nejen deklarovat pole s libovolnou velikostí, ale dokonce tuto velikost na již existujícím poli měnit (např. PHP). My víme, že C# je virtuální stroj, tedy cosi mezi kompilerem a interpretem. Proto můžeme pole založit s velikostí, kterou dynamicky zadáme až za běhu programu, ale velikost již existujícího pole už modifikovat nemůžeme. Toto lze samozřejmě obejít nebo použít jiné datové struktury, ale k tomu se dostaneme později.

Možná vás napadá, proč se tu polem zabýváme, když má evidentně mnoho omezení a existují lepší datové struktury. Odpověď je prostá: pole je totiž jednoduché. Nemyslíme tím pouze pro nás na pochopení, ale zejména pro samotný jazyk C#. S polem se rychle pracuje, protože prvky jsou v paměti jednoduše uloženy za sebou, všechny zabírají stejně místa a rychle se k nim přistupuje. Mnoho vnitřních funkčností v .NET proto nějak pracuje s polem nebo pole vrací. Jedná se tedy o klíčovou strukturu.

Pro hromadnou manipulaci s prvky pole se používají cykly.

Pole deklarujeme pomocí hranatých závorek:

int[] pole;

Na české klávesnici jsou hranaté závorky ukryté pod Pravým Alt společně s klávesami F a G:

Hranaté závorky - Základní konstrukce jazyka C# .NET

Výraz pole je samozřejmě název naší proměnné. Nyní jsme však pouze deklarovali, že v proměnné bude pole prvků typu int. Nyní musíme pole založit, abychom ho mohli používat. Použijeme k tomu klíčové slovo new, které na naší úrovni znalostí nejsme zatím schopní podrobně vysvětlit. Je to kvůli tomu, že pole je referenční datový typ, který budeme probírat v navazujícím kurzu Objektově orientovaného programování v C# .NET:

int[] pole = new int[10];

Nyní máme v proměnné pole pole o velikosti deseti prvků typu int.

K prvkům pole potom přistupujeme přes hranatou závorku. Pojďme nyní na první index (tedy index 0) uložit číslo 1.

int[] pole = new int[10];
pole[0] = 1;

Plnit pole takto ručně by bylo příliš pracné, proto použijeme cyklus a naplníme si pole čísly od 1 do 10. K naplnění použijeme for cyklus:

int[] pole = new int[10];
pole[0] = 1;
for (int i = 0; i < 10; i++)
    pole[i] = i + 1;

Abychom pole vypsali, můžeme za předchozí kód připsat:

for (int i = 0; i < pole.Length; i++)
    Console.Write("{0} ", pole[i]);

Všimněme si, že pole má vlastnost Length, kde je uložena jeho délka, tedy počet prvků.

Konzolová aplikace
1 2 3 4 5 6 7 8 9 10

Můžeme použít zjednodušenou verzi cyklu pro práci s kolekcemi, známou jako foreach. Tento cyklus projede všechny prvky v poli a jeho délku si zjistí sám. Jeho syntaxe je následující:

foreach (datovytyp promenna in kolekce)
{
    // příkazy
}

Cyklus projede prvky v kolekci (což je obecný název pro struktury, které obsahují více prvků, u nás to bude pole) postupně od prvního do posledního. Prvek máme v každé iteraci cyklu uložený v dané proměnné.

Také pro tento cyklus existuje ve Visual Studiu užitečný snippet: napíšeme foreach a dvakrát stiskneme Tabulátor, zbytek cyklu se sám dopíše. Zkuste si to.

Přepišme tedy náš dosavadní program pro foreach. Cyklus foreach nemá řídicí proměnnou, není tedy vhodný pro vytvoření našeho pole a použijeme ho jen pro výpis.

int[] pole = new int[10];
pole[0] = 1;
for (int i = 0; i < 10; i++)
    pole[i] = i + 1;
foreach (int i in pole)
    Console.Write("{0} ", i);
Console.ReadKey();

Výstup programu:

Konzolová aplikace
1 2 3 4 5 6 7 8 9 10

Pole samozřejmě můžeme naplnit ručně, a to i bez toho, abychom dosazovali postupně do každého indexu. Použijeme k tomu složené závorky a prvky oddělujeme čárkou:

string[] simpsonovi = {"Homer", "Marge", "Bart", "Lisa", "Maggie"};

Pole často slouží k ukládání mezivýsledků, které se potom dále v programu používají. Když potřebujeme nějaký výsledek 10x, tak ho nebudeme 10x počítat, ale spočítáme ho jednou a uložíme ho do pole, odkud poté výsledek jen načteme.

Metody na třídě Array

.NET nám poskytuje třídu Array, která obsahuje pomocné metody pro práci s poli. Pojďme se na ně podívat:

Sort()

Jak již název napovídá, metoda nám pole seřadí. Její jediný parametr je pole, které chceme seřadit. Metoda je dokonce tak chytrá, že pracuje podle toho, co máme v poli uložené. Stringy třídí podle abecedy, čísla podle velikosti. Zkusme si setřídit a vypsat naši rodinku Simpsonů:

string[] simpsonovi = {"Homer", "Marge", "Bart", "Lisa", "Maggie"};
Array.Sort(simpsonovi);
foreach (string s in simpsonovi)
    Console.Write("{0} ", s);
Console.ReadKey();

Konzolová aplikace
Bart Homer Lisa Maggie Marge

Zkuste si udělat pole čísel a vyzkoušejte si, že to opravdu funguje i pro ně.

Reverse()

Reverse() nám pole otočí (první prvek bude jako poslední atd.). Toho můžeme využít např. pro třídění pozpátku:

string[] simpsonovi = {"Homer", "Marge", "Bart", "Lisa", "Maggie"};
Array.Sort(simpsonovi);
Array.Reverse(simpsonovi);
foreach (string s in simpsonovi)
    Console.Write("{0} ", s);
Console.ReadKey();

IndexOf() a LastIndexOf()

Tyto metody vrátí index prvního nebo posledního nalezeného prvku. V případě nenalezení prvku metody vrátí -1. Každá z metod bere dva parametry: prvním je pole, druhým hledaný prvek. Umožníme uživateli zadat jméno Simpsona a řekneme mu, na které pozici je uložený. Teď to pro nás nemá hlubší význam, protože prvek pole je jen string. Bude se nám to však velmi hodit ve chvíli, kdy v poli budeme mít uloženy plnohodnotné objekty. Následující příklad tedy berme jako takovou přípravu.

string[] simpsonovi = {"Homer", "Marge", "Bart", "Lisa", "Maggie"};
Console.WriteLine("Ahoj, zadej svého oblíbeného Simpsona (z rodiny Simpsonů): ");
string simpson = Console.ReadLine();
int pozice = Array.IndexOf(simpsonovi, simpson);
if (pozice >= 0)
    Console.WriteLine("Jo, to je můj {0}. nejoblíbenější Simpson!", pozice + 1);
else
    Console.WriteLine("Hele, tohle není Simpson!");
Console.ReadKey();

Konzolová aplikace
Ahoj, zadej svého oblíbeného Simpsona (z rodiny Simpsonů):
Homer
Jo, to je můj 1. nejoblíbenější Simpson!

Copy()

Copy() již podle názvu zkopíruje část pole do jiného pole. Prvním parametrem je zdrojové pole, druhým cílové pole a třetím počet prvků, který se má zkopírovat.

Metody na poli

Třída Array není jedinou možností, jak s polem manipulovat. Přímo na samotné instanci pole (konkrétní proměnné) můžeme volat také spoustu metod. I když si zmíníme jen některé, je jich opravdu hodně. Nebudeme tedy uvádět příklady, metody si pouze popíšeme:

Length

Length jsme si již zmínili, vrátí délku pole. Není metodou, ale vlastností, proto se za ni nepíšou závorky ().

Následující metody jsou takzvané "extension metody". Podrobněji je probereme později. V tuto chvíli musíme jen vědět, že pro jejich zavolání potřebujeme balíček: using System.Linq;. Kód using System.Linq; si dopíšeme pod: using System;).

Min(), Max(), Average(), Sum()

Matematické metody, jež vracejí nejmenší prvek (Min()), největší prvek (Max()), průměr ze všech prvků (Average()) a součet všech prvků (Sum()). Metody nemají žádné parametry.

Concat(), Intersect(), Union()

Všechny tyto metody vrátí na výstupu nové pole a jako parametr mají druhé pole. Concat() vykoná nám již známou konkatenaci, tedy k našemu poli připojí druhé pole a takto vzniklé nové pole vrátí. Intersect() vykoná průnik obou polí, tedy sestaví pole s prvky, které jsou oběma polím společné. Union() naopak vykoná sjednocení, funguje tedy podobně jako Concat(), pouze prvky, které byly v obou polích, jsou v novém poli jen jednou.

First() a Last()

Již podle názvu metody vrátí první a poslední prvek, neberou žádné parametry.

Take() a Skip()

Obě tyto metody berou jako parametr počet prvků. Take() vrátí pole s daným počtem prvků zkopírovaných od začátku původního pole. Skip() naopak vrátí pole bez těchto prvních prvků.

Contains()

Metoda vrací true/false podle toho, zda se prvek uvedený v parametru metody v daném poli nachází.

Reverse()

Metodu Reverse() známe již z třídy Array. Pokud ji však voláme na konkrétním poli, tak se prvky v něm neotočí, nýbrž je vytvořeno nové otočené pole a to je vráceno. Metoda nemá žádné parametry.

Distinct()

Distinct() je metoda bez parametrů a zajistí, aby byl v poli každý prvek jen jednou, tedy vymaže duplicitní prvky a unikátní pole vrátí jako návratovou hodnotu metody, opět tedy nemodifikuje dané pole.

Mnoho metod nemění přímo naše pole, ale pouze vrátí pole nové (jsou to metody Concat(), Intersect(), Union(), Reverse() a Distinct()), ve kterém jsou provedeny požadované změny. Pokud chceme modifikovat původní pole, musíme do něj dosadit hodnoty. Zmíněné metody bohužel z důvodů, které pochopíme až později, nevracejí přímo pole, ale typ IEnumerable. Aby bylo dosazení výsledku zpět do pole možné, musíme ho ještě převést na pole metodou ToArray().

int[] cisla = { 1, 2, 3, 3, 3, 5 };
cisla = cisla.Distinct().ToArray();

Proměnná délka pole

Říkali jsme si, že délku pole můžeme definovat i za běhu programu. Pojďme si to zkusit a rovnou si vyzkoušejme nějakou metodu na poli:

Console.WriteLine("Ahoj, spočítám ti průměr známek. Kolik známek zadáš?");
int pocet = int.Parse(Console.ReadLine());
int[] cisla = new int[pocet];
for (int i = 0; i < pocet; i++)
{
    Console.Write("Zadejte {0}. číslo: ", i + 1);
    cisla[i] = int.Parse(Console.ReadLine());
}
Console.WriteLine("Průměr tvých známek je: {0}", cisla.Average());
Console.ReadKey();

Konzolová aplikace
Ahoj, spočítám ti průměr známek. Kolik známek zadáš?
5
Zadejte 1. číslo: 1
Zadejte 2. číslo: 2
Zadejte 3. číslo: 2
Zadejte 4. číslo: 3
Zadejte 5. číslo: 5
Průměr tvých známek je: 2,6

Tento příklad by bylo samozřejmě možné napsat i bez použití pole, ale co kdybychom chtěli spočítat např. medián? Nebo např. vypsat zadaná čísla pozpátku? To už by bez pole nešlo. Takto máme v poli k dispozici původní hodnoty a můžeme s nimi neomezeně a jednoduše pracovat.

To by pro dnešek stačilo, můžete si s polem hrát.

V následujícím kvízu, Kvíz - Podmínky, cykly, pole v C# .NET, 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 1415x (141.34 kB)
Aplikace je včetně zdrojových kódů v jazyce C#

 

Předchozí článek
Ošetření uživatelských vstupů v C# .NET
Všechny články v sekci
Základní konstrukce jazyka C# .NET
Přeskočit článek
(nedoporučujeme)
Kvíz - Podmínky, cykly, pole v C# .NET
Článek pro vás napsal David Hartinger
Avatar
Uživatelské hodnocení:
688 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