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:
{C_CONSOLE}
if (5 < 15)
printf("Pravda \n");
printf("Program zde pokracuje dal \n");
{/C_CONSOLE}
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á:
{C_CONSOLE}
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");
{/C_CONSOLE}
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
Č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:
{C_CONSOLE}
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);
{/C_CONSOLE}
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
.
{C_CONSOLE}
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);
{/C_CONSOLE}
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:
{C_CONSOLE}
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");
{/C_CONSOLE}
S tím si zatím vystačíme, operátory se pomocí závorek samozřejmě dají kombinovat.
{C_CONSOLE}
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");
{/C_CONSOLE}
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:
{C_CONSOLE}
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");
{/C_CONSOLE}
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
:
{C_CONSOLE}
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");
{/C_CONSOLE}
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 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í.
Měl jsi s čímkoli problém? Stáhni si vzorovou aplikaci níže a porovnej ji se svým projektem, chybu tak snadno najdeš.
Stáhnout
Stažením následujícího souboru souhlasíš s licenčními podmínkami
Staženo 319x (32.31 kB)
Aplikace je včetně zdrojových kódů v jazyce C