Slevový týden - Květen Office week
Pouze tento týden sleva až 80 % na e-learning týkající se MS Office
30 % bodů zdarma na online výuku díky naší Slevové akci!

Lekce 5 - Podmínky (větvení) v jazyce C

V minulé lekci, Typový systém v céčku podruhé: Datové typy, jsme si podrobně probrali datové typy. Abychom si něco naprogramovali, potřebujeme nějak reagovat na různé situace. Může to být například hodnota zadaná uživatelem, podle které budeme chtít měnit další běh programu. Říkáme, že se program větví a k větvení používáme podmínky, těm se budeme věnovat celý dnešní tutoriál. Vytvoříme program na výpočet odmocniny a vylepšíme naši kalkulačku.

Podmínky

Podmínky zapisujeme pomocí klíčového slova if, za kterým následuje logický výraz. Pokud je výraz pravdivý, provede se následující příkaz. Pokud ne, následující příkaz se přeskočí a pokračuje se až pod ním. Vyzkoušejme si to:

if (5 < 15)
    printf("Pravda \n");
printf("Program zde pokracuje dal \n");

Výstup programu:

Konzolová aplikace
Pravda
Program zde pokracuje dal

Pokud podmínka platí (což zde ano), provede se příkaz vypisující do konzole text "Pravda". V obou případech program pokračuje dál. Součástí výrazu samozřejmě může být i proměnná:

int a;
printf("Zadej nejake cislo \n");
scanf("%d", &a);
if (a > 5)
    printf("Zadal jsi cislo vetsi nez 5! \n");
printf("Dekuji za zadani \n");

Ukažme si nyní relační operátory, které můžeme ve výrazech používat:

Operátor C-Like zápis
Rovnost ==
Je ostře větší >
Je ostře menší <
Je větší nebo rovno >=
Je menší nebo rovno <=
Nerovnost !=
Obecná negace !

Rovnost zapisujeme dvěma == proto, aby se to nepletlo s běžným přiřazením do proměnné, které se dělá jen jedním =. Pokud chceme nějaký výraz znegovat, napíšeme ho do závorky a před něj vykřičník. Když budeme chtít vykonat více než jen jeden příkaz, musíme příkazy vložit do bloku ze složených závorek:

#include <stdio.h>
#include <stdlib.h>
#include <math.h> // Nesmíme zapomenout na include hlavičky math.h, obsahuje funkci pro odmocninu
int main(int argc, char** argv) {
    int a;
    printf("Zadej nejake cislo, ze ktereho spocitam odmocninu: \n");
    scanf("%d", &a);
    if (a > 0)
    {
        printf("Zadal jsi cislo vetsi nez 0, to znamena, ze ho mohu odmocnit!\n");
        double o = sqrt(a);
        printf("Odmocnina z cisla %d je %f \n", a, o);
    }
    printf("Dekuji za zadani \n");
    return (EXIT_SUCCESS);
}

Výstup:

Konzolová aplikace
Zadej nejake cislo, ze ktereho spocitam odmocninu:
144
Zadal jsi cislo vetsi nez 0, to znamena, ze ho mohu odmocnit!
Odmocnina z cisla 144 je 12.000000
Dekuji za zadani
Tento výukový obsah pomáhají rozvíjet následující firmy, které dost možná hledají právě tebe!

Často můžete vidět použití bloku i v případě, že je pod podmínkou jen jeden příkaz, mnohdy je to totiž přehlednější.

Program načte od uživatele číslo a pokud je větší než 0, vypočítá z něj druhou odmocninu. Mimo jiné jsme použili funkci z knihovny math.h, která v sobě obsahuje řadu užitečných matematických funkcí, někdy si ji blíže představíme. sqrt() vrací hodnotu druhé odmocniny jako double. Bylo by hezké, kdyby nám program vyhuboval v případě, že zadáme záporné číslo. S dosavadními znalostmi bychom napsali něco jako:

#include <stdio.h>
#include <stdlib.h>
#include <math.h> // Nesmíme zapomenout na include hlavičky math.h, obsahuje funkci pro odmocninu
int main(int argc, char** argv) {
    int a;
    printf("Zadej nejake cislo, ze ktereho spocitam odmocninu: \n");
    scanf("%d", &a);
    if (a > 0)
    {
        printf("Zadal jsi cislo vetsi nez 0, to znamena, ze ho mohu odmocnit!\n");
        double o = sqrt(a);
        printf("Odmocnina z cisla %d je %f \n", a, o);
    }
    if (a <= 0)
        printf("Odmocnina ze zaporneho cisla neexistuje \n");

    printf("Dekuji za zadani \n");
    return (EXIT_SUCCESS);
}

Všimněte si, že musíme pokrýt i případ, kdy se a == 0, nejen když je menší. Kód však můžeme výrazně zjednodušit pomocí klíčového slova else, které vykoná následující příkaz nebo blok příkazů v případě, že se podmínka neprovede:

#include <stdio.h>
#include <stdlib.h>
#include <math.h> // Nesmíme zapomenout na include hlavičky math.h, obsahuje funkci pro odmocninu
int main(int argc, char** argv) {
    int a;
    printf("Zadej nejake cislo, ze ktereho spocitam odmocninu:  \n");
    scanf("%d", &a);
    if (a > 0)
    {
        printf("Zadal jsi cislo vetsi nez 0, to znamena, ze ho mohu odmocnit!\n");
        double o = sqrt(a);
        printf("Odmocnina z cisla %d je %f \n", a, o);
    }
    else
        printf("Odmocnina ze zaporneho cisla neexistuje \n");

    printf("Dekuji za zadani \n");
    return (EXIT_SUCCESS);
}

Kód je mnohem přehlednější a nemusíme vymýšlet opačnou podmínku, což by v případě složené podmínky mohlo být někdy i velmi obtížné. V případě více příkazů by byl za else opět blok { }.

Klíčové slovo else se také využívá v případě, kdy potřebujeme v příkazu manipulovat s proměnnou z podmínky a nemůžeme se na ni tedy ptát znovu. Program si sám pamatuje, že se podmínka nesplnila a přejde do sekce else. Ukažme si to na příkladu: Mějme číslo a, kde bude hodnota 0 nebo 1 a po nás se bude chtít, abychom hodnotu prohodili (pokud tam je 0, dáme tam 1, pokud 1, dáme tam 0). Naivně bychom mohli kód napsat takto:

int a = 0; // do a si přiřadíme na začátku 0

if (a == 0) // pokud je a 0, dáme do něj jedničku
    a = 1;
if (a == 1) // pokud je a 1, dáme do něj nulu
    a = 0;

printf("%d", a);

Nefunguje to, že? Pojďme si projet, co bude program dělat. Na začátku máme v a nulu, první podmínka se jistě splní a dosadí do a jedničku. No ale rázem se splní i ta druhá. Co s tím? Když podmínky otočíme, budeme mít ten samý problém s jedničkou. Jak z toho ven? Ano, použijeme else.

int a = 0; // do a si přiřadíme na začátku 0

if (a == 0) // pokud je a 0, dáme do něj jedničku
    a = 1;
else // pokud je a 1, dáme do něj nulu
    a = 0;

printf("%d", a);

Podmínky je možné skládat a to pomocí dvou základních operátorů:

Operátor C-Like zápis
A zároveň &&
Nebo ||

Uveďme si příklad:

int a;
printf("Zadej cislo v rozmezi 10-20 \n");
scanf("%d", &a);
if ((a >= 10) && (a <= 20))
    printf("Zadal jsi spravne \n");
else
    printf("Zadal jsi spatne \n");

S tím si zatím vystačíme, operátory se pomocí závorek samozřejmě dají kombinovat.

int a;
printf("Zadej cislo v rozmezi 10-20 nebo 30-40 \n");
scanf("%d", &a);
if (((a >= 10) && (a <= 20)) || ((a >=30) && (a <= 40)))
    printf("Zadal jsi spravne \n");
else
    printf("Zadal jsi spatne \n");

switch

Zápis více podmínek pod sebou (relativně) zjednodušuje konstrukce switch. Vzpomeňme si na naši kalkulačku v prvních lekcích, která načetla 2 čísla a vypočítala všechny 4 operace. Nyní si ale budeme chtít zvolit, kterou operaci chceme. Bez switch bychom napsali kód podobný tomuto:

double a;
double b;
int volba; // Mohli bychom použít char, abychom zbytečně nepoužívali moc místa
double vysledek = 0.0;
printf("Vitejte v kalkulacce \n");
printf("Zadejte prvni cislo: \n");
scanf("%lf", &a);
printf("Zadejte druhe cislo: \n");
scanf("%lf", &b);
printf("Zvolte si operaci: \n");
printf("1 - scitani \n");
printf("2 - odcitani \n");
printf("3 - nasobeni \n");
printf("4 - deleni \n");
scanf("%d", &volba);
if (volba == 1)
    vysledek = a + b;
else if (volba == 2)
    vysledek = a - b;
else if (volba == 3)
    vysledek = a * b;
else if (volba == 4)
    vysledek = a / b;
if ((volba > 0) && (volba < 5))
    printf("Vysledek: %lf", vysledek);
else
    printf("Neplatna volba \n");
printf("\n");
printf("Dekuji za pouziti kalkulacky");

Výstup:

Konzolová aplikace
Vitejte v kalkulacce
Zadejte prvni cislo:
3.14
Zadejte druhe cislo:
2.14
Zvolte si operaci:
1 - scitani
2 - odcitani
3 - nasobeni
4 - deleni
2
Vysledek: 1.000000
Dekuji za pouziti kalkulacky

Všimněte si, že jsme proměnnou vysledek deklarovali na začátku, jen tak do ni můžeme potom přiřazovat. Kdybychom ji deklarovali u každého přiřazení, Céčko by kód nezkompilovalo a vyvolalo by chybu. Proměnná může být deklarována (založena v paměti) vždy jen jednou. Další vychytávka je kontrola správnosti volby. Program by v tomto případě fungoval stejně i bez else, ale nač se dále ptát, když již máme výsledek.

Nyní si zkusíme napsat ten samý kód pomocí switch:

double a;
double b;
int volba; // Mohli bychom použít char, abychom zbytečně nepoužívali moc místa
double vysledek;
printf("Vitejte v kalkulacce \n");
printf("Zadejte prvni cislo: \n");
scanf("%lf", &a);
printf("Zadejte druhe cislo: \n");
scanf("%lf", &b);
printf("Zvolte si operaci: \n");
printf("1 - scitani \n");
printf("2 - odcitani \n");
printf("3 - nasobeni \n");
printf("4 - deleni \n");
scanf("%d", &volba);
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))
    printf("Vysledek: %f", vysledek);
else
    printf("Neplatna volba \n");
printf("\n");
printf("Dekuji za pouziti kalkulacky");

Vidíme, že kód je trochu přehlednější. Pokud bychom potřebovali v nějaké větvi switch spustit více příkazů, překvapivě je nebudeme psát do bloku, ale rovnou pod sebe. Blok {} nám zde nahrazuje příkaz break, který způsobí vyskočení z celého switch. Konstrukce switch může místo case x: obsahovat ještě možnost default:, která se vykoná v případě, že nebude platit žádný case. Je jen na vás, jestli budete switch používat, obecně se vyplatí jen při větším množství příkazů a vždy jde nahradit sekvencí if a else. Nezapomínejte na příkazy break, pokud jej neuvedete, program propadne do další větve a to i když by nebyla splněná podmínka! V minulosti se takovéto propadávání využívalo schválně, dnešní IDE před tímto použitím ale spíše již varují. Kdybyste s tím měli problémy, použijte sekvenci if - else.

To bychom měli. V příští lekci, Řešené úlohy k 4.-5. lekci Céčka, nás čekají pole a cykly. Tím dovršíme základní znalosti, máte se na co těšit :)

V následujícím cvičení, Řešené úlohy k 4.-5. lekci Céčka, si procvičíme nabyté zkušenosti z předchozích lekcí.


 

Stáhnout

Staženo 274x (32.31 kB)
Aplikace je včetně zdrojových kódů v jazyce c

 

 

Článek pro vás napsal Samuel Kodytek
Avatar
Jak se ti líbí článek?
11 hlasů
Autor se věnuje všem jazykům okolo JVM. Rád pomáhá lidem, kteří se zajímají o programování. Věří, že všichni mají šanci se naučit programovat, jen je potřeba prorazit tu bariéru, který se říká lenost.
Předchozí článek
Typový systém v céčku podruhé: Datové typy
Všechny články v sekci
Základní konstrukce jazyka C
Miniatura
Následující článek
Řešené úlohy k 4.-5. lekci Céčka
Aktivity (20)

 

 

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

Avatar
Jan Tesař
Člen
Avatar
Jan Tesař:24.11.2019 8:58

Ahoj, v příkladu s odmocninou je chyba, odmocnina z nuly existuje - je to nula, s rovnítkem by měla být ta první podmínka. Honza

 
Odpovědět
24.11.2019 8:58
Avatar
Vojta Opravil:19. března 8:55

Ahoj
Nepochopil jsem co znamená toto double o = sqrt(a); ??

 
Odpovědět
19. března 8:55
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Vojta Opravil
DarkCoder:19. března 10:43

Příkaz

double o = sqrt(a);

představuje deklaraci proměnné o a zároveň její inicializaci voláním funkce sqrt() s argumentem a.

Odpovědět
19. března 10:43
"„Učíš-li se proto, aby sis zapamatoval, zapomeneš. Učíš-li se proto, abys porozuměl, zapamatuješ si."
Avatar
 
Odpovědět
19. března 10:59
Avatar
Vojta Opravil:19. března 11:03

printf ("\n"); to odděluje dva příkazy ?

 
Odpovědět
19. března 11:03
Tento výukový obsah pomáhají rozvíjet následující firmy, které dost možná hledají právě tebe!
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Vojta Opravil
DarkCoder:19. března 11:14

To co odděluje dva příkazy od sebe je středník.

printf ("\n");

Význam výše uvedeného příkazu je odřádkování. Použití funkce printf() je v tomto případě nešťastné. Argument uvnitř funkce \n je znaková konstanta a pro samotné odřádkování by se měl použít následující příkaz:

putchar('\n');

Funkce putchar() potřebuje mnohem méně strojových instrukcí a bude tak rychlejší nežli funkce printf().

Pokud ale součástí formátovacího řetězce bude i jiný znak než jen znak nového řádku, pak je třeba použít funkci printf().

Odpovědět
19. března 11:14
"„Učíš-li se proto, aby sis zapamatoval, zapomeneš. Učíš-li se proto, abys porozuměl, zapamatuješ si."
Avatar
Vojta Opravil:21. března 18:12

Ahoj chtěl jsem ,aby když celek bude menší než 100 aby to nevypsalo darek. Nevíte kde je chyba ??

int rohlik ;
int jabko;
int chleba;
int volba;
int kolik;
char pokracovat;
int celek;
int darek;
printf("vítejte v obchodě \n");
do
{
printf("zvolte pocet produktů\n");
scanf("%d",&kolik);
printf("1-rohlik\n");
printf("2-jabko\n");
printf("3-chleba\n");
printf("zvolte produkt\n");
scanf("%d",&volba);
switch(volba)
{ case 1:
rohlik = 2 * kolik ;
printf("rohliky stoji %d korun \n",rohlik);
break;

case 2:
jabko = 5 * kolik ;
printf(" jabka stoji %d korun \n",jabko);
break;

case 3:
chleba = 10 * kolik;
printf(" chleba stoji %d korun \n",chleba);
break;
}
celek = rohlik + jabko + chleba ;
printf("nakup stoji %d korun \n",celek);
if (celek => 100)

darek = celek / 100 ;
printf("dostanete %d darek/u \n", darek );

printf("Prejete si zadat dalsi nakup? [1/0]");
scanf("%d", &pokracovat);
}while (pokracovat == 1);
return (EXIT_SUCCESS);
}

 
Odpovědět
21. března 18:12
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Vojta Opravil
DarkCoder:21. března 21:11
if (celek >= 100){
        // nárok na dárek
}
else {
        // bez nároku na dárek
}

Pokud nebudeš se sekcí, kde celek < 100 pracovat, můžeš celý blok else vynechat. Což je tvůj případ. Jinak podmínka větší rovno má tvar >= nikoli =>.

Aby si provedl více příkazů v rámci platné podmínky, je třeba příkazy uzavřít do bloku mezi složené závorky.

if (celek >= 100){
        // příkaz 1
        // příkaz 2
        // …
        // příkaz N
}

Pokud provádíš pouze jeden příkaz, závorky psát nemusíš.

Pokud vícero nepracuješ s proměnnou, jen vypisuješ její hodnotu získanou výsledkem nějakého výrazu, pak tuto proměnnou nemusíš vůbec deklarovat a její výpis můžeš provést ve funkci printf() jako argument funkce. Argumentem funkce je pak výraz potřebný pro získání té dané proměnné. Pro začátek ale není na škodu si tuto proměnnou deklarovat.

Odpovědět
21. března 21:11
"„Učíš-li se proto, aby sis zapamatoval, zapomeneš. Učíš-li se proto, abys porozuměl, zapamatuješ si."
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Vojta Opravil
DarkCoder:21. března 21:22

Ještě jedna věc. V profi psaných programech nikdy neuvidíš kód jako je tento:

if (celek >= 100){
        // nárok na dárek
}

Obvykle to bude zkušeným programátorem napsáno třeba takto:

#define NAROK_NA_DAREK 100

if (celek >= NAROK_NA_DAREK){
        // nárok na dárek
}

To umožňuje mít větší kontrolu na kódem a vyhnout se chybě, pokud by se změnila hodnota, kdy je nárok na dárek a náhodou se hodnota 100 někde v programu nezměnila. Takto stačí změnit hodnotu makra na začátku programu.

Odpovědět
21. března 21:22
"„Učíš-li se proto, aby sis zapamatoval, zapomeneš. Učíš-li se proto, abys porozuměl, zapamatuješ si."
Avatar
 
Odpovědět
23. března 9:07
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 38. Zobrazit vše