„Ciklus (programozás)” változatai közötti eltérés

[ellenőrzött változat][nem ellenőrzött változat]
Tartalom törölve Tartalom hozzáadva
a Visszaállítottam a lap korábbi változatát 2001:738:809:6FB:A020:89A1:6F43:AE03 (vita) szerkesztéséről 2001:4C4C:2298:B500:A090:322E:D4C5:A378 szerkesztésére
Címke: Visszaállítás
Effendi (vitalap | szerkesztései)
Nincs szerkesztési összefoglaló
1. sor:
A '''ciklus''', vagy '''iteráció''' a [[számítógép-programozás]] és az [[algoritmus]]ok egyik alapvető eszköze, amely az ismétlődő (azonos vagy hasonló) tevékenységek megvalósítására szolgál. A ciklus beépítését a programba ''ciklusszervezés''nek is nevezik. A ciklust az egyes [[programozási nyelv]]ek különböző [[kulcsszó|kulcsszavakkal]] valósítják meg, de a működési módjukat tekintve három alaptípusba sorolhatók aszerint, hogy hányszor futnak le: ezek az elöltesztelő, a hátultesztelő és a számlálós ciklus.
 
A '''ciklus''', vagy '''iteráció''' a [[számítógép-programozás]] és az [[algoritmus]]ok egyik alapvető eszköze, amely az ismétlődő (azonos vagy hasonló) tevékenységek megvalósítására
{| {{széptáblázat}}
szolgál. A ciklus beépítését a programba ''ciklusszervezés''nek is nevezik. A ciklust az egyes [[programozási nyelv]]ek különböző [[kulcsszó|kulcsszavakkal]] valósítják meg.
!colspan="2"|A ciklus fajtája!!A futások száma!!Legkevesebb hányszor fut le?
 
|-
== Típusai==
|rowspan="2"|Feltételes|||Elöltesztelő||előre nem ismert||lehet, hogy egyszer sem
|-
|Hátultesztelő||előre nem ismert||legalább egyszer
|-
|colspan="2" style="text-align:center;"|Számlálós||előre ismert||lehet, hogy egyszer sem
|}
 
== A ciklus részei ==
Alább egy egyszerű [[BASIC]] nyelvű ciklust láthatunk, amelyik 102-től 155-ig egynegyedes lépésközzelegyesével haladva kiírja a számokat és a négyzetüket:
 
<syntaxhighlight lang="freebasic">
FOR i=102 TO 155 STEP 0.251
PRINT i," négyzete: ",i*i
NEXT i
</syntaxhighlight>
Ebben a ciklusban az ''i'' a '''ciklusváltozó''', amely a ciklus kezdetén [[értékadás|értéket kap]]. A szerepe kettős: egyrészt vezérli a ciklust, mivel a ciklusváltozó értékétől függ, hogy folytatódik-e a futás, másrészt a pillanatnyi értéket a program felhasználja. A ciklus futásának kezdetén tehát az ''i'' értéke 102 lesz; mivel ez kisebb, mint 155, ezért a ciklusmag lefut, vagyis a program kiírja a képernyőre a
102 négyzete: 1004
sort. Ezután ''i'' értéke 10,253-ra változik, és ismét lefut. Ez addig ismétlődik, amíg az ''i'' értéke 155 lesz. Ekkor még utoljára lefut a ciklus, tehát a képernyőn még megjelenik aaz 155 négyzete is, majd az ''i'' értéke 15,256 lesz, de ez már nagyobb, mint 155, ezért a program kilép a ciklusból, és a futás a következő sorral folytatódik.
 
Ebben a ciklusban a ciklusváltozónak van '''kezdőértéke''' (102), '''végértéke''' (155) és '''lépésköze''' (0,251). Nem minden ciklusban van ciklusváltozó. Egyes programnyelvekben több is lehet belőle.
 
A ciklus első sorát '''ciklusfejnek''' nevezik. Általában ez vezérli a ciklust; itt kap helyet a ciklusváltozó(k) definíciója, valamint a futási feltétel is. A középső sor a '''ciklusmag''', vagyis a ténylegesen ismétlődő utasítások meghatározása. Ennek a ciklusnak a magja egyetlen utasításból áll. Végül az utolsó sor a '''ciklusvég'''; az elöltesztelőelöl tesztelő és a számlálós ciklus esetében ez puszta lezáró utasítás, amely a ciklusmag végét jelzi (egyes programnyelvekben esetenként el is maradhat), a hátultesztelőhátul tesztelő ciklus esetén pedig ez a rész tartalmazza a futási feltételt.
 
== Feltételes ciklusok (WHILE)==
A feltételes ciklusokat (néha ''végfeltételes ciklus'' néven is említik őket)ciklusok olyankor használjukhasználatosak, amikor nem tudjukismert előre, hogy hányszor kell a ciklusnak lefutnia,. Azt viszont tudjuk, hogy milyen feltétel teljesülése esetén kell tovább futnia vagy leállnia. (Ez a kettő egymással [[logikai ekvivalencia|ekvivalens]], hiszen a további futás, illetve a leállás feltétele egymás [[Logikai művelet#Negáció|tagadása]].) A feltétel teljesülését vizsgálhatjuk a ciklusfejben vagy a ciklusvégben is; a különbség abban fog állni, hogy legalább egyszer lefut-e a ciklus.
 
=== ElöltesztelőElöl tesztelő ciklus ===
[[Fájl:While-loop-diagram.svg|100px200px|jobbra|bélyegkép]]
Az elöltesztelőelöl tesztelő ciklus sémája:
<pre>Ismételd, amíg a feltétel igaz
utasítások
ciklus vége</pre>
Az elöltesztelőelöl tesztelő ciklus tehát először megvizsgálja, hogy a feltétel fennáll-e. Ha igen, akkor lefuttatja a ciklusmagot, és újból kezdődik; ha nem, akkor a program a ciklus utáni ponton folytatódik, azaz a ciklusmag kimarad. Lehetséges tehát, hogy az elöltesztelőelöl tesztelő ciklus egyszer sem fog lefutni.
 
Az elöltesztelőelöl tesztelő ciklus tipikus példája az [[adatállomány]]ok beolvasása; előfordulhat ugyanis, hogy az állomány üres, és ilyenkor nincs mit beolvasni. Hasonló a helyzet a [[Mappa (számítástechnika)|könyvtárak]] listázásakor is, hiszen a könyvtárban nem biztos, hogy van állomány.
 
Az elöltesztelőelöl tesztelő ciklus tipikus kulcsszava a <code>while</code>.
Általános alakja a következő:
<pre>
while(feltétel){
utasítás(ok);
}
</pre>
Példa (awk):
<pre>
while (i<10){
print i;
}
</pre>
 
=== HátultesztelőHátul tesztelő ciklus ===
[[Fájl:Do-while-loop-diagram.svg|100px200px|jobbra|bélyegkép]]
A hátultesztelőhátul tesztelő ciklus sémája:
<pre>Ismételd
utasítások
amíg a feltétel igaz</pre>
Mivel a feltételvizsgálat a ciklusmag után áll, ezért a hátultesztelőhátul tesztelő ciklus legalább egyszer mindenképpen lefut.
 
A konkrét programnyelvi megvalósítástól függ, hogy a hátultesztelőhátul tesztelő ciklusban a folytatás vagy a kilépés feltételét kell-e megadni. A ciklus az első esetben addig fut, amíg a ciklusvégben megadott feltétel igaz (ennek tipikus kulcsszava a <code>while</code>), a másik esetben pedig addig, amíg igazzá nem válik (tipikus kulcsszava az <code>until</code>).
 
Általános alakja a következő:
Jellemző példa a hátultesztelő ciklusra az adatbevitel ellenőrzése. Tegyük fel, hogy regisztrálni szeretnénk egy ingyenes [[E-mail|postafiókot]] az [[internet]]en. A [[szerver]]en futó programnak először ellenőriznie kell, hogy szabad-e még a választott azonosító, majd azt is, hogy kitöltöttük-e az összes kötelező adatmezőt, és addig kell ismételnie ezt a lépést, amíg az összes adat helyessé nem válik. Sok szolgáltató ezt egy lépésben végzi el, vagyis először ki kell töltenünk az űrlapot, aztán tudjuk meg, hogy szabad-e még az azonosító. Ebben az esetben a ciklus a következőképpen nézhet ki:
<pre>
do
{
utasítás(ok);
}while(feltétel);
</pre>
Jellemző példa a hátul tesztelő ciklusra az adatbevitel ellenőrzése. Tegyük fel, hogy regisztrálni szeretnénk egy ingyenes [[E-mail|postafiókot]] az [[internet]]en. A [[szerver]]en futó programnak először ellenőriznie kell, hogy szabad-e még a választott azonosító, majd azt is, hogy kitöltöttük-e az összes kötelező adatmezőt, és addig kell ismételnie ezt a lépést, amíg az összes adat helyessé nem válik. Sok szolgáltató ezt egy lépésben végzi el, vagyis először ki kell töltenünk az űrlapot, aztán tudjuk meg, hogy szabad-e még az azonosító. Ebben az esetben a ciklus a következőképpen nézhet ki:
<pre>
Ismételd
58 ⟶ 72 sor:
Ha egy kötelező mező hiányzik, írd ki, és add vissza az űrlapot
amíg hibás az űrlap</pre>
Mivel a feltételt csak az adatbeolvasás után ellenőrzi a program, ezért az adatbeolvasás legalább egyszer mindenképpen megtörténik. Ha sikerült elsőre jól kitöltenünk az adatlapot, akkor tovább lehet lépni.
 
Mivel a feltételt csak az adatbeolvasás után ellenőrzi a program, ezért az adatok beolvasása legalább egyszer mindenképpen megtörténik. Ha sikerült elsőre jól kitölteni az adatlapot, akkor tovább lehet lépni.
Zavart okozhat a szöveges leírásokban a magyar '''amíg''' szó két, egymással lényegében ellentétes jelentése. Az algoritmusok leírásában az ''amíg'' szót mindig a 'mialatt', 'miközben' értelmében használjuk, ami az angol ''while''-nak felel meg. A fenti eljárást úgy is fogalmazhatnánk, hogy ''„olvasd be az adatokat, ahányszor kell, amíg jók lesznek”'' – ebben az esetben az ''amíg'' szót az angol ''until'' értelmében használtuk, ami szintén lehet a hátultesztelő ciklus kulcsszava. Ezért előfordulhat, hogy a programkódban épp a szöveges algoritmusban látható feltétel tagadását kell megfogalmaznunk.
 
Zavart okozhat a szöveges leírásokban a magyar '''amíg''' szó két, egymással lényegében ellentétes jelentése. Az algoritmusok leírásában az ''amíg'' szót mindig a 'mialatt', 'miközben' értelmében használjuk, ami az angol ''while''-nak felel meg. A fenti eljárást úgy is fogalmazhatnánk, hogy ''„olvasd be az adatokat, ahányszor kell, amíg jók lesznek”'' – ebben az esetben az ''amíg'' szót az angol ''until'' értelmében használtuk, ami szintén lehet a hátul tesztelő ciklus kulcsszava. Ezért előfordulhat, hogy a programkódban épp a szöveges algoritmusban látható feltétel tagadását kell megfogalmaznunk.
== Számlálós (FOR) ciklus ==
[[Fájl:For-loop-diagram.png|100px|jobbra|bélyegkép]]
 
== Számláló (FOR) ciklus ==
A számláló (vagy iteráló) ciklus általánosságban olyan előltesztelő ciklust jelent, amely egy felsorolható típus adott intervallumán léptet végig, speciálisan egész számokon. Üres intervallumra nem fut le.
[[Fájl:For-loop-diagram.png|200px|jobbra|bélyegkép]]
 
A számláló ciklus általánosságban olyan elöl tesztelő ciklust jelent, amely egy felsorolható típus adott intervallumán léptet végig, speciálisan egész számokon. Üres intervallumra nem fut le.
C++-ban a <code>for</code> ciklus majdnem teljesen ekvivalens az elől tesztelős ciklussal (a <code>continue</code> viselkedése más), de más nyelvekben nem feltétlenül van ez így: a <code>for</code> ciklus átírható más ciklussá, de visszafelé általában nem. A <code>for</code> ciklusnak kisebb lehet a kifejezőereje, de könnyebb olvasni ezért a használata javasolt ott ahol ez lehetséges.
 
C-ben a <code>for</code> ciklus majdnem teljesen ekvivalens az elől tesztelő ciklussal, de más nyelvekben nem feltétlenül van ez így: a <code>for</code> ciklus átírható más ciklussá, de visszafelé általában nem.
Összegzés <code>for</code>-ral C++-ban:
A <code>for</code> ciklusnak kisebb lehet a kifejezőereje, de könnyebb olvasni: ezért a használata javasolt minden olyan esetben, ahol csak lehetséges.
 
Számok összegzése <code>for</code>ciklussal C-ben:
 
<syntaxhighlight lang="cpp">
int sum = 0; // Kezdetben a szumma 0
int i;
for(int i=1; i<201; ++i) // Kezdőérték; feltétel; növelés
for(i=0; i<200; ++i) // Kezdőérték; feltétel; növelés
sum = sum + i; // Az i hozzáadása sum-hoz
sum += i; // Az i hozzáadása sum-hoz
</syntaxhighlight>
 
ÖsszegzésSzámok összegzése <code>while</code>-lalciklussal C++-banben:
 
<syntaxhighlight lang="cpp">
int sum = 0;
int i = 10;
while(i<201200){
sum = sum += i;
++i;
}
</syntaxhighlight>
 
Az ADÁban<code>ADA</code> nyelvben ez nem áll fent, a <code>for</code> ciklus itt egy szigorúan kötött, ellenőrzött konstrukció, például nem lehet a ciklusváltozót változtatni:
 
<syntaxhighlight lang="ada">
96 ⟶ 112 sor:
</syntaxhighlight>
 
== Iteráló ciklus (FOR IN, FOREACH) ==
Ez a példa az [[MS-DOS]] [[kötegelt állomány]]ában szerepel, és törli az aktuális könyvtárból az ideiglenes állományokat néhány tipikus kiterjesztés alapján:
Egyes nyelvekben a <code>foreach</code> [[kulcsszó]]t kell használni. Arra való, hogy egy egy [[tároló (adatszerkezet)|tároló]] (pl.: tömb, lista, bináris fa, stb., stb.) elemeit bejárjuk. Erre egy egyszerű példa PHP-ban:<ref>{{Cite web |url=http://hu.php.net/manual/en/control-structures.foreach.php# |title=Archivált másolat |accessdate=2010-01-19 |archiveurl=https://web.archive.org/web/20090213012453/http://hu.php.net/manual/en/control-structures.foreach.php# |archivedate=2009-02-13 }}</ref>
<syntaxhighlight lang="dos">
for %%c in (*.bak *.tmp *.$$$ *.wbk) do del %%c
</syntaxhighlight>
 
=== Iteráló ciklus ===
Gyakran <code>for</code> vagy <code>foreach</code> [[kulcsszó]]val szokták rendelkezésre bocsátani. Arra való egy egy [[tároló (adatszerkezet)|tároló]] elemeit bejárjuk. Erre egy egyszerű példa PHP-ban:<ref>{{Cite web |url=http://hu.php.net/manual/en/control-structures.foreach.php# |title=Archivált másolat |accessdate=2010-01-19 |archiveurl=https://web.archive.org/web/20090213012453/http://hu.php.net/manual/en/control-structures.foreach.php# |archivedate=2009-02-13 }}</ref>
 
<syntaxhighlight lang="php">
$arr = array(1, 2, 3, 4); // Tömb az 1,2,3,4 számokból
109 ⟶ 119 sor:
$value = $value * 2; // Minden elem megszorzása 2-vel
}
// A $arr elemei itt rendre 1, 2, 3 és 4,6,8
</syntaxhighlight>
 
Egy lista bejárása (AutoLISP):
=== Beavatkozás a ciklus menetébe ===
<syntaxhighlight lang="lisp">
Gyakran előfordul, hogy ''n'' darab különböző számot kell generálnunk vagy bekérnünk. Ilyenkor kézenfekvő a <code>for</code> ciklus használata, ugyanakkor ismétlődés vagy hibás adat esetén szükség lehet a visszalépésre.
(foreach n '(a b c) (print n))
</syntaxhighlight>
Egyenértékű a
 
<syntaxhighlight lang="lisp">
(print a)
(print b)
(print c)
</syntaxhighlight>
megadásával. Mivel egy lista elemszáma nem kötött, az előny nyilvánvaló.
 
Néhány programozási nyelv a <code>for in</code>utasítással valósítja meg a
tömbök, listák bejárását, pl. awk:
(már létezik a ''szavak'' nevú tömb)
<syntaxhighlight lang="cpp">
for (x in szavak) {
if (length(x) > 12) { # ha a szó hosszabb, mint 12 karakter
print x # akkor kiírjuk
}
}
</syntaxhighlight>
Ez a példa egy [[MS-DOS]] [[kötegelt állomány]]ában szerepel, és törli az aktuális könyvtárból az ideiglenes állományokat néhány tipikus kiterjesztés alapján:
<syntaxhighlight lang="dos">
for %%c in (*.bak *.tmp *.$$$ *.wbk) do del %%c
</syntaxhighlight>
 
== Beavatkozás a ciklus menetébe ==
Egy ciklus menetébe beavatkozni többféleképpen lehet:
* a ciklusváltozó növelésével, ill. csökkentésével;
* a <code>break</code> utasítással;
* a <code>continue</code> utasítással.
Mindhárom módszer használható a <code>for</code> és a <code>while</code> segítségével létrehozott ciklusokban. Az egyetlen követelmény, hogy a ciklus törzén belül kell elhelyezni,különben hibajelzést kapunk.
 
=== Ciklusváltozó módosítása ===
Gyakran előfordul, hogy ''n'' darab különböző számot kell generálnunk vagy bekérnünk. Ilyenkor kézenfekvő a <code>for</code> ciklus használata, ugyanakkor ismétlődés vagy hibás adat esetén szükség lehet a ''visszalépés''re.
 
<syntaxhighlight lang="cpp">
126 ⟶ 171 sor:
} else {
cerr << "A szám nem megfelelő vagy már volt." << endl;
--i; // visszalépés
}
}
</syntaxhighlight>
 
=== A BREAK utasítás ===
 
Ez a speciális, ciklusok esetén használható utasítás azonnal ''megszakítja'' a ciklus futását, és függetlenül a ciklus vezérlő feltétel értékétől, függetlenül minden mástól azonnal (erőszakosan) befejezi a ciklus futását. A program futása ettől nem szakad meg, folytatódik a ciklusra rákövetkező utasítás végrehajtásával.
 
=== A CONTINUE utasítás ===
A <code>break</code>-hez hasonló utasítás a code<>continue</code>. Ennek használata esetén a ciklus futása nem szakad meg (fejeződik be) mint a <code>break</code>, sőt, ellenkezőleg. A <code>continue</code> hatására a ciklusmag maradék utasításai ebben a menetben már nem hajtódnak végre, de a ciklus futása folytatódik, mintha elértük volna a ciklusmag végét, vagyis újra a vezérlő feltétel kiértékelése következik. Például szeretnénk kihagyni az 1234-es irányítószámot:
 
<pre>
kimarad = 1234;
start = 1230;
end = 1240;
 
for(i= start; i<=end; i++){
if(i== kimarad){continue} else{
print i,"\n";
}
}
</pre>
 
A <code>continue</code> utasítás pl. menük ,,kiszürkítésére" is jól használható.
 
== Néhány nevezetes alkalmazás ==
143 ⟶ 209 sor:
std::cout << "A cellák összege: " << sum << std::endl;
</syntaxhighlight>
A ciklusokat használó programok rendszerint korllátozzák a ciklusok egymásba
 
ágyazhatóságának számát. Egyrészt a kiértékelések száma hatványozódik, ami
drámaian megnöveli a program futásidejét (kibírhatatlanul lassúvá válik).
Másrészt pedig a kiértékeléshez használt veremtár betelhet a sok átmeneti adattól,
ami pedig a program működését akadályozza meg (elszáll a program).
=== A végtelen ciklus ===
A végtelen ciklus olyan ciklus, melynek futása külső esemény bekövetkezte nélkül sohasem zárulna le.
189 ⟶ 260 sor:
Üresnek neveznek egy ciklust akkor, ha a magja egyszer sem fut le.
 
=== Ciklus ugró utasítással =(GOTO)==
Ugró utasítással akkor lehetséges ciklust szervezni, ha az adott nyelv támogatja
a címkék elhelyezését, továbbá van olyan utasítás, amellyel egy már megadott
címkére lehet ugrani. Ez azt jelenti, hogy a program az adott címkétől folytatódik.
Használata kerülendő.
 
Az alábbi program egy ciklust valósít meg [[BASIC]]-ben a <code>GOTO</code> ugró utasítás segítségével.
 
213 ⟶ 289 sor:
{{DEFAULTSORT:Ciklus (programozas)}}
[[Kategória:Programozási alapfogalmak]]
 
[[en:Control flow#Loops]]