döngüler loops nedir

0
1818

Bir program parçasının yinelemeli olarak çalıştırılmasını sağlayan kontrol deyimlerine döngü denir. C dilinde 3 ayrı döngü deyimi vardır:

Kontrolün başta yapıldığı while döngüleri
Kontrolün sonda yapıldığı while döngüleri (do while döngüleri)
for döngüleri

Bu döngü deyimlerinden en fazla kullanılanı for deyimidir. for deyimi yalnızca C dilini değil, tüm programlama dillerinin en güçlü döngü yapısıdır. Aslında while ya da do while döngüleri olmasa da bu döngüler kullanılarak yazılan kodlar, for döngüsüyle yazılabilir. Ancak okunabilirlik açısından while ve do while döngülerinin tercih edildiği durumlar vardır.

kontrolun basta yapıldığı while döngüleri :

genel biçim .

while (ifade)
deyim;

while anahtar sözcüğünü izleyen parantez içerisindeki ifadeye kontrol ifadesi (control statement) denir. while parantezini izleyen ilk deyime döngü gövdesi denir. Döngü gövdesi basit bir deyim olabileceği gibi, bloklanmış birden fazla deyimden de (bileşik deyim) oluşabilir.

while deyiminin icrası şu şekilde olur :
Kontrol ifadesinin sayısal değeri hesaplanır. Kontrol ifadesinin sayısal değeri 0 dışı bir değerse, mantıksal olarak (Doğru) kabul edilir ve döngüye devam kararı verilir ve döngü gövdesindeki deyim ya da deyimler çalıştırılır. Kontrol ifadesinin sayısal değeri 0 ise mantıksal olarak (Yanlış) kabul edilir programın akışı döngünün dışındaki ilk deyimle devam eder. Yani while döngüsü, kontrol ifadesinin sayısal değeri 0 dışı bir değer olduğu sürece, döngü gövdesini oluşturan deyim(ler)in icrası ile devam eder.
Daha önce belirttiğimiz gibi C dilinde yalın bir deyimin olduğu yere bileşik bir deyim de yerleştirilebilir. Bu durumda while döngüsü aşağıdaki gibi de oluşturulabilir :

while (ifade) {
ifade1;
ifade2;
ifade3;
……
}

Bu durumda kontrol ifadesinin sayısal değeri 0 dışı bir değer olduğu (Doğru) sürece blok parantezleri arasında kalan tüm deyimler icra edilecektir. Örnek:

#include

void main(void)
{
int i = 0;

while (i < 10) {
printf (“%d\n”, i)
++i;
}
}

başka bir örnek :

#include
#include

void main(void)
{
char ch;

while (ch = getch(), toupper(ch) != ‘Q’)
putchar(ch);
}

başka bir örnek :

void main(void)
{
char ch;

while (ch = getch(), isupper (ch))
putchar(ch);
}

while parantezinin içindeki ifade yani koşul ifadesi, ifade tanımına uygun herhangi bir ifade olabilir. ifade (expression) tanımını hatırlayalım.

while (1) {
….
}

yukarıdaki while deyiminde kontrol ifadesi olarak bir sabit olan 1 sayısı kullanılmıştır. 1 değeri 0 dışı bir değer olduğundan ve kontrol ifadesi bir değişkene bağlı olarak değişemeyeceğinden, böyle bir döngüden çıkmak mümkün olmayacaktır. Bu tür döngülere sonsuz döngüler (infinite loops) denir. Sonsuz döngüler bir yanlışlık sonucu oluşturulabildiği gibi , bilinçli olarak da oluşturulabilir. Sonsuz döngülerden bazı yöntemlerle çıkılabilir.

break anahtar sözcüğü

break anahtar sözcüğü ile bir döngü kırılabilir. Kullanımı

break;

şeklindedir. Programın akışı break anahtar sözcüğünü gördüğünde, döngü kırılarak döngünün akışı döngü gövdesi dışındaki ilk deyim ile devam eder. Yani koşulsuz olarak döngüden çıkılır.

void main (void)
{
char ch;

while (1) {
ch = getch();
if (ch == ‘q’)
break;
putchar(ch);
}
printf(“döngüden çıkıldı!..\n”);
}

Yukarıdaki programda bir sonsuz döngü oluşturulmuştur. Döngü içerisinde, döngünün her bir iterasyonunda ch değişkenine klavyeden bir değer alınmaktadır. Eğer klavyeden alınan karakter ‘q’ ise break anahtar sözcüğüyle programın akışı whilde döngü gövdesi dışındaki ilk deyimle devam edecektir.

içiçe döngüler :

bir döngünün gövdesini başka bir kontrol deyimi oluşturabilir. Döngü gövdesini oluşturan kontrol deyimi bir if deyimi olabileceği gibi başka bir döngü deyimi de olabilir. (while, do – while, for deyimleri)

void main(void)
{
int i = 0;
int k = 0;

while (i < 10) {
while (k < 10) {
printf(“%d %d”, i, k);
++k;
}
}
++i;
}

İçiçe döngülerde içerideki döngüde break deyimi kullanıldığında yalnızca içerideki döngüden çıkılır, her iki döngüden birden çıkmak için goto deyimi kullanılmalıdır. (ileride göreceğiz.)

while döngüsü bir bütün olarak tek deyim içinde ele alınır. Örnek:

while (1)
while (1) {
…..
…..
…..,
}

burada ikinci while döngüsü tek bir kontrol deyimi olarak ele alınacağı için, bloklamaya gerek yoktur.

while döngüsünün yanlışlıkla boş deyim ile kapatılması :

çok sık yapılan bir hatadır.

void main(void)
{
int i = 10;

while (–i > 0);
printf(“%d\n”, i);

döngü while parantezi içerisindeki ifadenin değeri 0 olana kadar döner ve sonunda döngüden çıkarak 0 basar.

sonlandırıcı ; while parantezinden sonra konulursa herhangi bir sentaks hatası oluşmaz. Derleyici while döngüsünün gövdesinin yalnızca bir boş deyimden oluştuğu sonucunu çıkartır. Eğer bir yanlışlık sonucu değil de bilinçli olarak while döngüsünün gövdesinde boş deyim (null statement) bulunması isteniyorsa, okunabilirlik açısından, bu boş deyim while parantezinden hemen sonra değil, alt satırda ve bir tab içeriden yazılmalıdır.

while döngüsü içerisinde postfix ++ ya da — operatörünün kullanılması :

bir postfix artırım ya da eksiltme işlemi yapıldığında önce döngüye devam edilip edilmeyeceği kararı verilir, sonra artırım ya da eksiltim uygulanır. Örnek :

void main(void)
{
int i = 0;

while (i++ <= 100)
printf(“%d\n”, i);
printf(“%d\n”, i); /* ekrana 101 değerini basar. */
}

başka bir örnek :

int i = 10;

while (i– > 0)
printf(“%d\n”, i);
printf(“%d\n”, i);

kalıp

n bir pozitif tam sayı olmak üzere while döngüsü kullanılarak n defa dönen bir while döngüsü oluşturmak için

while (n– > 0)

ya da

while (n–)

kullanılabilir. Aşağıdaki içiçe döngü yapısı bir gecikme sağlamak için kullanılmıştır.

void main(void)
{
int i = 0;
long j;

while (i++ < 10) {
printf(“%d\n”, i);
j = 1000000L;
while (j–> 0 )
;
}

Bazen döngüler bilinçli bir şekilde boş deyimle kapatılmak istenebilir. Bu durumda boş deyim normal bir deyim gibi tablama kuralına uygun olarak yerleştirilmelidir.

kontrolün sonda yapıldığı while döngüleri (seyrek rastlanır)

genel biçim

1) do
ifade 1;
while (ifade 2);

2) do {
ifade 1;
ifade 2;
} while (ifade);

do while döngüsünde kontrol ifadesi sondadır. while parantezi ; ile kapatılmak zorundadır. Yani buradakı sonlandırıcı yanlışlık sonucu koyulmamıştır, deyime ilişkin sentaksın bir parçasıdır. Döngü gövdesindeki deyim(ler) en az bir kere icra edilecektir. Örnek :

void main(void)
{
int i = 0;
do {
++i;
printf(“%d\n”, i);
} while (i < 10);

Başka bir örnek:

void main(void)
{
char ch;

do {
printf (“(e)vet / (h)ayıt?\n”);
ch = getch();
} while (ch != ‘e’ && ch != ‘h’);
printf(“ok…\n”);
}

Örnek program : 1’den 100’e kadar sayılan her satıra beş tane olacak biçimde ekrana yazan bir C programının yazılması:

#include

void main(void)
{
int i = 0;

do {
printf(“%d “, ++i);
if (i % 5 == 0)
printf(“\n”);
} while (i < 100);
}

başka bir çözüm :

#include

void main(void)
{
int i = 0;
while (i < 100) {
printf (“%d”, i);
if (i % 5 == 4)
printf(“\n”);
++i;
}

do while döngülerinin kullanılmasına bir örnek :

bir tamsayının basamak sayısını bulan program

/* numdigit.c calculates the number of digits in an integer */

#include

main()
{
int digits = 0;
int number;

printf(“bir tamsayi girin: “);
scanf(“%d”, &number);

do {
n /= 10;
digits++;
} while (n > 0);
printf(“the number has %d digit(s).\n”, digits);
return 0;
}

aynı programı while döngüsüyle yazdığımızı düşünelim.

….
while (n > 0) {
n /= 10;
digits++;
}

do while döngüsü yerine while döngüsü kullanıldığında , girilen sayının 0 olması durumunda döngü gövdesindeki deyimler hiç icra edilmeyecekti. Bu durumda ekranda :

The number has 0 digit(s)

yazısı çıkacaktı, yani bir bug oluşacaktı.

for döngüleri

for döngüleri yalnızca C dilinin değil, belki de tüm programlama dillerinin en güçlü döngü yapılarıdır. for döngülerinin genel biçimi şu şekildedir :

for (ifade1; ifade2; ifade3)
deyim1;

for (ifade1; ifade2; ifade3) {
deyim1;
deyim2;
………..
}

derleyici for anahtar sözcüğünden sonra bir parantez açılmasını ve parantez içerisinde iki noktalı virgül bulunmasını bekler. Bu iki noktalı virgül for parantezini üç kısıma ayırır. Bu kısımlar yukarıda ifade1 ifade2 ve ifade 3 olarak gösterilmiştir.

for parantezi içinde mutlaka 2 noktalı virgül bulunmalıdır. for parantezi içinin boş bırakılması, ya da for parantezi içerisinde 1, 3 ya da daha fazla noktalı virgülün bulunması derleme zamanında hata oluşmasına yol açacaktır.

for parantezinin kapanmasından sonra gelen ilk deyim döngü gövdesini (loop body) oluşturur. Döngü gövdesi basit bir deyimden oluşabileceği gibi, bileşik deyimden de yani blok içine alınmış birden fazla sayıda deyimden de oluşabilir.

for parantezi içerisindeki her üç kısımın da ayrı ayrı işlevleri vardır.

2. kısım : for parantezinin 2. kısımını oluşturan ifadeye kontrol ifadesi denir. (control expression). Tıpkı while parantezi içindeki ifade gibi, döngünün devamı konusunda bu ifade söz sahibidir. Bu ifadenin değeri 0 dışı bir değer ise, yani mantıksal olarak DOĞRU ise, döngü devam eder, yani bir sonraki iterasyona geçilir. Döngü gövdesindeki deyim(ler) icra edilir. Kontrol ifadesinin değeri 0 ise programın akışı for döngüsünün dışındaki ilk deyimle devam edecektir.

1. kısım : Programın akışı for deyimine gelince, for parantezinin 1. kısmı 1 kez icra edilir ve genellikle döngü değişkenine ilk değer verme amacıyla kullanılır. (Böyle bir zorunluluk yoktur).

3. kısım : for döngüsünün 3. kısım döngü gövdesindeki deyim ya da deyimler icra edildikten sonra, dönüşte çalıştırılır. Ve çoğunlukla döngü değişkeninin artırılması ya da azaltılması amacıyla kullanılır. (Böyle bir zorunluluk yok.)

for (ilk değer; koşul; işlem) {



}

void main(void)
{
int i;

for (i = 0; i < 3; ++i)
printf(“%d\n”, i);
printf(“son değer = %d\n”, i);
}

yukarıdaki programı inceleyelim :

programın akışı for deyimine gelince

1. Önce for parantezi içindeki 1. kısımdaki ifade ele alınarak bir deyim gibi icra ediliyor. Yani i değişkenine 0 değeri atanıyor.

2. Şimdi programın akışı for parantezinin 2. kısmına yani kontrol ifadesine geliyor. ve i < 3 koşulu sorgulanıyor. Kontrol ifadesinin değeri 0 dışı bir değer olduğu için, ifade mantıksal olarak doğru kabul ediliyor ve programın akışı döngü gövdesine geçiyor.

3. Döngü gövdesi bloklanmadığı için, döngü gövdesinde tek bir deyim var. (basit deyim). Bu deyim icra ediliyor. Yani ekrana i değişkeninin değeri yazılıarak imleç alt satıra geçiriliyor.

4. Programın akışı bu kez for parantezinin 3. kısımına geliyor ve buradaki ifade bir deyimmiş gibi icra edeiliyor, yani i değişkeninin değeri 1 artırılıyor.i değişkeninin değeri 2 oluyor.

6. Programın akışı yine for parantezinin 3. kısımına geliyor ve buradaki ifade bir deyimmiş gibi icra edeiliyor, yani i değişkeninin değeri 1 artırılıyor. i değişkeninin değeri 3 oluyor.

7. programın akışı yine for parantezinin 2. kısmına geliyor. ve buradaki kontrol ifadesi tekrar sorgulanıyor. i < 3 ifadesi bu kez yanlış olduğu için programın akışı döngü gövdesine girmiyor ve programın akışı döngü gövdesi dışındaki ilk deyimle devam ediyor.
yani ekrana :

son değer = 3

yazılıyor.

Başka bir örnek : 1’den 100’e kadar olan sayıların toplamını bulan program :

void main(void)
{
int i;
int total = 0;

for (i = 0; i < 100; ++i)
total += i;
printf(“Toplam = %d”, total);
}

döngü değişkeninin tamsayı türlerinden birinden olması gibi bir zorunluluk yoktur. Döngü değişkeni gerçek sayı türlerinden de olabilir.

void main (void)
{
double i;

for (i = 0; i < 6.28; i = i + 0.01)
printf(“lf\n”, i);
}

Daha önce de söylendiği gibi for parantezi içindeki her 3 kısım da ifade tanımına uygun ifadeler içerebilir, yani bir döngü değişkenine ilk değer verilmesi, döngü değişkenine bağlı bir koşul ifadesi olması, döngü değişkeninin de azaltılması ya da artırılması bir zorunluluk değildir.

void main(void)
{
char ch;

for (ch = getch(); ch != ‘p’ ; ch = getch())
putchar(ch);
}

Başka bir örnek :

void main(void)
{
for (printf(“Birinci kısım\n); printf(“İkinci kısım\n”, getch() != ‘q’; printf(“üçüncü kısım\n));
}

for döngüsünün 1. kısmı hiç olmayabilir. Örneğin döngü dışında, programın akışı for deyiminin icrasına gelmeden önce, döngü değişkenine ilk değer verilmiş olabilir.

…..

i = 0;
for (; i < 100; ++i)
printf(“%d\n”, i);

for döngüsünün 3. kısmı da hiç olmayabilir. Döngü değişkeninin artırılması ya da eksiltilmesi for parantezi içi yerine döngü gövdesi içerisinde gerçekleştirilebilir.

1. ve 3. kısmı olmayan (yalnızca 2. kısma sahip) bir for döngüsü örneği:

i = 0;
for (; i < 100; ) {
printf(“%d\n”, i);
++i;
}

1.ve 3. kısmı olmayan for döngüleri tamamen while döngüleriyle eşdeğerdir. C’de for döngüleri ile while döngüleriyle yapabildiğimiz herşeyi yapabildiğimiz gibi daha fazla olanakları da kullanabiliriz. O zaman şöyle bir soru aklımıza gelebilir : Madem for döngüleri while döngülerini tamamen kapsıyor, o zaman while döngülerine ne gerek var? while döngülerinin bazı durumlarda kullanılması for döngülerine göre çok daha okunabilir bir yapı yaratmaktadır.

for parantezinin 2. kısmı da hiç olmayabilir. Bu durumda kontrol ifadesi olmayacağı için döngü bir koşula bağlı olmaksızın sürekli dönecektir. Yani sonsuz döngü oluşturulacaktır.

Ancak iki adet noktalı virgül yine parantez içinde mutlaka bulunmak zorundadır.

for parantezinin hiçbir kısmı olmayabilir. Ancak yine iki noktalı virgül bulunmak zorundadır:

i = 0;
for (;;) {
printf(“%d\n”, i);
++i;
if (i == 100)
break;
}

for (;;) ile while (1) eşdeğerdir. İkisi de sonsuz döngü belirtir.

Sonsuz döngü oluşturmak için for(;;) biçimi while(1) e göre daha çok tercih edilir. Bunun nedeni eski derleyicilerde while(1) ifadesi kullanıldığında dögünün her dönüşünde kontrol ifadesinin tekrar test edilmesidir. Ama yeni derleyicilerde böyle bir kontrol söz konusu değildir. Ama bazı programcılar while (1) ifadesini tercih ederler. (Tabi burada kontrol ifadesi 1 yerine 0 dışı herhangi bir değer de olabilirdi ama geleneksel olarak 1 ifadesi kullanılmaktadır.)

Sonsuz döngülerden çıkış 4 şekilde olabilir :

1. break anahtar sözcüğü ile

bu durumda programın akışı döngü gövdesi dışındaki ilk deyime yönlenecektir.
(eğer iç içe döngü varsa break anahtar sözcüğü ile yalnızca içteki döngüden çıkılacaktır.)

2. return anahtar sözcüğü ile

bu durumda fonksiyonun (main de olabilir) icrası sona erecektir.

3. goto anahtar sözcüğüyle.
bu şekilde içiçe birden fazla döngü varsa en içteki döngü içinden en dıştaki döngünün dışına kadar çıkabiliriz. (goto anahtar sözcüğünün çok az faydalı kullanımından biri budur.)

4. exit fonksiyonu ile. (ileride göreceğiz)