6.1. Vyrazovy
prikaz
6.2. Prazdny prikaz
6.3. Bloky.
6.4. Oblast platnosti
identifikatoru
6.5. Podmineny prikaz
if-else.
6.6. Prepinac
6.7. Cykly
6.8. Prikaz skoku
V dosavadnim vykladu jsme se dozvedeli, ze se program
sklada z funkce main()
a z prikazu, ktere tato
funkce obsahuje. Sve intuitivni predstavy o programu
rozsirime nejen o pripadne dalsi funkce, ale detailneji1 se
podivame i na obsah funkci. Telo funkce obsahuje radu
prikazu. Nasim cilem je provadet prave ty prikazy,
ktere odpovidaji zvolenemu zameru. Vyber z prikazu je
urcen stavem dosavadniho behu programu, vstupnimi udaji a
ridicimi strukturami, ktere jsme pouzili.
Program, provadejici prikazy v pevnem a nemennem poradi, ktere odpovida jejich umisteni ve zdrojovem textu a navic bez moznosti jejich vyberu, jiste neni nasim idealem. A to bez ohledu na zvoleny vyssi programovaci jazyk. Cilem teto kapitoly je proto seznameni s ridicimi strukturami.
Pred podrobnym pristupem nejprve uvedme prehledne prikazy, ktere mame v C k dispozici:
Vyraz zname z predchoziho textu. Vyrazem je nejen
aritmeticky vyraz (napriklad a+b
, ci 5+1.23*a
),
prosty vyskyt konstanty (literalu) ci promenne, ale i
funkcni volani a prirazeni. Jestlize vyraz ukoncime
symbolem ;
(strednik), ziskame vyrazovy
prikaz.
Prazdny prikaz je vyrazovy prikaz, v nemz neni
vyrazova cast. Tato konstrukce neni tak nesmyslna, jak se
na prvni pohled muze zdat. Dava nam v nekterych
pripadech moznost umistit nadbytecny strednik;
do zdrojoveho textu. Napriklad i za vnoreny blok. Protoze
se o prazdnem prikazu muzeme tezko dozvedet neco
dalsiho, podivejme se radeji na dalsi prikazy jazyka C.
Vsude v C, kde se muze vyskytovat prikaz, se muze
vyskytovat i slozeny prikaz. Slozeny prikaz
je posloupnosti prikazu2. Konstrukce, ktera slozeny prikaz vymezuje,
zacina levou a konci pravou slozenou zavorkou {}
,
a nazyva se blok. V bloku muzeme, krome jiz
zminene realizace slozeneho prikazu, provadet lokalni
deklarace a definice. Ty ovsem pouze na zacatku bloku.
Jejich platnost je omezena na blok a pripadne dalsi
vnorene bloky. Vnoreny blok nemusi byt ukoncen
strednikem. Predstavuje slozeny prikaz a jeho konec je
jasne urcen. Neni na skodu si uvedomit, ze telo kazde
funkce je blokem. Proto jsme mohli v tele funkce main()
definovat a pouzivat lokalni promenne. Syntakticky muzeme
blok popsat nasledovne:
{
[declaration_1[; declaration_2 ... ];]
[statement_1 [; statement_2 ... ] ]
}
Blok tedy muze obsahovat zadnou, jednu ci vice
deklaraci. Pokud deklaraci obsahuje, musi byt od dalsi
casti bloku oddelena strednikem. Dale blok muze obsahovat
jednotlive prikazy, rovnez oddelene strednikem.
Povsimneme si, ze posledni z prikazu nemusi byt od
uzaviraci slozene zavorky bloku strednikem oddelen.
Identifikator, ktery deklarujeme ci definujeme, si ponechava svou platnost v programu, v nemz je deklarovan ci definovan. Jeho jmeno je v tomto rozsahu viditelne, neni-li maskovano:
Jmeno makra je platne od jeho definice (direktivou define
)
az do mista, kdy je definice odstranena (direktivou undef
,
pokud vubec odstranena je). Jmeno makra nemuze byt
maskovano3.
if-else
. Operator podmineneho vyrazu ? :
pouzivame
pro vyber casti vyrazu. Pro vyber z prikazu mame k
dispozici podmineny prikaz. Mohli bychom rici, ze se
jedna o prikazy dva. Jejich syntakticky zapis je
nasledujici
if ( <expression> ) <statement1>;
if ( <expression> ) <statement1>;
else <statement2>;
Vyznam prikazu if
je nasledujici. Po
vyhodnoceni vyrazu expression
(musi byt v
zavorkach) se v pripade jeho nenulove hodnoty provede
prikaz statement1
. Po jeho provedeni pokracuje
program za timto prikazem. V pripade nuloveho vysledku
vyrazu se rizeni programu preda bezprostredne za
podmineny prikaz. Jinak receno se prikaz statement1
preskoci.
Prikaz if
muzeme pouzit i s variantou else
.
Semantika takoveho prikazu if-else
je v prvni
casti totozna se samotnym if
. Je-li vyslednou
hodnotou vyrazu expression
jedna (nenulova
hodnota), provede se prikaz statement1
. V
opacnem pripade, kdy vysledkem je nula, se provede prikaz statement2
.
V obou pripadech se rizeni programu po provedeni prvniho,
respektive druheho, prikazu preda za cely podmineny
vyraz.
Nekdy se vyklad semantiky predklada zpusobem, kdy se
nulove hodnote rika nepravda a nenulove (jednicce) pravda.
Jak ostatne zname z logickych vyrazu. Pak lze ve druhe
variante rici, ze je-li podminka splnena, vykona se prvni
prikaz statement1
, jinak prikaz druhy statement2
.
Zdurazneme, ze oba prikazy jsou ukonceny strednikem4.
Z predchozich odstavcu vime, ze misto prikazu muze
byt umisten blok. V takovem pripade je jasne prikaz
vymezen a strednik za blokem pred else
nepiseme!
Priklad nam ukaze pouziti podmineneho prikazu if-else
.
Mame vypocist a zobrazit podil dvou zadanych racionalnich
cisel. Protoze je znamo, ze nulou delit nelze, vyuzijeme
podmineny prikaz k osetreni tohoto omezeni.
/**********************/ /* soubor
if-else1.c
*/ /**********************/ #include <stdio.h> int main(void) { float a, b; puts("Zadej dve racionalni cisla:"); scanf("%f %f", &a, &b); if (b == 0.0) puts("\b\nNulou delit nelze!\n"); else { float podil; podil = a / b; printf("Jejich podil je: %10.2f\n", podil); } return 0; }
Jako prvni prikaz po testu if
je jednoduchy
vystup retezce puts()
. Je ukoncen strednikem a
nasleduje klicove slovo else
. Prikaz v teto
casti je tvoren blokem. Za blokem strednik neni. Pokud by
tam byl, byl by chapan jako prazdny prikaz. Tak je
interpretovan i strednik za poslednim prikazem v bloku.
V uvodu teto kapitoly jsme si shrnuli prikazy jazyka C.
Neprekvapi nas tedy umisteni podmineneho prikazu if
jako jednoho z prikazu if-else
. Zpravidla se
umistuje na misto druheho prikazu. Vysledna konstrukce
byva casto nazyvana if-else-if
5:
if ( <expression1> ) <statement1>;
else if ( <expression2> ) <statement2>;
else if ( <expression3> ) <statement3>;
...
else if ( <expressionN> ) <statementN>;
else <statementN+1>;
Jeji casto vyuzivanou vlastnosti je skutecnost, ze se
provede prave jeden z prikazu. Pokud neni posledni
prikaz bez podminky statementN+1
uveden, nemusi
se provest zadny. Jinak receno, provede se nejvyse jeden.
Zapamatujme si dobre tuto konstrukci. Nejen pro jeji
uzitecnost. Po prikladu ji budeme moci porovnat s konstrukci
zvanou prepinac.
Nasim ukolem je programove osetrit, jaky alfanumericky
znak byl zadan. Pripadne vydat zpravu o zadani znaku
jineho. Protoze je jiste, ze zadany znak patri prave do
jedne z trid mala pismena, velka pismena, cislice a
jine, pouzijeme konstrukci podmineneho prikazu. Pri
pouziti if-else
by pro kazdou tridu byla znovu
testovana prislusnost nacteneho znaku. Bez ohledu, zdali
znak jiz nekterou z predchozich podminek splnil. Pouzita
konstrukce if-else-if
pripadne nadbytecne testy
odstrani. Vzdy bude vybran prave jednen z prikazu.
Pripomenme si rovnez logicky vyraz, ktery tvori
podminku
if ((znak >= 'a') && (znak <= 'z'))
Vnejsi zavorky jsou nezbytne, nebot ohranicuji
podminku prikazu if
. Vnitrni zavorky naopak
uvest nemusime. Priorita operatoru &&
je
nizsi nez relacnich operatoru <=
a >=
.
Zavorky jsme presto uvedli, nebot zvysuji citelnost. Cely
vypis zdrojoveho textu nasleduje.
/**********************/ /* soubor
if-else2.c
*/ /**********************/ #include <stdio.h> int main(void) { int znak; printf("Zadej alfanumericky znak:"); scanf("%c", &znak); printf("\nZadal jsi "); if ((znak >= 'a') && (znak <= 'z')) printf("male pismeno\n"); else if ((znak >= 'A') && (znak <= 'Z')) printf("velke pismeno\n"); else if ((znak >= '0') && (znak <= '9')) printf("cislici\n"); else printf("\nNezadal jsi alfanumericky znak!\n"); return 0; }
Prepinac slouzi k rozdeleni posloupnosti prikazu na casti, nasledne vybrani a provedeni nektere, ci nekterych z nich. Pokud nam tato formulace prepinac prilis nepriblizila, pokusme se jinak.
Prepinac slouzi k vetveni vypoctu podle hodnoty celociselneho vyrazu.
Syntakticky zapsany prikaz prepinac ma tento tvar:
switch ( <expression> ) <statement>
case <constant expression> :
default :
Syntaktickou definici prepinace ovsem musime upresnit.
Po klicovem slove switch
nasleduje
celociselny vyraz expression
uzavreny v
zavorkach. Za nim je prikaz statement
,
zpravidla tvoreny blokem. Blok predstavuje posloupnost
prikazu, v niz mohou byt umistena navesti, jejichz
syntaxi vidime na druhe radce definice.
Ridici prikaz tvori celociselny konstantni vyraz6 constant
expression
uvozeny klicovym slovem case
a
ukonceny dvouteckou :
. Jedno z navesti muze
byt klicovym slovem default
, prirozene
ukoncenym dvouteckou :
.
Semantika prepinace je pomerne slozita. Popiseme si
jednotliva pravidla, jimiz se ridi:
Program vyhodnoti konstantni vyraz a jeho hodnotu
porovnava s kazdym z case
navesti
prepinace. Navesti case
muze byt obsazeno
uvnitr jinych prikazu (v ramci prepinace), krome
pripadneho vnoreneho prepinace.
V jednom prepinaci se nesmi pouzivat dve navesti se stejnou hodnotou.
Nastane-li shoda hodnoty case
navesti s
hodnotou switch
vyrazu expression
, je
preneseno rizeni programu na toto navesti. Jinak je
rizeni preneseno na navesti default
v ramci
prislusneho prepinace. Pro navesti default
plati stejne zasady jako pro jina navesti.
Pokud nenapiseme default
navesti a hodnota
vyrazu switch
se nebude shodovat s zadnym z
navesti, bude rizeni preneseno na prikaz nasledujici
za prepinacem.
Pokud program pri provadeni prepinace vykona prikaz break
,
bude rizeni preneseno na prikaz nasledujici za
prepinacem. Prikaz break
muze byt v ramci
prepinace umisten v libovolnych prikazech, krome
pripadnych vnorenych do
, for
, switch
nebo while
prikazech7.
Prepinac switch
muze mit mnoho forem.
Podivejme se na priklad, v nemz pouzijeme jednu z nich.
Nasim ukolem je podat informaci o tom, jaka hodnota padla
pri simulovanem hodu kostky. Misto kostky pouzijeme
generator pseudonahodnych cisel (dale jim budeme rikat
jen nahodna). Protoze takovou elektronickou kostku budeme
pouzivat i v prikladu v nasledujicim odstavci, venovanem
cyklum, probereme si funkce s ni spojene podrobneji.
Pomoci funkce srand()
8nastavime posloupnost nahodnych cisel. Jako
pocatecni hodnotu nemuzeme zvolit konstantu, nebot pak by
byla generovana posloupnost nahodnych velicin vzdy stejna.
Proto potrebujeme vhodnou hodnotu, ktera bude pri kazdem
spusteni programu jina. Takto vhodne se meni napriklad
cas. Proto pouzijeme jako argument navratovou hodnotu funkce time()
9. Jine
zamery s funkci time()
nemame, proto pouzijeme
jako jeji argument NULL
. Nesmime jen zapomenout
cas spravne pretypovat. A generator mame pripraven:
srand((unsigned) time(NULL) );
Ted musime umet kostkou hazet. Pri volani funkce rand()
dostavame nahodne cele cislo v rozsahu 0 az RAND_MAX
.
16-ti bitove BC31 definuje tuto hodnotu jako MAXINT
,
konkretne 32767. Pro nasi potrebu staci cislo v rozsahu 0
az 5, k nemuz pricteme jednicku. Tuto praci odvede operace
modulo sesti.
switch (rand() % 6 + 1)
Ziskana hodnota 1 az 6 je vyrazem prepinace switch
.
V zavislosti na teto hodnote se rizeni programu prenese na
konstantni navesti. Problem je v tom, ze pokud bychom
takto oznacenou posloupnost prikazu neukoncili prikazem break
,
pokracoval by od navesti program dale, az po konec
prepinace. I teto vlastnosti se da vyuzit. Ukazku vidime
ve spojenem hlaseni pro hodnoty 2 a 3. Umisteni
navesti default
v prepinaci je libovolne.
Zpravidla se pise na konec, coz je pomerne zakoreneny
zvyk. Budeme jej rovnez dodrzovat.
/**********************/ /* soubor
switch-1.c
*/ /**********************/ #include <stdlib.h> #include <stdio.h> #include <time.h> int main(void) { char *s; printf("\nHazim kostkou...\n"); srand((unsigned) time(NULL) ); switch (rand() % 6 + 1) { case 1: s = "jednicka"; break; case 2: case 3: s = "dvojka nebo trojka"; break; case 4: s = "ctyrka"; break; case 5: s = "petka"; break; default: s = "sestka"; break; } printf("\nPadla %s.\n\n", s); return 0; }
Srovname-li prepinac s konstrukci if-else-if
,
vidime zasadni rozdily:
if
muze testovat
hodnoty jakehokoliv typu10, zatimco rozhodovaci vyraz prikazu switch
musi byt vyhradne celociselnym vyrazem. if-else-if
se provede nejvyse
(ci podle pouziti prave) jeden z prikazu. I u
prepinace se nemusi provest zadny z prikazu.
Muze jich byt ovsem provedeno vice. Konstantni
navesti urcuje pouze prvni z nich. Pokud chceme,
oddelime nasledujici prikazy prikazem break
. default
muze
vyskytovat kdekoliv. Odpovidajici varianta v
konstrukci ifelseif
muze byt
umistena pouze na konci11. Cyklus je cast programu, ktera je v zavislosti na podmince provadena opakovane. U cyklu obvykle rozlisujeme ridici podminku cyklu a telo cyklu. Ridici podminka cyklu urcuje, bude-li provedeno telo cyklu, ci bude-li rizeni predano za prikaz cyklu. Telo cyklu je prikaz, zpravidla v podobe bloku.
Cykly muzeme rozdelit podle toho, provede-li se telo
alespon jedenkrat, a cykly, kde telo nemusi byt provedeno
vubec. Rozhodne muzeme rici, ze i kdyz v C existuji
ruzne typy cyklu, je mozne vystacit s jednim z nich.
Presto si v teto podkapitole povime o vsech. Jejich vyber
ponechame na vhodnosti pouziti v dane situaci i na jejich
individualni oblibe. V casti venovane prikazu while
si popiseme nektere vlastnosti spolecne vsem cyklum.
Postupne tedy while
, for
a do
.
Prikaz while
, vykonava prikaz statement
(telo cyklu) vicekrat, nebo vubec, dokud ma v danem
kontextu testovaci vyraz expression
nenulovou
hodnotu. Syntaxe prikazu while
je nasledujici:
while ( <expression> ) <statement>
Prikaz je velmi casto blokem. Zde se zejmena
zacatecnici mylne domnivaji, ze pokud se kontext kdykoliv
behem provadeni prikazu bloku tela cyklu zmeni, a
podminka tak prestane byt splnena, je cyklus opusten. To
ovsem neni pravda. Pravidlo rika, ze se prikaz statement
provede, je-li podminka expression
splnena. Je-li
prikazem blok, provede se tedy blok cely. Teprve pote je
znovu proveden test. Nazornejsi bude, podivat se na
vyvojovy diagram.
Ve vyvojovem diagramu se vyskytuji nepovinne prikazy break
a continue
. S prvnim z nich jsme se jiz setkali u
prepinace. Druhy zatim nezname. Jejich semantiku,
zakreslenou ve vyvojovem diagramu, si nyni popiseme. Predem
poznamenejme, ze oba jsou pokladany za prostredky
strukturovaneho programovani.
Prikaz break
ma ve vsech cyklech stejny
vyznam. Ukonci provadeni prikazu tela cyklu a preda
rizeni prvnimu prikazu za prikazem while
.
Timto zpusobem muzeme bezprostredne ukoncit prubeh cyklu
bez ohledu na hodnotu podminky.
Prikaz continue
rovnez ukonci provadeni
prikazu tela cyklu. Rizeni ovsem preda tesne pred
prikaz cyklu. Probehne tedy vyhodnoceni testovaciho vyrazu
a podle jeho hodnoty pokracuje program stejne, jako by bylo
telo cyklu vykonano do konce (tedy bez predcasneho
ukonceni vykonanim continue
). Podobne jako break
,
ma prikaz continue
ve vsech cyklech stejny
vyznam.
Pouziti prikazu while
ukazuje priklad.
Opet v nem pouzivame kostku. S ni souvisejici funkce jsme
popsali v predchozim prikladu. Tentokrat je nasim cilem
secist pocet pokusu, potrebnych k tomu, abychom hodili
sestku POCET
-krat. Soucasne s novou latkou si
pripomeneme nektere poznatky z predchozich kapitol.
Konstanta POCET
12, ktera nema uveden typ ma implicitne typ
int. Klicovym slovem static
pouzitym pri
deklaraci promennych celkem
a pocet
(je to jiny identifikator nez POCET
), nejen
umistujeme tyto promenne do datoveho segmentu programu, ale
zaroven je jim pri spusteni programu definovana
pocatecni hodnota nula. Diky tomu je dale nemusime
inicializovat.
Cyklus while
samotny probiha tak dlouho, dokud
plati podminka (pocet < POCET)
. Za blokem,
tvoricim prikaz cyklu, nemusime psat ukoncovaci
strednik. Nasleduje formatovany standardni vystup
vysledku a zaver funkce main()
.
/**********************/ /* soubor
while-1.c
*/ /**********************/ #include <stdlib.h> #include <stdio.h> #include <time.h> const POCET = 10; int main(void) { static int celkem, pocet; printf("\nHazim kostkou dokud mi nepadne %d-krat sestka. ...\n", POCET); srand((unsigned) time(NULL) ); while (pocet < POCET) { celkem++; if ((rand() % 6 + 1) == 6) pocet++; } printf("\nA je to! Hodu bylo celkem %d.\n\n", celkem); return 0; }
Nasledujici priklad ukazuje pouziti prikazu while
spolu s if-else-if
a prikazy break
a continue
.
Nasim ukolem je porovnani dvou nactenych retezcu a
zobrazeni mensiho z nich. Tento priklad pouziva
aritmetiku ukazatelu, probiranou v ramci jedne z dalsich
kapitol. V tomto okamziku prijmeme skutecnost, ze
prostrednictvim ukazatelu porovnavame ASCII hodnoty
jednotlivych znaku odpovidajicich retezcu. Kazdy
retezec je ukoncen znakem s kodem nula.
Zvolena mnemonika pojmenovava dva retezce a
a b
, ukazatele na, respektive do, techto retezcu pa
a pb
. Identifikator pk
predstavuje
ukazatel na kratsi z porovnavanych retezcu.
Algoritmus ulohy srovnava postupne znaky obou retezcu,
dokud jsou si rovny:
else if (*pa == *pb)
{
pa++; pb++;
continue;
}
Pouziti continue
neni v nasem pripade
nezbytne. Diky if-else-if
nemuze v teto vetvi
tela cyklu nasledovat jiny prikaz. Naopak break
v
obou zbyvajicich vetvich opousti cyklus. Ukoncuje tim
srovnavani retezcu a urcuje kratsi z nich. V prvnim ze
zminenych pripadu je
if (*pa < *pb)
{
pk = a;
break;
}
hodnota znaku v retezci a
mensi, nez v
retezci b
. a
je tudiz kratsi.
Cyklus je ukoncen. Dale bychom totiz opustili definovany
rozsah retezce a
. A protoze je podminka cyklu
napsana tak, ze zajistuje jeho opakovani, dokud nenarazime
na konec alespon jednoho z retezcu:
while ((*pa != 0x0) && (*pb != 0x0)) /* '\0' 0
*/
Mame jistotu, ze pokud nenastaly predchozi moznosti,
musi platit:
else
{
pk = b;
break;
}
Tedy, ze kratsi je druhy retezec. Tesne za telem
cyklu mame osetrenu variantu, kdy skonci druhy z retezcu
drive, nez se jejich obsahy lisily. Pak je kratsim z
retezcu. Nam nezbyva, nez jej zobrazit a ukoncit program.
Nasleduje nepreruseny vypis zdrojoveho textu reseni.
/************************************************/ /* soubor
cmp_str.c
- compare two strings */ /* porovna dva nactene retezce a zobrazi mensi */ /************************************************/ #include <stdio.h> #define DELKA 50 int main(void) { char a[DELKA], b[DELKA], *pa, *pb, *pk; /* pa[], pb[], pk[] */ pk = pa = gets(a); pb = gets(b); while ((*pa != 0x0) && (*pb != 0x0)) /* '\0' 0 0x0 - totez*/ { if (*pa < *pb) { pk = a; break; } else if (*pa == *pb) { pa++; pb++; continue; } else { pk = b; break; } } if ((*pa != 0x0) && (*pb == 0x0)) pk = b; puts("\nkratsi je:"); puts(pk); return 0; }
Prikaz for
provadi prikaz statement
vicekrat,
nebo vubec, dokud je hodnota nepovinneho testovaciho vyrazu expr2
nenulova. V prikazu for
muzeme jeste napsat
dva dalsi vyrazy s vedlejsim efektem, expr1
a expr3
.
Syntaxe for
:
for ( [<expr1>] ; [<expr2>] ;
[<expr3>] ) <statement>
Nepovinny vyraz expr1
je proveden pred prvnim
vyhodnocenim testu. Typicky se pouziva pro inicializaci
promennych pred cyklem. Po kazdem provedeni tela cyklu statement
,
provede program nepovinny vyraz expr3
. Typicky se
jedna o pripravu dalsi iterace cyklu. Pokud neuvedeme
testovaci vyraz expr2
, pouzije prekladac
hodnotu 1
, a tedy bude provadet nekonecny
cyklus. Nastesti muzeme pouzit prikazy break
a continue
se stejnym vyznamem, jaky jsme popsali
u while
.
Vyvojovy diagram uplne varianty prikazu for
je na obrazku, v nemz jsme ponechali znaceni odpovidajici
vyse uvedene syntaxi:
Pro tisk ASCII tabulky znaku s kody 32 az 127 pouzijeme
prikaz for
v uplne variante:
for (znak = ' '; znak < 128; znak++)
V tomto pripade muzeme nazyvat promennou znak
ridici
promennou cyklu. Pred testem ji inicializujeme mezerou13, tedy
prvnim zobrazitelnym ASCII znakem. Nasleduje test na hodnotu
128. Provadi se pred kazdym pruchodem telem cyklu.
Neni-li podminka splnena, pokracuje se za cyklem.
Po kazdem pruchodu telem cyklu je ridici promenna
cyklu znak
zvysena o jednicku. Tak je pripraven
dalsi pruchod cyklem s hodnotou nasledneho ASCII znaku.
Samotne telo cyklu vlastne jen zobrazuje jednotlivy znak.
Je-li jeho ASCII hodnota delitelna 16 beze zbytku, zajisti
vyslanim konce radku tvar tabulky.
/**********************/ /* soubor
for-1.c
*/ /**********************/ #include <stdio.h> int main(void) { int znak; putchar('\n'); for (znak = ' '; znak < 128; znak++) { if (znak % 16 == 0) putchar('\n'); putchar(znak); } putchar('\n'); return 0; }
/*
!"#$%&'()*+,-./
0123456789:;<=>?
@ABCDEFGHIJKLMNO
PQRSTUVWXYZ[\]^_
`abcdefghijklmno
pqrstuvwxyz{|}~&127
*/
Prikaz do
je jedinym z cyklu, ktery
zajistuje alespon jedno provedeni tela cyklu. Jinak
receno, jeho testovaci prikaz statement
je
testovan az po pruchodu telem cyklu. Pokud je test splnen,
provadi se telo cyklu. Po syntakticke strance tvori telo
cyklu opet vyraz expression
:
do <statement> while ( <expression> );
Vyvojovy diagram prikazu do
tuto vlastnost
ukazuje jeste nazorneji:
Prikazy break
a continue
v tele
cyklu se chovaji stejne, jaako v cyklech ostatnich. Po break
je cyklus opusten, zatimco po continue
je
proveden vyraz expression
a podle jeho vysledku se
pokracuje dale.
Caste pouziti prikazu do
nalezneme
napriklad v tech numerickych vypoctech, kdy je alespon
jedna iterace nezbytna. V nasem pripade se jedna o
vypocet priblizne hodnoty Eulerova cisla. V prvnim
priblizeni polozime hodnotu e
rovnu jedne
stejne, jako hodnotu prirustku epsilon
. Za
upozorneni stoji datovy typ longdouble
, a tedy
i odpovidajici vhodne urceni typu ciselnych konstant. I
ve formatovanem vystupu jsme museli specifikovat prislusny
datovy typ. Operatory prirazeni spojene s operaci nad svou
levou stranou jsou pouzity spise pro pripomenuti jejich
existence.
/**********************/ /* soubor
dowhile2.c
*/ /**********************/ #include <stdio.h> #include <math.h> #define chyba 1.0e-15L int main(void) { long double e = 1.0L, epsilon = 1.0L; unsigned long n = 0L; printf("\n"); do { epsilon /= ++n; e += epsilon; } while (epsilon > chyba); printf("e=%21.18Lf\tpocet diteraci:%ld", e, n); return 0; }
Prikaz skoku patri k zatracovanym prikazum
strukturovaneho programovani. Skutecne s jeho pomoci
dokaze mene zkuseny programator vytvorit zdrojovy text,
pro nejz se vzilo oznaceni spagetovy.
Skutecnost, ze jsme si prikaz skoku nezatajili ma tri
priciny:
break
, continue
a return
15 jsou oznacovany jako strukturovane
skoky. Jejich pouziti teorie (ani praxe) programovani
neodmita. Zustava nam tedy jen prikaz skoku goto
.
Jeho syntaxe je jednoducha:
identifier: <statement> ;
goto <identifier> ;
Uvedli jsme si nejen syntaxi goto
samotneho, ale
i souvisejiciho navesti identifier
.
Navesti neprovadi zadnou akci a nema jiny vliv na
rizeni behu. Jeho identifikator jen oznacuje nejake
misto ve zdrojovem textu. Prikaz goto
prenasi
rizeni na prikaz, oznaceny navestim. V ramci jedne
funkce nesmi byt dve stejna navesti.
Vysvetlivky:
1 V tomto skriptu venujeme
funkcim celou kapitolu.
2 Nezapomenme, jednotlive
prikazy jsou ukonceny stredniky.
3 To je jasne, uvedomime-li
si, ze makra zpracovava preprocesor. Teprve takto zpracovany
text s expandovanymi makry je vstupem pro samotny prekladac.
4 Jinak by se o prikazy
nejednalo.
5 Nektere programovaci jazyky
kvuli ni dokonce zavadi klicove slovo elif.
6 Tedy vyraz vycislitelny
behem prekladu. K celociselnym vyrazum patri i znakove
vyrazy.
7 Tyto prikazy mohou break
obsahovat. Jeho vyznam pak ovsem bude spojen s nimi, nikoliv s
vnejsim prikazem case
.
8 Jeji prototyp je umisten v
hlavickovem souboru stdlib.h
.
9 Jeji prototyp je umisten v
hlavickovem souboru time.h
.
10 Je vhodne, aby vysledkem
testu byla celociselna hodnota, nejlepe 0 a 1. Jinak
automaticky probehne konverze.
11 Pripadne jen na zacatku.
To bychom museli neobvykle negovat podminky.
12 Diky tomu, ze je
definovana mimo telo funkce je rozsahem jeji platnosti cely
soubor (pocinaje mistem definice).
13 ASCII kod mezery je 32.
14 Prelozeny tvar nasich
"peknych strukturovanych programu" skoky ostatne
stejne obsahuje.
15 Prvni dva jsme jiz popsali
drive v teto kapitole. Prikazu return
se
venujeme v souvislosti s funkcemi.
Nazev: | Programovani v jazyce C |
Autor: | Petr Saloun |
Do HTML prevedl: | Kristian Wiglasz |
Posledni uprava: | 29.11.1996 |