IT rekvalifikácia. Seniorní programátori zarábajú až 6 000 €/mesiac a rekvalifikácia je prvým krokom. Zisti, ako na to!

6. diel - Cykly v Dart

V predchádzajúcom cvičení, Riešené úlohy k 5. lekcii Dart, sme si precvičili získané skúsenosti z predchádzajúcich lekcií.

V minulej lekcii, Riešené úlohy k 5. lekcii Dart , sme si vysvetlili podmienky. Teraz prejdeme k cyklom, po dnešnom Dart tutoriálu už budeme mať takmer kompletnú výbavu základných konštrukcií a budeme schopní tvoriť rozumné aplikácie.

Cykly

Ako už slovo cyklus napovie, niečo sa bude opakovať. Keď chceme v programe niečo urobiť 100x, určite nebudeme písať pod seba 100x ten istý kód, ale vložíme ho do cyklu. Cyklov máme niekoľko druhov, vysvetlíme si, kedy ktorý použiť. Samozrejme si ukážeme praktické príklady.

For cyklus

Tento cyklus má stanovený pevný počet opakovaní a hlavne obsahuje tzv. Riadiace premennú (celočíselnú), v ktorej sa postupne počas behu cyklu menia hodnoty. Syntax (zápis) cyklu for je nasledovná:

for (promenna; podminka; prikaz)
  • premenna je riadiaca premenná cyklu, ktoré nastavíme počiatočnú hodnotu (najčastejšie 0, pretože v programovaní všetko začína od nuly, nie od jednotky). Napr. teda int i = 0. Samozrejme si môžeme premennú aj vytvoriť niekde nad tým a už nemusíme písať slovíčko int, býva ale zvykom používať práve int i.
  • podmienka je podmienka vykonanie ďalšieho kroku cyklu. Akonáhle nebude platiť, cyklus sa ukončí. Podmienka môže byť napr (i < 10).
  • prikaz nám hovorí, čo sa má v každom kroku s riadiacou premennou stáť. Teda či sa má zvýšiť alebo znížiť. K tomu využijeme špeciálnych operátorov ++ a --, tie samozrejme môžete používať aj úplne bežne mimo cyklus, slúži na zvýšenie alebo zníženie premenné o 1.

Poďme si urobiť jednoduchý príklad, väčšina z nás určite pozná Sheldona z The Big Bang Theory. Pre tých čo nie, budeme simulovať situáciu, kedy klope na dvere svojej susedky. Vždy 3x zaklope a potom zavolá: "Penny!". Náš kód by bez cyklov vyzeral takto:

print('Knock');
print('Knock');
print('Knock');
print('Penny!');

My ale už nič nemusíme otrocky opisovať:

for (int i = 0; i < 3; i++) {
    print('Knock');
}

print('Penny!');

Výstup programu:

Konzolová aplikácia
Knock
Knock
Knock
Penny!

Cyklus prebehne 3x, spočiatku je v premennej i nula, cyklus vypíše "Knock" a zvýši premennú i o jedna. Potom beží rovnako s jednotkou a dvojkou. Akonáhle je v i trojka, už nesúhlasí podmienka i < 3 a cyklus končí. O vynechávanie zložených zátvoriek platí to isté, čo u podmienok. V tomto prípade tam nemusí byť, pretože cyklus spúšťa iba jediný príkaz. Teraz môžeme miesto trojky napísať do deklarácie cyklu desiatku. Príkaz sa spustí 10x bez toho aby sme písali niečo navyše. Určite vidíte, že cykly sú mocným nástrojom.

Skúsme si teraz využiť to, že sa nám premenná inkrementuje. Vypíšme si čísla od jednej do desať. Pretože nebudeme chcieť, aby sa nám v konzole text vždy odřádkoval, nemôžeme použiť metódu print(). Podobne ako pri načítaní využívame stdin, využijeme stdout s metódou write(). (Alternatíva k print() by bola metóda stdout.writeln()). Aby metóda fungovala, nezabudnite načítať knižnicu dart:io.

for (int i = 1; i <= 10; i++)
    stdout.write('$i');

Vidíme, že riadiaci premenná má naozaj v každej iterácii (priebehu) inú hodnotu. Všimnite si, že v cykle tentoraz nezačíname na nule, ale môžeme nastaviť počiatočnú hodnotu 1 a koncovú 10. V programovaní je však zvykom začínať od nuly, neskôr zistíme prečo.

Teraz si vypíšeme malú násobilku (násobky čísel 1 až 10, vždy do desať). Stačí nám urobiť cyklus od 1 do 10 a premennú vždy násobiť daným číslom. Mohlo by to vyzerať asi takto:

print('Malá násobilka pomocí cyklu:');
for (int i = 1; i <= 10; i++)
    stdout.write('${i} ');
stdout.writeln();
for (int i = 1; i <= 10; i++)
    stdout.write('${i * 2} ');
stdout.writeln();
for (int i = 1; i <= 10; i++)
    stdout.write('${i * 3} ');
stdout.writeln();
for (int i = 1; i <= 10; i++)
    stdout.write('${i * 4} ');
stdout.writeln();
for (int i = 1; i <= 10; i++)
    stdout.write('${i * 5} ');
stdout.writeln();
for (int i = 1; i <= 10; i++)
    stdout.write('${i * 6} ');
stdout.writeln();
for (int i = 1; i <= 10; i++)
    stdout.write('${i * 7} ');
stdout.writeln();
for (int i = 1; i <= 10; i++)
    stdout.write('${i * 8} ');
stdout.writeln();
for (int i = 1; i <= 10; i++)
    stdout.write('${i * 9} ');
stdout.writeln();
for (int i = 1; i <= 10; i++)
    stdout.write('${i * 10} ');

Výstup programu:

Konzolová aplikácia
Malá násobilka pomocí cyklu:
1 2 3 4 5 6 7 8 9 10
2 4 6 8 10 12 14 16 18 20
3 6 9 12 15 18 21 24 27 30
4 8 12 16 20 24 28 32 36 40
5 10 15 20 25 30 35 40 45 50
6 12 18 24 30 36 42 48 54 60
7 14 21 28 35 42 49 56 63 70
8 16 24 32 40 48 56 64 72 80
9 18 27 36 45 54 63 72 81 90
10 20 30 40 50 60 70 80 90 100

Program funguje pekne, ale stále sme toho dosť napísali. Ak vás napadlo, že v podstate robíme 10x to isté a len zvyšujeme číslo, ktorým násobíme, máte pravdu. Nič nám nebráni vložiť 2 cykly do seba:

print('Malá násobilka pomocí dvou cyklů:');
for (int j = 1; j <= 10; j++) {
    for (int i = 1; i <= 10; i++)
        stdout.write('${i * j} ');
    print('');
}

Pomerne zásadný rozdiel, že? Pochopiteľne nemôžeme použiť u oboch cyklov i, pretože sú vložené do seba. Premenná j nadobúda vo vonkajšom cykle hodnoty 110. V každej iterácii (rozumejte priebehu) cyklu je potom spustený ďalší cyklus s premennou i. Ten je nám už známy, vypíše násobky, v tomto prípade násobíme premennú j. Po každom behu vnútorného cyklu treba odřádkovat, to vykoná print('') alebo stdout.writeln(). Môžete si skúsiť vypísané riadky upravená pomocou metódy padLeft() tak, aby boli čísla pekne v stĺpcoch.

Urobme si ešte jeden program, na ktorom si ukážeme prácu s vonkajšou premennou. Aplikácia bude vedieť spočítať ľubovoľnú mocninu ľubovoľného čísla:

print('Mocninátor');
print('==========');
print('Zadejte základ mocniny: ');
int a = int.parse(stdin.readLineSync(encoding: UTF8));
print('Zadejte exponent: ');
int n = int.parse(stdin.readLineSync(encoding: UTF8));

int vysledek = a;
for (int i = 0; i < (n - 1); i++)
    vysledek = vysledek * a;

print('Výsledek: $vysledek');
print('Děkuji za použití mocninátoru');

Asi všetci tušíme, ako funguje mocnina. Pre istotu pripomeniem, že napríklad 2 3 = 2 * 2 * 2. Teda a n spočítame tak, že n-1 krát vynásobíme číslo a číslom a. Výsledok si samozrejme musíme ukladať do premennej. Spočiatku bude mať hodnotu a a postupne sa bude v cykle pronásobovat. Ak ste to nestihli, máme tu samozrejme článok s algoritmom výpočtu ľubovoľnej mocniny. Vidíme, že naša premenná vysledek je v tele cyklu normálne prístupná. Ak si však nejakú premennú založíme v tele cyklu, po skončení cyklu zanikne a už nebude prístupná.

Konzolová aplikácia
Mocninátor
==========
Zadejte základ mocniny:
2
Zadejte exponent:
3
Výsledek: 8
Děkuji za použití mocninátoru

Už tušíme, na čo sa for cyklus využíva. Zapamätajme si, že je počet opakovaní pevne daný. Do premennej cyklu by sme nemali nijako zasahovať ani dosadzovať, program by sa mohol tzv. Zacykliť, skúsme si ešte posledný, odstrašujúci príklad:

// tento kód je špatně
for (int i = 1; i <= 10; i++)
    i = 1;

Au, vidíme, že sa program zasekol. Cyklus stále inkrementuje premennú i, ale tá sa vždy zníži na 1. Nikdy teda nedosiahne hodnoty> 10, cyklus nikdy neskončí. Okno programu zatvoríme alebo použijeme tlačidlo stop (červené tlačidlo v tvare štvorca).

While cyklus

While cyklus funguje inak, jednoducho opakuje príkazy v bloku kým platí podmienka. Syntax cyklu je nasledovné:

while (podminka)
{
    // příkazy
}

Ak vás napadá, že možno cez while cyklus urobiť aj for cyklus, máte pravdu:) For je vlastne špeciálny prípad while cyklu. While sa ale používa na trochu iné veci, často máme v jeho podmienke napr. Metódu vracajúci logickú hodnotu true / false. Pôvodný príklad z for cyklu by sme urobili nasledovne pomocou while:

int i = 1;
while (i <= 10) {
    stdout.write('$i ');
    i++;
}

To ale nie je ideálne použitie while cyklu. Vezmeme si našu kalkulačku z minulých lekcií a opäť ju trochu vylepšíme, konkrétne o možnosť zadať viac príkladov. Program teda hneď neskončí, ale spýta sa užívateľa, či si praje spočítať ďalší príklad. Pripomeňme si pôvodnú verziu kódu (je to tá verzia so switchom, ale pokojne použite aj tú bez neho, záleží na vás):

print('Vítejte v kalkulačce');
print('Zadejte první číslo:');
double a = double.parse(stdin.readLineSync(encoding: UTF8));
print('Zadejte druhé číslo:');
double b = double.parse(stdin.readLineSync(encoding: UTF8));
print('Zvolte si operaci:');
print('1 - sčítání');
print('2 - odčítání');
print('3 - násobení');
print('4 - dělení');
int volba = int.parse(stdin.readLineSync(encoding: UTF8));
double vysledek;
switch (volba) {
    case 1:
        vysledek = a + b;
        break;
    case 2:
        vysledek = a - b;
        break;
    case 3:
        vysledek = a * b;
        break;
    case 4:
        vysledek = a / b;
        break;
}
if ((volba > 0) && (volba < 5))
    print('Výsledek: $vysledek');
else
    print('Neplatná volba');
print('Děkuji za použití kalkulačky, aplikaci ukončíte libovolnou klávesou.');

Teraz vložíme takmer celý kód do while cyklu. Našou podmienkou bude, že používateľ zadá "áno", budeme teda kontrolovať obsah premennej pokracovat. Spočiatku bude táto premenná nastavená na "ano", aby sa program vôbec spustil, potom do nej necháme načítať voľbu užívateľa:

print('Vítejte v kalkulačce');
String pokracovat = 'ano';

while (pokracovat == 'ano') {
    print('Vítejte v kalkulačce');
    print('Zadejte první číslo:');
    double a = double.parse(stdin.readLineSync(encoding: UTF8));
    print('Zadejte druhé číslo:');
    double b = double.parse(stdin.readLineSync(encoding: UTF8));
    print('Zvolte si operaci:');
    print('1 - sčítání');
    print('2 - odčítání');
    print('3 - násobení');
    print('4 - dělení');
    int volba = int.parse(stdin.readLineSync(encoding: UTF8));
    double vysledek;
    switch (volba) {
        case 1:
            vysledek = a + b;
            break;
        case 2:
            vysledek = a - b;
            break;
        case 3:
            vysledek = a * b;
            break;
        case 4:
            vysledek = a / b;
            break;
    }
    if ((volba > 0) && (volba < 5))
        print('Výsledek: $vysledek');
    else
        print('Neplatná volba');
    print('Přejete si zadat další příklad? [ano/ne]');
    pokracovat = stdin.readLineSync(encoding: UTF8);
}

print('Děkuji za použití kalkulačky.');

Výstup programu:

Konzolová aplikácia
Vítejte v kalkulačce
Vítejte v kalkulačce
Zadejte první číslo:
12
Zadejte druhé číslo:
128
Zvolte si operaci:
1 - sčítání
2 - odčítání
3 - násobení
4 - dělení
1
Výsledek: 140.0
Přejete si zadat další příklad? [ano/ne]
ano
Vítejte v kalkulačce
Zadejte první číslo:
-10.5
Zadejte druhé číslo:
6
Zvolte si operaci:
1 - sčítání
2 - odčítání
3 - násobení
4 - dělení
3
Výsledek: -63.0
Přejete si zadat další příklad? [ano/ne]
ne
Děkuji za použití kalkulačky.

Naši aplikáciu možno teraz používať viackrát a je už takmer hotová. V budúcej lekcii, Riešené úlohy k 6. lekcii Dart , si ukážeme, ako zabezpečiť všetky vstupy od užívateľa.

Už toho vieme celkom dosť, začína to byť zábava, že?:)

V nasledujúcom cvičení, Riešené úlohy k 6. lekcii Dart, si precvičíme 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é 5x (3.38 kB)
Aplikácia je vrátane zdrojových kódov v jazyku Dart

 

Predchádzajúci článok
Riešené úlohy k 5. lekcii Dart
Všetky články v sekcii
Základné konštrukcie jazyka Dart
Preskočiť článok
(neodporúčame)
Riešené úlohy k 6. lekcii Dart
Článok pre vás napísal Honza Bittner
Avatar
Užívateľské hodnotenie:
Ešte nikto nehodnotil, buď prvý!
FIT ČVUT alumnus :-) Sleduj mě na https://twitter.com/tenhobi a ptej se na cokoli na https://github.com/tenhobi/ama.
Aktivity