[Přednáška 1] | [Obsah] | [Přednáška 3] |
int getchar()
, pro výstup
jednoho znaku na standardní výstup (obrazovku, terminál) slouží funkce
int putchar(int c)
z knihovny stdio.h
.
Tzv. hlavičku funkce, tj. jak funkce vypadá, čteme následovně: funkce getchar vrací číslo typu int
a nemá žádné parametry (prázdné závorky, upřesnění a detaily si povíme později).
Funkce putchar vrací číslo typu int
a má jeden parametr typu int
.
Funkce getchar()
nevrací překvapivě hodnotu typu char
,
ale hodnotu typu int
. Původ této skutečnosti je ve funkcích sloužící ke čtení znaků ze souboru,
resp. k zápisu znaků do souboru. Návratové hodnoty mimo rozsah 0 až 255 (tedy rozsah odpovídající znakům) dovolují
programu signalizovat, že došlo k nějaké chybě (např. konec souboru atd.).
Ve funkci putchar(int c)
je c
znak vystupující na terminál.
Samozřejmě, skutečným parametrem funkce putchar(int c)
může být proměnná typu char
, dojde k automatické konverzi.
V případě, že návratová hodnotá funkce getchar()
je přiřazena do proměnné typu char
, překladač většinou
hlásí varování typu „Conversion may lose significant digits“.
putchar('A'); putchar(65);
výraz1 ? výraz2 : výraz3
Hodnota podmíněného výrazu je výraz2, pokud má výraz1 nenulovou hodnotu (neboli je pravdivý, true); v opačném případě má hodnotu výraz3.
(a==3) ? 1 : 0 // je-li hodnota proměnné a rovna 3, podmíněný výraz má hodnotu 1, jinak 0
Podmíněný výraz lze s výhodou využít např. při přiřazení:
x = (a==3) ? 1 : 0 // je-li hodnota proměnné a rovna 3, do proměnné x se přiřadí hodnota 1
Pomocí podmínky bychom zapsali přiřazení takto:
if (a==3) x = 1; else x = 0;
Poznámka: První výraz není nutné uzavírat do závorky, ale často se uzavírá kvůli čitelnosti kódu. Uvědomte se, že podmíněným výrazem nelze nahradit jakoukoliv podmínku
if
!
výraz1, výraz2, výraz3
Zapsaná trojice výrazů je považována za jeden výraz. Význam je následující: nejprve se vyhodnotí výraz1, pak výraz2 a naposledy výraz3. Hodnotou celého výrazu je hodnota posledního vyhodnoceného výrazu. Vše vysvětlí malý příklad, i když poněkud nesmyslný:
Z příkladu je viditelné, že operátor čárka není příliš přehledný z hlediska čitelnosti kódu, čtenář možná pochybuje o jeho smyslu (a v tomto případě má pravdu). Proto je také doporučeno omezit jeho používání pouze v případě cyklu typux = a=1, 3, a+b;
Nejprve se vyhodnotí přiřazovací výraz, tedy do proměnné
a
se přiřadí hodnota 1; hodnota výrazua=1
je 1, ale tato hodnota se „zahodí“. Vyhodnotí se další výraz, tedy 3, tato hodnota se opět „zapomene“. Nakonec se sečtou hodnoty proměnnýcha
ab
. Součet je hodnotou celého výrazu a je přiřazen do proměnnéx
.
for
.
for
má v jazyku C poněkud odlišnou syntaxi i sémantiku než v jazycích typu Pascal nebo Basic.
Jeho možnosti jsou mnohem bohatší oproti zmíněným jazykům. Obecný zápis cyklu vypadá takto:
for(výraz1;výraz2;výraz3) příkaz;
Chování cyklu for
je ekvivaletní cyklu typu while
s tímto zápisem:
výraz1; while(výraz2) { příkaz; výraz3; }Nejprve se vyhodnotí výraz1 (pouze jednou, před vstupem do cyklu!). Pak se provádí tělo cyklu, dokud je splněn výraz2. Na konci každého provedení těla cyklu je vždy ještě vyhodnocen výraz3. Typické využití cyklu
for
je ve tvaru cyklu s pevným počtem opakování, např.
for(i=1;i<=n;i++) příkaz;
, resp. for(i=n;i>=1;i--) příkaz;
Na místě výrazů mohou být skutečně libovolné výrazy, tedy na místě výraz2 může být libovolně složitá podmínka, zvětšit hodnotu proměnné na konci cyklu je možné např. o 2 aj.
Poznámka: Proměnná i se nazývá řídicí proměnná cyklu.Ekvivalence obou cyklů je ukázána na jednoduchém příkladě, který vypíše násobilku 3, viz tabulka 1.
Cyklus for | Cyklus while |
int i; for(i=1;i<=10;i++) printf("%d",3*i); |
int i; i=1; while(i<=10) { printf("%d",3*i); i++; } |
Tabulka 1: Ekvivalence cyklů
Pro ověření, zda dobře rozumíte cyklu for
, zkuste analyzovat
následující příklad.
Napište program, který vypočte součet přirozených čísel od 1 do n, číslo n se zadává z klávesnice.
Řešení:
Na této úloze si ukážeme několik specialit, které cyklusfor
v jazyce C nabízí. V popisech řešení vynecháme pro stručnost deklaraci proměnných (všechny jsou typuint
), načtení čísla n z klávesnice a výpis výsledku na obrazovku.
Přirozené řešení, odpovídající filozofii zápisu algoritmu i v jiných jazycích, uvedeme jako první:s = 0; for(i=1;i<=n;i++) s+=i;Právě zde je rozumné využít operátor čárka a přidat inicializační výrazs = 0
do cyklu k inicializaci proměnnéi
:for(s=0,i=1;i<=n;i++) s+=i;Libovolný z výrazů je možné v cyklu vynechat. Pokud bychom chtěli zvýšení hodnoty proměnnéi
o jedničku provést v těle cyklu současně se sumací (využijeme operátor ++ v postfixové formě), můžeme napsat:for(s=0,i=1;i<=n;) s+=i++;V krajním případě bychom mohli celý výraz představující sumaci a následné zvýšení hodnoty proměnnéi
zahrnout do cyklu jako výraz3 a tělo ponechat prázdné:for(s=0,i=1;i<=n;s+=i++); /* zde ma strednik vyznam prazdneho prikazu v tele cyklu */Poslední dvě řešení se nedoporučuje příliš využívat, protože slučují příkazy těla cyklu a kód související s řídicí proměnnou cyklu, což ubírá na čitelnosti a přehlednosti kódu. Nicméně příklady poslouží jako vhodná ukázka, jaká „kouzla“ jazyk C dovoluje.
Poznámka: S cykly (se všemi typy) v jazyce C souvisejí dvě klíčová slova: break
a continue
.
Příkaz break
ukončuje předčasně cyklus (používá se v souvislosti s nějakou podmínkou). Příkaz continue
ukončí přeruší pouze aktuální iteraci, provede se skok na testovací podmínku, je-li splněna, provádí se další iterace.
Napíšeme program, který přečte z klávesnice text (posloupnost znaků) zakončený stiskem klávey Enter a který převede velká písmena anglické abecedy na malá.
int main(int argc, char **argv) { int c; while((c = getchar())!='\n') putchar((c >='A' && c <= 'Z') ? c+('a'-'A') : c); system("PAUSE"); return 0; }Jako ukázku přepíšeme cyklus s využitím
break
a continue
. Reálný kód by takto vypadat ale neměl.
while (1) { c = getchar(); if (c == '\n') break; if (c >= 'A' && c <= 'Z') { putchar(c+('a'-'A')); continue; } putchar(c); }
switch
představuje přepínač variant, je obdobou příkazu case
v jazyce Pascal. Obecný tvar příkazu
můžeme zapsat:
switch (výraz) { case konstanta1: příkaz1; case konstanta2: příkaz2; atd. default: příkaz; }Výraz je libovolný výraz, který musí být celočíselného typu (nelze tedy použít přepínač např. s proměnnými typu
float
nebo double
).
Jednotlivé varianty, zapsané za klíčovým slovem case
, mohou být pouze konstanty, není dovoleno psát proměnné ani
např. intervaly ohraničené konstantami. Pokud je nutné zapsat k dané variantě více
příkazů, nemusejí být tentokrát uzavřeny do bloku mezi znaky { ... }
. Varianta uvedená za klíčovým slovem default
je vykonána
v případě, že hodnota výrazu neodpovídá ani jedné z uvedených variant. Varianta default
je nepovinná, pokud není uvedena a hodnota výrazu neodpovídá
žádné z variant, žádný příkaz se neprovede.
Upozornění: S konstrukcíswitch(getchar()) { case '1': printf("Zadal jste 1!"); case '2': printf("Zadal jste 2!"); case '3': printf("Zadal jste 3!"); }Je pravděpodobné, že skutečné chování příkazu (jak jsme jej zapsali výše) se bude lišit od čtenářovy představy. Zadá-li uživatel programu znak 2, na obrazovce se vytiskne následující text:Zadal jste 2! Zadal jste 3!Zadaný znak se nejprve porovná s konstantou'1'
, není-li shodný, pokračuje se v porovnání s konstantou'2'
atd. Nastane-li shoda, provedou se příkazy u dané varianty a pokračuje se v provádění příkazů u dalších variant (příkaz switch je většinou přeložen do strojového kódu jako „rozskok“ pomocí tabulky a instrukce typu JMP). Abychom dosáhli výběru jediné varianty, je třeba doplnit jednotlivé větve klíčovým slovembreak
:switch(getchar()) { case '1': printf("Zadal jste 1!"); break; case '2': printf("Zadal jste 2!"); break; case '3': printf("Zadal jste 3!"); break; default: printf("Zadal jste něco jiného"); }Pak bude po zadání znaku 2 na obrazovce skutečně jedna věta:Zadal jste 2!Na uvedení příkazubreak
programátoři, kteří začínají s jazykem C, často zapomínají.Vynechání příkazu
break
může být účelem, je dovoleno vynechat dokonce i příkaz. Tímto způsobem se zajistí obsloužení více variant jedním kódem:switch(getchar()) { case '1': printf("Zadal jste 1!"); break; case '2': case '3': printf("Zadal jste 2 nebo 3!"); break; default: printf("Zadal jste něco jiného"); }
switch
souvisí pouze příkaz break
,
nikoliv continue
.
[Přednáška 1] | [Obsah] | [Přednáška 3] |