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

C# .NET Základní konstrukce Ošetření uživatelských vstupů American English version English version

ONEbit hosting Unicorn College 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 C#, 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í C# tutoriál.

Připomeňme si kód naší kalkulačky:

Console.WriteLine("Vítejte v kalkulačce");
string pokracovat = "ano";
while (pokracovat == "ano")
{
        Console.WriteLine("Zadejte první číslo:");
        float a = float.Parse(Console.ReadLine());
        Console.WriteLine("Zadejte druhé číslo:");
        float b = float.Parse(Console.ReadLine());
        Console.WriteLine("Zvolte si operaci:");
        Console.WriteLine("1 - sčítání");
        Console.WriteLine("2 - odčítání");
        Console.WriteLine("3 - násobení");
        Console.WriteLine("4 - dělení");
        int volba = int.Parse(Console.ReadLine());
        float vysledek = 0;
        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))
                Console.WriteLine("Výsledek: {0}", vysledek);
        else
                Console.WriteLine("Neplatná volba");
        Console.WriteLine("Přejete si zadat další příklad? [ano/ne]");
        pokracovat = Console.ReadLine();
}
Console.WriteLine("Děkuji za použití kalkulačky, aplikaci ukončíte libovolnou klávesou.");
Console.ReadKey();

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 místo metody Parse() použít metodu TryParse(). Metoda vrací true/false podle toho, jestli se parsování podařilo či nikoli. Jestli se ptáte, jak z metody tedy dostaneme naparsovanou hodnotu, tak ta se nám uloží do proměnné předané druhým parametrem. U parametru musíme uvést modifikátor out, zatím se jím nebudeme zatěžovat, budeme brát jako fakt, že to metoda TryParse() takhle má. Hodnota proměnné, kterou jsme takto předali do druhého parametru, bude ovlivněna. Ukážeme si to u prvního čísla, u druhého to bude samozřejmě analogické a jen to opíšeme. Ideálně bychom si na to měli vytvořit metodu, abychom nepsali 2x ten samý kód, ale zatím není vhodná doba se tímto zabývat, metody se naučíme definovat až u objektově orientovaného programování.

Console.WriteLine("Zadejte první číslo:");
float a;
while (!float.TryParse(Console.ReadLine(), out a))
        Console.WriteLine("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 TryParse(), podmínku znegujeme operátorem !. Dokud tedy vrací false, bude se cyklus stále opakovat a vyzývat k novému zadání. Zadaný text z konzole se naparsuje do proměnné a je navráceno true. Pokud se parsování nepovede, je vráceno false.

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 a potvrzovat ho enterem, stačí načíst jediný znak z klávesnice a ten nemusíme ničím potvrzovat. K načtení jediného znaku slouží nám již známá metoda Console.ReadKey(). Abychom výsledek dostali jako char (znak), musíme na této metodě použít vlastnost KeyChar. Ve switchi nezapomínejme, že char se zapisuje do apostrofů.

char volba = Console.ReadKey().KeyChar;
float vysledek = 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;
                break;
}
if (platnaVolba)
        Console.WriteLine("Výsledek: {0}", vysledek);
else
        Console.WriteLine("Neplatná volba");

Do proměnné volba si uložíme stisknutý znak jako char. 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á). Konstrukce switch zůstane podobná, jen čísla dáme nyní do apostrofů, protože se nyní jedná o jednotlivé znaky. Přidáme možnost default:, která v případě jiné hodnoty než jmenovaných nastaví námi připravenou proměnnou platnaVolba na false. Potom není nic jednoduššího, než tuto proměnnou otestovat. Vyzkoušejte si to, program se používá nyní pohodlněji.

Nakonec upravíme ještě výzvu k pokračování, zadávat budeme opět char 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 Console.ReadKey().KeyChar.ToString().ToLower(), které načte znak z konzole a vrátí ho jako string malými písmeny.

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

Console.WriteLine("Vítejte v kalkulačce");
bool pokracovat = true;
while (pokracovat)
{
        // načtení čísel
        Console.WriteLine("Zadejte první číslo:");
        float a;
        while (!float.TryParse(Console.ReadLine(), out a))
                Console.WriteLine("Neplatné číslo, zadejte prosím znovu:");
        Console.WriteLine("Zadejte druhé číslo:");
        float b;
        while (!float.TryParse(Console.ReadLine(), out b))
                Console.WriteLine("Neplatné číslo, zadejte prosím znovu:");
        // volba operace a výpočet
        Console.WriteLine("Zvolte si operaci:");
        Console.WriteLine("1 - sčítání");
        Console.WriteLine("2 - odčítání");
        Console.WriteLine("3 - násobení");
        Console.WriteLine("4 - dělení");
        char volba = Console.ReadKey().KeyChar;
        Console.WriteLine();
        float vysledek = 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;
                        break;
        }
        if (platnaVolba)
                Console.WriteLine("Výsledek: {0}", vysledek);
        else
                Console.WriteLine("Neplatná volba");
        Console.WriteLine("Přejete si zadat další příklad? [a/n]");
        // dotaz na pokračování
        platnaVolba = false;
        while (!platnaVolba)
        {
                switch (Console.ReadKey().KeyChar.ToString().ToLower())
                {
                        case "a":
                                pokracovat = true;
                                platnaVolba = true;
                        break;
                        case "n":
                                pokracovat = false;
                                platnaVolba = true;
                        break;
                        default:
                                Console.WriteLine("Neplatná volba, zadejte prosím a/n");
                        break;
                }
        }
        Console.WriteLine();
}

Konzolová aplikace
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
Přejete si zadat další příklad? [a/n]
h
Neplatná volba, zadejte prosím a/n

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 tuto sekci 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 C# kurzu také zaměříme.

V příští lekci, Pole v C#, se opět ponoříme do nových konstrukcí. Čeká nás pole 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 750x (24.01 kB)
Aplikace je včetně zdrojových kódů v jazyce C#

 

 

Článek pro vás napsal David Čápka
Avatar
Jak se ti líbí článek?
51 hlasů
Autor pracuje jako softwarový architekt a pedagog na projektu ITnetwork.cz (a jeho zahraničních verzích). Velmi si váží svobody podnikání v naší zemi a věří, že když se člověk neštítí práce, tak dokáže úplně cokoli.
Unicorn College Autor sítě se informační technologie naučil na Unicorn College - prestižní soukromé vysoké škole IT a ekonomie.
Miniatura
Předchozí článek
Cykly v C#
Miniatura
Všechny články v sekci
Základní konstrukce jazyka C#
Miniatura
Následující článek
Pole v C#
Aktivity (8)

 

 

Komentáře
Zobrazit starší komentáře (85)

Avatar
pocitac770
Redaktor
Avatar
pocitac770:26.10.2017 9:06

//Edit: Za while se nepíše středník, takto se ten následující řádek vykoná vždy

Editováno 26.10.2017 9:08
 
Odpovědět 26.10.2017 9:06
Avatar
Arny
Člen
Avatar
Arny:26.10.2017 19:22

Aha, diky.

 
Odpovědět 26.10.2017 19:22
Avatar
Jirka Kouba
Člen
Avatar
Jirka Kouba:6.11.2017 21:12

Z nějakýho důvodu mi to píše chybu, ale když ho zkusím spustit, funguje mi v pořádku. Posím najděte mi tu chybu :-)

           var repeater = "a";
            while (repeater = "a")
{
//kalkulačka
 Console.WriteLine("Přejete si spočítat další příklad?");
                Console.WriteLine("a/n");
                repeater = Console.ReadKey(). KeyChar;
}
 
Odpovědět 6.11.2017 21:12
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Jirka Kouba
DarkCoder:6.11.2017 21:21

Co třeba místo dvojitých uvozovek používat jednoduché

Odpovědět 6.11.2017 21:21
"„Učíš-li se proto, aby sis zapamatoval, zapomeneš. Učíš-li se proto, abys porozuměl, zapamatuješ si."
Avatar
Fíla N.
Člen
Avatar
Fíla N.:13.11.2017 22:35

Console.Clear();

;-)
 
Odpovědět 13.11.2017 22:35
Avatar
Fíla N.
Člen
Avatar
Odpovídá na Jirka Kouba
Fíla N.:13.11.2017 22:42

Ahoj,
jak píše DarkCoder, pokud používáš proměnnou typu char, tak tam bys měl mít asi jednozovky :)
Pak ještě vypadá podezřele:
while (repeater = "a") - > to by asi mělo být -> while (repeater == 'a')

 
Odpovědět 13.11.2017 22:42
Avatar
Fíla N.
Člen
Avatar
Odpovídá na Jirka Kouba
Fíla N.:13.11.2017 22:50

Pokračování :)
Jak bych to viděl já:

var repeater = 'a';
while (repeater == 'a')
{
//kalkulačka
Console.Write­Line("Přejete si spočítat další příklad?");
Console.Write­Line("a/n");
repeater = Console.ReadKe­y().KeyChar;
}

Editováno 13.11.2017 22:51
 
Odpovědět 13.11.2017 22:50
Avatar
Petr Zajac
Člen
Avatar
Petr Zajac:21. února 16:55

Díky za další díl.
Sice mi v tom konečném dotazu [a/n] není jasné proč se to převádí na string?
Zkoušel jsem to nechat jako char, jako u volby 1-4, ale pak mi tam při vynechání "ToString()"
ten převod na malá písmenka ToLower() hlásí "Chyba CS1501 Žádné přetížení pro metodu ToLower nepřevezme tento počet argumentů: 0."

 
Odpovědět 21. února 16:55
Avatar
Odpovídá na Petr Zajac
Dušan Kovářík:2. června 19:07

Ahoj, právě proto, že metoda ToLower() pracuje s řetězci, tak je potřeba znak převést na řetězec o délce jednoho znaku. Ano, z hlediska obsahu takovéto proměnné je to to samé, ale z hlediska jejího datového typu je to rozdíl.

 
Odpovědět 2. června 19:07
Avatar
Patrik Herman:11. srpna 19:03

Zdravím, nevíte jak bych mohl ve své kalkulačce zadat odmocnitel za pomoci int.Parse(Con­sole.ReadLine());?

 
Odpovědět 11. srpna 19:03
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.

Zobrazeno 10 zpráv z 95. Zobrazit vše