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 39088×

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ů

13.9.2017 8:00 /František Kučera

Máš rád svobodný software a hardware nebo se o nich chceš něco dozvědět? Zajímá tě DIY, CNC, SDR nebo morseovka? Přijď na sraz spolku OpenAlt – tentokrát netradičně v pondělí: 18. září od 18:00 v Radegastovně Perón (Stroupežnického 20, Praha 5).


Přidat komentář

3.9.2017 20:45 /Redakce Linuxsoft.cz
PR: Dne 21. září 2017 proběhne v Praze konference "Mobilní řešení pro business". Hlavní tématy konference budou: nejnovější trendy v oblasti mobilních řešení pro firmy, efektivní využití mobilních zařízení, bezpečnostní rizika a řešení pro jejich omezení, správa mobilních zařízení ve firmách a další.
Přidat komentář

15.5.2017 23:50 /František Kučera
Máš rád svobodný software a hardware nebo se o nich chceš něco dozvědět? Zajímá tě DIY, CNC, SDR nebo morseovka? Přijď na sraz spolku OpenAlt, který se bude konat ve čtvrtek 18. května od 18:00 v Radegastovně Perón (Stroupežnického 20, Praha 5).
Přidat komentář

12.5.2017 16:42 /Honza Javorek
PyCon CZ, česká konference o programovacím jazyce Python, se po dvou úspěšných ročnících v Brně bude letos konat v Praze, a to 8. až 10. června. Na konferenci letos zavítá např. i Armin Ronacher, známý především jako autor frameworku Flask, šablon Jinja2/Twig, a dalších projektů. Těšit se můžete na přednášky o datové analytice, tvorbě webu, testování, tvorbě API, učení a mentorování programování, přednášky o rozvoji komunity, o použití Pythonu ve vědě nebo k ovládání nejrůznějších zařízení (MicroPython). Na vlastní prsty si můžete na workshopech vyzkoušet postavit Pythonem ovládaného robota, naučit se učit šestileté děti programovat, efektivně testovat nebo si v Pythonu pohrát s kartografickým materiálem. Kupujte lístky, dokud jsou.
Přidat komentář

2.5.2017 9:20 /Eva Rázgová
Putovní konference československé Drupal komunity "DrupalCamp Československo" se tentokrát koná 27. 5.2017 na VUT FIT v Brně. Můžete načerpat a vyměnit si zkušenosti z oblasti Drupalu 7 a 8, UX, SEO, managementu týmového vývoje, využití Dockeru pro Drupal a dalších. Vítáni jsou nováčci i experti. Akci pořádají Slovenská Drupal Asociácia a česká Asociace pro Drupal. Registrace na webu .
Přidat komentář

1.5.2017 20:31 /Pavel `Goldenfish' Kysilka
PR: 25.5.2017 proběhne v Praze konference na téma Firemní informační systémy. Hlavními tématy jsou: Informační systémy s vlastní inteligencí, efektivní práce s dokumenty, mobilní přístup k datům nebo využívání cloudu.
Přidat komentář

15.4.2017 15:20 /František Kučera
Máš rád svobodný software a hardware nebo se o nich chceš něco dozvědět? Zajímá tě IoT a radiokomunikace? Přijď na sraz spolku OpenAlt, který se bude konat ve středu 19. dubna od 18:30 v Šenkovně (Sokolská 60, Praha 2).
Přidat komentář

5.3.2017 19:12 /Redakce Linuxsoft.cz
PR: 23. března proběhne v Praze konferenci na téma Cloud computing v praxi. Hlavními tématy jsou: Nejžhavější trendy v oblasti cloudu a cloudových řešení, Moderní cloudové služby, Infrastruktura současných cloudů, Efektivní využití cloudu, Nástrahy cloudových řešení a jak se jim vyhnout.
Přidat komentář

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

> Poslední diskuze

18.9.2017 14:37 / Rojas
high security vault

15.9.2017 7:33 / Wilson
new zealand childcare jobs

31.8.2017 12:11 / Jaromir Obr
Re: ukůládání dat ze souboru

30.7.2017 11:12 / Jaromir Obr
Národní znaky

27.7.2017 12:24 / Jaromir Obr
Cteni/zapis

Více ...

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