Bölüm 5 / 15
Döngüler
for, while, do-while, foreach, break/continue.
8 dakikalık okuma
Üçüncü ve son akış yapısı: tekrar. Bilgisayarın asıl
gücü bir işi milyonlarca kez, yorulmadan ve şaşmadan yapabilmesidir; döngü bu gücün
sözdizimidir. Bu derste dört döngü biçimini (while, for,
do-while, foreach), akışa müdahale eden break ve
continue'yu ve döngülerin iki temel kalıbını — sayaç ve biriktirici —
kuracaksın. Dersin sonunda mülakat klasiği FizzBuzz'ı yazıyor olacaksın.
01Ne öğreneceksin
whilevefor'un anatomisi; hangisinin ne zaman doğal seçim olduğudo-while'ın farkı (en az bir kez çalışma) veforeach'e ilk bakışbreakile erken çıkış,continueile turu atlama- İki üretim kalıbı: biriktirici (toplam/sayma) ve iç içe döngü; sonsuz döngü ve bir-eksik (off-by-one) hatalarından korunma
02Tekrar: neden döngü?
1'den 100'e kadar sayıların toplamını yazdırmak isteseydin, elindeki araçlarla 100
satır toplam += ...; yazman gerekirdi — 1'den 1.000.000'a istendiğinde bu
yaklaşım çöker. Döngü, "şu bloğu, şu koşul sağlandıkça yinele" demenin yoludur: kod
sabit kalır, tekrar sayısı veriye göre değişir. Her döngüde üç öge bulunur ve döngü
hatalarının tamamı bu üçünden birinin eksikliğidir:
- Başlangıç durumu — sayaç ya da durum değişkeni ilk değerini alır.
- Devam koşulu — her turdan önce (do-while'da sonra) denenen bool ifade; false olduğunda döngü biter.
- İlerleme — her turda durumu koşula yaklaştıran değişiklik; yoksa döngü sonsuzdur.
03while: koşul sağlandıkça
En yalın biçim: while, koşulu her turun başında dener; true
ise bloğu çalıştırır, false olduğu anda döngüden çıkar:
var sayac = 1; // başlangıç
while (sayac <= 5) // devam koşulu
{
Console.WriteLine(sayac);
sayac++; // ilerleme
}
Console.WriteLine("Bitti"); // çıktı: 1 2 3 4 5 Bitti
İzleme disiplinini (1. ders) döngüye uygula: sayac=1 → koşul true → yaz, artır →
sayac=2 → ... → sayac=6 → koşul false → çık. Koşul baştan denendiği için ilk
anda false ise blok hiç çalışmaz (var sayac = 9; ile dene).
Sonsuz döngü: ilerleme satırını silersen koşul hep true kalır ve program
sonsuza kadar döner. Bunu bir kez bilerek yaşa: sayac++; satırını yorum
yapıp çalıştır, terminalin aktığını gör ve Ctrl+C ile durdur
(Hat 0'ın terminal dersindeki kesme sinyali). Bir döngü yazarken soracağın standart
soru: "koşulu false yapacak şey her turda gerçekleşiyor mu?"
04for: üç ögeyi tek satırda toplamak
Yukarıdaki while'da üç öge üç ayrı yere dağılmıştı. Tekrar sayısı belli olan
döngülerde bu üçlü o kadar standarttır ki for onları tek satırda,
noktalı virgülle ayrılmış üç bölmede toplar:
for (var i = 1; i <= 5; i++)
{
Console.WriteLine(i);
}
// ^ başlangıç ^ koşul ^ ilerleme — sıra: başlangıç → koşul → blok → ilerleme → koşul → ...
Çalışma sırası önemlidir ve sınavda sorulur: başlangıç bir kez çalışır;
sonra her turda önce koşul denenir, true ise blok, ardından
ilerleme çalışır ve koşula dönülür. Sayaç adı olarak i (ve iç içe
döngülerde j, k) evrensel gelenektir; anlamlı ad kuralının
(2. ders) yerleşik istisnasıdır.
Üç bölme esnektir — geriye sayım ve adımlı ilerleme de aynı kalıptır:
for (var i = 10; i >= 1; i--) // 10 9 8 ... 1
for (var i = 0; i <= 20; i += 5) // 0 5 10 15 20
Seçim kılavuzu: tekrar sayısı önceden belliyse for ("100 kez", "1'den n'e"), bir durum değişene kadar dönülecekse while ("kullanıcı 'çık' yazana kadar", "dosya bitene kadar"). İkisi birbirine çevrilebilir; fark okunabilirliktir.
05do-while: önce iş, sonra koşul
do-while koşulu turun sonunda dener; blok bu yüzden en az bir
kez çalışır. Doğal kullanım alanı, en az bir kez yapılması zorunlu işlerdir —
tipik örnek geçerli girdi alana kadar sormak:
int puan;
do
{
Console.Write("0-100 arası puan gir: ");
puan = int.Parse(Console.ReadLine());
} while (puan < 0 || puan > 100); // geçersizse tekrar sor
Console.WriteLine($"Kabul edildi: {puan}");
Sözdizimi ayrıntısı: while (...) satırı burada noktalı virgülle biter.
Koşulun okunuşuna dikkat: "geçersizken dönmeye devam et" — devam koşulu, çıkış
koşulunun tersidir; ters çevirmeyi geçen dersin mantık operatörleriyle yapıyorsun.
do-while dört biçim içinde en az kullanılanıdır; "en az bir kez" garantisi gerekmeyen
her yerde while ya da for tercih edilir.
06foreach: her eleman için
Dördüncü biçim foreach, bir topluluğun her elemanı için bloğu
çalıştırır — sayaç yok, koşul yok, indeks hesabı yok. String bir karakter dizisi
olduğu için ilk örneği hemen verebiliyoruz:
foreach (var harf in "merhaba")
{
Console.WriteLine(harf); // m e r h a b a — her satırda bir karakter
}
Okunuşu: ""merhaba" içindeki her harf için". Döngü
değişkeni (harf) her turda sıradaki elemanın değerini alır; kaç eleman
olduğunu senin bilmen gerekmez. foreach'in asıl sahnesi bir sonraki iki derstir —
diziler (6. ders) ve koleksiyonlar (7. ders) üzerinde gezinmenin standart yolu odur.
Bugünlük kalıbı tanıman yeterli.
07break ve continue
İki anahtar kelime döngünün olağan akışına müdahale eder:
break döngüyü tamamen bitirir; akış döngüden sonraki satıra
atlar. Tipik kullanım: aranan şey bulununca daha fazla dönmemek.
for (var i = 100; i <= 999; i++)
{
if (i % 7 == 0)
{
Console.WriteLine($"İlk bulunan: {i}"); // 105
break; // gerisini aramaya gerek yok
}
}
continue yalnızca içinde bulunulan turu keser; akış bir sonraki
tura (for'da önce ilerleme bölmesine) geçer. Tipik kullanım: istenmeyen elemanları
atlamak.
for (var i = 1; i <= 10; i++)
{
if (i % 2 == 1)
{
continue; // tek sayıysa bu turu atla
}
Console.WriteLine(i); // 2 4 6 8 10
}
switch'ten tanıdığın break ile aynı kelimedir ama buradaki iş farklıdır: switch'te dalı kapatır, döngüde döngüyü. İkisini de ölçülü kullan — bir döngüde çok sayıda break/continue, koşulun aslında yanlış kurulduğunun işaretidir.
08Kalıplar: biriktirici ve iç içe döngü
Biriktirici (accumulator): döngü dışında tanımlanan bir değişkenin her turda güncellenmesi. Toplam, sayma ve en-büyüğü-bulma bu tek kalıbın çeşitleridir; 1. dersin "kendini güncelleyen değişken" kuralı burada meslek halini alır:
var toplam = 0;
var ciftAdedi = 0;
for (var i = 1; i <= 100; i++)
{
toplam += i; // toplama biriktirici
if (i % 2 == 0) { ciftAdedi++; } // sayma biriktirici
}
Console.WriteLine(toplam); // 5050
Console.WriteLine(ciftAdedi); // 50
Biriktiricinin döngüden önce ve dışarıda tanımlanması şarttır — içeride tanımlansaydı her turda sıfırlanırdı.
İç içe döngü: bir döngünün gövdesine başka döngü koymak. Dıştaki her tur için içteki döngü baştan sona döner; toplam tur sayısı çarpımdır (5 × 10 = 50). Klasik örnek çarpım tablosu:
for (var i = 1; i <= 5; i++)
{
for (var j = 1; j <= 10; j++)
{
Console.Write($"{i * j}\t"); // \t: sekme — sütunları hizalar
}
Console.WriteLine(); // satır sonu: dış turda bir kez
}
Bir-eksik (off-by-one) hatası: döngü hatalarının en yaygını, sınırın bir
eksik ya da bir fazla dönmesidir. i < 10 ile i <= 10
arasındaki fark bir turdur; i = 0 ile i = 1 başlangıcı da
öyle. Alışkanlık edin: her döngü yazdığında ilk ve son turu kafanda (gerekirse kağıtta)
tek tek işlet — "i ilk turda kaç, son turda kaç, blok kaç kez çalıştı?"
09Mini alıştırma — FizzBuzz ve biriktiriciler
Yaklaşık 20 dakika · dotnet new console -o donguler
- FizzBuzz (mülakatların eleme klasiği): 1'den 50'ye kadar dön; sayı 3'ün
katıysa
Fizz, 5'in katıysaBuzz, hem 3'ün hem 5'in katıysaFizzBuzz, hiçbiri değilse sayının kendisini yazdır. Koşul sırası kritik: 15 kontrolü en üstte olmalı — neden olduğunu geçen dersin "ilk eşleşen kazanır" kuralıyla açıkla. Doğrulama: 15 ve 30 satırlarındaFizzBuzzgörmelisin. - Biriktiriciler: tek döngüde 1-100 arası sayıların toplamını (5050), çift olanların toplamını (2550) ve 7'ye bölünenlerin adedini (14) hesaplayıp üç satırda yazdır.
- do-while ile girdi doğrulama: kullanıcıdan 1-12 arası ay numarası iste; geçersizse tekrar sor. Geçerli ayı aldıktan sonra bir for döngüsüyle o aydan yıl sonuna kaç ay kaldığını listele.
- Kırıp gözle: FizzBuzz'daki
i++'ı silip çalıştır, sonsuz döngüyü Ctrl+C ile kes. Sonra koşului < 50yapıp son satırın kaybolduğunu gör — bir-eksik hatasını kendi elinle üretmiş oldun.
10Kendini sına
while ile do-while arasındaki fark nedir? Hangi durumda do-while doğal seçimdir?
while koşulu turun başında dener — koşul baştan false ise blok hiç çalışmaz. do-while koşulu turun sonunda dener — blok her koşulda en az bir kez çalışır. En az bir kez yapılması zorunlu işlerde do-while doğaldır; tipik örnek, geçerli girdi alınana kadar kullanıcıya sormaktır.
for döngüsünün üç bölmesi hangi sırayla çalışır?
Başlangıç bir kez, en başta. Sonra döngü şu çevrimi izler: koşul denenir → true ise blok çalışır → ilerleme çalışır → koşula dönülür. Koşul false çıktığı anda döngü biter. Yani ilerleme her turun sonunda, koşul her turun başında çalışır; blok hiç çalışmadan da döngü bitebilir (koşul ilk denemede false ise).
break ile continue arasındaki fark nedir?
break döngüyü tamamen sonlandırır; akış döngüden sonraki satırdan devam eder — tipik kullanımı aranan bulununca durmaktır. continue yalnızca o turu keser; akış sonraki tura geçer (for'da önce ilerleme bölmesi çalışır) — tipik kullanımı istenmeyen elemanları atlamaktır. İç içe döngülerde ikisi de yalnızca içinde bulundukları döngüyü etkiler.
for (var i = 0; i < 10; i++) bloğu kaç kez çalıştırır? i <= 10 olsaydı?
i < 10: 10 kez (i = 0,1,...,9). i <= 10:
11 kez (0'dan 10'a). Aradaki tek tur farkı, bir-eksik (off-by-one) hatasının
kaynağıdır; döngü yazarken ilk ve son turu elle işletip doğrulamak bu hatayı
yakalamanın standart yoludur.
11Sınav köşesi
Yazılıda nasıl sorulur
Üç kalıp: (1) "Döngü kaç kez döner?" — başlangıç, koşul (< mü
<= mi) ve adımı dikkatle oku; iç içe döngüde sayılar çarpılır.
(2) Çıktı sorusu — break/continue içeren döngü verilir; izleme tablosuyla tur tur
işle, kestirmeden gitme. (3) Hata avı — ilerlemesi olmayan while (sonsuz döngü)
ya da biriktiricisi döngü içinde tanımlanmış (her turda sıfırlanan) kod gösterilir.
1-100 toplamı, çift sayı sayma ve FizzBuzz mantığı hem yazılının hem kodlama
mülakatlarının demirbaşıdır.
Sözlüde nasıl anlatılır — 2 dakikalık taslak
"C#'taki döngü türlerini karşılaştırır mısınız?" için: (1) Ortak iskelet — başlangıç, devam koşulu, ilerleme; sonsuz döngü bu üçlüden ilerlemenin eksilmesidir. (2) for — tekrar sayısı belli işler; üçlüyü tek satırda toplar. (3) while — bir durum değişene kadar; do-while — aynı şey ama en az bir tur garantili, girdi doğrulama örneğini ver. (4) foreach — koleksiyon elemanları üzerinde, sayaçsız; dizi ve koleksiyonlarla birlikte asıl değerini bulur. Kapanışta break/continue'yu tek cümleyle tanımla ve ekle: "Döngü yazarken ilk ve son turu elle doğrularım — off-by-one hataları en yaygın döngü hatasıdır."
