Categories: C

C Programlama Dersi – 5

Selam,

Kaldığım yerden eğitimime devam ediyorum. Bugün öğrenmeye çalışacağım konu, döngüler ve break ve continue. break‘i geçen derste hafif öğrenmiştim zaten. C programlama dilinde kullanılan birden fazla döngü var:

  • for
  • while
  • do while

Döngüler, adından da anlaşıldığı gibi belirli komutları tekrar tekrar çalıştırmamızı sağlar. Tabii ki belirli koşulları sağladığı sürece… Ne zaman, ne kadar, nasıl, niçin olacağını belirleyip, kontrol edebiliyoruz.

for döngüsü

for(başlangıç değeri; koşul; arttırma / azaltma) 
{ 
   //koşul sağlandıkça çalışacak kodlar
}

Yukarıda for döngüsünün genel yapısı var. Daha açıklayıcı olması için hemen basit bir örnek yapalım:

#include <stdlib.h>
#include <stdio.h>
int main(void)  
{
    int i;
    for (i=0; i<5; i++)
    {
        printf("Selamn");
    }
    return 0;
}

Örnekteki  kodlar çalıştığı zaman ekrana 5 kere “Selam” yazılacak. for döngüsünün çalışma mantığı c4learn‘deki resimle daha iyi anlaşılabilir.

  1. İlk olarak 1 nolu işlem gerçekleşiyor. Yani, i değişkenine 0 değeri başlangıç olarak verildi.
  2. 2. adımda koşul kontrol ediliyor. i’nin değeri 5’ten küçük mü?
  3. Koşul doğru olduğu için 3. adıma geçtik. Yani kodlarımız çalışacak ve ekrana “Hello” yazılacak.
  4. Kodlarımızın çalışması bitince 4. adıma geçiyoruz. i’nin değerini 1 attırıyoruz. i=1 oldu.
  5. 5. adımda tekrar koşulumuzu kontrol ediyoruz. i’nin değeri 5’ten küçük mü? Koşul doğru olduğu için 3. adıma geçiyoruz.
  6. 3. adımda tekrar kodlarımız çalışıyor ve ekrana “Hello” yazılıyor.
  7. Bu şekilde koşul doğru oldukça 3., 4. ve 5. adımlar tekrar ediliyor.
  8. i’nin değeri 5’e ulaştığı zaman, koşulumuz artık doğru olmayacağı için döngümüz sonlanacak.

Basitçe bir for döngüsü bu şekilde işliyor. Şimdi de basit bir faktöriyel hesabı yapan programı for döngüsüyle yapalım:

#include <stdlib.h>
#include <stdio.h>
int main(void)  
{
    int faktoriyel, i, sonuc = 1; 

    faktoriyel = 5;
    for(i = 1; i <= faktoriyel; i++)
    {
        sonuc *= i;
        printf("%d!: %dn",i, sonuc);
    }
    return 0;
}

Çıktı:

1!: 1
2!: 2
3!: 6
4!: 24
5!: 120

Basit bir faktöriyel hesabı bu şekilde oluyor. sonuc değişkeninin ilk değeri 1 çünkü faktöriyel hesaplaması 1’den başlar. Eğer ilk değer ataması yapmazsak, int veri tipinin varsayılan değeri 0 olduğu için, ilk değer 0 alınırdı ve sonuç hep 0 olurdu. Aynı şekilde, i değişkeni de 1’den başlayarak faktöriyeli bulunacak sayıya kadar birer birer artıyor.

Yukarıdaki faktöriyel hesabını farklı bir şekilde daha yapabiliriz. Yukarıda, 1’den başlayarak 5’e kadar olan sayıları çarpmıştık. Bu örnekte 5’ten başlayarak 1’e kadar sayıları çarpalım:

for ( i = faktoriyel; i>=1; i--)
{
   sonuc *= i;
   printf("i: %d, sonuc: %dn", i, sonuc);
}

Çıktı:

i: 5, sonuc: 5
i: 4, sonuc: 20
i: 3, sonuc: 60
i: 2, sonuc: 120
i: 1, sonuc: 120

Şimdi bu zamana kadar öğrendiğim tüm bilgilerle faktöriyel hesabı yapan bir program yazmayı deniyorum. Programın amacı kullanıcıdan bir sayı alacak ve bu sayının faktöriyel değerini hesaplayacak. Bu arada negatif sayıların faktöriyel değerleri hesaplanmıyor ve 0!’in sonucu 1’e eşit.

#include <stdlib.h>
#include <stdio.h>
int main(void)  
{
    int sayi, i;
    unsigned long  int faktoriyel = 1; //sonuç negatif olamayacağı için sadece pozitif sayıları tutan veri tipini kullandım
    
    printf("Lütfen, faktoriyeli hesaplanacak sayıyı girin: ");
    scanf("%d", &sayi);
    
    if(sayi < 0) //girilen sayı negatifse
    {
        printf("Negatif sayıların faktöriyeli hesaplanamıyor.");
    }
    else if( (sayi == 0) || (sayi == 1) ) //girilen sayı 0 ya da 1 ise sonuç 1'e eşit olacak.
    {
        printf("%d!: 1", sayi);
    }
    else // 0 veya 1 haricinde girilen pozitif sayılar için hesaplama
    {
        for ( i = 2; i<=sayi; i++)
        {
            faktoriyel *= i;
        }
            printf("%d!: %lun", sayi, faktoriyel);
    }
    return 0;
}

Şöyle de biraz fantezi yapabiliriz 🙂

#include <stdlib.h>
#include <stdio.h>
int main(void)  
{
    int sayi, i;
    unsigned long  int faktoriyel = 1; //sonuç negatif olamayacağı için sadece pozitif sayıları tutan veri tipini kullandım
    
    printf("Lütfen, faktoriyeli hesaplanacak sayıyı girin: ");
    scanf("%d", &sayi);
    
    if(sayi < 0) //girilen sayı negatifse uyarı verecek
    {
        printf("Negatif sayıların faktöriyeli hesaplanamıyor.");
    }
    else //pozitif sayılar için işleme devam
    {
        switch(sayi)
        {
            // 0 ve 1 için sonuç 1 olacaktır.
            case 0:
            case 1:
                printf("%d!: 1n", sayi);
                break;
            // 0 ve 1 haricindeki değerler için hesap yapmalıyız
            default: 
                for ( i = 2; i<=sayi; i++)
                {
                    faktoriyel *= i;
                }
                printf("%d!: %lun", sayi, faktoriyel);
        }
    }
    return 0;
}

for döngüsü bu kadar değil tabii ki. Farklı şekillerde yazılmış birçok for döngüsü oluşturulabilir. c4learn üzerinde 8 farklı şekilde yazılmış for döngüsü mevcut. Kullanım senaryoları, en sık yapılan hatalar da açıklanmış. İçlerinden birini burada da paylaşıyorum.

for (i=0,j=90; i<100 && j>60; i++,j--)

Görüldüğü üzere başlangıç  değerleri, koşullar, arttırma / azaltma birden fazla değişken ile yapılabiliyor.

while

İlk olarak while‘ın genel yapısına göz atalım:

while(//koşul)
{
   //komutlar
}

while döngüsünde  koşulumuzun doğru olup olmadığı girişte kontrol ediliyor. Eğer doğruysa döngü çalışacak. Koşulun yanlış olması durumda ise döngüye hiç giriş yapılmaz.

while(1)
    {
        puts("Bu döngü sonsuza kadar gidiyor...");
    }

Örneğin yukarıdaki döngümüz sonsuza kadar devam edecektir. Çünkü koşulumuz 0’dan farklı olduğu için her zaman doğru demektir. c4learn‘de while ile düşülen sonsuz döngülere örnekler verilmiş. Basit ama gözden kaçan hatalar her zaman olabilir. Dikkat etmek gerek. Şimdi de while ile ilgili bir örnek yapalım:

#include <stdlib.h>
#include <stdio.h>
int main(void)  
{
    int sayi, sayac = 0;
    
    printf("Lütfen bir değer girin: ");
    scanf("%d", &sayi);
    printf("<<< 0 - %d arasındaki çift sayılar >>>", sayi);
    while (sayac <= sayi) //girilen sayıdan küçük ve eşit oldukça döngü devam edecek
    {
        if( (sayac % 2) == 0) //sayac değerinin 2 ile bölümünden kalan 0 ise o anki sayac değeri çift sayı demektir
        {
           printf("n%d", sayac); //o anki sayac değerini ekrana yazdırıyorum
        }
        sayac++; //sayac değerini 1 arttırıyorum
    }
    return 0;
}

5 değerini girdiğimizde elde ettiğimiz çıktı:

Lütfen bir değer girin: 5
<<< 0 - 5 arasındaki çift sayılar >>>
0
2
4

 do while

while ile hemen hemen aynı ama arasında ufak bir fark var. while, girişte koşulu kontrol ediyordu. do while ise çıkışta koşulu kontrol ediyor. Yani bu demektir ki, koşul doğru ya da yanlış olsun, döngü en az 1 kere çalışacaktır.

do while‘ın genel yapısı:

do 
{
   //komutlar
} while( //koşul);

Basit bir örnekle başlıyorum:

#include <stdlib.h>
#include <stdio.h>

#define TRUE 1
#define FALSE 0

int main(void)  
{
    do
    {
        puts("Selam");
    } while(FALSE);
    
    return 0;
}

Yukarıdaki örnekte koşul yanlış olmasına karşın ekrana bir kere “Selam” yazılacaktır. Çünkü önce kod blokları ( { } ) arasındaki komutlar çalışacak, daha sonra while içindeki koşul kontrol edilecektir. Koşul yanlış olduğu için döngü sonlanacaktır.

Daha iyi anlamak için basit bir kullanıcı adı ve şifre kontrolü yapan program yazıyorum:

#include <stdlib.h>
#include <stdio.h>

int main(void)  
{
    int kullaniciAdi = 123, sifre = 123, girilenKullaniciAdi, girilenSifre;
    do
    {
        printf("nKullanıcı adınızı girin: ");
        scanf("%d", &girilenKullaniciAdi);
        printf("nSifreyi girin: ");
        scanf("%d", &girilenSifre);
    } while( !( (kullaniciAdi == girilenKullaniciAdi) && (sifre == girilenSifre) ) );
    
    return 0;
}

Program çalışmaya başladığı zaman, ilk olarak kullanıcı adı ve şifre girilmesini istiyor. while içinde, girilen değerleri mevcut değerler ile karşılaştırıyor.

13. satırda koşulu kontrol ediyoruz. Hem kullanıcı adının hem de şifrenin doğru olması gerek. Her ikisinin de doğru olduğunu varsayarsak (1 && 1) = 1 olacağından, döngü devam edecektir. Bunu önlemek için koşulun başına ! ekleyerek döngüden çıkmasını sağlıyorum.

Kullanıcı adı ya da şifreden birisi yanlışsa, ya da ikisi de yanlışsa (1 && 0) = 0 ya da (0 && 0) = 0 yapacağı için koşulun başındaki ! ile koşulları tekrar 1 yaparak döngüye devam ediyoruz.

break ve continue

break

break‘i, önceki derste switch ile beraber görmüştüm zaten. Komutları sonlandırmaya yarıyordu. Evet, break‘in işi bu. Bir şeyleri sonlandırmak. Mesela döngümüz 1453 kere daha dönecek ama istisnai bir durum olduğu için o anda döngüden çıkmamız lazım. Bu durumda break devreye giriyor. Şöyle ki:

int sayac = 0;
    
    while(sayac < 100)
    {
        printf("sayaç değeri: %dn", sayac);
        if(sayac == 5)
        {
            printf("sayaç %d olduğu için döngü sonlandı.", sayac);
            break;
        } 
        sayac++;
    }

Çıktı:

sayaç değeri: 0
sayaç değeri: 1
sayaç değeri: 2
sayaç değeri: 3
sayaç değeri: 4
sayaç değeri: 5
sayaç 5 olduğu için döngü sonlandı.

Döngü için koşul, sayacın 100’den küçük olduğu durumlarda devam etmesiydi ama 6. satırdaki koşulda sayacın 5’e eşit olması durumda break komutu devreye girdi ve döngüden tamamen çıkıldı.

continue

continue, break ile benzer ama biraz daha insaflı hali. break, döngüyü tamamen sonlandırıyordu. continue ise, belirlediğimiz komutları işleme sokmadan döngüye devam ediyor. Şöyle ki:

int sayac = 0;
    
    while(sayac < 15)
    {  
        sayac++;
        if( (sayac % 5) == 0)
        {
            continue;
        }
        else
        {
            printf("%d-", sayac);
        }
    }

Çıktı:

1-2-3-4-6-7-8-9-11-12-13-14-

Yukarıdaki örnekte sayac değerinin 5 ile bölümünden kalan değer 0 ise, continue komutu devreye giriyor ve böylece else içindeki komutlar çalışmıyor.

break ve continue komutlarını açıklayan görsellerle bugünkü dersimi noktalıyorum. Kaynağım yine c4learn

break için görseller

do while

İç içe for döngüsü

for döngüsü

 

while döngüsü

 

continue için görseller

for

while

do while

Özet

  • döngü koşullarını belirlerken dikkat et. bazen sonsuz döngülere düşebilirsin.
  • while, girişte koşulu kontrol ederken do while, çıkışta koşulu kontrol eder. yani do while, koşul ister doğru ister yanlış olsun en az 1 kere çalışır.
  • break içinde bulunduğu döngüyü kırıp çıkar.
  • continue belirlenen komutları atlayıp, döngüye devam eder.

 

Son olarak şu hatırlatmayı tekrar yapmak istiyorum. Bu web sitesinde öğrendiklerimi geliştirmek için çalışıyorum. Eğer hatalı ya da eksik bir şeyler fark ederseniz lütfen bana bildirin.

Çalışma Soruları

Senaryo1: 1/x^2 + 3/x^4 + 5/x^6 +  7/x^8 +⋯+ (2n-1)/x^2n serisini hesaplayan program. n değeri pozitif tam sayı ve x reel sayı olacak. (n=3 ve x=1 için sonuç 9 0lmalı)

Senaryo2: Bir okyanusta 1044 tane kelebek balığı, 4544 tane palyaço balığı vardır. 1 yılda kelebek balıkları %5.71, palyoça balıkları 1.07 oranında çoğalıyor. Kaç yıl sonra kelebek balıklarının, palyaço balıklarının sayısını geçeceğini hesaplayan program.

Eğitimim için kullandığım örnekleri bu adresteki github reposunda saklıyorum. Ders başlığıyla eşit olan klasörde kaynak kodları bulabilirsiniz.

Senaryo 1

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

int main(int argc, char** argv) {

    int n;
    float x;

    do {
        puts("Enter positive number for n: ");
        scanf("%d", &n);
    } while (n <= 0);
    
    puts("Enter reel number for x: ");
    scanf("%f", &x);

    int count;
    float result = 0;
    
    for (count = 1; count <= (2 * n) - 1; count += 2) {
        result += count / pow(x, count * 2);
        //pow(n,m) fonksiyonu bir sayının(n) kuvvetini(m) bulur.
        //math.h kütüphanesini eklemeyi unutma.
        //pow(n,m) returns n raised to the power of m.
        //don't forget to add math.h library.
    }

    printf("Result: %f", result);
    return (EXIT_SUCCESS);
}

 Senaryo 2

#include <stdio.h>
#include <stdlib.h>

#define CHELMON_INC (5.71 / 100)
#define ANEMON_INC  (1.07 /100)
int main(int argc, char** argv) {

    int chelmonFish = 1042, anemonFish = 4544; 
    int year = 0;
    
    while(chelmonFish < anemonFish) {
        chelmonFish += chelmonFish * CHELMON_INC;
        anemonFish += anemonFish * ANEMON_INC;
        year++;
        printf("%d year laters, chelmons: %d, anemons: %dn", year, chelmonFish, anemonFish);
    }
    return (EXIT_SUCCESS);
}

 Eğer yanlış ya da düzeltilmesi gereken bir nokta farkettiyseniz, lütfen bana bildirin.

Share
Published by
yusufkaracin

Recent Posts

Celery Checklist [Python]

Celery ile alakalı "best practice"leri ve faydalı araçları bir araya getiren güzel bir checklist'e denk…

5 yıl ago

JavaScript Dizileri için 13 İpucu

Diziler en temel ve sık kullandığımız araçlardan... Kod yazarken işimizi kolaylaştıracak, daha temiz kod yazmamızı…

5 yıl ago

List & Tuple Mini Test (Python)

listve tuple bilginizi test etmek ister misiniz? realpython.com da keşfettiğim ve Türkçe'ye çevirdiğim mini teste…

5 yıl ago

Bilmeniz Gereken 11 Python Mülakat Sorusu

Rehberlik sağlaması ve bilgi tazelemesi açısından faydalı olduğunu düşündüğüm bir Toptal blog paylaşımınıTürkçe'ye çevirdim.Devamını okuyunBilmeniz…

5 yıl ago

Angular Componentlere Konsol Üzerinden Hızlı Erişim

Angular componentlerine console üzerinden hızlıca erişmek için kullanılan bir teknik. Unutmamak için kendime not düşüyorum.Devamını…

5 yıl ago

Birkaç Güzel JavaScript Sorusu İster Miydiniz?

Geçtiğimiz günlerde keşfettiğim ve oldukça da hoşuma giden repoyu paylaşmak istiyorum: lydiahallie/javascript-questions Genel olarak temel…

5 yıl ago