Předvánoční slevová akce PHP týden
Pouze tento týden sleva až 80 % na PHP e-learning!
Využij předvánočních slev a získej od nás 20 % bodů zdarma! Více zde

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

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, 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, Cykly v Céčku, nás čekají pole a cykly. Tím dovršíme základní znalosti, máte se na co těšit :)


 

Stáhnout

Staženo 261x (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
Cvičení k 4.-5. lekci Céčka
Aktivity (18)

 

 

Komentáře

Avatar
Daniel Vítek
Tým ITnetwork
Avatar
Daniel Vítek:15.9.2014 11:20

Jak jde udělat větvení pomocí switche s textovými příkazy ?

Odpovědět
15.9.2014 11:20
Na síti působím už pěknou řádku let. Pokud budeš něco potřebovat, písni mi, pokusím se ti poradit :)
Avatar
xxxvodnikxxx
Člen
Avatar
Odpovídá na Daniel Vítek
xxxvodnikxxx:15.9.2014 22:22

Myslim, že céčko Stringy v case nepodporuje, ale je možný to řešit např. takhle http://stackoverflow.com/…with-strings

btw Samuel Kodytek - To okno výstupu je z netbeans?
Je možný v nich nějak pod win zprovoznit kompilátor a programovat Céčko ? dík..
Objevil jsem Cintr https://edux.fit.cvut.cz/…tbeans/CIntr
ale nějak mi nešel zprovoznit

Odpovědět
15.9.2014 22:22
Unix- svět, kde chcete být nulou :) (UID)
Avatar
Samuel Kodytek
Šéfredaktor
Avatar
Odpovídá na Daniel Vítek
Samuel Kodytek:16.9.2014 17:44

String (textový řetězec) Céčko nepodporuje ale je v céčku něco jako by String ale tím se chci zabývat později :). potřebuješ na to znát pole.

Odpovědět
16.9.2014 17:44
There is more than one way to screw it
Avatar
Samuel Kodytek
Šéfredaktor
Avatar
Odpovídá na xxxvodnikxxx
Samuel Kodytek:16.9.2014 17:45

Pořádně jsem nepochopil co potřebuješ? Myslíš nainstalovat kompilátor do netbeanu? Pokud ano tak to máš v prvním tutoriálu ( http://www.itnetwork.cz/…-kompilatoru ) :)

Odpovědět
16.9.2014 17:45
There is more than one way to screw it
Avatar
Johny Petka
Člen
Avatar
Johny Petka:18.4.2016 20:19

Ahoj, prosím o pomoc, mám problém s funkcí sqrt() v jazyce C. Pouzivam
NetBeans IDE 8.1 a Debian.

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

/*
*
*/
int main(int argc, char** argv) {
int a;
double o = sqrt (a);

printf("Zadej cislo, ktere muzu odmocnit : \n");
scanf("%d", &a);
if (a>=0)
printf("Odmocnia cisla %d je %f",a,o);
return (EXIT_SUCCESS);

výstup:

cd '/home/chlup/Net­BeansProjects/tet­s'
/usr/bin/make -f Makefile CONF=Debug
"/usr/bin/make" -f nbproject/Makefile-Debug.mk QMAKE= SUBPROJECTS= .build-conf
make[1]: Vstupuje se do adresáře „/home/chlup/Net­BeansProjects/tes­t“
"/usr/bin/make" -f nbproject/Makefile-Debug.mk dist/Debug/GNU-Linux/test
make[2]: Vstupuje se do adresáře „/home/chlup/Net­BeansProjects/tes­t“
mkdir -p dist/Debug/GNU-Linux
gcc -o dist/Debug/GNU-Linux/tets build/Debug/GNU-Linux/main.o
build/Debug/GNU-Linux/main.o: In function `main':
/home/chlup/Net­BeansProjects/tet­s/main.c:28: undefined reference to `sqrt'
collect2: error: ld returned 1 exit status
nbproject/Makefile-Debug.mk:62: návod pro cíl „dist/Debug/GNU-Linux/test“ selhal
make[2]: *** [dist/Debug/GNU-Linux/tets] Chyba 1
make[2]: Opouští se adresář „/home/chlup/Net­BeansProjects/tes­t“
nbproject/Makefile-Debug.mk:59: návod pro cíl „.build-conf“ selhal
make[1]: *** [.build-conf] Chyba 2
make[1]: Opouští se adresář „/home/chlup/Net­BeansProjects/tet­s“
nbproject/Makefile-impl.mk:39: návod pro cíl „.build-impl“ selhal
make: *** [.build-impl] Chyba 2

googlil jsem, na par forech jsem nasel, ze muze byt problem s libm.so, jenze
mi nejak uniklo, co s tim libm.so delat, jsem zacatecnik. Dekuji za Vas cas :)

 
Odpovědět
18.4.2016 20:19
Avatar
Libor Šimo (libcosenior):19.4.2016 6:04

Po 1. nemáš uzavretý blok main()
po 2.
int a;
double o = sqrt (a);
je blbosť, pretože a nemáš definované.

Skús to takto:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

/*
*
*/
int main(int argc, char** argv)
{
    int a;
    //double o = sqrt (a);

    printf("Zadej cislo, ktere muzu odmocnit : \n");
    scanf("%d", &a);
    if (a>=0)
    printf("Odmocnia cisla %d je %f",a , sqrt(a));
    return (EXIT_SUCCESS);
}
Odpovědět
19.4.2016 6:04
Aj tisícmíľová cesta musí začať jednoduchým krokom.
Avatar
Johny Petka
Člen
Avatar
Odpovídá na Libor Šimo (libcosenior)
Johny Petka:19.4.2016 18:33

Díky moc za reakci :) a omlouvám se, tělo jsem uzavřené měl, neokopíroval jsem složenou závorku. Vyzkušel jsem Tvůj prográmek a přesto mi výstup hází toto :

cd '/home/chlup/Net­BeansProjects/tet­s'
/usr/bin/make -f Makefile CONF=Debug
"/usr/bin/make" -f nbproject/Makefile-Debug.mk QMAKE= SUBPROJECTS= .build-conf
make[1]: Vstupuje se do adresáře „/home/chlup/Net­BeansProjects/tet­s“
"/usr/bin/make" -f nbproject/Makefile-Debug.mk dist/Debug/GNU-Linux/tets
make[2]: Vstupuje se do adresáře „/home/chlup/Net­BeansProjects/tet­s“
mkdir -p build/Debug/GNU-Linux
rm -f "build/Debug/GNU-Linux/main.o.d"
gcc -c -g -MMD -MP -MF "build/Debug/GNU-Linux/main.o.d" -o build/Debug/GNU-Linux/main.o main.c
mkdir -p dist/Debug/GNU-Linux
gcc -o dist/Debug/GNU-Linux/tets build/Debug/GNU-Linux/main.o
build/Debug/GNU-Linux/main.o: In function `main':
/home/hydra/Net­BeansProjects/tet­s/main.c:29: undefined reference to `sqrt'
collect2: error: ld returned 1 exit status
nbproject/Makefile-Debug.mk:62: návod pro cíl „dist/Debug/GNU-Linux/tets“ selhal
make[2]: *** [dist/Debug/GNU-Linux/tets] Chyba 1
make[2]: Opouští se adresář „/home/chlup/Net­BeansProjects/tet­s“
nbproject/Makefile-Debug.mk:59: návod pro cíl „.build-conf“ selhal
make[1]: *** [.build-conf] Chyba 2
make[1]: Opouští se adresář „/home/chlup/Net­BeansProjects/tet­s“
nbproject/Makefile-impl.mk:39: návod pro cíl „.build-impl“ selhal
make: *** [.build-impl] Chyba 2

BUILD FAILED (exit value 2, total time: 118ms)

 
Odpovědět
19.4.2016 18:33
Avatar
Odpovídá na Johny Petka
Libor Šimo (libcosenior):19.4.2016 18:36

Vykasli sa .na netbeans a nainštaluj si code::blocks.
Pozri sem:h
ttp://www.itnet­work.cz/cplus­plus/cecko-linux/tutorial-c-linux-codeblocks

Editováno 19.4.2016 18:37
Odpovědět
19.4.2016 18:36
Aj tisícmíľová cesta musí začať jednoduchým krokom.
Avatar
Johny Petka
Člen
Avatar
Odpovídá na Libor Šimo (libcosenior)
Johny Petka:19.4.2016 19:46

Funguje, díky moc!!!

 
Odpovědět
19.4.2016 19:46
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Samuel Kodytek
DarkCoder:6.10.2016 1:23

Obecná negace ! není relační operátor ale logický. Operátory && a || jsou rovněž logické, pojem základní nikomu nic neřekne.

Používáme-li funkci, kontroluji nejen její návratový typ ale i typy parametrů které přebírá. Funkce sqrt() opravdu nepřebírá typ i. Argumentem funkce je typ double. Takže buď proměnná a bude typu double nebo je třeba argument přetypovat na double.

double o = sqrt((double)a);

Výraz

(a == 0) je lepší psát jako (!a)  a  (a == 1) je lepší psát jako (a)
printf("Vysledek: %lf", vysledek);

pro typ double se používá %f

else
    printf("Neplatná volba \n");
    printf("\n");
    printf("Dekuji za pouziti kalkulacky");

Pokud není použit blok, je dobré dodržovat odsazování. Odsazení v tomto případě může vést čtenáře k domněnce, že všechny příkazy za else patří k sobě.

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("Neplatná volba \n");

Kód lze zapsat lépe:

scanf("%d", &volba);
switch(volba)
{
    case 1:
        printf("Vysledek: %f\n", a+b);
        break;
    case 2:
        printf("Vysledek: %f\n", a-b);
        break;
    case 3:
        printf("Vysledek: %f\n", a*b);
        break;
    case 4:
        printf("Vysledek: %f\n", a/b);
        break;
    default: printf("Neplatná volba \n");
}

Není třeba používat proměnnou výsledek, vyhodnocení výrazu lze předat jako argument funkci printf().
Navíc odpadá zbytečné porovnávání na neplatnou volbu.

Odpovědět
6.10.2016 1:23
"„Učíš-li se proto, aby sis zapamatoval, zapomeneš. Učíš-li se proto, abys porozuměl, zapamatuješ si."
Avatar
Lukáš Rác
Člen
Avatar
Lukáš Rác:28.8.2017 15:59

Zdravím, mám problém nejspíš s kompilací.Vytvořil jsem tu kalkulačku přesně podle tohoto návodu, ale když ho chci debugovat a spustit, tak to přestane pracovat, nebo se nic nestane. Nevíte co s tím? Compiler mám samozřejmě nainstalovaný. Tady to mám ve videu: https://www.youtube.com/watch?…

zde je zdroják: https://www.itnetwork.cz/dev-lighter/964

 
Odpovědět
28.8.2017 15:59
Avatar
Marek Uhlik
Člen
Avatar
Odpovídá na Lukáš Rác
Marek Uhlik:28.8.2017 16:07

První bych zkusil dopsat & do scanf kde jsem koukal že ti to chybí a tím by to i mohlo být

 
Odpovědět
28.8.2017 16:07
Avatar
Lukáš Rác
Člen
Avatar
Lukáš Rác:28.8.2017 16:24

Super, pomohlo, Díkyyy moc!! :)

 
Odpovědět
28.8.2017 16:24
Avatar
Jan Jenda
Člen
Avatar
Jan Jenda:31.10.2017 22:54
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char** argv) {

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");
        return (EXIT_SUCCESS);
}

Ahoj rád bych kód pochopil , ale né vše mi je jasné

  1. Proč je na začátku za výsledkem to 0.0?
  2. else a else if znamená co?
 
Odpovědět
31.10.2017 22:54
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Jan Jenda
DarkCoder:31.10.2017 23:56
  1. Proměnná výsledek je v tomto příkladu nadbytečná, neboť výrazy mohou být přímo součástí argumentu funkce printf(). Chyba to ovšem není. Tento příklad je jednoduchý, ale u složitějších příkladů by se mohlo dále s proměnnou pracovat a pak by měla svůj význam. Proměnná vysledek je lokální proměnnou a bývá zvykem tyto proměnné před použitím inicializovat na nějakou hodnotu. Neinicializovaná lokální proměnná v sobě může obsahovat různé hodnoty a může tak být příčinou chyb v programu. Jelikož se jedná o číselnou proměnnou s desetinnou čárkou (double), je třeba překladači sdělit, že se jedná o číslo s desetinou čárkou, proto je proměnná správně inicializována hodnotou 0.0 a nikoli 0.
  2. if-else-if (schody, žebřík if-else-if) je druh podmíněného příkazu užívaného pro porovnání hodnot z několika variant. Používá se obvykle u menšího počtu těchto variant, u vyššího počtu switch, které ale zase má svá omezení. if-else-if je efektivnější nežli použití samotných if. Pro zpracování potřebuje méně strojových instrukcí a zároveň, pokud je nalezena shoda, ostatní if se přeskočí.
Odpovědět
31.10.2017 23:56
"„Učíš-li se proto, aby sis zapamatoval, zapomeneš. Učíš-li se proto, abys porozuměl, zapamatuješ si."
Tento výukový obsah pomáhají rozvíjet následující firmy, které dost možná hledají právě tebe!
Avatar
Jan Jenda
Člen
Avatar
Jan Jenda:1.11.2017 8:54

Ahoj moc děkuji DarkCoder. Ale pořád mi to není úplně jasné zkusím začít hned na začátku.

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char** argv) {

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);
        return (EXIT_SUCCESS);
}

Pod tím je napsáno, že to nefunguje. Chápu správně, že se proměnná nezamění protože to jede postupně resp. platí první podmínka dá se tam jednička, tím pádem začne platit i druhá a skončí to zase druhou.

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char** argv) {

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");
        return (EXIT_SUCCESS);
}

jaký je rozdíl mezi čisté if, a else if, a existuje ješě if else?

vlastně kdybych měl jen if, if ,if ,if a né if, else if, else if, else if nebude to to samé? Protože pokud nebude platit podmínka 1 skočí na druhou, pokud to nebude ani 2 skočí na 3, která bude platit.

 
Odpovědět
1.11.2017 8:54
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Jan Jenda
DarkCoder:1.11.2017 13:05
  1. Přesně tak, ke změně proměnné nedojde. Tím, jak se jednotlivé příkazy vyhodnocují postupně, se provedou obě podmínky a proměnná tak zůstane nezměněna.
  2. Rozdíl jsem popsal na konci předchozího příspěvku. if-else-if je efektivnější nežli použití samotných if. Pro zpracování potřebuje méně strojových instrukcí a zároveň, pokud je nalezena shoda, ostatní if se přeskočí.

Mějme následující dva úryvky kódu a podívejme se co se stane, když volba bude 2.

if (volba == 1) vysledek = a + b;
if (volba == 2) vysledek = a - b;
if (volba == 3) vysledek = a * b;
if (volba == 4) vysledek = a / b;
if ((volba > 0) && (volba < 5)) printf("Vysledek: %lf", vysledek);
if ((volba <= 0) && (volba >= 5)) printf("Neplatna volba \n");

Zde se budou postupně provádět a vyhodnocovat všechny podmínky, i tehdy když už je výsledek známý. Přiřadí proměnné vysledek rozdíl dvou hodnot a zobrazí jej. Na tuto verzi zapomenout a neužívat - neefektivní.

kdežto:

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");

Zde se budou postupně provádět a vyhodnocovat všechny podmínky, dokud není podmínka platná. Zbylé podmínky (test na rovnost 3 a 4) se přeskočí, kromě té kde vypisuji výsledek. Přiřadí proměnné vysledek rozdíl dvou hodnot a zobrazí jej.

pro srovnání:

switch(volba){
    case 1:
        printf("Vysledek: %f\n", a+b);
        break;
    case 2:
        printf("Vysledek: %f\n", a-b);
        break;
    case 3:
        printf("Vysledek: %f\n", a*b);
        break;
    case 4:
        printf("Vysledek: %f\n", a/b);
        break;
    default: printf("Neplatná volba \n");
}

Zde nepotřebuji proměnnou a ještě mi odpadlo vyhodnocování další podmínky.

Odpovědět
1.11.2017 13:05
"„Učíš-li se proto, aby sis zapamatoval, zapomeneš. Učíš-li se proto, abys porozuměl, zapamatuješ si."
Avatar
DarkCoder
Člen
Avatar
DarkCoder:1.11.2017 20:46

Chyba v mém předchozím příspěvku. Pro výpis proměnné typu double se pochopitelně u funkce printf() používá specifikátor formátu %f nikoli %lf. Tato odlišnost je pouze u funkce scanf().

Odpovědět
1.11.2017 20:46
"„Učíš-li se proto, aby sis zapamatoval, zapomeneš. Učíš-li se proto, abys porozuměl, zapamatuješ si."
Avatar
Tomas Bahensky:9.2.2018 16:23

Ahoj mam dotaz ohledne funkce switch. U prikladu se Simpsonovymi je vzdy u "case" uvedena dana volba v jednoduchych zavorkach....case 'a'....case 'b'...atd. Pokud je tam nedam, hlasi mi to chybu a program se ani nespusti.
Kdyz dam mezi zvorky cislo, tak to funguje, ovsem cislo bez zavorek opet nefunguje respektive compiler to prechrousta, spusti se program, ale dana volba nezobrazi zadny vysledek.
No ale v kapitole 5 u prikladu s kalkulackou za vyuziti switch, je vzdy pouzito cislo (case 1, case 2) bez zavorek a vse funguje bez problemu.

Muzete mi prosim nekdo vysvetlit cim to je pripadne odkazat na nejaky clanek, kde je to vysvetleno?

Diky!

 
Odpovědět
9.2.2018 16:23
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Tomas Bahensky
DarkCoder:9.2.2018 17:08

Příklad se Simpsonovými jsem neviděl, nicméně vysvětlení lze podat i bez něj.

Příkaz switch pracuje s celočíselnými proměnnými (typ int a typ char). Typ char lze použít i tam kde postačí malé celé číslo. Každý znak má svoji hodnotu, v jazyce C se vychází s ASCII tabulky. Konkrétně:

case 1: není totéž co     case '1':

V prvním případě se porovnává řídící proměnná příkazu switch s hodnotou 1, ve druhém případě se řídící proměnná porovnává s hodnotou 49 (ASCII hodnota znaku '1' je 49);

Proto je důležité a je třeba rozlišovat to, zda v case použiji jednoduché uvozovky nebo ne.

Oba způsoby je možno kombinovat ale je třeba znát hodnotu znaku. Např. následující úryvek kódu není správný

char c;

switch(c) {
  case 'A': printf("Pismeno A"); break;
  case 65: printf("Cislo 65"); break;
}
Odpovědět
9.2.2018 17:08
"„Učíš-li se proto, aby sis zapamatoval, zapomeneš. Učíš-li se proto, abys porozuměl, zapamatuješ si."
Avatar
Odpovídá na DarkCoder
Tomas Bahensky:9.2.2018 20:09

Diky moc za reakci....akorat jsem tedy zjistil, ze je to krapet slozitejsi, nez jsem si myslel :))) Jsem samouk zacatecnik, takze se dostavam casto do slepych ulicek...

Nicmene jsem jsem mel na mysli priklad viz nize versus ta kalkulacka zminena o ctyri prispevky v diskuzi zpet.

int main()
{
char volba;
printf ("Vyber si nejakou postavu ze Simpsonovych: \n");
printf ("\n");

printf ("a) Homer \n");
printf ("b) Bart \n");
printf ("c) Marge \n");
printf ("d) Liza \n");
printf ("e) Maggie \n");
printf ("\n");

scanf ("%c", &volba);
switch (volba)
{
case 'a':
printf ("Jmeno: Homer Simpson \n");
printf ("Vek: 38 \n");
printf ("Zamestnani: bezpecnostni technik \n");
break;
case 'b':
printf ("Jmeno: Bart Simpson \n");
printf ("Vek: 10 \n");
printf ("Zamestnani: student \n");
break;
case 'c':
printf ("Jmeno: Marge Simpson \n");
printf ("Vek: 35 \n");
printf ("Zamestnani: zena v domacnosti \n");
break;
case 'd':
printf ("Jmeno: Liza Simpson \n");
printf ("Vek: 8 \n");
printf ("Zamestnani: studentka \n");
break;
case 'e':
printf ("Jmeno: Maggie Simpson \n");
printf ("Vek: 8 mesicu \n");
printf ("Zamestnani: batole \n");
break;
}
return (0);
}

Na prvni pohled mi to prislo jako stejna konstrukce, ale evidentne to tak neni. Kdyz dam do tohoto prikladu se Simpsnovejma jednoduchy cisla bez zavorek, tak to nefunguje, kdezto u kalkulacky jo. A netusim proc. Jestli jsi to v tom predchozim prispevku vysvetlil, tak se omlouvam, ale zrejme jsem to nepochopil :)

Diky!

 
Odpovědět
9.2.2018 20:09
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Tomas Bahensky
DarkCoder:9.2.2018 22:11

Není to složité. Čím více si budeš s řídícími příkazy pohrávat, bude Ti to víc a víc jasnější.

Příkaz switch očekává nějaký identifikátor (v našem případě proměnnou volba). Proměnná volba je typu char, tedy je očekáván znak. Znak může být reprezentován mnoha způsoby. Tím nejčastějším je znak uzavřený mezi jednoduchými uvozovkami. Ale může být i číselně (každý znak má svoji ASCII hodnotu). Např. ASCII hodnota znaku 'A' je 65. A jelikože switch nesmí obsahovat dvě totožné hodnoty, je příklad v mém předchozím příspěvku nesprávný. I s čísly příklad se Simpsonovýma funguje. Viz. následující z důvodu jednoduchosti poupravené dva kódy, které jsou funkčně totožné:

Varianta s čísly

#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>

int main(void){
        char volba;

        printf("Vyber si nejakou postavu ze Simpsonovych\n\n");
        printf("a) Homer\n");
        printf("b) Bart\n");
        printf("c) Marge\n");
        printf("d) Liza\n");
        printf("e) Maggie\n\n");

        volba = getchar();
        fseek(stdin, 0L, SEEK_END);

        switch (volba){
                case 97:  printf("Homer Simpson\n");
                                break;
                case 98:  printf("Bart Simpson\n");
                                break;
                case 99:  printf("Marge Simpson\n");
                                break;
                case 100: printf("Liza Simpson\n");
                                break;
                case 101: printf("Maggie Simpson\n");
                                break;
        }

        return 0;
}

Varianta se znaky

#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>

int main(void){
        char volba;

        printf("Vyber si nejakou postavu ze Simpsonovych\n\n");
        printf("a) Homer\n");
        printf("b) Bart\n");
        printf("c) Marge\n");
        printf("d) Liza\n");
        printf("e) Maggie\n\n");

        volba = getchar();
        fseek(stdin, 0L, SEEK_END);

        switch (volba){
                case 'a':  printf("Homer Simpson\n");
                                break;
                case 'b':  printf("Bart Simpson\n");
                                break;
                case 'c':  printf("Marge Simpson\n");
                                break;
                case 'd': printf("Liza Simpson\n");
                               break;
                case 'e': printf("Maggie Simpson\n");
                               break;
        }

        return 0;
}
Odpovědět
9.2.2018 22: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 Tomas Bahensky
DarkCoder:9.2.2018 22:53

A takto to máš s čísly jako volba menu:

#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>

int main(void) {
        int volba;

        printf("Vyber si nejakou postavu ze Simpsonovych\n\n");
        printf("1) Homer\n");
        printf("2) Bart\n");
        printf("3) Marge\n");
        printf("4) Liza\n");
        printf("5) Maggie\n\n");

        scanf("%d", &volba);

        switch (volba) {
        case 1:  printf("Homer Simpson\n"); break;
        case 2:  printf("Bart Simpson\n"); break;
        case 3:  printf("Marge Simpson\n"); break;
        case 4:  printf("Liza Simpson\n"); break;
        case 5:  printf("Maggie Simpson\n"); break;
        }

        return 0;
}

To nejpodstatnější je typ řídící proměnné, specifikace formátu ve funkci scanf() a zápis case.

Odpovědět
9.2.2018 22:53
"„Učíš-li se proto, aby sis zapamatoval, zapomeneš. Učíš-li se proto, abys porozuměl, zapamatuješ si."
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Tomas Bahensky
DarkCoder:9.2.2018 23:16

S číselnou volbou jako znaky

#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>

int main(void) {
        char volba;

        printf("Vyber si nejakou postavu ze Simpsonovych\n\n");
        printf("1) Homer\n");
        printf("2) Bart\n");
        printf("3) Marge\n");
        printf("4) Liza\n");
        printf("5) Maggie\n\n");

        volba = getchar();
        fseek(stdin, 0L, SEEK_END);

        switch (volba) {
        case '1':  printf("Homer Simpson\n"); break;
        case '2':  printf("Bart Simpson\n"); break;
        case '3':  printf("Marge Simpson\n"); break;
        case '4':  printf("Liza Simpson\n"); break;
        case '5':  printf("Maggie Simpson\n"); break;
        }

        return 0;
}
Odpovědět
9.2.2018 23:16
"„Učíš-li se proto, aby sis zapamatoval, zapomeneš. Učíš-li se proto, abys porozuměl, zapamatuješ si."
Avatar
Odpovídá na DarkCoder
Tomas Bahensky:10.2.2018 14:06

Diky DarkCoder! Uz mi to zacina byt jasny.... :) Cele to je tedy o tom, jaky typ promenne definuji a zdali ma byt vkladana promenna cislo nebo znak. Podle toho pouziji bud samotne cislo (odpovidajici potrebnemu znaku v ASCII), cislo v zavorkach a nebo znak v zavorkach. Je to tak?

A jeste posledni otazku, jak tu vlozim do diskuze priklad tak, aby byl graficky zobrazen jako v compileru a ne jako prosty text (ctrl C, ctrl V)?

Diky!

 
Odpovědět
10.2.2018 14:06
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Tomas Bahensky
DarkCoder:10.2.2018 15:17

Přesně tak. Celé to je o typu a o tom, jak danou proměnnou zpracováváš. Příklad, kde znaku odpovídá číslo, ber z hlediska zajímavosti. Takto bys to ve skutečnosti dělat neměl, ale jsou případy, kdy se to velmi hodí. Stejně tak by bylo nesmyslné, abys číslo reprezentoval znakem.

Jednoduše, je-li identifikátor typu znak, použij znak uzavřený mezi jednoduché uvozovky, je-li celočíselný, použij celočíselnou hodnotu bez jakýchkoli uvozovek. Př.

char cVolba;

switch(cVolba){
  case 'a': //...
}

nebo

int iVolba;

switch(iVolba){
  case 1: //...
}

Výše uvedené příklady jsou primitivní, ale v komplexních úlohách si můžeš vypomoci prefixem, kde Ti i letmý pohled na identifikátor řekne jakého je typu a jak s ním pracovat (Např. cVolba, iVolba, pVolba apod.).

Pro zobrazení kódu jako v překladači použij párový tag (vložení zdrojového kódu, je umístěn nad textovým polem) do kterého následně vložíš zdrojový kód.

Odpovědět
10.2.2018 15:17
"„Učíš-li se proto, aby sis zapamatoval, zapomeneš. Učíš-li se proto, abys porozuměl, zapamatuješ si."
Avatar
Tomáš Daniel:4.5.2018 8:48

PROČ TA DAL NAJEDNOU ("%lf") a ne pouze ("%f")???

Odpovědět
4.5.2018 8:48
Proč chtít cokoliv jiného, než IT
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Tomáš Daniel
DarkCoder:4.5.2018 11:24

Specifikator formátu %lf se používá ve funkci scanf() pro načtení proměnné typu double. Oproti tomu specifikator formátu %f se používá ve funkci scanf() pro načtení proměnné typu float. Ve funkci printf() se pro výpis proměnné typu float i double používá specifikator formátu %f.

Odpovědět
4.5.2018 11:24
"„Učíš-li se proto, aby sis zapamatoval, zapomeneš. Učíš-li se proto, abys porozuměl, zapamatuješ si."
Avatar
Jan Tesař
Člen
Avatar
Jan Tesař:24. listopadu 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. listopadu 8:58
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 29 zpráv z 29.