Přidej si svou IT školu do profilu a najdi spolužáky zde na síti :)

7. díl - Ošetření uživatelských vstupů

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

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 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í 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 "!", tedy dokud 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á). 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.ReadKe­y().KeyChar.ToS­tring().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 seriálu 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 708x (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?
41 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 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 (6)

 

 

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

Avatar
gcx11
Redaktor
Avatar
gcx11:7. června 14:23

Musíš si upravit i zbytek, aby to pak fungovalo, když už teď máš jistotu, že budeš mít dobře volbu operace.

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();
                bool platnaVolba = false;
                float vysledek = 0;
                while (!platnaVolba)
                {
                    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();
                    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;
                            Console.WriteLine("Neplatná volba");
                            break;
                    }
                }
                Console.WriteLine("Výsledek: {0}", vysledek);
                // dotaz na pokračování
                platnaVolba = false;
                Console.WriteLine("Přejete si zadat další příklad? [a/n]");
                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();
            }
 
Odpovědět  +1 7. června 14:23
Avatar
Martin Kostelka:19. června 11:00

ježiši už vím proč mi ta cikle předtím nefungovala nemněl jsem tam } ve volbě oprerace na konci jsem tam mněl 1 a musej tam bejt dvě takže jsem to zkoušel předtím dobře jen jsem zapomněl složenou závorku taková prkotina a dokáže pozlobit XD jinak omlouvám se mněl jsem hodně práce dítě na cestě tak jsme předělávali chodbu tak jsem nemněl čas :-)

 
Odpovědět 19. června 11:00
Avatar
havlat82
Člen
Avatar
havlat82:27. srpna 12:41

Ahoj, kdysi dávno sem programoval v turbo pascalu a tam byli procedury a funkce. funkce vraceli hodnotu a procedury byli jako metody bez návratové hodnoty. parametr procedur mohl mít modifikátor var. procedura pak do parametru ukládala hodnotu. A byla to možnost jak získat víc hodnot najednou, protože stejně jako metody v C# vraceli pouze jednu hodnotu. Chová se modifikátor out jako obdoba modifikátoru var v turbo pascalu? A dá se tak získat z metody víc hodnot najednou?

string zapisCisla = "51";
int cislo = 0;
bool povedloSe = int.TryParse(zapisCisla, out cislo);
 
Odpovědět 27. srpna 12:41
Avatar
David Čápka
Tým ITnetwork
Avatar
Odpovídá na havlat82
David Čápka:27. srpna 12:44

Z toho jak to popisuješ tak asi no. Nicméně to není moc dobrá praktika, když chceš, aby ti metoda vrátila více hodnot, tak by měla vrátit objekt. Vše je ukázáno dále v seriálu. Předávání přes parametry po jedné hodnotě je dlouhé a nepřehledné.

Odpovědět 27. srpna 12:44
Miluji svou práci a zdejší komunitu, baví mě se rozvíjet, děkuji každému členovi za to, že zde působí.
Avatar
havlat82
Člen
Avatar
Odpovídá na David Čápka
havlat82:27. srpna 12:48

nebyla to podle mě dobrá technika a ni v dobách turbo pascalu. funkce sem bral jako element, kterej mi dá hodnotu a proceduru jako příkaz. obcházení čehokoliv je dycky na pizzu. ptal sem se, protože mě to zaujalo. seriál teď čtu už asi po ixtý. se nudim :D

 
Odpovědět 27. srpna 12:48
Avatar
David Čápka
Tým ITnetwork
Avatar
Odpovídá na havlat82
David Čápka:27. srpna 12:49

Tak přejdi na OOP seriál, tam je toto popsané :)

Odpovědět 27. srpna 12:49
Miluji svou práci a zdejší komunitu, baví mě se rozvíjet, děkuji každému členovi za to, že zde působí.
Avatar
havlat82
Člen
Avatar
Odpovídá na David Čápka
havlat82:27. srpna 12:51

No spíš se vrhnu na ASP.Net a návrhový vzory, ty fakt potřebuju

 
Odpovědět 27. srpna 12:51
Avatar
František Hejský:30. srpna 22:19

Mam tam někde chybu a nevim kde:

using System;
using System.Collec­tions.Generic;
using System.Linq;
using System.Text;
using System.Threadin­g.Tasks;

namespace Opravená_kalkulačka
{
class Program
{
static void Main(string[] args)
{
Console.Write­Line("Vítejte v kalkulačce");
bool pokracovat = true;
while (pokracovat)
{
Console.Write­Line("Zadejte první číslo");
float a;
while (!float.TryPar­se(Console.Re­adLine(), out a))
Console.Write­Line("Neplatné číslo, zadejte prosím znovu:");
Console.Write­Line("Zadejte druhé číslo");
float b;
while (!float.TryPar­se(Console.Re­adLine(), out a))
Console.Write­Line("Neplatné číslo, zadejte prosím znovu:");
Console.Write­Line("Zvolte si operaci");
Console.Write­Line("1 - sčítání");
Console.Write­Line("2 - odčítání");
Console.Write­Line("3 - násobení");
Console.Write­Line("4 - dělení");
char volba = Console.ReadKe­y().KeyChar;
Console.Write­Line();
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.Write­Line("Výsledek: {0}", vysledek);
else
Console.Write­Line("Neplatná volba");
Console.Write­Line("Přejete si zadat další příklad? [ano/ne]");
platnaVolba = false;
while (!platnaVolba)
{
switch (Console.Read­Key().KeyChar­.ToString().To­Lower())
{
case "ano":
pokracovat = true;
platnaVolba = true;
break;
case "ne":
pokracovat = false;
platnaVolba = true;
break;
default:
Console.Write­Line("Neplatná volba, zadejte prosím ano/ne");
break;
}
}
Console.Write­Line();
}
}

 
Odpovědět 30. srpna 22:19
Avatar
Odpovídá na František Hejský
František Hejský:31. srpna 19:26

Na tohle už nemusíte reagovat. Už jsem to vyřešil sám.

 
Odpovědět 31. srpna 19:26
Avatar
lukas.kotyza
Člen
Avatar
lukas.kotyza:5. září 15:21

Dobrý den osobně bych na konci kódu rád viděl vyčištění konzole pro větší přehlednost při opakovaném používání kalkulačky.

 
Odpovědět 5. září 15:21
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 84. Zobrazit vše