Dnes se naučíme pracovat s logickými hodnotami. Dojde i na jejich využití: podmínku a podmíněný výraz.
19.11.2004 16:00 | Jan Němec | czytane 45602×
RELATED ARTICLES
KOMENTARZE
Porovnání
Pro logické hodnoty ano/ne není v C zvláštní typ. Místo něj se používá se int,
nula znamená ne a jakákoli jiná hodnota ano. Jako ano se v praxi nejčastěji
používá jednička, ale stejně dobře poslouží třeba minus sto dvacet pět.
Typ int chápaný jako logická hodnota vracejí porovnávací operátory
<, <=, ==, >= a >
s významem menší, menší nebo rovno, rovná se, větší nebo rovno a větší.
Všimněte si, že rovnost se testuje operátorem
== a nikoli prostým =,
které je rezervováno pro přiřazení. Dělá to problémy mnoha začínajícím céčkařům
zvyklým na jiný jazyk. Porovnávat můžeme celá i reálná čísla. Při práci
s reálnými čísly se musíme smířit se zaokrouhlovací chybou a nepřesností
některých aritmetických operátorů. Zejména test na rovnost nemusí dopadnout
podle představ programátora, pokud porovnává čísla jako 1.0000000298023
a 0.99999997542, i když třeba vznikla výpočtem, který by
v ideálním světě matematiky vedl přesně k 1.0.
Logické operátory
Úlohu logických spojek mají v C operátory !, && a
||. Vykřičník je negace (not/ne),
&& má význam konjunkce (and/a) a || je alternativa
(or/nebo). Logické xor C nemá, nicméně je možné vyxorovat dvě čísla bit po bitu,
ukážeme si to v některém z dalších dílů.
Nejvyšší prioritu má negace, potom konjunkce a nakonec alternativa.
muze_ridit = !pil && ma_ridicak || ma_poslaneckou_imunitu;
Operátory && a || zaručují pořadí vyhodnocování. Nejprve se vyhodnotí
levý operand a vyhodnocení pravého následuje pouze pokud je to nezbytné pro
vypočtení hodnoty výrazu.
V našem případě by tak u abstinenta s řidičákem již nedošlo na test
imunity. Je proto zcela korektní psát kód jako
muzeme_lyzovat = lyzaru > 0 && hulek / lyzaru >= 2;
/* neboli
muzeme_lyzovat = ((lyzaru > 0) && ((hulek / lyzaru) >= 2))); */
V jazykách s úplným (nebo nespecifikovaným) vyhodnocováním výrazů by nám
mohl obdobný příklad spadnout na dělení nulou, pokud je lyzaru nula, ale
v Céčku vše projde.
Podmíněný příkaz
Přirozeným využitím logických hodnot je podmíněný příkaz.
unsigned synacku = 5, jablicek = 11;
if (synacku > 0)
printf("Každý synáček dostane %u jablíček "
"a %u jich zbude na tatínka.\n",
jablicek / synacku, jablicek % synacku);
else {
puts("Tatínek má 0 synů.");
puts("Raději nebudeme dělit nulou.");
}
Podmínka má syntaxi
if (výraz)
příkaz1 nebo blok1
[
else
příkaz2 nebo blok2
]
Nejprve se vyhodnotí podmínka, je-li splněna vykoná se příkaz1/blok1,
v opačném případě se přeskočí a pokud následuje nepovinná větev else
vykoná se příkaz2/blok2. Podmínit lze jen jeden příkaz, pokud
chceme
podmíněně vykonat příkazů více, je třeba je pomocí složených závorek
seskupit do bloku, jako v případě else větve z příkladu se synáčky
a jablíčky.
Po vykonání podmínky (ať už byla splněna nebo ne) program pokračuje
následujícím příkazem. Podmínky lze podobně jako jiné konstrukce v C do
sebe zanořovat.
if (hotovost > cena)
if (ucet > cena)
puts("Můžeš platit kartou i hotovostí.");
else
puts("Zaplať hotovostí.");
else
if (ucet > cena)
puts("Zaplať kartou.");
else
puts("Ten nový počítač nepotřebuješ.");
Nejasnost by mohla vzniknout v případě
if (výraz1)
if (výraz2)
příkaz1
else
příkaz2
příkaz3 nebo konec bloku
Není totiž jasné ke které podmínce se váže else větev. Norma C to
vyřešila jednoznačně, v podobných případech else větev patří
ke vnitřní podmínce,
vykoná se tedy pokud výraz1 && !výraz2, ovšem z důvodu
čitelnosti
programu je lepší celou vnitřní podmínku od druhého if až po
příkaz2 uzavřít pomocí složených závorek do bloku.
Podmíněný výraz
Kromě klíčového slova if a podmíněného příkazu, nabízí C i ternární
operátor ?: - podmíněný výraz.
Nejprve se vyhodnotí logická hodnota a. Je-li splněna, je výsledkem
výrazu b, v opačném případu c.
V čistém C (narozdíl od C++) nikdy není výsledkem podmíněného výrazu
l-hodnota. Není tedy možné
mít podmíněný výraz na levé straně přiřazení a podmínku použít na určení
proměnné, do které se má přiřadit. Ačkoli některé překladače toto omezení
nemají, není dobré toho využívat.
/* Tohle v C nemusí projít */
(c > 0 ? a : b) = c;
Podmíněný výraz naopak můžeme s úspěchem použít na ošetření dělení nulou.
vysledek = i ? 128 / i : 0;
Někteří programátoři se podmíněnému výrazu systematicky vyhýbají a rozepisují
jej pomocí
if a else.
Pokračování příště
V dalším dílu probereme cykly.