„Ciklus (programozás)” változatai közötti eltérés
[ellenőrzött változat] | [ellenőrzött változat] |
Tartalom törölve Tartalom hozzáadva
a kisebb javítások |
|||
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ő [[
▲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.
== A ciklus részei ==
Alább egy egyszerű [[BASIC]] nyelvű ciklust láthatunk, amelyik 2-től 5-ig egyesével haladva kiírja a számokat és a négyzetüket:
<syntaxhighlight lang="freebasic">
FOR i=2 TO 5 STEP 1
NEXT i
</syntaxhighlight>
Ebben a ciklusban az ''i'' a '''ciklusváltozó''', amely a ciklus kezdetén [[
2 négyzete: 4
sort. Ezután ''i'' értéke 3-ra változik, és ismét lefut. Ez addig ismétlődik, amíg az ''i'' értéke 5 lesz. Ekkor még utoljára lefut a ciklus, tehát a képernyőn még megjelenik az 5 négyzete is, majd az ''i'' értéke 6 lesz, de ez már nagyobb, mint 5, ezért a program kilép a ciklusból, és a futás a következő sorral folytatódik. Végeredményben a következőt írja ki a program:
Ebben a ciklusban a ciklusváltozónak van '''kezdőértéke''' (2), '''végértéke''' (5) és '''lépésköze''' (1). 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''' – ismert még a '''ciklus törzse''' néven is –, vagyis a ténylegesen ismétlődő utasítások meghatározása. A fenti példában ciklus magja mindössze egyetlen utasításból áll. Végül az utolsó sor a '''ciklusvég'''; az elöltesztelő és a számláló 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ő ciklus esetén pedig ez a rész tartalmazza a futási feltételt.
▲ 5 négyzete: 25
Ciklus nélkül a program:
<syntaxhighlight lang="freebasic">
PRINT 2, " négyzete: ", 2*2
PRINT 3, " négyzete: ", 3*3
PRINT 4, " négyzete: ", 4*4
PRINT 5, " négyzete: ", 5*5
</syntaxhighlight>
Bár ez a programocska ciklus nélkül is megírható, azonban eltérő adatok esetén teljesen át kellene írni, míg a ciklust tartalmazó változatban csupán a kiindulási adatokat kell módosítani. A példában mindössze 4 számot és a négyzeteiket kellett kiíratni. Nagyobb intervallum esetén a ciklus tömörsége nyilvánvaló, szemben a ciklus nélküli program terjengősségével.
== Típusai==
A feltételes
====
▲A feltételes ciklusok olyankor használatosak, amikor nem feltétlenül ismert előre, hogy futásidőben hányszor kell a ciklusnak lefutnia (például egy számítógép lemezkatalógusában lévő fájlok listázása). Az viszont ismert, hogy milyen feltétel teljesülése esetén kell a programnak 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.
[[Fájl:While-loop-diagram.svg|200px|jobbra|bélyegkép]]
Az
<pre>
Ismételd, amíg a feltétel igaz utasítások
ciklus vége
</pre> Az
Az
Az
<pre>
while (feltétel) {
}
</pre>
Példa (awk):
<pre>
i = 0;
while (i < 10) {
}
</pre>
====
[[Fájl:Do-while-loop-diagram.svg|200px|jobbra|bélyegkép]]
A
<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
A konkrét programnyelvi megvalósítástól függ, hogy a
Általános alakja a következő:
<pre>
do {
utasítás(ok);
} while (feltétel);
</pre>
Jellemző példa a
<pre>
Ismételd
amíg hibás az űrlap
</pre> 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
=== Számláló ciklus (
[[Fájl:For-loop-diagram.png|200px|jobbra|bélyegkép]]
A számláló ciklus általánosságban olyan
C-ben a <code>for</code> ciklus majdnem teljesen ekvivalens az
▲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-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.
Számok összegzése <code>for</code>ciklussal C-ben:
<syntaxhighlight lang="cpp">
int sum = 0; // Kezdetben a szumma 0
int i;
for (i = 0; i < 200; ++i) // Kezdőérték; feltétel; növelés
sum += i; // Az i hozzáadása sum-hoz
</syntaxhighlight>
115 ⟶ 108 sor:
int sum = 0;
int i = 0;
while (i < 200) {
sum += i;
++i;
121 ⟶ 114 sor:
</syntaxhighlight>
=== Iteráló ciklus (for in, foreach) ===
Egyes nyelvekben a <code>foreach</code> [[kulcsszó]]t kell használni. Arra való, hogy egy egy [[tároló (adatszerkezet)|tároló]] (pl.
▲=== Iteráló ciklus (FOR IN, FOREACH) ===
▲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árják és minden egyes elemre
▲ 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
foreach ($arr as &$value) { // A tömb bejárása
$value = $value * 2; // Minden elem megszorzása 2-vel
138 ⟶ 130 sor:
(foreach n '(a b c) (print n))
</syntaxhighlight>
Egyenértékű a▼
▲Egyenértékű a
<syntaxhighlight lang="lisp">
(print a)
145 ⟶ 137 sor:
(print c)
</syntaxhighlight>
megadásával. Mivel egy lista elemszáma nem kötött, az előny nyilvánvaló. Ráadásul a végrehajtandó utasítások száma sincs korlátozva (
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. az [[awk]]: (már létezik a ''szavak'' nevű tömb)
<syntaxhighlight lang="cpp">
for (x in szavak) {
}
</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">
</syntaxhighlight>
171 ⟶ 162 sor:
=== 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">
using namespace std;
set<int> lottoSzamok;
for (int i = 0; i < 5; ++i) {
int aktualis;
cout << (i + 1) << ". lottó szám: ";
cin >> aktualis;
if (aktualis >= 1 && aktualis <= 90 && lottoSzamok.find(aktualis) == lottoSzamok.end()) {
lottoSzamok.insert(aktualis);
} else {
191 ⟶ 181 sor:
<syntaxhighlight lang="ada">
for I in 1..200 loop
SUM := SUM + I;
end loop;
</syntaxhighlight>
=== A
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 nm szakad meg, folytatódik a ciklus után következő utasítás végrehajtásával. A <code>break</code> és a ciklus vége közötti utasítások nem lesznek végrehajtva.▼
▲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 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;
209 ⟶ 195 sor:
end = 1240;
for (i = start; i <= end; i++){
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 ==
=== Egymásba ágyazott ciklusok ===
Egymásba ágyazott ciklusokat tipikusan akkor szokás használni, amikor egy területen (például egy kép [[képpont]]jain, vagy egy [[Mátrix (matematika)|mátrixon]]) kell műveleteket végezni. Bizonyos rendező algoritmusok (pl. [[buborékrendezés]]) is egymásba ágyazott ciklusokat használnak. Egy számtáblázat celláinak az összegzése pl. így néz ki:
<syntaxhighlight lang="cpp">
int **t, n, m;
// <-- Beolvasás n-be, m-be (méretek) és t-be
int sum = 0;
for (int i = 0; i < n; ++i)
for (int j = 0; j < m; ++j)
sum = sum + t[i][j];
std::cout << "A cellák összege: " << sum << std::endl;
</syntaxhighlight>
A ciklusokat használó programok rendszerint korlátozzák a ciklusok egymásba ágyazhatóságának számát. Egyrészt a ciklusok egymásba ágyazásával a kiértékelések száma hatványozódik, ami drámaian nö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, amelynek futása külső esemény bekövetkezte nélkül sohasem zárulna le.Végtelen ciklus történhet egy programban előre eltervezetten vagy pedig a program hibájából is: a programozónak más volt a szándéka, de mégis olyan ciklust sikerült írnia, amely néhány helyzetben (vagy soha) nem tud kilépni a ciklusból. Általában vagy a hibás feltétel megadása vagy a feltétel vizsgálatának hibája okozza az ilyen végtelen ciklust.
Példa:
<syntaxhighlight lang=c++>
int x = 1; /* számláló kezdőértéke */
while (x != 10) { /* csináld míg x nem lesz 10 */
/*
A ciklus törzse:
itt helyezkedne el a többször futtatandó kódunk
*/
x = x + 2;
</syntaxhighlight>
A program futása során az x a következő értékeket veszi fel: 1, 3, 5, 7, 9, 11
==== Előre tervezett végtelen ciklus ====
Végtelen ciklust akkor terveznek be egy programba, ha azt szeretnék elérni, hogy a program bizonyos része ''örökké'' fusson. Ilyen eset például a menük kirajzolása a képernyőre, adatbevitel a parancsértelmezők készenléti jelére stb. Az előre tervezett végtelen ciklusból is ki lehet lépni a <code>break</code> utasítással.
<syntaxhighlight lang=c++>
//
while (1) {
▲ // itt helyezkedne el a többször futtatandó kódunk
▲ // ami a végtelenségig ismétlődik
}
//
do {
//
//
// "amíg-nem" végtelen ciklus
until (false) {
▲ // itt helyezkedne el a többször futtatandó kódunk
▲ // ami a végtelenségig ismétlődik
//
do {
//
//
} until (1);
// végtelen for ciklus
for ( ; ; ) {
//
//
}
</syntaxhighlight>
===
Vak- vagy várakozó ciklusnak az olyan ciklust nevezik, amelynek a magja üres. Az ilyen ciklusokat a program futásának lassítására vagy várakozáshoz szokták használni.
Például az [[ABC 80]] BASIC nyelve nem tartalmazott várakozó utasítást. Időnként szükség lehet egy program futásának szándékos szüneteltetésére. Ilyen lehet például a képernyőre írás utáni várakozás vagy egy játékprogram, ahol különböző nehézségi szintek vannak megadva. Az alábbi számláló ciklus elszámol tízezerig és ezzel lassítja a futást (időt adva a felhasználónak az üzenet elolvasására.):
<syntaxhighlight lang="freebasic">
FOR I=10 TO 10000
308 ⟶ 277 sor:
</syntaxhighlight>
Hasonló példa a [[Pascal (programozási nyelv)|Pascalban]] írt alábbi
<syntaxhighlight lang="pascal">
repeat until keypressed;
319 ⟶ 287 sor:
Üresnek neveznek egy ciklust akkor, ha a magja egyszer sem fut le.
== Ciklus ugró utasítással (
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.
<syntaxhighlight lang="freebasic">
10 PRINT "Meddig irjam ki a szamokat? ";
346 ⟶ 310 sor:
{{Portál|Informatika|i }}
[[Kategória:Programozási alapfogalmak]]
|