Vianoce v ITnetwork sú tu! Dobí si teraz kredity a získaj až 80 % extra kreditov na e-learningové kurzy ZADARMO. Zisti viac.
Hľadáme nové posily do ITnetwork tímu. Pozri sa na voľné pozície a pridaj sa k najagilnejšej firme na trhu - Viac informácií.

8. diel - Poľa v C# .NET

V minulej lekcii kurzu, Ošetrenie užívateľských vstupov v C# .NET, sme si ukázali ošetrenie užívateľských vstupov.

Dnes si v C# .NET tutoriále predstavíme dátovú štruktúru poľa a vyskúšame si, čo všetko vie.

Pole

Predstavme si, že si chceme uložiť nejaké údaje o viacerých prvkoch. Napr. chceme v pamäti uchovávať 10 čísel, hracie pole šachovnice alebo mená 50 užívateľov. Asi nám dôjde, že v programovaní bude nejaká lepšia cesta ako začať búšiť premenné user1, user2 až napr. user50. Nehľadiac na to, že ich môže byť treba 1000. Ako by sa potom navyše v takomto systéme hľadalo? Brrr, takto nie :)

Ak potrebujeme uchovávať väčšie množstvo premenných rovnakého typu, tento problém nám rieši pole. Pole si môžeme predstaviť ako rad priehradiek, kedy v každej máme uložený jeden prvok. Priehradky sú očíslované tzv. indexy, pričom prvá priehradka má index 0:

Štruktúra poľa - Základná konštrukcia jazyka C# .NET

(Na obrázku je vidieť pole ôsmich čísel.)

Programovacie jazyky sa veľmi líšia v tom, ako s poľom pracujú. V niektorých jazykoch (najmä starších, kompilovaných) nebolo možné za behu programu vytvoriť pole s dynamickou veľkosťou (napr. mu dať veľkosť podľa nejakej premennej). Pole sa muselo deklarovať s konštantnou veľkosťou priamo v zdrojovom kóde. Toto sa obchádzalo tzv. pointermi a vlastnými dátovými štruktúrami, čo často viedlo k chybám pri manuálnej správe pamäte a k nestabilite programu (napr. v C++). Naopak niektoré interpretované jazyky umožňujú nielen deklarovať pole s ľubovoľnou veľkosťou, ale dokonca túto veľkosť na už existujúcom poli meniť (napr. PHP). My vieme, že C# je virtuálny stroj, teda čosi medzi kompilerom a interpretom. Preto môžeme pole založiť s veľkosťou, ktorú dynamicky zadáme až za behu programu, ale veľkosť už existujúceho poľa už modifikovať nemôžeme. Toto je samozrejme možné obísť alebo použiť iné dátové štruktúry, ale k tomu sa dostaneme neskôr.

Možno vás napadá, prečo sa tu poľom zaoberáme, keď má evidentne mnoho obmedzení a existujú lepšie dátové štruktúry. Odpoveď je jednoduchá: pole je totiž jednoduché. Nemyslíme tým iba pre nás na pochopenie, ale najmä pre samotný jazyk C#. S poľom sa rýchlo pracuje, pretože prvky sú v pamäti jednoducho uložené za sebou, všetky zaberajú rovnako miesta a rýchlo sa k nim pristupuje. Veľa vnútorných funkčností v .NET preto nejako pracuje s poľom alebo poľa vracia. Ide teda o kľúčovú štruktúru.

Na hromadnú manipuláciu s prvkami poľa sa používajú cykly.

Pole deklarujeme pomocou hranatých zátvoriek:

int[] array;

Na slovenskej klávesnici sú hranaté zátvorky ukryté pod Pravým Alt spoločne s klávesmi F a G:

Hranaté zátvorky - Základná konštrukcia jazyka C# .NET

Výraz array je samozrejme názov našej premennej. Teraz sme však iba deklarovali, že v premennej bude pole prvkov typu int. Teraz musíme pole založiť, aby sme ho mohli používať. Použijeme na to kľúčové slovo new, ktoré na našej úrovni znalostí nie sme zatiaľ schopní podrobne vysvetliť. Je to kvôli tomu, že pole je referenčný dátový typ, ktorý budeme preberať v nadväzujúcom kurze Objektovo orientovaného programovania v C# .NET:

int[] array = new int[10];

Teraz máme v premennej array poľa o veľkosti desiatich prvkov typu int.

K prvkom poľa potom pristupujeme cez hranatú zátvorku. Poďme teraz na prvý index (teda index 0) uložiť číslo 1:

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

Plniť pole takto ručne by bolo príliš pracné, preto použijeme cyklus a naplníme si pole číslami od 1 do 10. Na naplnenie použijeme for cyklus:

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

Aby sme pole vypísali, môžeme za predchádzajúci kód pripísať:

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

Všimnime si, že pole má vlastnosť Length, kde je uložená jeho dĺžka, teda počet prvkov.

Výstup:

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

Môžeme použiť zjednodušenú verziu cyklu pre prácu s kolekciami, známu ako foreach. Tento cyklus prejde všetky prvky v poli a jeho dĺžku si zistí sám. Jeho syntax je nasledovná:

foreach (datatype variable in collection)
{
    // commands
}

Cyklus prejde prvky v kolekcii (čo je všeobecný názov pre štruktúry, ktoré obsahujú viac prvkov, u nás to bude pole) postupne od prvého do posledného. Prvok máme v každej iterácii cyklu uložený v danej premennej.

Aj pre tento cyklus existuje vo Visual Studiu užitočný snippet: napíšeme foreach a dvakrát stlačíme Tabuľátor, zvyšok cyklu sa sám dopíše. Skúste si to.

Prepíšme teda náš doterajší program pre foreach. Cyklus foreach nemá riadiacu premennú, nie je teda vhodný na vytvorenie nášho poľa a použijeme ho len na výpis:

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

Výstup programu:

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

Pole samozrejme môžeme naplniť ručne, a to aj bez toho, aby sme dosadzovali postupne do každého indexu. Použijeme na to zložené zátvorky a prvky oddeľujeme čiarkou:

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

Pole často slúžia na ukladanie medzivýsledkov, ktoré sa potom ďalej v programe používajú. Keď potrebujeme nejaký výsledok 10x, tak ho nebudeme 10x počítať, ale spočítame ho raz a uložíme ho do poľa, odkiaľ potom výsledok len načítame.

Metódy na triede Array

.NET nám poskytuje triedu Array, ktorá obsahuje pomocné metódy pre prácu s poľami. Poďme sa na ne pozrieť:

Sort()

Ako už názov napovedá, metóda nám pole zoradí. Jej jediný parameter je pole, ktoré chceme zoradiť. Metóda je dokonca taká múdra, že pracuje podľa toho, čo máme v poli uložené. Stringy triedia podľa abecedy, čísla podľa veľkosti. Skúsme si zotriediť a vypísať našu rodinku Simpsonovcov:

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

Výstup:

Konzolová aplikácia
Bart Homer Lisa Maggie Marge

Skúste si urobiť pole čísel a vyskúšajte si, že to naozaj funguje aj pre nich.

Reverse()

Reverse() nám pole otočí (prvý prvok bude ako posledný atď.). To môžeme využiť napr. pre triedenie dozadu:

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

IndexOf() a LastIndexOf()

Tieto metódy vrátia index prvého alebo posledného nájdeného prvku. V prípade nenájdenia prvku metódy vráti -1. Každá z metód berie dva parametre: prvým je pole, druhým hľadaný prvok. Umožníme užívateľovi zadať meno Simpsona a povieme mu, na ktorej pozícii je uložený. Teraz to pre nás nemá hlbší význam, pretože prvok poľa je len string. Bude sa nám to však veľmi hodiť vo chvíli, keď v poli budeme mať uložené plnohodnotné objekty. Nasledujúci príklad teda berme ako takú prípravu:

string[] simpsons = {"Homer", "Marge", "Bart", "Lisa", "Maggie"};
Console.WriteLine("Hello! What is your favorite character in the Simpsons (you may only choose from the core family members): ");
string simpson = Console.ReadLine();
int position = Array.IndexOf(simpsons, simpson);
if (position >= 0)
    Console.WriteLine("If I had to rank them, that would be no. {0} on my list.", position + 1);
else
    Console.WriteLine("Hey! That's not a Simpson!");
Console.ReadKey();

Výstup:

Konzolová aplikácia
Hello! What is your favorite character in the Simpsons (you may only choose from the core family members):
Homer
If I had to rank them, that would be no. 1 on my list.

Copy()

Copy() už podľa názvu skopíruje časť poľa do iného poľa. Prvým parametrom je zdrojové pole, druhým cieľové pole a tretím počet prvkov, ktorý sa má skopírovať.

Metódy na poli

Trieda Array nie je jedinou možnosťou, ako s poľom manipulovať. Priamo na samotnej inštancii poľa (konkrétne premenné) môžeme volať aj veľa metód. Aj keď si spomenieme len niektoré, je ich naozaj veľa. Nebudeme teda uvádzať príklady, metódy si iba popíšeme:

Length

Length sme si už spomenuli, vráti dĺžku poľa. Nie je metódou, ale vlastností, preto sa za ňu nepíšu zátvorky ().

Nasledujúce metódy sú takzvané "extension metódy". Podrobnejšie ich preberieme neskôr. V tejto chvíli musíme len vedieť, že na ich zavolanie potrebujeme balíček: using System.Linq;. Kód using System.Linq; si dopíšeme pod: using System;.

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

Matematické metódy, ktoré vracajú najmenší prvok (Min()), najväčší prvok (Max()), priemer zo všetkých prvkov (Average()) a súčet všetkých prvkov (Sum()). Metódy nemajú žiadne parametre.

Concat(), Intersect(), Union()

Všetky tieto metódy vrátia na výstupe nové pole a ako parameter majú druhé pole. Concat() vykoná nám už známu konkatenáciu, teda k nášmu poľu pripojí druhé pole a takto vzniknuté nové pole vráti. Intersect() vykoná prienik oboch polí, teda zostaví polia s prvkami, ktoré sú obom poliam spoločné. Union() naopak vykoná zjednotenie, funguje teda podobne ako Concat(), iba prvky, ktoré boli v oboch poliach, sú v novom poli len raz.

First() a Last()

Už podľa názvu metódy vráti prvý a posledný prvok, neberú žiadne parametre.

Take() a Skip()

Obe tieto metódy berú ako parameter počet prvkov. Take() vráti pole s daným počtom prvkov skopírovaných od začiatku pôvodného poľa. Skip() naopak vráti pole bez týchto prvých prvkov.

Contains()

Metóda vracia true / false podľa toho, či sa prvok uvedený v parametri metódy v danom poli nachádza.

Reverse()

Metódu Reverse() poznáme už z triedy Array. Pokiaľ ju však voláme na konkrétnom poli, tak sa prvky v ňom neotočia, ale je vytvorené nové otočené pole a to je vrátené. Metóda nemá žiadne parametre.

Distinct()

Distinct() je metóda bez parametrov a zaistí, aby bol v poli každý prvok len raz, teda vymaže duplicitné prvky a unikátne pole vráti ako návratovú hodnotu metódy, opäť teda nemodifikuje dané pole.

Mnoho metód nemení priamo naše pole, ale iba vráti nové pole (sú to metódy Concat(), Intersect(), Union(), Reverse() a Distinct()), v ktorom sú vykonané požadované zmeny. Ak chceme modifikovať pôvodné pole, musíme doň dosadiť hodnoty. Spomínané metódy bohužiaľ z dôvodov, ktoré pochopíme až neskôr, nevracajú priamo pole, ale typ IEnumerable. Aby bolo dosadenie výsledku späť do poľa možné, musíme ho ešte previesť na pole metódou ToArray():

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

Premenná dĺžka poľa

Hovorili sme si, že dĺžku poľa môžeme definovať aj za behu programu. Poďme si to skúsiť a rovno si vyskúšajme nejakú metódu na poli:

Console.WriteLine("Hello, I'll calculate your grade average.");
Console.WriteLine("How many grades would you like to enter?");
int count = int.Parse(Console.ReadLine());
int[] numbers = new int[count];
for (int i = 0; i < count; i++)
{
    Console.Write("Enter grade number {0}: ", i + 1);
    numbers[i] = int.Parse(Console.ReadLine());
}
Console.WriteLine("Your grade average is: {0}", numbers.Average());
Console.ReadKey();

Výstup:

Konzolová aplikácia
Hello, I'll calculate your grade average.
How many grades would you like to enter?
5
Enter grade number 1: 1
Enter grade number 2: 2
Enter grade number 3: 2
Enter grade number 4: 3
Enter grade number 5: 5
Your grade average is: 2.6

Tento príklad by bolo samozrejme možné napísať aj bez použitia poľa, ale čo keby sme chceli spočítať napr. medián? Alebo napr. vypísať zadané čísla pospiatky? To už by bez poľa nešlo. Takto máme v poli k dispozícii pôvodné hodnoty a môžeme s nimi neobmedzene a jednoducho pracovať.

To by pre dnešok stačilo, môžete sa s poľom hrať.

V nasledujúcom kvíze, Kvíz - Podmienky, cykly, polia v C# .NET, si vyskúšame nadobudnuté skúsenosti z predchádzajúcich lekcií.


 

Mal si s čímkoľvek problém? Stiahni si vzorovú aplikáciu nižšie a porovnaj ju so svojím projektom, chybu tak ľahko nájdeš.

Stiahnuť

Stiahnutím nasledujúceho súboru súhlasíš s licenčnými podmienkami

Stiahnuté 3x (189.72 kB)
Aplikácia je vrátane zdrojových kódov v jazyku C#

 

Predchádzajúci článok
Ošetrenie užívateľských vstupov v C# .NET
Všetky články v sekcii
Základná konštrukcia jazyka C# .NET
Preskočiť článok
(neodporúčame)
Kvíz - Podmienky, cykly, polia v C# .NET
Článok pre vás napísal David Hartinger
Avatar
Užívateľské hodnotenie:
4 hlasov
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 sa informačné technológie naučil na Unicorn University - prestížnej súkromnej vysokej škole IT a ekonómie.
Aktivity