For vagy while?
Csendes Dávid · 2021.08.24.
Mikor használunk while-t, és mikor for-t?
for
vagy while
?
Mikor használunk while
-t, és mikor for
-t? Először is tisztázni kell – ahol for
használható, ott while
is ugyanúgy működik, és fordítva. Ezt hamar beláthatjuk, ha egy for
ciklust átírunk:
// for ciklussal
for (int i = 0; i < max; i = i + 1) {
// ciklustörzs
}
// ugyanez while ciklussal
int i = 0;
while (i < max) {
// ciklustörzs
i = i + 1;
}
Működés szempontjából emiatt mindegy, melyiket használjuk, de kód szépsége szempontjából (egyes esetekben) nagyon nem!
Mégis akkor mi alapján lehet eldönteni, melyiket érdemesebb használni? Röviden: ha a for
ciklus fejlécében valamelyik rész üresen
maradna, akkor érdemesebb a while
, ha mind kitölthető, akkor for
.
Milyen esetekben fordulhat elő, hogy a for
ciklus fejlécének 3 része közül valamelyik üresen marad?
- Például a ciklusváltozónk már létezik korábbról (és használjuk is ott, nem inicializálhatjuk a ciklus kezdeténél). Ha ezt
for
-ral írnánk, akkor az első része üresen maradna – érdemesebb ilyenkorwhile
-t használni. - A ciklusváltozó léptetése valamilyen különleges módon / feltételhez kötve történik. Ebben az esetben a
for
harmadik része üres lenne, mert ezt a komplexebb logikát a ciklustörzsbe írtuk le – ismét awhile
egy nyerőbb választás. - Egyes esetekben nincsen konkrét ciklusváltozónk. Ekkor egyértelmű a
while
használata, hisz csak a feltételünk van meg,for
esetén a két szélső rész üresen maradna.
Egy példa az utóbbira:
while (scanf("%d", &szam) == 1)
Mikor lesz kitöltve a for
ciklus fejléce teljesen? Tulajdonképpen bármilyen olyan esetben, ami az előzőekből kimaradt. De különös
hangsúllyal arra, mikor egy tárolót kell végigjárni, vagy egy olyan ciklusról van szó, ahol az a lényeg, hogy a ciklustörzsben
lévő kód adott számú alkalommal fusson le (számlálás alapú ciklus). Ebben a két esetben mindenképp for
ciklust használjunk!
int tomb[10];
for (int i = 0; i < 10; i = i + 1)
tomb[i] = 1;
for
ciklus ciklusszámlálója
Honnan indítsuk a ciklusváltozónkat? Meddig menjen? Ez egy jóval egyszerűbb kérdés, mint az előző volt.
for (int i = 0; i < 5; i = i + 1)
// vagy
for (int i = 1; i <= 5; i = i + 1)
Mind a kettő teljesen ugyanazt végzi – 5 alkalommal futtatja le a ciklustörzset. De mégis melyiket válasszuk?
Mind a két variációnak van létjogosultsága: az első esetben azt mondhatjuk, hogy a ciklusváltozó azt mutatja, hány iteráció fejeződött már be, míg a második esetben azt, hogy épp hányadik iteráció fut.
Azonban van kettő (plusz egy) indok, hogy miért a 0-val inicializált verziót használjuk:
- egy karakterrel rövidebb :)
- tömbökkel történő munka során muszáj 0-tól indulni, ha minden elemmel akarunk dolgozni, hisz ezeknek az indexelés 0-tól indul.
- ez csak extra – hagyományosan az informatikában minden 0-tól indul (erről bővebben itt).
Előfordulhat olyan eset, hogy az 1-gyel inicializált verzió könnyebben átlátható kódot eredményez a ciklustörzsben (arról nem is beszélve, hogy valami konkrét értékről kell indítani a ciklusváltozót), de általában biztonsággal használható a 0 kezdetű – érdemes megszokni!
Egy valamit ne csináljunk semmiképp sem:
for (int i = 1; i < 6; i = i + 1)
Ha a ciklusunk számlálásos, a feltételben lévő szám tükrözze mindenképp azt, hogy hányszor fut le a ciklus. Erről nem lehet ránézésre megmondani, hogy 5-ször fut le!
Ha nem 0-ról/1-ről indul a ciklusváltozó, jellemzően az a célunk, hogy a kezdeti értéktől a lezáró értékig bezárólag minden előforduló számmal csináljunk valamit (például kiíratni a számokat visszafelé).
for (int i = 23; i >= 4; i = i - 1)
printf("%d", i);
A fenti kódrészlet 23-tól 4-ig (beleértve mindkettőt) kiírja az összes számot. Honnan lehet tudni? Onnan, hogy mind a két szám szerepel a fejlécben! Azok az értékek, melyek a feladatban megjelennek, érdemes a kódban is előfordulniuk, lehetőleg módosítás nélkül.
// így mi is lesz az utolsó kiírt szám? :(
for (int i = 23; i > 3; i = i - 1)
printf("%d", i);