← Kursa Dön
📄 Text · 12 min

if-else ve Koşullu Operatör

Programlar her zaman düz bir çizgide ilerlemez. Bazen bir yol ayrımına gelirsin: "Kullanıcı doğru şifreyi girdi mi? Evet ise giriş yap, hayır ise hata göster." İşte if-else yapısı tam olarak bu yol ayrımlarını yönetir.

Bir trafik ışığı düşün. Yeşilse geç, kırmızıysa dur, sarıysa yavaşla. Programlama da aynı mantıkla çalışır — koşullara bakarsın ve ona göre bir yol seçersin. Bu derste C++'ta karar verme mekanizmalarının tamamını öğreneceksin.


if Yapısı — En Temel Karar

if ifadesi, bir koşulun doğru (true) olup olmadığını kontrol eder. Koşul doğruysa süslü parantez içindeki kod çalışır. Değilse o blok tamamen atlanır.

#include <iostream>
using namespace std;

int main() {
    int sicaklik = 35;

    if (sicaklik > 30) {
        cout << "Hava çok sıcak, bol su iç!" << endl;
    }

    cout << "Program devam ediyor." << endl;
    return 0;
}

Burada sicaklik > 30 koşulu doğru olduğu için mesaj ekrana yazdırılır. Eğer sicaklik değeri 25 olsaydı, if bloğunun içi atlanacak ve direkt "Program devam ediyor." yazacaktı.

Koşul İfadesi Ne Döndürür?

C++'ta koşullar her zaman bool tipinde değerlendirilir — ya true ya false. Karşılaştırma operatörlerini hatırlayalım:

OperatörAnlamÖrnek
==Eşit mix == 5
!=Eşit değil mix != 0
<Küçük müx < 10
>Büyük müx > 3
<=Küçük eşit mix <= 100
>=Büyük eşit mix >= 18

⚠️ Dikkat: = ile == karıştırma! Tek = atama yapar, çift == karşılaştırma yapar. if (x = 5) yazmak x'e 5 atar ve her zaman true döner — bu çok yaygın bir hatadır.


if-else — İki Yollu Karar

Bazen "koşul doğru değilse şunu yap" demek istersin. İşte else bunun için var.

#include <iostream>
using namespace std;

int main() {
    int yas = 16;

    if (yas >= 18) {
        cout << "Ehliyet alabilirsiniz." << endl;
    } else {
        cout << "Ehliyet için yaşınız yetmiyor." << endl;
    }

    return 0;
}

if ve else birbirini tamamlar. Koşul doğruysa if bloğu çalışır, değilse else bloğu çalışır. İkisi aynı anda asla çalışmaz.

Bu yapıyı günlük hayattan şöyle düşün: "Yağmur yağıyorsa şemsiye al, yağmıyorsa güneş gözlüğü tak." İki seçenek var ve birini mutlaka seçiyorsun.


else if — Çoklu Karar Zinciri

Bazen iki seçenek yetmez. Not hesaplama, fiyat kategorisi belirleme gibi durumlar birden fazla koşul gerektirir. İşte else if ile zincirleme koşullar yazabilirsin.

#include <iostream>
using namespace std;

int main() {
    int puan = 73;

    if (puan >= 90) {
        cout << "Not: A" << endl;
    } else if (puan >= 80) {
        cout << "Not: B" << endl;
    } else if (puan >= 70) {
        cout << "Not: C" << endl;
    } else if (puan >= 60) {
        cout << "Not: D" << endl;
    } else {
        cout << "Not: F (Kaldı)" << endl;
    }

    return 0;
}

Burada dikkat edilmesi gereken önemli bir nokta var: koşullar yukarıdan aşağıya sırayla kontrol edilir ve ilk doğru olan çalışır. Puan 73 olduğunda program önce >= 90 kontrol eder (hayır), sonra >= 80 (hayır), sonra >= 70 (evet!) ve "Not: C" yazdırır. Geri kalan koşullara bakmaz bile.

Bu yüzden sıralama önemli. Eğer >= 60 koşulunu en üste koysaydın, 73 puan alan öğrenci D alırdı — çünkü ilk eşleşen koşul çalışır.


Mantıksal Operatörlerle Koşul Birleştirme

Birden fazla koşulu tek bir if içinde birleştirebilirsin. C++'ta üç mantıksal operatör var:

OperatörAnlamAçıklama
&&VE (AND)İki koşul da doğruysa true
`\\`VEYA (OR)En az biri doğruysa true
!DEĞİL (NOT)Koşulun tersini alır
#include <iostream>
using namespace std;

int main() {
    int yas = 25;
    bool ehliyetVar = true;

    if (yas >= 18 && ehliyetVar) {
        cout << "Araba kullanabilirsiniz." << endl;
    }

    int sicaklik = 5;
    if (sicaklik < 0 || sicaklik > 40) {
        cout << "Aşırı hava koşulları!" << endl;
    }

    bool kapali = false;
    if (!kapali) {
        cout << "Dükkan açık." << endl;
    }

    return 0;
}

&& operatörü her iki koşulun da doğru olmasını ister. || operatörü ise en az birinin doğru olmasını yeterli görür. ! operatörü ise true'yu false, false'u true yapar.

💡 Short-circuit evaluation: C++ mantıksal operatörlerde kısa devre değerlendirmesi yapar. && kullanıyorsan ve ilk koşul false ise, ikinci koşula bakmaz bile — çünkü sonuç zaten false olacak. Aynı şekilde || kullanıyorsan ve ilk koşul true ise ikinciye bakmaz. Bu davranış performans için faydalıdır ve bazen bilinçli olarak kullanılır.


Ternary Operatör (?:) — Tek Satırda Karar

Basit if-else yapılarını tek satıra sıkıştırmak istiyorsan ternary operatör (koşullu operatör) kullanabilirsin. Söz dizimi:

koşul ? doğruysa_değer : yanlışsa_değer
#include <iostream>
using namespace std;

int main() {
    int yas = 20;

    // Klasik if-else ile
    string mesaj1;
    if (yas >= 18) {
        mesaj1 = "Yetişkin";
    } else {
        mesaj1 = "Çocuk";
    }

    // Ternary operatör ile — aynı iş, tek satır
    string mesaj2 = (yas >= 18) ? "Yetişkin" : "Çocuk";

    cout << mesaj1 << endl;  // Yetişkin
    cout << mesaj2 << endl;  // Yetişkin

    return 0;
}

Ternary operatör özellikle değişken ataması veya fonksiyon argümanı gibi yerlerde kullanışlıdır. Ama karmaşık koşullarda okunabilirliği bozar — o yüzden sadece basit durumlar için kullan.

// Güzel kullanım — kısa ve anlaşılır
int minimum = (a < b) ? a : b;

// Kötü kullanım — okuması zor
int sonuc = (x > 0) ? ((x > 100) ? 100 : x) : ((x < -100) ? -100 : x);
// Bunu if-else ile yazmak çok daha okunabilir olur

⚠️ Dikkat: Ternary operatörü iç içe kullanmaktan kaçın. Bir ternary'nin içine başka bir ternary koymak kodu okunmaz hale getirir. Kural basit: tek satırda rahat okunmuyorsa if-else kullan.


Nested if — İç İçe Koşullar

Bir if bloğunun içine başka bir if koyabilirsin. Buna nested if (iç içe if) denir.

#include <iostream>
using namespace std;

int main() {
    int yas = 25;
    bool ogrenciMi = true;

    if (yas >= 18) {
        cout << "Yetişkin." << endl;

        if (ogrenciMi) {
            cout << "Öğrenci indirimi uygulanır." << endl;
        } else {
            cout << "Tam fiyat uygulanır." << endl;
        }
    } else {
        cout << "18 yaş altı giriş yasaktır." << endl;
    }

    return 0;
}

Nested if'ler bazen gereklidir ama fazla derinleşirse kodun okunabilirliği ciddi şekilde düşer. Genel kural: 3 seviyeden fazla iç içe if kullanma. Daha fazlası gerekiyorsa, koşulları fonksiyonlara böl veya mantıksal operatörlerle birleştir.

Nested if'i Düzleştirme — Early Return

Özellikle fonksiyonlarda, iç içe if'ler yerine "erken çıkış" (early return) stratejisi kullanabilirsin:

#include <iostream>
#include <string>
using namespace std;

// Kötü — derin iç içe yapı
string kategori_kotuOrnek(int yas, bool uye) {
    string sonuc;
    if (yas >= 0) {
        if (yas < 18) {
            sonuc = "Cocuk";
        } else {
            if (uye) {
                sonuc = "Yetiskin Uye";
            } else {
                sonuc = "Yetiskin";
            }
        }
    } else {
        sonuc = "Gecersiz";
    }
    return sonuc;
}

// İyi — düz ve okunabilir
string kategori_iyiOrnek(int yas, bool uye) {
    if (yas < 0) return "Gecersiz";
    if (yas < 18) return "Cocuk";
    if (uye) return "Yetiskin Uye";
    return "Yetiskin";
}

İkinci versiyon çok daha temiz, değil mi? Her koşul bir kapı gibi — geçemezsen geri dönersin. Geçebilirsen bir sonraki kapıya ilerlersin.


if with Initializer (C++17)

C++17 ile birlikte if ifadesinin içinde bir değişken tanımlayıp aynı anda koşul kontrolü yapabilirsin. Bu özelliğe if with initializer denir.

#include <iostream>
#include <map>
#include <string>
using namespace std;

int main() {
    map<string, int> notlar = {{"Ali", 85}, {"Ayse", 92}};

    // C++17 öncesi — değişken dışarıda kalıyor
    auto it = notlar.find("Ali");
    if (it != notlar.end()) {
        cout << "Ali'nin notu: " << it->second << endl;
    }
    // 'it' burada hâlâ erişilebilir — gereksiz yere scope'u kirletiyor

    // C++17 ile — değişken sadece if bloğunda yaşar
    if (auto it2 = notlar.find("Ayse"); it2 != notlar.end()) {
        cout << "Ayse'nin notu: " << it2->second << endl;
    }
    // 'it2' burada artık erişilemez — temiz scope

    return 0;
}

Söz dizimi: if (tanımlama; koşul). Noktalı virgülle ayrılan iki kısım var — birincisi değişkeni tanımlar, ikincisi koşulu kontrol eder.

Bu özellik özellikle şu durumlarda faydalı:

  • map/set find işlemlerinde iterator'ı scope'a hapsetmek

  • Fonksiyon çağrısı sonucunu kontrol edip kullanmak

  • Geçici değişkenlerin scope kirliliğini önlemek

#include <iostream>
#include <string>
using namespace std;

int hesaplaYas(int dogumYili) {
    return 2026 - dogumYili;
}

int main() {
    // Fonksiyon sonucunu hem kontrol et hem kullan
    if (auto yas = hesaplaYas(1990); yas >= 18) {
        cout << "Yas: " << yas << " - Giris izni var." << endl;
    }
    // 'yas' burada mevcut değil

    // String uzunluk kontrolü
    string isim = "Tolgahan";
    if (auto len = isim.length(); len > 5) {
        cout << isim << " uzun bir isim (" << len << " karakter)" << endl;
    }

    return 0;
}

💡 İpucu: if with initializer, C++17 ve sonrasında çalışır. Derleyicinde -std=c++17 veya daha üstünü kullandığından emin ol. Modern C++ projelerinde bu özellik çok yaygın ve kodun okunabilirliğini artırır.


Koşullarda Yaygın Hatalar

Yeni başlayanların en sık düştüğü tuzakları özetleyelim:

1. Atama ile Karşılaştırmayı Karıştırmak

int x = 10;

// YANLIŞ — x'e 5 atar, her zaman true olur
if (x = 5) {
    cout << "Bu her zaman çalışır!" << endl;
}

// DOĞRU — x'in 5'e eşit olup olmadığını kontrol eder
if (x == 5) {
    cout << "x beştir." << endl;
}

2. Süslü Parantez Unutmak

int x = 10;

// TEHLİKELİ — sadece ilk satır if'e bağlı
if (x > 5)
    cout << "x büyük" << endl;
    cout << "Bu her zaman çalışır!" << endl;  // if'in dışında!

// GÜVENLİ — her zaman süslü parantez kullan
if (x > 5) {
    cout << "x büyük" << endl;
    cout << "Bu da sadece koşul doğruysa çalışır." << endl;
}

3. Floating-Point Karşılaştırması

double a = 0.1 + 0.2;

// YANLIŞ — floating-point hassasiyet sorunu
if (a == 0.3) {
    cout << "Eşit" << endl;  // Bu çalışmayabilir!
}

// DOĞRU — epsilon ile karşılaştır
if (abs(a - 0.3) < 1e-9) {
    cout << "Yaklaşık eşit" << endl;
}

Ondalıklı sayılar bilgisayarda tam olarak temsil edilemez. Bu yüzden == yerine bir tolerans değeri (epsilon) kullanmak gerekir.


Gerçek Dünya Örneği — Giriş Doğrulama

Öğrendiklerimizi bir araya getirelim:

#include <iostream>
#include <string>
using namespace std;

int main() {
    string kullaniciAdi;
    string sifre;

    cout << "Kullanıcı adı: ";
    cin >> kullaniciAdi;
    cout << "Şifre: ";
    cin >> sifre;

    if (kullaniciAdi.empty() || sifre.empty()) {
        cout << "Kullanıcı adı ve şifre boş olamaz!" << endl;
    } else if (kullaniciAdi == "admin" && sifre == "1234") {
        cout << "Hoş geldiniz, yönetici!" << endl;
    } else if (kullaniciAdi == "user" && sifre == "abcd") {
        cout << "Hoş geldiniz, kullanıcı!" << endl;
    } else {
        cout << "Hatalı kullanıcı adı veya şifre." << endl;
    }

    return 0;
}

Bu örnekte sırasıyla: boş giriş kontrolü, yönetici girişi, normal kullanıcı girişi ve hatalı giriş senaryolarını ele aldık. Gerçek bir uygulamada şifreler düz metin olarak karşılaştırılmaz ama mantık aynıdır.


Özet

  • if tek koşul kontrol eder — doğruysa bloğu çalıştırır, değilse atlar

  • else if'in alternatifidir — koşul yanlışsa çalışır

  • else if ile zincirleme koşullar yazabilirsin — ilk doğru olan çalışır, gerisine bakılmaz

  • Ternary operatör (?:) basit if-else'leri tek satıra sıkıştırır ama karmaşık durumlar için uygun değildir

  • Nested if yerine mümkünse early return veya mantıksal operatörlerle düzleştirme tercih et

  • if with initializer (C++17) değişkeni if scope'una hapsetmenin temiz yoludur: if (auto x = expr; koşul)