IT rekvalifikace s garancí práce. Seniorní programátoři vydělávají až 160 000 Kč/měsíc a rekvalifikace je prvním krokem. Zjisti, jak na to!
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í.

7. diel - Ošetrenie užívateľských vstupov v Dart

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

V minulej lekcii, Riešené úlohy k 6. lekcii Dart , sme sa zaoberali cykly. Dnes to bude také oddychové, dokončíme si totiž našu kalkulačku, ďalej už ju nebudeme potrebovať a bolo by pekné ju dotiahnuť do konca. Asi tušíte, že u nej chýba zabezpečenia vstupov od užívateľa, tým sa bude zaoberať dnešný tutoriál.

Pripomeňme si kód našej kalkulačky:

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.');

Už sme si raz hovorili, že by sme mali vstupy od užívateľa vždy ošetrovať. Poviem vám tajomstvo úspešných a obľúbených aplikácií, je veľmi jednoduché: počítajú s tým, že je používateľ úplný hlupák.:) Čím hlúpejšieho užívateľa budete predpokladať, tým väčší úspech budú vaše aplikácie mať. Pokiaľ tu používateľ zadá miesto "áno" napr. "Áno" (áno medzera) alebo "Áno" (s veľkým písmenom), program rovnako skončí. To ešte nemusí byť kvôli hlúposti, ale preto, že sa preklepli. Môže nám však zadať aj niečo úplne nezmyselného, napr. "Možno".

To nie je však najväčší problém nášho programu, keď používateľ nezadá číslo, ale nejaký nezmysel, celý program sa zastaví a spadne s chybou. Poďme teraz tieto dva problémy opraviť.

Na overenie správnosti vstupu pri jeho parsovanie môžeme použiť metódu parse() s prídavným parametrom onError. Parameter onError očakáva metódu, ktorá nejakým spôsobom spracuje neplatný reťazec a vráti výslednú hodnotu.

print('Zadejte první číslo:');
double a;
while ((a = double.parse(stdin.readLineSync(encoding: UTF8), (_) => null)) == null)
    print('Neplatné číslo, zadejte prosím znovu:');

Na kódu nie je nič zložité. Najprv vyzveme užívateľa na zadanie čísla a deklarujeme premennú a. Následne priamo do podmienky while cyklu vložíme parse(), výsledok uložíme do premennej aa hodnotu porovnáme voči hodnote null (o tom, čo je null a ako s hodnotou pracovať si povieme neskôr, zatiaľ ju berme ako prázdnu hodnotu). Kým podmienka bude platiť, bude sa cyklus stále opakovať a vyzývať k novému zadaniu.

Teraz sa ešte pozrieme na výber operácie a pokračovanie. Obe voľby načítame ako String aj keď to nie je úplne vhodné. U čísel to má opodstatnenie, pretože môžu mať dĺžku väčšie ako jeden znak a musí byť odenterovány. U voľby operácií 1-4 ale vôbec nepotrebujeme načítavať text, stačí načítať jediný znak z klávesnice. Dart nemá načítanie z konzoly vyriešené najlepšie a okrem načítanie celé riadky (stdin.readLineSync()) poskytuje ešte metódu stdin.readByteSync() na načítanie jediného znaku (konkrétnejšie asi bytu). Keďže nám vráti len hondnotu znaku, musíme ho ešte napríklad pomocou ASCII dekodéra previesť na znak, kedy je v tomto riešení problém napr. S diakritikou. Otázka u tejto metódy ale tiež je, ako sa presne bude správať na rôznych operačných systémoch a či nám vždy naozaj načíta celý znak. Metódu si vyskúšame, ale ďalej budeme načítavať celý riadok a hodnoty si parsovať ako doteraz.

String volba = ASCII.decode([stdin.readByteSync()]);
bool platnaVolba = true;
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;
    default:
        platnaVolba = false;
}
if (platnaVolba)
  print('Výsledek: $vysledek');
else
  print('Neplatná volba');

Do premennej volba si uložíme stlačený znak ako String. Pretože rozsah znakov neotestujete s doterajšími znalosťami tak jednoducho ako rozsah čísiel, pomôžeme si iným spôsobom. Pripravíme si premennú platnaVolba typu bool, ktorú nastavíme na true (budeme predpokladať, že je voľba správna). Switch zostane podobný, len čísla dáme teraz do apostrofov či úvodzoviek. Pridáme možnosť default, ktorá v prípade iné hodnoty než menované nastaví nami pripravenú premennú platnaVolba na false. Potom nie je nič jednoduchšie, než túto premennú otestovať. Vyskúšajte si to. Určite si všimnete ďalšie "chyby" pri používaní stdin.readByteSync() a to síce toho, že prečíta náš znak, ale nechá nám na vstupe odriadkovanie, čo následne dotaz na opakovanie kalkulačky zle vyhodnotí a program nám ukončí.

Program si teda upravíme do pôvodnej podoby. Upraviť musíme ešte výzvu na pokračovanie. Zadávať budeme opäť A / N, budeme tolerovať rôznu veľkosť písmen a reagovať na zlé zadanie. Opäť použijeme switch, našu premennú pokracovat zmeníme na typ bool. Kód je asi zbytočné viac popisovať, za zmienku stojí iba kombo stdin.readLineSync(encoding: UTF8).trim().toLowerCase(), ktoré načíta vstup z konzoly a vráti ho ako String malými písmenami a bez počiatočných či ukončovacích medzier.

Pretože sa jedná o väčší kus kódu, použijeme tzv. Komentáre. Tie sa píšu pomocou dvojlomítka (dvoch lomítok za sebou). Sú to informácie pre programátora, program si ich nevšíma.

print('Vítejte v kalkulačce');
bool pokracovat = true;
while (pokracovat) {
    // načtení čísel
    print('Zadejte první číslo:');
    double a;
    while ((a = double.parse(stdin.readLineSync(encoding: UTF8), (_) => null)) == null)
        print('Neplatné číslo, zadejte prosím znovu:');
    print('Zadejte druhé číslo:');
    double b;
    while ((b = double.parse(stdin.readLineSync(encoding: UTF8), (_) => null)) == null)
        print('Neplatné číslo, zadejte prosím znovu:');
    // volba operace a výpočet
    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 = 0.0;
    bool platnaVolba = true;
    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;
        default:
            platnaVolba = false;
    }
    if (platnaVolba)
        print('Výsledek: $vysledek');
    else
        print('Neplatná volba');
    print('Přejete si zadat další příklad? [a/n]');
    // dotaz na pokračování
    platnaVolba = false;
    while (!platnaVolba)
    {
        switch (stdin.readLineSync(encoding: UTF8).trim().toLowerCase())
        {
            case 'a':
                pokracovat = true;
                platnaVolba = true;
                break;
            case 'n':
                pokracovat = false;
                platnaVolba = true;
                break;
            default:
                print('Neplatná volba, zadejte prosím a/n');
                break;
        }
    }
}
print('Děkuji za použití kalkulačky.');

Výstup programu:

Konzolová aplikácia
Vítejte v kalkulačce
Zadejte první číslo:
cislo
Neplatné číslo, zadejte prosím znovu:
13
Zadejte druhé číslo:
22
Zvolte si operaci:
1 - sčítání
2 - odčítání
3 - násobení
4 - dělení
3
Výsledek: 286.0
Přejete si zadat další příklad? [a/n]
n
Děkuji za použití kalkulačky.

Gratulujem, práve ste vytvorili svoj prvý blbovzdorný program:) Kód sa nám trochu skomplikoval, snáď ste to všetko pochytia. Niekedy v budúcnosti to treba napravíme a rozdelíme ho do prehľadných metód, pre tento kurz však považujme kalkulačku za hotovú, možno by sa do nej len mohlo pridať viac matematických funkcií, na tie sa v kurze tiež zameriame.

V budúcej lekcii, Zoznamy v Dart , sa opäť ponoríme do nových konštrukcií. Čakajú nás zoznamy a pokročilá práca s reťazcami. Potom to bude z konštrukcií v tejto sekcii všetko, blížime sa ku koncu.:)


 

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é 8x (2.81 kB)
Aplikácia je vrátane zdrojových kódov v jazyku Dart

 

Predchádzajúci článok
Riešené úlohy k 6. lekcii Dart
Všetky články v sekcii
Základné konštrukcie jazyka Dart
Preskočiť článok
(neodporúčame)
Zoznamy v 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