Cykly slouží k opakovanému provádění příkazů. V Javě máme tři cykly:
while, do
a for. Cyklus
while začíná klíčovým slovem
while, za kterým následuje v závorkách
podmínka a dále tělo cyklu. Tělem cyklu je buď příkaz nebo blok.
Cyklus se provádí takto: vyhodnotí se podmínka a je-li splněna,
provede se tělo cyklu. Poté se znovu vyhodnotí podmínka a je-li
splněna, opět se provede tělo cyklu, atd. Pokud podmínka není
splněna, pokračuje se příkazy za cyklem.
Scanner sc = new Scanner( System.in );
int x = sc.nextInt();
while( x > 0 ) { // dokud je x větší než nula, prováděj...
System.out.println( x );
x /= 2;
}
Jestliže na začátku není podmínka splněna, tělo cyklu se neprovede
ani jednou. Cyklus while je tedy cyklus
s počtem opakování 0 nebo více.
Cyklus do začíná klíčovým slovem
do, za kterým je tělo cyklu, klíčové
slovo while a podmínka. Provádí se takto:
nejprve se provede tělo cyklu, pak se vyhodnotí podmínka a je-li
splněna, znovu se provede tělo cyklu, vyhodnotí se podmínka, atd.
Není-li podmínka splněna, pokračuje se za cyklem.
int x = sc.nextInt();
do {
System.out.println( x );
x /= 2;
} while( x > 0 );
Tělo cyklu se provede vždy alespoň jednou. Počet opakování je
tedy 1 nebo více.
Cyklus for má tento tvar:
for( inicializace; podmínka; aktualizace ) tělo cyklu.
Provádí se takto: nejprve se provede inicializace, pak se vyhodnotí
podmínka a je-li splněna, provede se tělo cyklu. Poté se provede
aktualizace, znovu se vyhodnotí podmínka a je-li splněna, opět se
provede tělo cyklu, atd. Inicializace se tedy provede pouze jednou
na začátku. Pokud na začátku není podmínka splněna, tělo cyklu se
neprovede ani jednou.
int i;
for( i = 1; i <= 10; i++ ) {
System.out.println( i );
}
Inicializace může obsahovat deklaraci proměnné. Tato deklarace je
platná pouze v daném cyklu (tj. v hlavičce a těle cyklu). Říkáme,
že proměnná je v tomto cyklu lokální.
for( int i = 1; i <= 10; i++ ) {
System.out.println( i * i );
}
Libovolná z částí inicializace, podmínka a aktualizace může chybět.
Chybí-li podmínka, jde o nekonečný cyklus (podmínka je stále
splněna). Pokud není uvedena inicializace nebo aktualizace,
neprovede se v daný okamžik žádný příkaz.
int n = sc.nextInt();
for( ; n > 0; n-- ) {
System.out.println( n );
}
U všech třech cyklů je tělem cyklu příkaz nebo blok. Pro lepší
čitelnost se často zapisuje blok i v případě, že tělo cyklu
obsahuje pouze jeden příkaz. V těle cyklu můžeme používat příkazy
break a continue.
Příkaz break okamžitě ukončí provádění
cyklu. Pokračovat se bude příkazy za cyklem.
int s = 100;
while( s > 0 ) {
int n = sc.nextInt();
if( n == 0 ) {
break;
}
s -= n;
System.out.println( s );
}
// tady se bude pokračovat po provedení break
Příkaz continue ukončí provádění těla
cyklu a přejde na vyhodnocení podmínky cyklu.
int s = 0;
do {
int n = sc.nextInt();
if( n == 0 ) {
continue;
}
s += n;
System.out.println( s );
// sem přejde continue
} while( s < 100 );
Věnujme se teď načtení posloupnosti čísel. Neznáme-li předem počet
prvků, máme dvě možnosti: buď tento počet zadáme jako první hodnotu,
nebo stanovíme, jakou hodnotou bude vstupní posloupnost končit.
Oba přístupy si ukážeme na úloze nalezení součtu vstupní
posloupnosti. Nejprve uvedeme řešení se zadaným počtem prvků:
int n = sc.nextInt(), s = 0;
for( ; n > 0; n-- ) {
s += sc.nextInt();
}
System.out.println( s );
Dále si ukážeme řešení s koncovou hodnotou. Pro ukončení vstupní
posloupnosti použijeme nulu. Podmínku cyklu
while lze napsat tak, že načteme hodnotu,
přiřadíme ji do proměnné pomocí operátoru
= a návratovou hodnotu operátoru
porovnáme s nulou.
int x, s = 0;
while( ( x = sc.nextInt() ) != 0 ) {
s += x;
}
System.out.println( s );
Cykly lze libovolně vnořovat. Např. tisk obdélníka o velikosti
a x b
ze znaků '@' zajistíme pomocí dvou vnořených cyklů
for:
int a = sc.nextInt(), b = sc.nextInt();
for( ; a > 0; a-- ) {
for( int i = 0; i < b; i++ ) {
System.out.print( '@' );
}
System.out.println();
}
Vnitřní cyklus vytiskne b znaků '@' na
jednu řádku. Po jeho skončení přejdeme na nový řádek metodou
println(). Vnější cyklus zajistí, že se
vytiskne a řádek.
V části inicializace můžeme deklarovat i více proměnných. Všechny
však musí být stejného typu. Chceme-li v části aktualizace zapsat
více výrazů, oddělujeme je čárkou.
int n = sc.nextInt();
System.out.print( n + 1 );
for( int i = 1, j = n; i < j; i++, j-- ) {
System.out.printf( "=%d+%d", i, j );
}
System.out.println();
Zde v cyklu for deklarujeme dvě proměnné.
Proměnná i bude nabývat hodnot
1, 2, ..., proměnná j hodnot n, n−1, ...
Zvyšování hodnoty i zajišťuje příkaz
i++, snižování hodnoty
j příkaz j−−
v části aktualizace. Cyklus se bude provádět tak dlouho, dokud je
i menší než j.
Pro hodnotu 6 se tedy vytiskne: 7=1+6=2+5=3+4.
Úloha 1
Doplňte podmínku u cyklu while tak,
aby se vypsaly všechny nezáporné mocniny 3 menší než zadaná hodnota.
Úloha 2
Doplňte podmínku cyklu do tak,
aby pro n > 1 končil výpis hodnotou 1.
Úloha 3
Pro celé kladné číslo n je faktoriál n (značíme n!) definován
jako součin hodnot od 1 do n, tj. n! = n * (n−1) * … * 1.
Doplňte chybějící části tak, aby po skončeni cyklu byla v proměnné
f hodnota n!
Úloha 4
Doplňte chybějící části.
Úloha 5
Určete, co se vytiskne, pokud na vstupu zadáme hodnotu 10.
Úloha 6
Určete, co se vytiskne, pokud na vstupu zadáme hodnotu 20.
Úloha 7
Napište ve správném pořadí.
Úloha 8
Doplňte věty.
Otázky a odpovědi
Student:
Mistře, mám pocit, že každý cyklus
while se dá přepsat pomocí cyklu
for. Např.
while( x > 0 ) {
System.out.println( x );
x /= 2;
}
můžeme vyjádřit také takto:
for( ; x > 0; x /= 2 ) {
System.out.println( x );
}
Není tedy cyklus while nadbytečný?
Java guru:
Ano, každý cyklus while lze nahradit
cyklem for a i každý cyklus
for lze přepsat pomocí cyklu
while. Jediný rozdíl mezi těmito
cykly je v tom, že cyklus for
umožňuje deklarovat lokální proměnné (tj. proměnné, které jsou
platné pouze v daném cyklu). Např.
for( int i = 0; i < 10; i++ ) {
System.out.println( i );
} // touto závorkou končí platnost deklarace i
// tady už i nemůžeme použít
Takže cyklus while se opravdu může
zdát nadbytečný. To, že můžeš jednu věc vyjádřit více způsoby
však není nic neobvyklého. Totéž platí např. pro zvětšení
hodnoty proměnné x o jedničku:
x = x + 1;
x += 1;
x++; // zkušený programátor zvolí tuto možnost
Většinou dáváme přednost čitelnějším a úspornějším zápisům.
Student:
Jaký cyklus mám tedy používat, mistře?
Java guru:
Používej všechny tři cykly. Je-li potřeba provést tělo cyklu
vždy alespoň jednou, použij cyklus do.
Jinak si můžeš vybrat mezi cyklem
while a for.
Volba je často věc osobního stylu a je možné, že tvůj kolega si
ve stejné situaci zvolí něco jiného. Jsou však také situace,
kdy je jeden cyklus mírně lepší volbou. Např. pokud víme předem,
kolikrát se bude cyklus opakovat, je lepší cyklus
for, protože kód je pak čitelnější.
Cyklus while se hodí pro zápis cyklu
„dokud platí podmínka, prováděj příkaz.“