Letní akce! Lákají tě IT školení C#, Javy a PHP v Brně? Přihlas se a napiš nám do zpráv kód "BRNO 500" pro slevu 500 Kč na libovolný brněnský kurz. Lze kombinovat se slevami uvedenými u školení i použít pro více kurzů. Akce končí 28.7.

Lekce 7 - Ošetření uživatelských vstupů v Dartu

Dart Základy Ošetření uživatelských vstupů v Dartu

Unicorn College ONEbit hosting Tento obsah je dostupný zdarma v rámci projektu IT lidem. Vydávání, hosting a aktualizace umožňují jeho sponzoři.

V minulé lekci, Cykly v Dartu, jsme se zabývali cykly. Dnes to bude takové oddechové, dokončíme si totiž naši kalkulačku, dále už ji nebudeme potřebovat a bylo by hezké ji dotáhnout do konce. Asi tušíte, že u ni chybí zabezpečení vstupů od uživatele, tím se bude zabývat dnešní tutoriál.

Připomeňme si kód naší 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ž jsme si jednou říkali, že bychom měli vstupy od uživatele vždy ošetřovat. Řeknu vám tajemství úspěšných a oblíbených aplikací, je velmi jednoduché: počítají s tím, že je uživatel naprostý hlupák. :) Čím hloupějšího uživatele budete předpokládat, tím větší úspěch budou vaše aplikace mít. Pokud zde uživatel zadá místo "ano" např. "ano " (ano mezera) nebo "Ano" (s velkým písmenem), program stejně skončí. To ještě nemusí být kvůli hlouposti, ale proto, že se překlepl. Může nám však zadat i něco úplně nesmyslného, např. "možná".

To není však největší problém našeho programu, když uživatel nezadá číslo, ale nějaký nesmysl, celý program se zastaví a spadne s chybou. Pojďme nyní tyto dva problémy opravit.

K ověření správnosti vstupu při jeho parsování můžeme použít metodu parse() s přídavným parametrem onError. Parametr onError očekává metodu, která nějakým způsobem zpracuje neplatný řetězec a vrátí výslednou 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 není nic složitého. Nejprve vyzveme uživatele k zadání čísla a deklarujeme proměnnou a. Následně přímo do podmínky while cyklu vložíme parse(), výsledek uložíme do proměnné a a hodnotu porovnáme vůči hodnotě null (o tom, co je null a jak s hodnotou pracovat si řekneme později, zatím ji berme jako prázdnou hodnotu). Dokud podmínka bude platit, bude se cyklus stále opakovat a vyzývat k novému zadání.

Nyní se ještě podíváme na výběr operace a pokračování. Obě volby načítáme jako String i když to není úplně vhodné. U čísel to má opodstatnění, protože mohou mít délku větší než jeden znak a musí být odenterovány. U volby operací 1-4 ale vůbec nepotřebujeme načítat text, stačí načíst jediný znak z klávesnice. Dart nemá načítání z konzole vyřešeno nejlépe a kromě načtení celé řádky (stdin.readLineSync()) poskytuje ještě metodu stdin.readByteSync() k načtení jediného znaku (konkrétněji asi bytu). Jelikož nám vrátí jen hondnotu znaku, musíme jej ještě například pomocí ASCII dekodéru převést na znak, kdy je v tomto řešení problém např. s diakritikou. Otázka u této metody ale také je, jak se přesně bude chovat na různých operačních systémech a jestli nám vždy opravdu načte celý znak. Metodu si vyzkoušíme, ale dále budeme načítat celý řádek a hodnoty si parsovat jako doposud.

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 proměnné volba si uložíme stisknutý znak jako String. Protože rozsah znaků neotestujeme s dosavadními znalostmi tak jednoduše jako rozsah čísel, pomůžeme si jiným způsobem. Připravíme si proměnnou platnaVolba typu bool, kterou nastavíme na true (budeme předpokládat, že je volba správná). Switch zůstane podobný, jen čísla dáme nyní do apostrofů či uvozovek. Přidáme možnost default, která v případě jiné hodnoty než jmenované nastaví námi připravenou proměnnou platnaVolba na false. Potom není nic jednoduššího, než tuto proměnnou otestovat. Vyzkoušejte si to. Určitě si všimnete další "chyby" při používání stdin.readByteSync() a to sice toho, že přečte náš znak, ale nechá nám na vstupu odřádkování, což následně dotaz na opakování kalkulačky špatně vyhodnotí a program nám ukončí.

Program si tedy upravíme do původní podoby. Upravit musíme ještě výzvu k pokračování. Zadávat budeme opět A/N, budeme tolerovat různou velikost písmen a reagovat na špatné zadání. Opět použijeme switch, naši proměnnou pokracovat změníme na typ bool. Kód je asi zbytečné více popisovat, za zmínku stojí pouze kombo stdin.readLineSync(encoding: UTF8).trim().toLowerCase(), které načte vstup z konzole a vrátí ho jako String malými písmeny a bez počátečních či ukončovacích mezer.

Protože se jedná o větší kus kódu, použijeme tzv. komentáře. Ty se píší pomocí dvojlomítka (dvou lomítek za sebou). Jsou to informace pro programátora, program si jich nevšímá.

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á aplikace
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.

Gratuluji, právě jste vytvořili svůj první blbovzdorný program :) Kód se nám trochu zkomplikoval, snad jste to všechno pochytili. Někdy v budoucnu to třeba napravíme a rozdělíme ho do přehledných metod, pro tento kurz však považujme kalkulačku za hotovou, možná by se do ní jen mohlo přidat více matematických funkcí, na ty se v kurzu také zaměříme.

V příští lekci, Seznamy v Dartu, se opět ponoříme do nových konstrukcí. Čekají nás seznamy a pokročilá práce s řetězci. Potom to bude z konstrukcí v této sekci vše, blížíme se ke konci. :)


 

Stáhnout

Staženo 1x (2.81 kB)
Aplikace je včetně zdrojových kódů v jazyce Dart

 

 

Článek pro vás napsal Honza Bittner
Avatar
Jak se ti líbí článek?
1 hlasů
Milovník Dartu. Student FIT ČVUT. Sleduj mě na https://twitter.com/tenhobi a ptej se na cokoli na https://github.com/tenhobi/ama.
Miniatura
Předchozí článek
Cykly v Dartu
Miniatura
Všechny články v sekci
Základní konstrukce jazyka Dart
Miniatura
Následující článek
Seznamy v Dartu
Aktivity (3)

 

 

Komentáře

Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zatím nikdo nevložil komentář - buď první!