Bir önceki yazıda for deyiminin temel özelliklerine değinmiştik. Daha önceden belirttiğim gibi bu deyim C ve C++ programlama dillerindeki en önemli deyimlerden biridir. Özellikle C++’da bu deyimden yola çıkarak çeşitli veri yapıları üzerinde kolayca dolaşmayı sağlayan ek özellikler getirilmiştir. Bu bölümde for döngüsünün çeşitli özelliklerini açıklayacak ve son olarak da onunla ilgili çeşitli örnekler yaparak for döngüsü konusunu tamamlayacağız.
İlk olarak for döngüsünün başlık kısmında yer alan bütün kısımlarda çeşitli aritmetik ifadeler kullanılabilir. Şimdiye kadar sadece “++“, “<” ve “<=” gibi operatörlerin kullanımını gördük. Ama bundan daha fazlasını da yapabilirsiniz. Aşağıdaki kod parçasına bakalım:
int sayi = 10;
for(int i = sayi; i <= sayi * 5; i += sayi / 2)
{
printf("%d\n", i);
}
15
20
25
30
35
40
45
50
Gördüğünüz gibi bir sayi değişkeni tanımlayıp onu hem bir başlangıç değeri atarken, hem döngü koşulunda hem de sayaç değişkenini değiştirirken kullanabiliyoruz. Yani for döngüsünün başlık kısmında illaki tanımladığımız sayaç değişkenini kullanacağız diye bir olay yoktur. Bunun yanında koşulda da ilişkisel operatörlerin yanında “*” gibi aritmetik operatörleri de kullanabiliriz. Sayaç değişkenini değiştirme kısmında ise “/” gibi aritmetik operatörleri ve “+=” gibi birleşik atama operatörlerini kullanabiliriz. Yani bunları kullanmamızda herhangi bir sınır yoktur.
for döngüsü ile ilgili bir başka konu ise, sayaç değişkenine sadece arttırma değil azaltma da yapabiliriz. Böylece döngü belli bir sayıdan geriye doğru sayar ve koşul değişkenini de buna göre düzenlememiz gerekir. Hemen bir örnek verelim:
for(int i = 5; i > 0; i--)
{
printf("%d\n", i);
}
4
3
2
1
Yine bir başka göz önüne almamız gereken şey ise, eğer döngü koşulu en başta yanlış olursa, program döngüye girmeden döngüden sonraki ifadeden çalışmaya devam eder. Hemen bir örnek verelim:
printf("for oncesi\n");
for(int i = 6; i < 6; i++)
{
printf("%d\n", i);
}
printf("for sonrasi\n");
for sonrasi
Burada i sayaç değişkenine başlangıç değeri olarak 6 verdikten sonra döngü koşulu kontrol edilmektedir. Koşul ilk anda yanlış olduğundan for döngüsünün gövdesinde yer alan kısım asla çalışmadan bir sonraki deyime geçilir. Bunu bir önceki yazıda verdiğim GIF resminden yola çıkarak da kavrayabilirsiniz.
Döngü için tanımladığımız kontrol değişkeni, döngü gövdesinde sıklıkla kullanılabilir veya direk değeri ekrana basılabilir. Ancak bu bir zorunluluk değildir. Sayaç değişkeni sadece döngünün kaç kez döneceğine karar vermek için kullanılıp döngü içerisinde hiç kullanılmayabilir. Örneğin ekrana 3 defa "Mustafa Yemural" yazdıralım:
for(int i = 0; i < 3; i++)
{
puts("Mustafa Yemural");
}
Mustafa Yemural
Mustafa Yemural
Gördüğünüz gibi sayaç değişkeni döngü gövdesinde kullanılmadan da işlem yapılabilir. for deyimi ile alakalı son bahsedeceğimiz şey ise “for” döngüsünü bir akış şemasında gösterirken tıpkı while döngüsünde yaptığımız gibi çizim yapmalıyız. Örneğin şu kodu akış şemasına dökelim:
for(int i = 0; i <= 5; i++)
{
printf("%d\n", i);
}
Bu saydıklarım aslında for deyimi ile alakalı katı özellikler değildir. Ancak göz önünde bulundurulması gereken önemli bilgilerdir. Son olarak bu özellikleri bir liste şeklinde özet geçelim:
- for döngüsünün başlık kısmında çeşitli aritmatiksel operatörler ve ifadeler kullanılabilir.
- for döngüsünün sayaç değişkenini değiştirme kısmında, sayaç değişkenini arttırma yerine azaltma da yapılabilir. Ancak döngü koşulunun buna göre düzenlenmesi gerektiği unutulmamalıdır.
- Eğer for döngüsünün döngü koşulu kısmı ilk aşamada yanlış gelirse, program for döngüsünün gövdesine girmeden bir sonraki deyimden çalışmaya devam eder.
- for döngüsünün kaç kere döneceğini belirten sayaç değişkeni, döngü gövdesinde sıkça kulanılabileceği gibi hiç kullanılmayabilir.
- for döngsünün akış şemasındaki gösterimi while ile oldukça benzerdir.
Şimdi de for döngüsü ile ilgili çeşitli örnekler yapalım. İlk programımızda 0’dan 16’ya kadar olan sayıların onluk, sekizlik ve onaltılık sistemdeki karşılıklarını güzel bir tabloda listeleyeceğiz. Burada sayı çevrimlerini zaten format belirteçleri halletmektedir. Ancak boşluk formatlarını iyi ayarlamak gerekir:
// Code 4.2.1: Code4_2_1.c
// 0'dan 16'ya kadar olan sayıların belli tabanlarda (8, 10, 16) tabloya dökülmesi
#include <stdio.h>
int main()
{
puts("10'luk | 8'lik | 16'lik");
puts("-----------------------");
for(int i = 0; i <= 16; i++)
{
printf("%6d | %5o | %6X\n", i, i, i);
}
return 0;
}
——————————————————————
1 | 1 | 1
2 | 2 | 2
3 | 3 | 3
4 | 4 | 4
5 | 5 | 5
6 | 6 | 6
7 | 7 | 7
8 | 10 | 8
9 | 11 | 9
10 | 12 | A
11 | 13 | B
12 | 14 | C
13 | 15 | D
14 | 16 | E
15 | 17 | F
16 | 20 | 10
Burada aslında bütün olay 12. satırdadır. “%6d” belirteci ile 6 karakterlik bir boşluk oluşturulup sağa yaslı bir biçimde sayının onluk sistemdeki karşılığı ekrana basılmaktadır. Yine “%5o” ile 5 karakterlik bir boşluk oluşturulup sayı sekizlik tabanda sağa yaslı olarak (bırakılan boşluğun içerisinde) ekrana basılmaktadır. Son olarak da “%6X” ile aynı şekilde 6 karakterlik boşluk bırakılıp sayı onaltılık tabanda sağa yaslı bir biçimde ekrana basılmaktadır. Burada “%X” yerine “%x” de kullanabilirdik. Bunu yaparsak A, B, C gibi onaltılık tabana ait karakterler küçük harf ile ekrana basılacaktı. Buradaki boşluk miktarları tamamen tablonun yukarısında yazanlara göre ayarlanarak belirlenmiştir.
Şimdi de klasik for döngüsü uygulaması olan ekrana üçgen çizme örneğini yapalım. Programlama ile tanışan pek çok öğrenci bu tip örneklerin gereksiz olduğunu ve pratikte hiçbir işe yaramayacağını düşünmektedir. Ancak durum böyle değildir. Özellikle for döngüsü ile yapılan bu tip uygulamalar, ileride karşınıza çıkacak algoritmik problemlere yaklaşımınızı geliştirmektedir. Örneğin bazen bir programda sayaç değişkeninin (veya değişkenlerinin) belli koşullarda kullanılmasını, belli koşullarda da kullanılmamasını isteriz. Bu gibi durumlarda bu tip pratikler faydalı olacaktır.
// Code 4.2.2: Code4_2_2.c
// C'de for döngüsü ile ekrana üçgen çizme
#include <stdio.h>
int main()
{
int secim;
printf("Lutfen seciminizi yapin (0: Duz Ucgen, 1: Ters Ucgen): ");
scanf("%d", &secim);
int alan;
printf("Lutfen cizim alanini birim cinsinden girin: ");
scanf("%d", &alan);
if(secim == 0)
{
// Duz ucgen cizme:
for(int i = 0; i <= alan; i++)
{
for(int j = 0; j <= i; j++)
{
printf("*");
}
printf("\n");
}
}
else if(secim == 1)
{
// Ters ucgen cizme:
for(int i = alan; i >= 0; i--)
{
for(int j = i; j >= 0; j--)
{
printf("*");
}
printf("\n");
}
}
else
{
puts("Hatali secim yaptiniz!");
}
return 0;
}
Lutfen cizim alanini birim cinsinden girin: 5
*
**
***
****
*****
******
Lutfen cizim alanini birim cinsinden girin: 12
************
***********
**********
*********
********
*******
******
*****
****
***
**
*
Bu programda kullanıcıya düz üçgen çizme ve ters üçgen çizme olmak üzere 2 seçenek sunuyoruz. Şekillerin tam olarak neye benzeyeceğini çıktılardan anlayabilirsiniz. Çizilecek olan üçgen türünün yanında bir de kullanıcıdan çizim alanının kaç birim genişlik ve yükeklikte olacağı bilgisini alıp alan değişkenine atıyoruz. Burada bizim için önemli olan 19. satırdaki düz üçgen çizen for döngüsü ve 31. satırdaki ters üçgen çizen for döngüsüdür.
Üçgen bildiğiniz gibi 2 boyutlu bir şekildir. Tek boyutlu bir hattı taramak için tek bir for döngüsü yeterli iken, 2 boyutlu bir alanı taramak için iç içe 2 for döngüsü kullanmak gerekir. Çünkü ilk for döngüsü ile satırları dolaşıp ikinci for döngüsü ile bu satırların hangi sütununda yıldız (*) olacağını belirlememiz gerekir. 19. satırdan başlayalım. Burada 0’dan girdiğimiz alan değerine kadar dönen bir “for” döngüsü görmekteyiz. 21. satırda içte bulunan for döngüsü ise 0’dan o anki adım sayısına kadar dönmektedir. Bunu yapmamızın sebebi her seferinde i değişkeni 1 arttığında bu artışa göre ekrana yıldız basmak istememizden kaynaklanmaktadır. Yıldız basma işini 23. satırda yapıyoruz. İçerideki for döngüsünden çıktığımızda ise alt satırdan çizime devam etmek için 25. satırda bir alt satıra iniyoruz. Bu bu şekilde devam ediyor ve sonunda ortaya bir dik üçgen çıkartıyoruz.
Düz üçgen çizme olayı nispeten anlaması oldukça kolay olsa da ters üçgen çizmede biraz daha akıl yürütmek gerekir. Öncelikle 31. satırda tanımladığımız for döngüsünde i sayaç değişkenini önce alan değişkenine eşitleyip değerini her turda azaltarak 0’a yaklaşmasını istiyoruz. Bunu yapmamızın sebebi bu sefer üçgeni tabanından itibaren çizmeye başlayacağımızdan, içerideki for döngüsünde i sayaç değişkenini o anki değerini kullandığımızda en yüksekten en düşüğe doğru olmasını sağlamaktır. Böylelikle örneğin alan değişkenine 9 değerini atadığımızda i değişkeni de 9’dan başlayıp her turda 1 azalarak en son 1’e gelecektir.
Dıştaki for döngüsünün mantığını anlattığımıza göre sıra geldi içteki for” döngüsüne… 33. satırda öncelikle Bu çubuk grafiği biraz ilkel olsa da en azından işlevini yerine getirmektedir. Kullanıcıdan 3 adet miktar bilgisi alıp bunu “aSayisi”, “bSayisi” ve “cSayisi” değişkenlerine atıyoruz. Burada verdiğimiz sayılar frekans (sıklık) bilgisini içermekte ve o değere ait grafikteki yıldız sayısını belirtmektedir. Bu değerleri bir çubuk grafiğine basmak için 3 adet “for” döngüsü kullanıyoruz. Bu döngülerin aralarına da çeşitli görselleştirmeler katması amacıyla String’ler yerleştiriyoruz. Böylelikle girdiğimiz sayıları ilkel bir çubuk grafiğinde gösteren bir program karşımıza çıkıyor.j sayaç değişkenini o andaki i değişkenine eşitliyoruz. Her seferinde i değeri azaldığından bu döngüye her girişte de daha küçük bir j değeri ile karşılaşırız. Bu for döngüsü tamamen yıldızları çizmek içindir. Buradan çıkınca yine satır atlamayı unutmuyoruz. Böylelikle for döngüsü kullanarak en azından düz ve onun X eksenine göre simetriği olan bir üçgenin nasıl çizilebileceğini görmüş olduk. for döngüsü ile bunun gibi çok farklı çizimler yapılabilir. Örneğin siz de bu üçgenlerin Y eksenine göre simetrilerini çizebilirsiniz.
Şimdi de başka bir for döngüsü örneğine gelelim. Burada yine bir çizim yapacağız. Ama bu biraz daha kullanışlı olacak. İstatistikte Çubuk Grafiği (Bar Chart) adı verilen grafiği duymuşsunuzdur. Şöyle bir örnek vereyim:
Gördüğünüz gibi bir çubuk grafiği aslında bir varlığın sayısının ne kadar olduğunu gösteren ve diğer varlıkların sayısı ile görsel olarak kıyasalama yapmaya izin veren bir tür grafiktir. Bu grafik yatay veya dikey çiizlebilir. Biz burada resmini de verdiğim yatay çizimi tercih edeceğiz. Öncelikle örnek kodumuza ve çıktımıza bakalım:
// Code 4.2.3: Code4_2_3.c
// C'de for döngüsü ile yatay çubuk grafiği çizimi
#include <stdio.h>
int main()
{
int aSayisi;
int bSayisi;
int cSayisi;
printf("A miktarini girin: ");
scanf("%d", &aSayisi);
printf("B miktarini girin: ");
scanf("%d", &bSayisi);
printf("C miktarini girin: ");
scanf("%d", &cSayisi);
printf("--\nA|");
for(int j = 0; j < aSayisi; j++)
{
printf("*");
}
printf("\n--\nB|");
for(int j = 0; j < bSayisi; j++)
{
printf("*");
}
printf("\n--\nC|");
for(int j = 0; j < cSayisi; j++)
{
printf("*");
}
printf("\n--\n");
return 0;
}
B miktarini girin: 12
C miktarini girin: 4
—
A|*******
—
B|************
—
C|****
—
Bu çubuk grafiği biraz ilkel olsa da en azından işlevini yerine getirmektedir. Kullanıcıdan 3 adet miktar bilgisi alıp bunu aSayisi, “bSayisi ve cSayisi değişkenlerine atıyoruz. Burada verdiğimiz sayılar frekans (sıklık) bilgisini içermekte ve o değere ait grafikteki yıldız sayısını belirtmektedir. Bu değerleri bir çubuk grafiğine basmak için 3 adet for döngüsü kullanıyoruz. Bu döngülerin aralarına da çeşitli görselleştirmeler katması amacıyla String’ler yerleştiriyoruz. Böylelikle girdiğimiz sayıları ilkel bir çubuk grafiğinde gösteren bir program karşımıza çıkıyor.
Bu arada her döngüde sayaç değişkeni olarak j isimli bir değişken tanımladık. Normalde aynı blok içerisinde aynı isimde birden fazla değişken tanımlanamaz. Ama bu şekilde bir tanım aslında o değişkeni for döngüsü bloğu içine alır ve bu döngünün dışında bu değişkenin görülmesini engeller. for döngüsü sonlandığında da değişken bellekten silinir. Bu şekilde aynı isimde değişkeni diğer for döngülerinde de rahatlıkla kullanabiliriz. Bu arada uygulamalarda genellikle döngülerin sayaç değişkeni olarak i, j, k gibi harfler kullanılır. Bu bir zorunluluk olmasa da programcılar açısından bir kültür oluşmuştur. Bunu da aklınızda bulundurun.
Bu bölümde C’de çok önemli bir yere sahip olan for döngüsünün çeşitli özelliklerini ve örneklerini gördük. for döngüsü ile ilgili konuşacak çok önemli bir şeyimizin artık kalmadığını düşünüyorum. Bu bölümün sonraki yazılarında da switch ve do…while gibi kullanım sıklığı biraz daha az, fakat yeri geldiğinde oldukça kullanışlı olan deyimlerden bahsedip bölümü kapatacağım.




