Příkazy pro opakování (cyklus)

Možnost opakování příkazu nebo skupiny příkazů je další ze základních součástí každého programovacího jazyka. Také samotné příkazy pro opakování se v různých jazycích dosti podobají.


Příkaz FOR

Příkaz for se používá v případech, kdy dopředu víme, kolikrát chceme, aby se příkaz nebo příkazy opakovaly, počet opakování je konkrétní číslo (hodnota).
Základní syntaxe tohoto příkazu vypadá například takto:

for ($pocet=1;$pocet<10;$pocet++) echo "$pocet <br />";

Pro příkaz je potřeba proměnná (v příkladě $pocet), která bude měnit svoji hodnotu podle příkazů v kulaté závorce a při každé změně se vykoná příkaz (nebo příkazy ve složené závorce) za kulatou závorkou.
$pocet=1; - určuje počáteční hodnotu této řídící proměnné cyklu
$pocet<10; - podmínka, při jejímž splnění jsou příkazy vykonány
$pocet++ - příkaz, který se provede při každém opakování (v tomto příkladě se zvětšuje $pocet o jedničku)
V uvedeném příkladě se tedy proměnná $pocet zvětšuje od jedničky po jedné dokud je menší než 10 a pokaždé se vypíše příkazem echo její hodnota, neboli se vypíšou čísla od 1 do 9. Pokud vám není ještě fungování příkazu FOR jasné, vyzkoušejte si uvedený příklad a zkuste měnit všechny hodnoty nebo příkazy v kulaté závorce.

Podobně jako u příkazu IF je možné do FOR cyklu vkládat i HTML příkazy (tagy), a složenou závorku pro větší počet příkazů nahradit dvojtečkou (při použití dvojtečky musí být podobně jako u IF použitý příkaz ENDFOR). Následující příklad vypíše pět vstupních polí formuláře pro jména členů družstva:

<h1>Družstva</h1>
<form action="zpracuj.php" method="post">
<?php for ($i=1;$i<=5;$i++):
echo "$i člen: "?>
<input name="jmeno[]" type="text"><br />
<?php endfor; ?>
<br />
<input type=submit>
</form>
(Parametr name="jmeno[]" bude rozebrán níže v projektu.)


Další situace při opakování příkazů je ta, že nevíme dopředu kolikrát se mají příkazy opakovat, ale známe podmínku, za které se mají opakovat, v takovém případě použijeme příkaz WHILE (dokud).

Příkaz WHILE

Příkaz while je možné použít dvěma způsoby - buď se nejprve kontroluje podmínka a potom vykonávají příkazy, nebo se mohou nejprve vykonat příkazy a potom zkontrolovat podmínka (druhý způsob se bude hodit v případě, kdy budeme chtít, aby se příkazy vykonaly alespoň jednou):
while s podmínkou na začátku:
while (podmínka) příkazy;
(dokud je splněna podmínka vykonávej příkazy)
while s podmínkou na konci:
do příkazy while (podmínka);
(vykonávej příkazy dokud je splněna podmínka)

Pomocí příkazu WHILE bychom mohli příklad uvedený u příkazu FOR zapsat takto (vypsání čísel od 1 do 9):
$pocet=1; while ($pocet<10) {echo "$pocet <br />"; $pocet++;}

Klasickou ukázkou využití příkazu WHILE je určení společného dělitele dvou čísel pomocí tzv. Eukleidova algoritmu, který využívá toho, že když mají dvě čísla společného dělitele, má stejného dělitele i jejich rozdíl
( a.k - b.k = (a-b).k ). Od většího čísla odečteme menší a větší číslo tímto rozdílem nahradíme, to děláme tak dlouho, až budou obě čísla stejná, to je potom společný dělitel původních čísel.
Zdrojový kód tohoto příkladu i s formulářem by mohl vypadat takto:

<h1>Společný dělitel dvou čísel</h1>
<form name="dělitel" action="" method="post">
1. číslo: <input type="text" name="a" value="" />
2. číslo: <input type="text" name="b" value="" />
<input type="submit" value="společný dělitel" />
</form>

<?php
if (!empty ($_POST)) //jestliže pole $_POST není prázdné, dělej příkazy ve složené závorce
{extract($_POST); //extrahuj (rozbal) pole $_POST
while ($a<>$b) //dokud je $a různé od $b dělej příkazy ve složené závorce
{if ($a>$b) $a=$a-$b; //je-li $a větší než $b ulož do $a jejich rozdíl
elseif ($b>$a) $b=$b-$a; } //jinak - je-li $b větší než $a ulož do $b jejich rozdíl a konec příkazu while
echo "společný dělitel čísel je $a";}
?>
V příkladu je použita další možnost pro získání hodnot proměnných z formuláře, a to příkaz
extract($_POST)
Tento příkaz "rozbalí" celé pole $_POST, čili načte hodnoty všech proměnných, což je určitě pohodlnější než načítání každé proměnné zvlášť, které jsme používali doposud (z pedagogických důvodů ;- )). Navíc je to i jednoduchá možnost jak v PHP verze 5 načíst hodnoty z adresového řádku, což budeme potřebovat později.

Určení společného dělitele je sice klasickou ukázkou použití cyklu WHILE, je ale otázka, kolikrát byste ji jako programátoři stránek použili. Pro projekt této lekce využijeme jiný příklad, tazvaný konfigurátor počítačových sestav, který běžně využívají internetové obchody počítačové techniky. Zájemcům o koupi počítače umožňují navolit si svoji konfiguraci kupovaného počítače a na základě voleb potom určí výslednou cenu. Při menším počtu položek bychom byli schopni už podobný konfigurátor naprogramovat dříve, jenže takové stránky obsahují někdy i velmi velký počet položek a v tom případě už bude vhodné využít příkazy pro opakování.

Konfigurátor PC sestav pro on-line obchod

Pro ukázku konfigurátoru jsem "vybrakoval" jeden skutečný on-line obchod (jen adresu si nepamatuji :-) ).
<h1>Zvolte konfiguraci PC</h1>
<form name="konfigurace" action="konfigurator.php" method="post">
Základní deska:
<SELECT name="cena[]">
<OPTION value="0">nevybráno</OPTION>
<OPTION value="5052">5 052 Kč|BUNDLE M/B ASUS P5GD1 PRO + VGA ASUS EN5750/TD/128</OPTION>
<OPTION value="1035">1 035 Kč|GIGABYTE MB Sc 775 8I865GME-775,VGA,AGP,mATX</OPTION>
<OPTION value="1247">1 247 Kč|GIGABYTE MB Sc 775 945GCMX-S2, VGA, 2x DDR2, 4xSATA2, mATX, C2D</OPTION>
</select><br>
Procesor:
<SELECT name="cena[]">
<OPTION value="0">nevybráno</OPTION>
<OPTION value="1727">1 727 Kč|AMD A64 X2 4000+ EE (AM2, 65nm) Box</OPTION>
<OPTION value="2137">2 137 Kč|AMD A64 X2 4400+ EE (AM2, 65nm) Box</OPTION>
<OPTION value="2371">2 371 Kč|AMD A64 X2 4600+ EE (socket AM2) Box</OPTION>
</select><br>
Paměť:
<SELECT name="cena[]">
<OPTION value="0">nevybráno
<OPTION value="2088">2 088 Kč|1024MB (2x512) DDRII 400 ECC reg. Kingston</OPTION>
<OPTION value="593">593 Kč|1024MB DDR II 533 A-DATA (LFT warranty)</OPTION>
<OPTION value="564">564 Kč|1024MB DDR II 533 V-DATA (3yrs. warranty)</OPTION>
</select><br>
Harddisk:
<SELECT name="cena[]">
<OPTION value="0">nevybráno
<OPTION value="1107">1 107 Kč|HDD WD1200BB CaviarXL, 120GB, 2MB, 7200rpm, ATA/100 2R</OPTION>
<OPTION value="1155">1 155 Kč|HDD WD1200JB CaviarXL, 120GB, 8MB, 7200rpm, ATA/100</OPTION>
<OPTION value="1132">1 132 Kč|HDD WD1200JS CaviarXL, 120GB, 8MB, 7200rpm, SATA/300</OPTION>
</select>
<br /><br />
<input type="submit" value="vypočti" />
</form>

<?php
if (!empty($_POST))
{$celkem=0; extract($_POST);
echo"<h1>Děkujeme za objednávku</h1>";
for ($i=0;$i<4;$i++) {echo "cena ", $i+1,". polozky: ", $cena[$i], " <br />";$celkem=$celkem+$cena[$i];};
echo"<b>Celková cena: $celkem Kč</b>";}
?>
Zdroj je opět trochu delší, ale to jen díky nabízeným možnostem ve formuláři, vlastní jádro zpracování je jen několikařádkové. Abychom mohli využít příkaz FOR pro opakování a tím zdroj zkrátit a zjednodušit, ukládáme příslušné ceny do pole proměnných, viz parametr name u jednotlivých položek formuláře:
name="cena[]"
Pole proměnných je vlastně očíslovaná řada proměnných, jejich indexy (pořadí) se zapisují do hranatých závorek, v tomto případě pracujeme s proměnnými cena[0], cena[1], cena[2] a cena[3]. Neudáme-li jinak, jsou proměnné číslované od nuly.
V našem formuláři jsme využili možnost, že nemusíme index v hranaté závorce uvádět (cena[]), potom se proměnné číslují automaticky podle pořadí ve zdroji. To je výhodné například kdybychom potřebovali někde uprostřed formuláře některou položku ubrat nebo přidat, pokud by byly u proměnných zapsané indexy, museli bychom všechny následující opravit.
Velká výhoda pole proměnných (očíslovaných proměnných) je ta, že se s nimi dá pracovat v cyklech, jedním zdrojovým řádkem můžeme "obsloužit" libovolný počet proměnných:
for ($i=0;$i<4;$i++) {echo "cena ", $i+1,". polozky: ", $cena[$i], " <br />";$celkem=$celkem+$cena[$i];}
V tomto cyklu se proměnná $i mění po jedné od nuly do tří a pro každou hodnotu se vypíše příslušná $cena[$i] a také se $cena[$i] přičte do proměnné $celkem (pokaždé chceme provést oba příkazy - výpis i přičtení, proto jsou uzavřené ve složené závorce). Pro pole proměnných existují i další příkazy, které si ukážeme později.


Úkoly:

Úkol (2 body)

Vytvořte konfigurátor PC podle lekce a doplňte ještě alespoň jednu hardwarovou komponentu.

Úkol (4 body)

Napište program, který zkrátí zadaný zlomek na základní tvar.

Název školy:Základní škola, Hradec Králové, M. Horákové 258
Název projektu:EU peníze školám
Číslo projektu:CZ.1.07/1.4.00/21.2575
Téma:Programování v PHP
Název:VY_32_INOVACE_08_10A_PHP8
Autor:Pavel Petr
Použité zdroje: Není-li uvedeno jinak, jsou všechny ilustrační obrázky dílem autora.