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.