Konuyu görüntüle
IUCODERS FORUM > Programlama > C / C++ > 1. Sınıflara c DE for döngüsü
Yazar
einsteine


avatar
istanbul
Kayıt: 29.10.2007
13.11.2007-19:54 #30410
Hemen her programlama dilinde yer alan for döngüsü de genel döngü anlayışıyla yani "çok sayıda yapılacak işlemleri bir kez yazıp tekrar ettirme" mantığının gerekli olduğu yerlerde kullanılır. Şablonu şu şekildedir:


for (ilk değer verme ; döngü koşulu ; döngü değeri değişimi)
{
	// tekrar edilecek kod
}


Görüldüğü üzere for döngüsünün başlığında 3 ana kısım vardır. Bu kısımlardan herhangi biri ya da hepsi yazılmayabilir. Bu kısımları açıklamaya geçmeden önce döngü değişkeninden bahsetmenin gerekli olduğunu düşünüyorum. Döngülerin çevrim (yani tekrarlanma) sayısı döngü değişkenlerine verilen ilk değerlere, değişkenin uyması gereken koşula ve değişkenin sayısal olarak değişim miktarına bağlıdır. Örneğin döngü değişkeni olarak -çoğunlukla olduğu gibi- bir tamsayı değişkeni kullandığımızı düşünelim. Bu değişkene ilk değer olarak 1 verirsek, döngü koşulunu bu sayının 10'dan küçük veya eşit olması olarak belirleyip her çevrimde değişkenin 2 artacağını belirtirsek for döngümüzün başlığı şu şekilde olur ve 5 kere çalışır:

...
int x;
for (x=1 ; x<=10 ; x=x+2)
...


Bunun nedeni for döngüsünün çalışma mantığındadır. Döngüye girildiğinde ilk olarak (ve sadece bir kere) döngü değişkenine ilk değer verme kısmı işletilir. Bundan sonra döngü koşulunun doğruluğu kontrol edilir ve döngünün tekrarlayacağı kod çalıştırılır. Dikkat! Döngünün ilk çalıştırışında döngü değişkeni, döngünün 3. kısmında yazdığı şekilde değiştirilmez. Döngü değişkeninin değerinin değiştirilmesi işlemi döngünün ikinci çalışışından itibaren olur. Birinciden sonraki çalışmalarda ise; döngü koşulu kontrol edilerek doğruysa döngü değeri değiştirilerek kod tekrarlanır ve bu böyle devam eder. Döngü koşulu yanlışsa döngüden çıkılır ve döngü yapısından hemen sonra gelen kod çalıştırılır. Ayrıca burada ekleyebileceğim önemli bir yöntem de for döngüsünde bu üç kısmın da virgül operatörüyle genişletilebileceğidir. Şimdi, artık teoriyi bırakıp bir şeyler öğreten kısma geçelim: pratik!

İlk örneğimiz başta kullanılan örnek. Bu örnekle, örneğin döngü çalıştırıldığı sürece döngü değişkeninin değerini yazdıralım:

#include<stdio.h>

int main(void)
{
	int x;

	for (x=1 ; x<=10 ; x+=2) /* x+=2 ifadesi x=x+2 anlamına gelir! */
		printf("x'in degeri: %d
", x);

return 0;
}


Döngünün başlık kısmının virgülle genişletildiği örnek ise:

#include<stdio.h>

int main(void)
{
	int x,y;

	for (x=0, y=10 ; x<=10, y>=0 ; ++x, --y)
		printf("x: %2d, y: %2d ve x+y = %d
", x, y, x+y);

	return 0;
}


Çıktısı ise:



İlk örnekte, görüldüğü gibi önce x'in değeri 1 yapılmış, daha sonra döngü koşulunun doğruluğu kontrol edilmiş (doğru olmasaydı çıktı verilmezdi), son olarak da x'in değerini değiştirmeden döngünün bloğundaki kod çalıştırılmış (Burdaki blok kelimesi if/if-else yapılarındakiyle aynı. Yani tek satırlık kod eklenecekse { ve } ile blok açmaya gerek yok. Birden fazla satır yazılacaksa -yapı tarafından varsayılan olarak sadece biri yapıya ait kabul edileceğinden- küme parantezleri ile blok açılmalıdır). Bu birinci çalışmadan sonra ise -çıktının ikinci satırında görüldüğü gibi x'in değeri artılıp koşul doğruysa döngü tekrarlanır ve böyle devam edilir. İkinci örnekte ise for döngüsünün her üç kısmı da 2 değişkenle kullanılmaktadır. x ve y'nin değeri beraber değiştirilmiştir (ve toplamları sabit kalmıştır). Burdaki ilk örnekteki gibi döngülerde döngünün kaç kere çalışacağı önceden bellidir. Bunun yerine kaç kere çalışılacağını kullanıcıdan da alabilirsiniz. Örneğin, bir kayıt programı yazılıyorsa kaç kayıt yapılacağını kullanıcıdan alıp döngü değişkenine atarsınız ve o sayı kadar çıktı verip kullanıcıdan kayıt istersiniz.

Döngü sayıları sınırlı olan döngülerden başka bir de sınırsız olanlar vardır. Bunlara sonsuz döngü (infinite loop) denir. İlk kısımda yazdığım gibi, for döngüsünün üç ana kısmından herhangi biri ya da hepsi yazılmayabilir. Yani döngü değişkenine ilk değeri döngüye girmeden verip ilk değer verme (initialization) kısmını, koşul kontrolünü döngü içinde yapıp koşul kontrolu kısmını, ve yine döngü içinde yapılan bir değişken değeri değiştirme kısmı ile de son kısmı yazmayabilirsiniz. Sonsuz döngüler de bu kısımların yazılmamasıyla oluşur. Örneğin bir for döngüsünün;

for (x=0 ; ; x++)


şeklinde koşul kontrolü kısmı yoksa ve birazdan göreceğimiz döngü kontrolu deyimi break kullanılmamışsa döngü sonsuz kere çalışır (Tabii ki bellek aşımı falan gözardı). Ancak bu sonsuz döngülerin de kullanıldıkları yerler vardır. Örneğin bir oyun ya da port kontrolü yapan bir güvenlik programını düşünelim. Oyunda kullanıcıdan gidilecek yön,.. vs. isteme kısmı ile aracın,karakterin,.. vs. hareketi kısmı bir sonsuz döngüye konulur ve de girilen karakterle oyundan çıkışın kontrolu yapılırsa büyük kolaylık olur (Örnek olarak geçen seneki dönem ödevimi makalenin en altına ekliyorum, dosya ismi killer_smiley.cpp, MS VC++ 'da yazdım, standart dışı işlevler var! Diğer derleyicilerde sorun çıkartabilir.) Güvenlik programının da sırasıyla bütün portları kontrol edip açık aradığını düşünürsek bu işlem sonsuz bir döngü içine konularak daha kolay bir şekilde yapılabilir. Mesela sonsuz bir döngü örneği yazalım:

#include<stdio.h>

int main(void)
{
	unsigned long x;

	for (x=1 ;  ; x++)
		printf("x' in değeri %u
", x);
	printf("Bu satir hic gözükmeyecek!");
}


Çıktısı:



Bu örnekte olduğu gibi sonsuz döngüler kontrolsüzdürler :). Bir de hiç çalışmayan döngüler vardır. Çalışmamanın sebebi de ilk değerin döngü koşuluna uymamasıdır. Örneğin;

#include<stdio.h>

int main(void)
{
int x;

for (x=0 ; x!=0 ; x*=4)
printf("x = %d
", x);

return 0;
}


Gördüğünüz gibi herhangi bir çıktı verilmedi. Yukarıdaki yazı MS VC++ 'ın bir kolaylığıdır. Win32 ortamında DOS programı çalıştırılınca program sonundaki çıktının görülebilmesini sağlar. Artık döngü kontrol deyimlerine geçebiliriz sanırım.

C dilinde iki tane döngü kontrol deyimi vardır. Bunlar döngüyü kesen ve bir sonraki çevrime atlatan break ve continue deyimleridir. Derleyici break ile karşılaştığı yerde hemen döngüyü durdurur ve varsa döngüden sonra gelen ifadeye geçer. Örnek:

#include<stdio.h>

int main(void)
{
	int x;

	for (x=0 ; x!=10 ; ++x)
	{
		printf("x'in degeri: %d
", x);
		if (x==7)
			break;
	}

	return 0;
}


Çıktısı ise şöyle:



Görüldüğü gibi x' in değeri 7' ye eşit olduğu zaman döngüye son verilmiştir. Yalnız for döngüsünün orta kısmında kullanılan x!=10 ifadesinin mantığına dikkat! x'in değeri arttığı için x<10 ile aynı anlama sahip. Bir de bu iki kullanım arasında hız farkı var, o konu için bir önceki makaleme bakabilirsiniz. continue deyimi ise döngüde bir çevrim devam ederken o çevrimde geriye kalan işlemleri bırakıp bir (varsa) sonraki çevrime geçmeye yarar. Sanırım bir örnekle daha iyi açıklayabilirim:

#include<stdio.h>

int main(void)
{
	int x;

	for (x=1 ; x!=10 ; ++x)
	{
		if (x==5)
			continue;
		printf("x'in degeri: %d
", x);
	}

	return 0;
}



Bu kodda ise önce x' in 5 olup olmadığına bakılır. Eğer bu koşul doğruysa değer basılmaz, yani 1,2,3,4,6,7,.. şeklinde gidecek:

Döngülerle ilgili bahsedeceğim son konu ise derleyicilerin en iyileme (optimization) seçenekleriyle ilgili. Derleyicilerin en iyileme seçenekleri genel olarak iki konu üzerinedir. Çalışabilir dosyanın boyutunu azaltma veya hızını artırmadır ki bu ikisi "genelde" ters orantılıdır. Mesela, derleyiciler bazen döngüleri "açarlar". Yani döngünün çalıştıracağı kodları, çalıştırılacakları sayı kadar alt alta yazarlar. Örneğin:

for (x=0 ; x<=3 ; ++x)
printf("Give peace a chance!
John Lennon
");


yerine

printf("Give peace a chance! 
		 John Lennon
");
printf("Give peace a chance! 
		 John Lennon
");
printf("Give peace a chance! 
		 John Lennon
");
printf("Give peace a chance! 
		 John Lennon
");


yazmak gibi. Valla burda çıktıya gerek yok ama gene de ekleyeceğim. Belki "böyyük hökümetimiz" duyar!

(* Barışa bir şans verin!)

Bu çeşit döngüleri açmak programa belli bir hız kazandıracaktır. Ancak bir de çalışabilir dosyanın boyutu meselesi var. Burda sadece 4 çevrimlik bir kodu açtığımızı varsaydık ancak bu bazen daha fazla da olabilir. Bu yüzden programcı bu ikisi arasında bir seçim yapmak zorundadır. Bana kalırsa sabit disk boyutları bellek boyutlarından daha fazla bir ivmeyle genişliyor ve fiyat/boyut oranı da belleklerde hala yüksek. Yani benim tercihim hızdan yana olurdu. Şimdilik benden bu kadar, gelecek makalenin konusu while ve do-while döngüleri olacak. Görüşmek üzere!











Del.icio.us
Digg
Facebook
Furl
Google
Blink
Simpy
Spurl
Y! MyWeb