Seçme Komutları

Seçme komutları kapsamında değerlendirilen komutlar ifelseswitchcase, ve default komutlarıdır.

Öncelikle tüm komutlar bir ifadenin doğruluğunu yanlışlığını test edeceği için doğru ve yanlış kavramlarını tekrar hatırlayalım: C'de 0 değeri yanlış 0'ın dışındaki değerler doğru kabul edilir.


if, else

İlk önce if komutunun yapısına bakalım. Bu komut else ile birlikte şöyle kullanılır:

if (ifade) 
kod1
else 
kod2

Burada önce ifadenin doğruluğu yanlışlığı kontrol edilir. Eğer ifade doğruysa kod1 çalıştırılır, diğer durumlarda kod2 çalıştırılır. else komutunu ve sonraki kodu koyup koymamak isteğe bağlıdır. Eğer else komutu eklenmezse ifadenin yanlış olması durumunda hiçbir işlem yapılmaz.

#include <stdio.h>

int main(void){
    printf("Enter a value for a\n");
    int a;
    scanf("%d",&a);
    if(a>0)
        printf("a is positive");
    else
        printf("a is negative");
    return 0;
}

Kodu incelemeden önce scanf fonksiyonuna kısaca değinelim. scanf fonksiyonu kullanıcının klavye ile veri girmesini ister ve bu şekilde bir değişkene kullanıcının istediği değer atanabilir.

Yukarıdaki kod "a>0" ifadesini kontrol edecek ve bu ifade doğru olduğu zaman "a is positive" ifadesini  yanlış olduğu zamansa "a is negative" ifadesini yazdıracaktır. Kod çalıştırılıp a'ya 1 ve -1 değerleri verilerek  bu durum gözlenebilir. Fakat bu kodda a'ya değer olarak 0 atanırsa bu durumda da "a is negative" ifadesi belirecektir. Bu durumu düzeltmek için bir if komutu daha ekleyerek bir deneme yapalım:

#include <stdio.h>

int main(void){
    printf("Enter a value for a\n");
    int a;
    scanf("%d",&a);
    if(a>0)
        printf("a is positive");
    if(a==0)
        printf("a is zero");
    else
        printf("a is negative");
    return 0;
}

Bu kod hatalıdır ve a'nın pozitif değerleri için istediğimiz sonucu vermeyecektir. Elde ettiğimiz sonuç şu olacaktır:

a is positivea is negative

Bunun sebebi şudur: yukarıdaki kod a'nın pozitif, 0 veya negatif olması gibi üç durum için seçim yapmayı sağlamamaktadır. else komutu sadece bloğu içindeki en yakın if'e bağlanır. Bu kod şunu söylemiştir:

1) "a > 0" ifadesini kontrol et. Doğruysa "a is positive" yazdır. Yanlış olması durumu için bir talimat verilmemiştir. a'ya pozitif değer verilmesi durumunda bu ifade doğru olduğu için "a is positive" yazdırılır. 
2) "a == 0" ifadesini kontrol et. Doğruysa "a is zero"  yanlışsa "a is negative" yazdır. a'nın pozitif değerleri için "a == 0" ifadesi yanlış olduğu için "a is negative" ifadesi belirmiştir.

Üç durum arasında seçme yapmak için ilk if için bir else konulmalı ve bu else içine de bir if-else ikilisi yerleştirilmelidir:

#include <stdio.h>

int main(void){
    printf("Enter a value for a\n");
    int a;
    scanf("%d",&a);
    if(a>0)
        printf("a is positive");
    else if(a==0)
        printf("a is zero");
    else
        printf("a is negative");
    return 0;
}

Yukarıdaki kod doğru sonuç verecektir. Çünkü bu kod şunları söylemiştir:

1) "a > 0" ifadesini kontrol et. Doğruysa "a is positive" yazdır. Yanlış olması durumu için aşağıdaki talimatları izle. 
2) "a == 0" ifadesini kontrol et. Doğruysa "a is zero" yazdır. Yanlışsa "a is negative" yazdır.

Böylece üç farklı durum birbirinden ayrılmıştır.

Ayrıca şunu da belirtmekte fayda var. Eğer if veya else komutlarının çalıştırması istenen kod bir satırdan fazla ise kod parçası blok içine alınmalıdır. Aksi takdirde ikinci satır if işleminden bağımsız olarak çalışacaktır. Daha iyi anlamak için aşağıdaki iki örneğin farkını inceleyebilirsiniz:

#include <stdio.h>

int main(void){
    printf("Enter a value for a\n");
    int a;
    scanf("%d",&a);
    if(a>0)
        printf("a is positive");
        printf("and it is %d",a);
    return 0;
}

#include <stdio.h>

int main(void){
    printf("Enter a value for a\n");
    int a;
    scanf("%d",&a);
    if(a>0){
        printf("a is positive");
        printf("and it is %d",a);
    }
    return 0;
}

Üstteki kodda "a > 0" ifadesi yanlış olsa bile ikinci printf çalıştırılacaktır. Çünkü o satır if'den bağımsız olarak çalışmaktadır. Alttaki kodda ise her iki printf de if'e bağlıdır. Kod tek satır olduğu zaman tırnaklı parantezler kullanarak blok oluşturmanın ise olumsuz bir yanı yoktur. Bu nedenle bu komutlardan sonra her zaman tırnaklı parantezler kullanılabilir.

if ve else bahsini kapatmadan önce son bir detay verelim. Daha önceki örneklerimizden birinde "if(a==1)" gibi bir ifadenin biraz amatörce göründüğünü söylemiştik. Bazı durumlarda mantıksal veya ilişkisel işlem oluşturmak gerçekten de biraz amatörce olmaktadır. Misalen 1000 sayısını verilen bir sayıya bölme kodu yazdığımızı düşünelim:

#include <stdio.h>

int main(void){
    printf("Enter a value for a\n");
    int a;
    scanf("%d",&a);
    if(a!=0)
        printf("%d",1000/a);
    else
        printf("Undefined");
    return 0;
}

Yukarıdaki kodda 0'a bölme işlemini engellemek için "a!=0" ifadesini içeren bir if komutu yazılmıştır. Peki bu gerçekten gerekli midir? a'nın 0 olmadığı her durumda "a!=0" ifadesi doğru olacaktır. Fakat a'nın 0'a eşit olmadığı her durumda a ifadesi tek başına da zaten her zaman doğru olacaktır. Hatırlarsanız C'de 0 dışındaki değerlerin doğru kabul edildiğini söylemiştik. Bu nedenle aşağıdaki kod daha kısa ve daha az işlem yaptırmaktadır:

#include <stdio.h>

int main(void){
    printf("Enter a value for a\n");
    int a;
    scanf("%d",&a);
    if(a)
        printf("%d",1000/a);
    else
        printf("Undefined");
    return 0;
}

switch, case, default

Bu komutlar kullanılarak oluşturulan bir ifade genel hatlarıyla şöyledir:

switch(ifade){
case sabit1:
kod1
case sabit2:
kod2
default:
kod3
}

Burada yazılacak ifade karakter veya tam sayı değeri oluşturmalıdır. Eğer karakter oluşturuyorsa bu değer otomatik olarak sayıya dönüştürülür. case kısımlarındaki sabitlerin ifadeye eşit olup olmadığı sırayla kontrol edilir ve eşit olan case'den sonraki tüm case komutlarının altındaki kod parçaları çalıştırılır. default'tan sonraki kod parçası ise sabitlerden birisi ifadeye eşit olsa da olmasa da çalıştırılır. default komutunu ekleyip eklememek isteğe bağlıdır.

#include <stdio.h>

int main(void){
    int a=8;
    switch(a){
        case 4:
        printf("4\n");
        case 8:
        printf("8\n");
        case 6:   
        printf("6\n");
        default:    
        printf("Shark");
    }
    return 0;
}

Yukarıdaki kodda "case 8:", "case 6:" ve "default" komutlarının altındaki kodlar çalıştırılır. if komutundan farklı olarak herhangi bir case içine blok olmaksızın istenen satırda kod yazılabilir. Tüm satırlar üstündeki case komutuna bağlı olacaktır. Aynı durum default için de geçerlidir.

switch komutunun if komutundan farkı sadece bir değere eşit olma durumunu kontrol edebilmesidir. switch komutunda if komutunda olduğu gibi ilişkisel veya mantıksal şartlar denetlenemez.

switch-case yapılarında iki case birden aynı değere sahip olamaz. Bu durumun gerçekleştirilebilmesi ancak iç içe iki switch-case yapısı kullanıldığında mümkündür. Aşağıdaki iki kod örnek olarak incelenebilir:

#include <stdio.h>

int main(void){
    int a=8;
    switch(a){
        case 0:
        printf("Zero\n");
        case 0:
        printf("0\n");
        case 1:   
        printf("One");
    }
    return 0;
}

#include <stdio.h>

int main(void){
    int a=0;
    int b=1;
    switch(a){
        case 0:
        switch(b){
            case 0:
            printf("Zero\n");
            case 1:   
            printf("One\n");
        }
        case 5:    
        printf("None");
    }
    return 0;
}

Yukarıdaki kodlardan ilki hata verecektir. Fakat alttaki, iki case komutunda birden 0 değeri olmasına rağmen düzgün şekilde çalışacaktır.

switch-case yapısında case komutlarından istenenlerin altı boş bırakılabilir. Bu durumda eğer o case komutundaki sabitin değeri istenen ifadeye eşitse alttaki tüm case komutlarının altındaki kod parçalarının çalışması sağlanmış olur.

Sıçrama komutları konusunda gösterilecek olan break komutundan sonra switch-case yapılarının daha anlamlı hale geleceği de söylenebilir.