A while ciklus általános formája a következőképpen írható le:
while (feltétel)
{
utasítás1;
utasítás2;
…
utasításn;
}
A fenti ciklus a while kulcsszóval kezdődik, majd a zárójelek közti részben a ciklusban maradás feltételét kell megadni. A ciklus magjában lévő utasításokat, melyek tetszőleges számban fordulhatnak elő, pontosvesszővel választjuk el egymástól. Innen tudja a fordító, hogy hol végződik az aktuális, és hol kezdődik a következő utasítás.
A ciklus magját kapcsos zárójelek { } közé kell tenni, jelezve ezzel a ciklus utasításainak a kezdetét és végét (egy utasítás esetén a zárójelek elhagyhatóak, de javasolt a használatuk a programok jobb áttekinthetősége érdekében). A kapcsos zárójelek közti utasítás blokkot ismétli a rendszer mindaddig, amíg a feltétel igaz, vagyis TRUE értékű.
Folyamatábrával szemléltetve a while ciklus a következő formában írható le:
A folyamatábra a while ciklus logikai modellje. Az első feldolgozást szimbolizáló téglalap csak akkor szükséges, ha a ciklusban használunk ciklus változót, esetleg azt a ciklus bennmaradási feltételeként alkalmazzuk. A ciklus feltétel része tartalmazza a ciklusban maradás feltételét. A második feldolgozás blokk tartalmazza a ciklus utasításait, valamint a ciklus változójának léptetését, természetesen csak abban az esetben, ha van ciklusváltozó. Ha megértjük a folyamatábra és az általános forma működési elvét, akkor azok alapján bármilyen while ciklust el tudunk készíteni.
Nézzünk meg egy konkrét példát a while ciklus használatára! A következő ciklus kiírja a 0-10 közötti egész számokat a konzol képernyőre.
int i=0;
while (i<=10)
{
Console.WriteLine(”{0}”,i);
i++;
}
(Természetesen a fenti ismétlést megvalósíthattuk volna egyszerűen for ciklussal is.)
A while-t használó megoldásnál ügyeljünk arra, hogy a ciklus változóját léptetni kell, vagyis az értékét minden lefutáskor növeljük meg eggyel, mert a for ciklussal ellentétben itt a rendszer erről nem gondoskodik. (Emlékezzünk vissza a for ciklusra! Ott a ciklus változó növelése automatikus és nem is célszerű azt külön utasítással növelni).
A változó léptetésére a következő formulát használtuk:
i++;
A C típusú nyelvekben, így a C# -ban is, ez a rövidített forma megengedett, ekvivalens az i=i+1; és az i+=1; utasítással. (A IV. fejezetben az aritmetikai műveletekről és azok rövidítéséről bővebben olvashattunk.)
Ügyeljünk arra is, hogy a ciklus változójának mindig adjunk kezdő értéket, ellenkező esetben az ismétlések száma nem lesz megfelelő.
Természetesen a while ciklust leginkább a logikai értékek vizsgálatakor használjuk, s nem számláló ciklusként (arra ott van a for ).
Az előző fejezetekben már láthattunk néhány példát a logikai ciklusokra, de ott nem részleteztük a működésüket. A következő példa bemutatja, hogyan lehet tízes számrendszerbeli számokat átváltani kettes számrendszerbe.
using System;
namespace Atvaltas
{
class atvalt
{
[STAThread]
static void Main(string[] args)
{
int[] t=new int[8];
int k=0;
int szam=8;
int j;
while (szam!=0)
{
t[k]=szam % 2;
szam=szam / 2;
k++;
}
j=k-1;
while (j>=0)
{
Console.Write("{0}",t[j]);
j--;
}
Console.ReadLine();
}
}
}
Az első while ciklus feltétele a (szam!=0), a ciklus szempontjából azt jelenti, hogy az ismétléseket addig kell végezni, míg a szam változó értéke nullától nagyobb. Nulla érték esetén a ciklus befejezi futását.
Megfigyelhetjük, hogy ebben a ciklusban nem tudjuk előre megmondani a lefutások számát, mivel az mindig a futás közben végrehajtott műveletek eredményétől függ (annyi lefutás van, ahány osztással elérjük a nulla értéket). A második ciklusban, amelyik a kettes számrendszerbeli számjegyeket írja a képernyőre, a ciklus változó kezdőértéke a k-1. Az értékét nem növeljük, hanem csökkentjük, így a tömbben lévő számjegyeket visszafelé írjuk ki a képernyőre, de csak azokat, melyek az osztás során jöttek létre. A tömb többi értékét nem vizsgáljuk, mivel azok a feladat szempontjából nem értékes számjegyek.
Az átváltás után a k változó értéke 5, mert az átváltandó számjegy a 8, így az első ciklusunkban négy osztás történt, és az utolsó lefutáskor még növeltük a k értékét eggyel. Ebből az következik, hogy az utolsó értékes számjegy a negyedik indexen, vagyis a k-1 helyen van. (Próbáljuk meg átírni a fenti programot úgy, hogy ne csak a 8-as számra működjön, hanem a felhasználótól beolvasott tetszőleges értékekre!)
Vegyük sorra, hogy mikor célszerű logikai, vagy más néven feltételes ciklusokat alkalmazni.
-
Amennyiben nem tudjuk meghatározni a ciklus ismétlésinek a számát (futás közben dől el).
-
Ha a leállás valamilyen logikai értéket szolgáltató kifejezés eredményétől függ.
-
Több leállási feltétel együttes használatakor.
-
Az előző három pont együttes fennállása esetén.
Több feltétel használatakor az egyes kifejezéseket, logikai értékeket célszerű ÉS, illetve VAGY kapcsolatba hozni egymással. A while ciklus ekkor addig fut, míg a feltétel minden része igaz. Ha bármelyik rész-feltétel, vagy a feltételek mindegyike hamissá válik, akkor az egész kifejezés értéke hamis lesz, és az ismétlés befejeződik.
Mindig gondoljuk végig, hogy a feltételek összekapcsolására && vagy || operátort használunk. Vannak olyan problémák, ahol mindkettőt használnunk kell egy kifejezésen belül. Ügyeljünk a megfelelő zárójelezésre.
Vizsgáljuk meg az alábbi két ciklust. Az első jó eredményt fog szolgáltatni, a futása akkor áll meg, ha az i értéke eléri a tömb elemszámát, vagy ha megtaláljuk a nulla elemet. A második ciklus nem biztos, hogy megáll.
i=0;
while ( (i<10) && (t[i] != 0) )
{
Console.WriteLine(” {0} ”,t[i]);
i += 1;
}
i=0;
while ( (i<10) || (t[i] != 0) )
{
Console.WriteLine(” {0} ”,t[i]);
i += 1;
}
Az ÉS kapcsolat, vagyis az && operátor használatakor ügyeljünk a megfelelő zárójelezésre és a precedencia szabályra. A zárójelek elhagyása, vagy rossz helyen történő alkalmazása nehezen észrevehető hibákat eredményez.
Az alábbi két formula közül az első helyes eredményt produkál, a második viszont hibásat, mivel abban szándékosan elrontottuk a zárójelezést.
while ( (i<10) && (a!=2))
while ( i<(10 && a)!=2)
A rosszul felírt zárójelek miatt a fordító először a (10 && a) részt értékeli ki, s ez hibához vezet.