Aktuálně: Postihly zákazy tvou profesi? Poptávka po ajťácích prudce roste, využij slevové akce 30% výuky zdarma!
Pouze tento týden sleva až 80 % na e-learning týkající se PHP
Discount week - April - 30

8. diel - Poľa vo Visual Basicu

V minulej lekcii, Ošetrenie užívateľských vstupov , sme si ukázali ošetrenie užívateľských vstupov. V dnešnom VB.NET tutoriálu si predstavíme dátovú štruktúru poľa a vyskúšame si, čo všetko vie.

Poľa

Predstavte si, že si chcete uložiť nejaké údaje o viac prvkoch. Napr. chcete v pamäti uchovávať 10 čísel, políčka šachovnice alebo mena 50tich užívateľov. Asi vám dôjde, že v programovaní bude nejaká lepšia cesta, než začať búšiť premenné Užívateľ 1, Užívateľ 2... až uzivatel50. Nehľadiac na to, že ich môže byť potrebné 1000. A ako by sa v tom potom 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 poľa. Môžeme si ho predstaviť ako rad priehradiek, kde v každej máme uložený jeden prvok. Priehradky sú očíslované tzv. indexy, prvý má index 0.

štruktúra poľa

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

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 nejaké premenné). Pole sa muselo deklarovať s konštantnou veľkosťou priamo v zdrojovom kóde. Toto sa obchádzalo tzv. Pointer a vlastnými dátovými štruktúrami, čo často viedlo k chybám pri manuálnej správe pamäte a 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 VB.NET je virtuálny stroj, teda čosi medzi kompilerem a interpretom. Preto môžeme pole založiť s veľkosťou, ktorú dynamicky zadáme až za behu programu, ale veľkosť existujúceho poľa modifikovať nemôžeme. Možno to samozrejme obísť alebo použiť iné dátové štruktúry, ale k tomu sa dostaneme.

Možno vás napadá, prečo sa tu zaoberáme s poľom, keď má evidentne veľa obmedzení a existujú lepšie dátové štruktúry. Odpoveď je prostá: poľa je totiž jednoduché. Nemyslím pre nás na pochopenie (to tiež), ale najmä pre Visual Basic. Rýchlo sa s ním pracuje, pretože prvky sú v pamäti jednoducho uložené za sebou, zaberajú všetky rovnako miesta a rýchlo sa k nim pristupuje. Mnoho vnútorných funkčnosťou v .NET preto nejako pracuje s poľom alebo poľa vracia. Je to kľúčová štruktúra.

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

Pole deklarujeme pomocou okrúhlych zátvoriek:

Dim pole(9) As Integer

Slovo pole je samozrejme názov našej premennej. Teraz sme deklarovali, že v premennej bude pole 10 prvkov typu Integer. Pole sa založí automaticky, ak zadáme počet prvkov v poli. Teraz máme v premennej pole poľa veľkosti 10 čísel typu Integer. Pozor na skutočnosť, že ako dĺžku zadávame posledný index, ktorý je číslovaný od nuly, pole(9) má teda 10 prvkov.

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

Dim pole(9) As Integer
pole(0) = 1

Plniť pole takhle ručne by bolo príliš pracné, použijeme cyklus a naplníme si pole číslami od 1 do 10. K naplneniu použijeme For cyklus:

Dim pole(9) As Integer
For i As Integer = 0 To 9
    pole(i) = i + 1
Next

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

For i As Integer = 0 To pole.Length - 1
    Console.Write("{0} ", pole(i))
Next

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

Konzolová aplikácia
1 2 3 4 5 6 7 8 9 10
Tento výukový obsah pomáhajú rozvíjať nasledujúce firmy, ktoré možno hľadajú práve teba!

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

For Each premenna As Integer In poľa
    Console.WriteLine(premenna)
Next

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

Prepíšme teda náš doterajší program pre For Each. For Each nemá riadiace premennú, nie je teda vhodný pre vytvorenie nášho poľa a použijeme ho len pre výpis.

Dim pole(9) As Integer
pole(0) = 1
For i As Integer = 0 To 9
    pole(i) = i + 1
Next
For Each promenna As Integer In pole
    Console.Write("{0} ", promenna)
Next
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ých zátvoriek a prvky oddeľujeme čiarkou:

Dim simpsonovi() = {"Homer", "Marge", "Bart", "Lisa", "Maggie"}

Všimnite si, že v tomto prípade sme nemuseli uviesť počet prvkov.

Pole často slúži na ukladanie medzivýsledkov, ktoré sa potom ďalej v programe používajú. Keď niečo potrebujeme 10x, tak to nebudeme 10x počítať, ale spočítame to raz a uložíme do poľa, odtiaľ 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 poľa zoradí. Jej jediný parameter je pole, ktoré chceme zoradiť. Je dokonca tak múdra, že pracuje podľa toho, čo máme v poli uložené. Stringy triedi podľa abecedy, čísla podľa veľkosti. Skúsme si zoradí a vypísať našu rodinku Simpson:

Dim simpsonovi() = {"Homer", "Marge", "Bart", "Lisa", "Maggie"}
Array.Sort(simpsonovi)
For Each s As String In simpsonovi
    Console.Write("{0} ", s)
Next
Console.ReadKey()

Konzolová aplikácia
Bart Homer Lisa Maggie Marge

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

Reverse ()

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

Dim simpsonovi() = {"Homer", "Marge", "Bart", "Lisa", "Maggie"}
Array.Sort(simpsonovi)
Array.Reverse(simpsonovi)
For Each s As String In simpsonovi
    Console.Write("{0} ", s)
Next
Console.ReadKey()

IndexOf () a lastIndexOf ()

Tieto metódy vráti index prvého alebo posledného nájdeného prvku. V prípade nenájdenia prvku vráti -1. Metóda berie dva parametre, prvým je pole, druhým hľadaný prvok. Umožníme užívateľovi zadať meno Simpsons a povieme mu, na akej 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, kedy v poli budeme mať uložené plnohodnotné objekty. Berme to teda ako takú prípravu.

Dim simpsonovi() = {"Homer", "Marge", "Bart", "Lisa", "Maggie"}
Console.WriteLine("Ahoj zadaj svojho obľúbeného Simpsni (z rodiny Simpson): ")
Dim simpson As String = Console.ReadLine()
Dim pozice As Integer = Array.IndexOf(simpsonovi, simpson)
If pozice >= 0 Then
    Console.WriteLine("Jo, to je môj {0}. najobľúbenejší Simpson!", pozice + 1)
Else
    Console.WriteLine("Hele, toto nie je Simpson")
End If
Console.ReadKey()

Konzolová aplikácia
Ahoj zadaj svojho obľúbeného Simpsni (z rodiny Simpsů):
Homer
Jo, to je môj 1. najobľúbenejší Simpson!

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é a tretím počet znakov, ktorý sa má skopírovať.

Metódy na poli

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

Length

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

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

Matematické metódy, vracajúci 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áti na výstupe nové pole a ako parameter majú druhé pole. Concat() vykoná nám už známu konkatenaci, teda k nášmu poli pripojí druhé pole a takto vzniknuté nové pole vráti. Intersect() vykoná prienik oboch polí, teda zostaví pole s prvkami, ktoré sú obom poliam spoločné. Union() naopak vykoná zjednotenie, funguje teda podobne ako Concat(), len 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ádzajú.

Reverse ()

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

Distinct ()

Distinct() je metóda bez parametrov a zabezpečí, 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 polia, ale vráti iba polia nové (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ň takto dosadiť. Tieto metódy bohužiaľ z dôvodov, ktoré pochopíme až neskôr, nevracia priamo pole, ale typ IEnumerable. Aby bolo dosadení výsledku späť do poľa možné, musíme ho ešte previesť na pole metódou ToArray().

Dim cisla() = { 1, 2, 3, 3, 3, 5 }
cisla = cisla.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("Ahoj, spočítám ti priemer známok. Koľko známok zadáš?")
Dim pocet As Integer = Console.ReadLine()
Dim cisla(pocet - 1) As Integer
For i As Integer = 0 To pocet - 1
    Console.Write("Zadajte {0}. číslo: ", i + 1)
    cisla(i) = Console.ReadLine()
Next
Console.WriteLine("Priemer tvojich známok je: {0}", cisla.Average())
Console.ReadKey()
Konzolová aplikácia
Ahoj, spočítám ti priemer známok. Koľko známok zadáš?
5
Zadajte 1. číslo: 1
Zadajte 2. číslo: 2
Zadajte 3. číslo: 2
Zadajte 4. číslo: 3
Zadajte 5. číslo: 5
Priemer tvojich známok je: 2,6

Tento príklad by išiel samozrejme 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 k dispozícii v poli pôvodnej hodnoty a môžeme s nimi neobmedzene a jednoducho pracovať.

To by pre dnešok stačilo, môžete si s poľom hrať. V budúcej lekcii, Riešené úlohy k 8. lekcii VB.NET , na vás čaká prekvapenie ;-)

V nasledujúcom cvičení, Riešené úlohy k 8. lekcii VB.NET, si precvičíme nadobudnuté skúsenosti z predchádzajúcich lekcií.


 

Predchádzajúci článok
Ošetrenie užívateľských vstupov
Všetky články v sekcii
Základné konštrukcie jazyka Visual Basic (VB .NET)
Článok pre vás napísal Michal Žůrek - misaz
Avatar
Ako sa ti páči článok?
Ešte nikto nehodnotil, buď prvý!
Autor se věnuje tvorbě aplikací pro počítače, mobilní telefony, mikroprocesory a tvorbě webových stránek a webových aplikací. Nejraději programuje ve Visual Basicu a TypeScript. Ovládá HTML, CSS, JavaScript, TypeScript, C# a Visual Basic.
Aktivity (2)

 

 

Komentáre

Avatar
Ondrej_d
Člen
Avatar
Ondrej_d:24.2.2015 19:33

Dovolim si opravit priemer znamok:

Console.Write­Line("Ahoj, spočítám ti průměr známek. Kolik známek zadáš?")
Dim pocet As Integer = Console.ReadLine()
Dim cisla(pocet - 1) As Integer
For i = 0 To (pocet - 1)
Console.Write("Za­dejte {0}. číslo: ", i + 1)
cisla(i) = Console.ReadLine()
Next
Console.Write­Line("Průměr tvých známek je: {0}", cisla.Average())
Console.ReadKey()

kedze 10 znamek znamena 11 vstupov

 
Odpovedať
24.2.2015 19:33
Avatar
Jaroslav Trojan
Redaktor
Avatar
Jaroslav Trojan:8.6.2016 9:57

pole simpsonovi() se nedá naplnit jmény, protože jména červeně podtrhne a hlásí error: String se nedá konvertovat na String , tak co s tím? Díky!

Odpovedať
8.6.2016 9:57
statik
Avatar
Jaroslav Trojan
Redaktor
Avatar
Jaroslav Trojan:8.6.2016 10:02

Dim simpsonovi() As String=("Homer", "Merge", ...atd )
Jména podtrhuje červeně a hlásí error

Odpovedať
8.6.2016 10:02
statik
Avatar
Odpovedá na Jaroslav Trojan
Michal Žůrek - misaz:8.6.2016 20:07

patří tam složené závorky, ne kulaté.

Dim simpsonovi() As String = {"Homer", "Marge", "Bart", "Lisa", "Meggie"}
 
Odpovedať
8.6.2016 20:07
Avatar
Miroslav Němeček:26.2.2017 12:06

Potřebuju ze stringů vstup2(), s hodnotami např "56794","71697" nebo "93156" vypsat hodnoty do proměnné dcis() typu Ulong(UInt64) ale pořád mi to hází chyby buď přetečení pole, nebo v téhle verzi kódu dcis() zůstane vždy 0.

For i as integer = 0 To vstup2.Length
dcis(i) = CULng(Convert­.ToUInt64(vstup2(i­)))
i = i + 1
Next

 
Odpovedať
26.2.2017 12:06
Tento výukový obsah pomáhajú rozvíjať nasledujúce firmy, ktoré možno hľadajú práve teba!
Avatar
Odpovedá na Miroslav Němeček
Michal Žůrek - misaz:26.2.2017 13:00

Ve VB se nepíše

i = i + 1

to se dělá samo.

Visual Basic cykl provádí i pro poslední hodnotu (v C# je to ekvivaletní k operátoru <= v podmínce cyklu), takže od koncové proměnné pole musíš odečíst 1.

For i as integer = 0 To vstup2.Length - 1
    dcis(i) = CULng(Convert.ToUInt64(vstup2(i)))
Next
 
Odpovedať
26.2.2017 13:00
Avatar
Odpovedá na Michal Žůrek - misaz
Miroslav Němeček:27.2.2017 20:37

Dík, tak teď to jen předělat.

 
Odpovedať
27.2.2017 20:37
Avatar
Neaktivní uživatel:7.6.2018 11:35

Ahoj, ten průměr známek nepočítá správně, tak jak by měl.
Pokud napíšeš, že máš 2 známky a každá z nich má hodnotu 2, tak ti to spočítá průměr 1.333333333, což je blbost.

Editované 7.6.2018 11:36
Odpovedať
7.6.2018 11:35
Neaktivní uživatelský účet
Avatar
David Čápka
Tým ITnetwork
Avatar
Odpovedá na Neaktivní uživatel
David Čápka:7.6.2018 11:44

Ahoj, má tam být Dim cisla(pocet - 1) As Integer, díky, opravil jsem to.

Odpovedať
7.6.2018 11:44
Jsem moc rád, že jsi na síti, a přeji ti top IT kariéru, ať jako zaměstnanec nebo podnikatel. Máš na to! :)
Avatar
Dávid Dopirák:7. apríla 19:17

Ahoj,
prečo pri dátovom type BYTE mi metóda

.Average

nevie počítať priemer ?

Je to predsa tiež číslený dátový typ nie ?

Díky za odpoveď

 
Odpovedať
7. apríla 19:17
Robíme čo je v našich silách, aby bola tunajšia diskusia čo najkvalitnejšia. Preto do nej tiež môžu prispievať len registrovaní členovia. Pre zapojenie sa do diskusie sa zaloguj. Ak ešte nemáš účet, zaregistruj sa, je to zadarmo.

Zatiaľ nikto nevložil komentár - buď prvý!