LINUXSOFT.cz Přeskoč levou lištu
Uživatel: Heslo:  
   CZUKPL

> Perl (9) - Cykly

Perl Další hojně užívanou řídící strukturou, bez které se neobejde žádný větší program, je cyklus.

23.5.2005 06:00 | Jiří Václavík | Články autora | přečteno 40666×

Cyklus umožňuje vykonávat určitou část programu opakovaně. Funguje v podstatě podobně jako podmínka. Na základě vyhodnocení testu se provede blok kódu. Rozdíl mezi podmínkou a cyklem je v tom, že u cyklu se vyhodnocuje test opakovaně. Dokud není test vyhodnocen jako false (nebo v některých speciálních cyklech true), stále se znovu a znovu opakuje blok kódu. Existuje hned několik druhů cyklů.

Cyklus while - předem neznámý počet iterací

Dokud platí test, provádí se blok kódu.

while (test){
    příkazy
}

Cyklus by měl mít možnost být ukončen - tj. vepsat nějaký kód, který ho bude přibližovat ke konci, až nakonec také skončí. Pro naše účely to lze vyřešit například takto:

$i = 0;
while ($i < 10){
    print "Probíhá cyklus $i.\n";
    $i++;
}

10× je proveden kód uvnitř cyklu. Je to stejné, jako kdybychom za sebe nakopírovali 10× blok.

$ perl while1.pl
Probíhá cyklus 0.
Probíhá cyklus 1.
Probíhá cyklus 2.
Probíhá cyklus 3.
Probíhá cyklus 4.
Probíhá cyklus 5.
Probíhá cyklus 6.
Probíhá cyklus 7.
Probíhá cyklus 8.
Probíhá cyklus 9.
$

Ano, je to dost netypická situace pro použití while. V praxi bychom v této situaci bez váhání sáhli po cyklu for. Avšak tento zápis se dá velmi snadno pochopit. Teď už ale přijde na řadu skutečné while. Další příklad totiž do nekonečna vypisuje to, co napíšete. V praxi má taková forma cyklu velmi časté využití.

while ($radek = <STDIN>){
    chomp $radek;
    print "Napsal jste: $radek\n";
}

Po spuštění kódu získáváme výstup:

$ perl while2.pl
Tento cyklus lze ukončit jen násilně. [ENTER]
Tento cyklus lze ukončit jen násilně.
Sám program, pokud není přerušen, by neskončil nikdy. [ENTER]
Sám program, pokud není přerušen, by neskončil nikdy.
[čeká na další vstup]

Zkusme kód poupravit tak, aby se při zadání q nebo exit ukončil. Dosáhneme toho přidáním podmínky (funkce die často nebude stačit. Příští díl osvětlí lepší řešení).

while ($radek = <STDIN>){
    chomp $radek;
    if ($radek eq "q" or $radek eq "exit"){
        die "Konec\n";
    }
    print "Napsal jste: $radek\n";
}

Cyklus for - předem známý počet iterací

Cyklus for se od while liší tím, že je předem znám počet iterací (jde sice změnit v bloku, ale potom je často lepší užít while). for a while jsou vzájemně zaměnitelné (for lze napsat jako while a naopak). Ale většinou je jeden konkrétní vhodnější a ten druhý méně.

Cyklu for se budeme podrobněji věnovat později, neboť je dobré mít zvládnutou práci se seznamy.

Podívejme se nyní pouze na základní užití. V každé iteraci přiřadíme do proměnné číslo postupně od 1 do 10.

for my $i (1 .. 10){
    print "Probíhá cyklus $i.\n";
}

Céčkovské for

Ve zbytku dílu se podívejme na několik zajímavých konstrukcí, které však pravděpodobně nikdy nepoužijeme. Proto klidně zbytek článku bez obav přeskočte.

Taktéž existuje cyklus s klasickou céčkovskou notací. Pro zajímavost ho zde zmíníme, ale kvůli přehlednosti bychom na něj měli hned zase zapomenout a nikdy ho nepoužívat. Syntaxe je následující:

for (počáteční_hodnota_počítadla; konečná_hodnota_počítadla; krok){
    příkazy
}

Počáteční_hodnota_počítadla spouští počítadlo. Konečná_hodnota_počítadla je vlastně testem. Dokud platí, je cyklus opakován (tj. proveden blok kódu). A krokem je výraz, který změní hodnotu počítadla.

for ($i=1; $i<10; $i++){
    print "Probíhá cyklus $i.\n";
}

Výstup je stejný jako u prvního příkladu u while. Nejprve se přiřadí do proměnné $i hodnota 1. Je-li test true, provede se blok, proměnná se inkrementuje (krok) a pokud opět platí test, opakuje se vše znovu. Ve chvíli, kdy test neplatí, je blok přeskočen a program pokračuje za ním.

Složitost výrazů v hlavičce for není omezena jen na takto jednoduché záležitosti. Můžeme třeba přidat další počítadlo. Operátor , (čárka) odděluje se dva výrazy, přičemž první se vyhodnotí a následně zapomene. Druhý výraz se také vyhodnotí a je výsledkem celkového vyhodnocení obou výrazů.

for ($i=0,$j=0; $i<10,$j<10; $i++,$j+=2){
    print "Probíhá cyklus $i. J: $j.\n";
}

Výstup:

$ perl for.pl
Probíhá cyklus 0. J: 0.
Probíhá cyklus 1. J: 2.
Probíhá cyklus 2. J: 4.
Probíhá cyklus 3. J: 6.
Probíhá cyklus 4. J: 8.
$

Je vidět, že počítadlem řídící cyklus je až druhá část výrazu - za čárkou (s proměnnou $j). Výraz s $i je sice každou iteraci zapomenut, ale hodnota je vždy změněna.

počáteční_hodnotu_počítadla, konečnou_hodnotu_počítadla ani krok není povinné uvést. Vynecháme-li počáteční_hodnotu_počítadla, zůstane v $i hodnota, která tam dosud byla. Pokud je nedefinovaná, v první iteraci bude stále proměnná $i nedefinovaná, ale v dalších už nemusí. Je-li totiž v kroku výraz $i++, v druhé iteraci bude hodnota $i = undef + 1 = 1.

Vynecháním konečné_hodnoty_počítadla se cyklus stává nekonečným. Nemá se co vyhodnocovat, a proto je za všech okolností true.

Neuvedení kroku má za následek, že se počítadlo (aspoň v hlavičce cyklu) nebude iterovat.

Tímto způsobem lze vynechat třeba i všechny tři výrazy. Zápis for (;;){...} je ekvivalentní while (1){...}.

Odtud plyne, že počáteční_hodnota_počítadla není nic jiného, než výraz, který se vyhodnotí před započetím cyklu, konečná_hodnota_počítadla je testem a krok výrazem, který se vyhodnocuje na konci každé iterace.

Céčkový cyklus for podle posledního tvrzení můžeme jednoduše přepsat do while (není to úplně přesné, krok by správně měl být až v bloku continue, který představíme příště. Toto řešení neplatí pro případy, kdy je konec bloku vynechán):

počáteční_hodnota_počítadla;
while (konečná_hodnota_počítadla){
    příkazy
    krok;
}

Alternativní cyklus until

Stejně jako jsou ve vztahu if a unless je ve vztahu i while a until. Cyklus je prováděn, dokud je test false. A i zde platí, že bychom takovou konstrukci neměli nadále používat.

Cyklus za příkazem

Cykly while a for se dají v Perlu napsat i za příkaz. Opět to výrazně snižuje čitelnost programu. Ukažme si alespoň pro představu zdrojový kód:

$i = 1;

$i++ while ($i < 10); # k $i se bude tak dlouho přičítat jednička, dokud bude $i nižší než 10
print $i;#10

$i-- until ($i < 0); # nyní se od $i bude pro změnu jednička odečítat a to tak dlouho, dokud nebude $i nižší než 0
print $i;#-1

Cyklus za blokem

Cykly do...while, do...until jsou dalšími variacemi cyklů. Jejich používání znovu nelze v žádném případě doporučit.

Nejprve se provede blok příkazů a až poté se vyhodnotí test (výsledný efekt je stejný, jako kdybyste blok v cyklu zkopírovali před klasický while). Je-li true (while) resp. false (until), vykonává se blok znovu.

$i = 0;

do{ #vykoná se i přesto, že $i má hodnotu 0. Testuje se až za blokem.
    print "Vykonáno\n";
}while ($i == 1);

Za testem musí být stejně jako u konstrukcí do...if a do...unless středník.

I cyklus for lze napsat za příkaz nebo blok. O tom se zmíníme až budu rozebírat další cyklus foreach.

Příklad

Napišme program, který bude ze vstupu přijímat kladná čísla. Zadáním nekladného čísla skončí zadávání (toto číslo se již nepočítá) a program vytiskne počet zadaných čísel, jejich součet a průměr.

Měli bychom získat přibližně takový výstup:

$ perl cisla.pl
Zadávejte kladná čísla, 0 pro konec.
12
994
328
666
666
9004
0
Počet: 6
Součet: 11670
Průměr: 1945
$

Kostra programu bude vypadat velmi podobně jako dnes již zmíněná ukázka kódu k while. Lišit se bude tím, že v každé iteraci se bude aktualizovat součet a počet zadaných čísel a před ukončením se ještě vytisknou výsledky.

#!/usr/bin/perl
use strict;

my $cislo;
my ($pocet, $prumer, $soucet);

print "Zadávejte čísla, 0 pro konec.";
while (chomp($cislo = <STDIN>)){
    if (int $cislo <= 0){
        ...vypsání statistik a konec...
    }

...mezivýpočet...
}

V mezivýpočtu stačí navyšovat součet a počet.

    $soucet += $cislo;
    $pocet++;

Na závěr je třeba dokončit výpis výsledků. Spočítáme průměr, vypíšeme výsledky a ukončíme.

        $prumer = $soucet / $pocet;
        print "Počet: $pocet\n";
        print "Součet: $soucet\n";
        print "Průměr: $prumer\n";
        die "\n"; #Pokud bychom neuvedli konec řádku, vypsala by automatická hláška (Tento řádek by šel lépe řešit pomocí funkce exit, 
#která zatím nebyla probrána)

Když dopíšeme program, je vždy nutné otestovat jeho reakce v závislosti na podmínkách. Všechny případy musí být ošetřeny. To my nemáme, protože program hlásí chybu, pokud neuvedeme žádný parametr. Tedy na začátek bloku v podmínce připišme:

        if ($pocet == 0){
            die "Nezadal jste žádné číslo!\n";
        }

A tím je úloha splněna. Zdrojový kód příkladu.

Verze pro tisk

pridej.cz

 

DISKUZE

Nekonečný while cyklus 11.11.2014 14:24 Libor Suchý




Příspívat do diskuze mohou pouze registrovaní uživatelé.
> Vyhledávání software
> Vyhledávání článků

28.11.2018 23:56 /František Kučera

Prosincový sraz spolku OpenAlt se koná ve středu 5.12.2018 od 16:00 na adrese Zikova 1903/4, Praha 6. Tentokrát navštívíme organizaci CESNET. Na programu jsou dvě přednášky: Distribuované úložiště Ceph (Michal Strnad) a Plně šifrovaný disk na moderním systému (Ondřej Caletka). Následně se přesuneme do některé z nedalekých restaurací, kde budeme pokračovat v diskusi.


Komentářů: 1

12.11.2018 21:28 /Redakce Linuxsoft.cz
22. listopadu 2018 se koná v Praze na Karlově náměstí již pátý ročník konference s tématem Datová centra pro business, která nabídne odpovědi na aktuální a často řešené otázky: Jaké jsou aktuální trendy v oblasti datových center a jak je optimálně využít pro vlastní prospěch? Jak si zajistit odpovídající služby datových center? Podle jakých kritérií vybírat dodavatele služeb? Jak volit vhodné součásti infrastruktury při budování či rozšiřování vlastního datového centra? Jak efektivně datové centrum spravovat? Jak co nejlépe eliminovat možná rizika? apod. Příznivci LinuxSoftu mohou při registraci uplatnit kód LIN350, který jim přinese zvýhodněné vstupné s 50% slevou.
Přidat komentář

6.11.2018 2:04 /František Kučera
Říjnový pražský sraz spolku OpenAlt se koná v listopadu – již tento čtvrtek – 8. 11. 2018 od 18:00 v Radegastovně Perón (Stroupežnického 20, Praha 5). Tentokrát bez oficiální přednášky, ale zato s dobrým jídlem a pivem – volná diskuse na téma umění a technologie, IoT, CNC, svobodný software, hardware a další hračky.
Přidat komentář

4.10.2018 21:30 /Ondřej Čečák
LinuxDays 2018 již tento víkend, registrace je otevřená.
Přidat komentář

18.9.2018 23:30 /František Kučera
Zářijový pražský sraz spolku OpenAlt se koná již tento čtvrtek – 20. 9. 2018 od 18:00 v Radegastovně Perón (Stroupežnického 20, Praha 5). Tentokrát bez oficiální přednášky, ale zato s dobrým jídlem a pivem – volná diskuse na téma IoT, CNC, svobodný software, hardware a další hračky.
Přidat komentář

9.9.2018 14:15 /Redakce Linuxsoft.cz
20.9.2018 proběhne v pražském Kongresovém centru Vavruška konference Mobilní řešení pro business. Návštěvníci si vyslechnou mimo jiné přednášky na témata: Nejdůležitější aktuální trendy v oblasti mobilních technologií, správa a zabezpečení mobilních zařízení ve firmách, jak mobilně přistupovat k informačnímu systému firmy, kdy se vyplatí používat odolná mobilní zařízení nebo jak zabezpečit mobilní komunikaci.
Přidat komentář

12.8.2018 16:58 /František Kučera
Srpnový pražský sraz spolku OpenAlt se koná ve čtvrtek – 16. 8. 2018 od 19:00 v Kavárně Ideál (Sázavská 30, Praha), kde máme rezervovaný salonek. Tentokrát jsou tématem srazu databáze prezentaci svého projektu si pro nás připravil Standa Dzik. Dále bude prostor, abychom probrali nápady na využití IoT a sítě The Things Network, případně další témata.
Přidat komentář

16.7.2018 1:05 /František Kučera
Červencový pražský sraz spolku OpenAlt se koná již tento čtvrtek – 19. 7. 2018 od 18:00 v Kavárně Ideál (Sázavská 30, Praha), kde máme rezervovaný salonek. Tentokrát bude přednáška na téma: automatizační nástroj Ansible, kterou si připravil Martin Vicián.
Přidat komentář

   Více ...   Přidat zprávičku

> Poslední diskuze

2.12.2018 23:56 / František Kučera
Sraz

5.10.2018 17:12 / Jakub Kuljovsky
Re: Jaký kurz a software by jste doporučili pro začínajcího kodéra?

20.9.2018 10:04 / Jan Ober
Jaký kurz a software by jste doporučili pro začínajcího kodéra?

20.9.2018 10:00 / Jan Ober
Re: Gimp

20.2.2018 18:48 / Ivan Majer
portal

Více ...

ISSN 1801-3805 | Provozovatel: Pavel Kysilka, IČ: 72868490 (2003-2018) | mail at linuxsoft dot cz | Design: www.megadesign.cz | Textová verze