switch-case Yapısı
Diyelim ki bir restoran menüsündesin ve garson sana soruyor: "1 numaralı menü mü, 2 numaralı mı, 3 numaralı mı?" Sen bir numara söylüyorsun ve garson ona göre yemeği getiriyor. İşte switch-case tam olarak böyle çalışır — bir değere bakarsın ve o değere göre doğru yolu seçersin.
if-else if zincirleri de aynı işi yapar ama bir değişkeni birçok sabit değerle karşılaştırıyorsan, switch çok daha temiz ve okunabilir bir yapı sunar.
switch Temel Yapısı
switch bir ifadenin değerini alır ve onu case etiketleriyle eşleştirir. Eşleşen case'in kodu çalışır.
#include <iostream>
using namespace std;
int main() {
int gun = 3;
switch (gun) {
case 1:
cout << "Pazartesi" << endl;
break;
case 2:
cout << "Salı" << endl;
break;
case 3:
cout << "Çarşamba" << endl;
break;
case 4:
cout << "Perşembe" << endl;
break;
case 5:
cout << "Cuma" << endl;
break;
default:
cout << "Hafta sonu" << endl;
break;
}
return 0;
}gun değeri 3 olduğu için case 3: eşleşir ve "Çarşamba" yazdırılır. break ifadesi switch'ten çıkmayı sağlar — birazdan neden bu kadar önemli olduğunu göreceksin.
switch'in Kuralları
switch ifadesi tam sayı (integer) veya enum tipinde olmalı.
string,float,doublekullanamazsın.Her
caseetiketi derleme zamanında bilinen sabit bir değer (constant expression) olmalı.Aynı switch içinde iki case aynı değere sahip olamaz.
// ÇALIŞMAZ — string ile switch kullanılamaz
string renk = "kirmizi";
switch (renk) { // Derleme hatası!
case "kirmizi": break;
}
// ÇALIŞIR — char ile switch
char harf = 'A';
switch (harf) {
case 'A': cout << "Harf A" << endl; break;
case 'B': cout << "Harf B" << endl; break;
default: cout << "Diğer" << endl; break;
}default — Hiçbir case Eşleşmezse
default etiketi, hiçbir case değeri eşleşmediğinde çalışan bloktur. if-else'deki son else gibi düşünebilirsin.
#include <iostream>
using namespace std;
int main() {
int secim = 7;
switch (secim) {
case 1:
cout << "Seçenek 1" << endl;
break;
case 2:
cout << "Seçenek 2" << endl;
break;
case 3:
cout << "Seçenek 3" << endl;
break;
default:
cout << "Geçersiz seçim!" << endl;
break;
}
return 0;
}default zorunlu değil ama her zaman eklenmesi iyi bir alışkanlıktır. Beklenmeyen değerlerle karşılaşıldığında programın sessizce hiçbir şey yapmaması yerine en azından bir uyarı vermesi çok daha sağlıklı.
default etiketini switch'in herhangi bir yerine koyabilirsin — sona koymak zorunlu değil ama konvansiyon olarak en sona yazılır.
break'in Önemi ve Fall-Through
İşte switch-case'in en tehlikeli ve en çok hata yapılan noktası: break yazmazsan ne olur?
break olmadan program bir sonraki case'e "düşer" (fall-through) ve o case'in kodunu da çalıştırır. Bu durum eşleşme kontrolü yapmadan devam eder — ta ki bir break bulana veya switch'in sonuna gelene kadar.
#include <iostream>
using namespace std;
int main() {
int sayi = 2;
// break OLMADAN — fall-through!
cout << "break olmadan:" << endl;
switch (sayi) {
case 1:
cout << "Bir" << endl;
case 2:
cout << "İki" << endl;
case 3:
cout << "Üç" << endl;
case 4:
cout << "Dört" << endl;
default:
cout << "Diğer" << endl;
}
return 0;
}Çıktı:
break olmadan:
İki
Üç
Dört
Diğersayi 2 olduğu için case 2: ile eşleşir ama break olmadığı için case 3:, case 4: ve default: da çalışır. Bu genellikle istemediğin bir davranıştır.
⚠️ Dikkat: Her
casebloğunun sonunabreak;koymayı alışkanlık edin. Unutmak en yaygın switch hatalarından biridir ve bulması zor bug'lara yol açar.
Bilinçli Fall-Through
Bazen fall-through davranışını bilerek isteyebilirsin. Birden fazla case'in aynı kodu çalıştırmasını istediğinde kullanışlıdır.
#include <iostream>
using namespace std;
int main() {
int ay = 4;
switch (ay) {
case 12:
case 1:
case 2:
cout << "Kış" << endl;
break;
case 3:
case 4:
case 5:
cout << "İlkbahar" << endl;
break;
case 6:
case 7:
case 8:
cout << "Yaz" << endl;
break;
case 9:
case 10:
case 11:
cout << "Sonbahar" << endl;
break;
default:
cout << "Geçersiz ay" << endl;
break;
}
return 0;
}Burada case 3:, case 4: ve case 5: hepsi aynı kodu çalıştırır. Bu yasal ve yaygın bir kullanımdır — çünkü boş case'ler bir sonraki case'e düşer.
[[fallthrough]] Attribute (C++17)
Peki bilinçli fall-through kullanırken case'in içinde kod varsa? Derleyici seni uyarabilir: "Hey, burada break unutmuş olabilirsin." Bu uyarıyı bastırmak ve "evet, bilerek yapıyorum" demek için C++17'de `[[fallthrough]]` attribute'u eklendi.
#include <iostream>
using namespace std;
int main() {
int seviye = 3;
cout << "Ödüllerin:" << endl;
switch (seviye) {
case 3:
cout << "- Altın kupa" << endl;
[[fallthrough]]; // Bilerek düşürüyorum
case 2:
cout << "- Gümüş rozet" << endl;
[[fallthrough]]; // Bilerek düşürüyorum
case 1:
cout << "- Bronz madalya" << endl;
break;
default:
cout << "- Katılım belgesi" << endl;
break;
}
return 0;
}Seviye 3 olan oyuncu üç ödülün hepsini alır, seviye 2 olan ikisini, seviye 1 olan sadece bronz madalyayı alır. [[fallthrough]] derleyiciye "bu bilerek yapılmış, uyarma" der.
💡 İpucu:
[[fallthrough]]kullanımı ender olmalı. Çoğu durumda fall-through kafa karıştırır. Ama ödül sistemi, log seviyeleri gibi kümülatif durumlarda mantıklı olabilir.
switch ile enum Kullanımı
switch en güzel enum'larla kullanılır. Enum değerleri tam sayı sabitleri olduğu için switch ile mükemmel uyum sağlar.
#include <iostream>
using namespace std;
enum class Renk {
Kirmizi,
Yesil,
Mavi,
Sari
};
int main() {
Renk secilen = Renk::Yesil;
switch (secilen) {
case Renk::Kirmizi:
cout << "Dur!" << endl;
break;
case Renk::Yesil:
cout << "Geç!" << endl;
break;
case Renk::Mavi:
cout << "Bilgi" << endl;
break;
case Renk::Sari:
cout << "Dikkat!" << endl;
break;
}
return 0;
}enum class (scoped enum) kullandığında, derleyici tüm enum değerlerini case olarak yazıp yazmadığını kontrol edebilir. Eğer bir değeri atlarsan uyarı verir — bu çok değerli bir güvenlik ağı.
// Derleyici uyarısı: Renk::Sari ele alınmamış!
switch (secilen) {
case Renk::Kirmizi: /* ... */ break;
case Renk::Yesil: /* ... */ break;
case Renk::Mavi: /* ... */ break;
// Sari yok — derleyici uyarır (eğer -Wall açıksa)
}Bu yüzden enum ile switch kullanırken default yazmamak bazen daha iyi olabilir — böylece yeni bir enum değeri eklendiğinde derleyici seni uyarır ve unuttuğun yeri bulursun.
switch vs if-else if — Hangisi Ne Zaman?
| Durum | Tercih |
|---|---|
| Bir değişkeni birçok sabit değerle karşılaştırma | switch |
Aralık kontrolü (x > 10 && x < 50) | if-else if |
| String karşılaştırması | if-else if |
Karmaşık koşullar (a > b && c != d) | if-else if |
| Enum değerleri üzerinde dallanma | switch |
| 2-3 basit koşul | if-else (daha kısa) |
Genel kural: Bir değişkeni belirli sabit değerlerle karşılaştırıyorsan switch kullan, karmaşık mantıksal ifadeler gerekiyorsa if-else if kullan.
Pratik Örnek — Basit Hesap Makinesi
#include <iostream>
using namespace std;
int main() {
double sayi1, sayi2;
char islem;
cout << "İlk sayı: ";
cin >> sayi1;
cout << "İşlem (+, -, *, /): ";
cin >> islem;
cout << "İkinci sayı: ";
cin >> sayi2;
switch (islem) {
case '+':
cout << "Sonuç: " << sayi1 + sayi2 << endl;
break;
case '-':
cout << "Sonuç: " << sayi1 - sayi2 << endl;
break;
case '*':
cout << "Sonuç: " << sayi1 * sayi2 << endl;
break;
case '/':
if (sayi2 != 0) {
cout << "Sonuç: " << sayi1 / sayi2 << endl;
} else {
cout << "Hata: Sıfıra bölme!" << endl;
}
break;
default:
cout << "Geçersiz işlem!" << endl;
break;
}
return 0;
}Bu örnekte char tipini switch ile kullandık. Her işlem karakteri bir case'e karşılık geliyor. Bölme işleminde sıfıra bölme kontrolünü if ile yaptık — switch içinde if kullanmakta hiçbir sorun yok.
switch İçinde Değişken Tanımlama
switch-case içinde değişken tanımlarken dikkatli olmak gerekir. Bir case'de tanımlanan değişken, teorik olarak diğer case'lerden de erişilebilir — bu da karışıklık yaratır.
// PROBLEM — derleme hatası verebilir
switch (x) {
case 1:
int y = 10; // y burada tanımlanıyor
cout << y << endl;
break;
case 2:
cout << y << endl; // y'ye erişim belirsiz!
break;
}
// ÇÖZÜM — süslü parantez ile scope oluştur
switch (x) {
case 1: {
int y = 10;
cout << y << endl;
break;
}
case 2: {
int z = 20;
cout << z << endl;
break;
}
}Her case'i süslü parantez içine almak iyi bir alışkanlıktır. Böylece her case kendi scope'una sahip olur ve değişken çakışması olmaz.
Özet
switch bir ifadeyi birden fazla sabit değerle karşılaştırır — tam sayı ve enum tipleri desteklenir, string desteklenmez
break her case'in sonunda olmalıdır — yoksa fall-through gerçekleşir ve bir sonraki case'in kodu da çalışır
default hiçbir case eşleşmediğinde çalışır — her zaman eklemek iyi bir alışkanlıktır
[[fallthrough]] (C++17) attribute'u bilinçli fall-through'u derleyiciye bildirir ve uyarıyı bastırır
enum class ile switch kullanımı en güçlü kombinasyondur — derleyici eksik case'leri yakalar
Karmaşık koşullar, aralık kontrolü veya string karşılaştırması gerekiyorsa if-else if tercih et
AI Asistan
Sorularını yanıtlamaya hazır