← Kursa Dön
📄 Text · 15 min

for, while, do-while ve Range-based for

Bir şarkıyı tekrar tekrar dinlemeyi düşün. "Bu şarkıyı 10 kere çal" diyorsun — bu bir for döngüsü. "Şarkı bitene kadar çal" diyorsun — bu bir while döngüsü. Programlamada aynı işi defalarca yapmak istediğinde döngüleri kullanırsın. Döngüler olmasaydı, ekrana 100 kere "Merhaba" yazmak için 100 satır kod yazman gerekirdi.

Bu derste C++'taki tüm döngü yapılarını öğreneceksin: klasik for, while, do-while ve modern C++'ın en sevilen özelliklerinden biri olan range-based for.


for Döngüsü — Klasik ve Güvenilir

for döngüsü, kaç kere tekrar edeceğini bildiğinde kullanılır. Üç parçası var:

for (başlangıç; koşul; artış) {
    // tekrar eden kod
}
  • Başlangıç: Döngü değişkenini tanımlar ve ilk değerini verir (bir kez çalışır)

  • Koşul: Her turda kontrol edilir — true ise devam, false ise çık

  • Artış: Her turun sonunda çalışır (genellikle sayacı artırır)

#include <iostream>
using namespace std;

int main() {
    // 1'den 5'e kadar sayıları yazdır
    for (int i = 1; i <= 5; i++) {
        cout << i << " ";
    }
    cout << endl;
    // Çıktı: 1 2 3 4 5

    return 0;
}

Bu döngünün akışı şöyle:

  1. int i = 1 — i tanımlanır, değeri 1

  2. i <= 5 kontrol — 1 ≤ 5? Evet → gövde çalışır

  3. i++ — i artık 2

  4. i <= 5 kontrol — 2 ≤ 5? Evet → gövde çalışır

  5. ... bu şekilde devam eder

  6. i <= 5 kontrol — 6 ≤ 5? Hayır → döngü biter

for Döngüsünün Esnekliği

for döngüsü çok esnek bir yapı. Parçalarını farklı şekillerde kullanabilirsin:

#include <iostream>
using namespace std;

int main() {
    // Geriye doğru sayma
    for (int i = 10; i >= 1; i--) {
        cout << i << " ";
    }
    cout << endl;
    // Çıktı: 10 9 8 7 6 5 4 3 2 1

    // İkişer atlama
    for (int i = 0; i <= 20; i += 2) {
        cout << i << " ";
    }
    cout << endl;
    // Çıktı: 0 2 4 6 8 10 12 14 16 18 20

    // Birden fazla değişken
    for (int i = 0, j = 10; i < j; i++, j--) {
        cout << "i=" << i << " j=" << j << endl;
    }

    return 0;
}

💡 İpucu: for döngüsü içinde tanımlanan değişken (mesela int i) sadece döngü bloğu içinde yaşar. Döngü bittiğinde i erişilemez olur — bu scope açısından temiz bir davranıştır.


while Döngüsü — Koşul Odaklı

while döngüsü, "şu koşul doğru olduğu sürece devam et" der. Kaç kere tekrar edeceğini önceden bilmediğinde idealdir.

while (koşul) {
    // tekrar eden kod
}
#include <iostream>
using namespace std;

int main() {
    // Kullanıcıdan 0 girene kadar sayı al
    int sayi;
    cout << "Bir sayı girin (çıkmak için 0): ";
    cin >> sayi;

    while (sayi != 0) {
        cout << "Girdiğiniz: " << sayi << endl;
        cout << "Bir sayı girin (çıkmak için 0): ";
        cin >> sayi;
    }

    cout << "Çıkış yapıldı." << endl;
    return 0;
}

Bu örnekte kullanıcı 0 girene kadar döngü devam eder. Ne zaman 0 gireceğini bilemeyiz — bu yüzden while uygundur.

while vs for

for ve while aslında birbirinin yerine kullanılabilir. Ama konvansiyon olarak:

  • Sayaç ile belirli sayıda tekrar → for

  • Koşula bağlı belirsiz tekrar → while

// Bu ikisi aynı işi yapar:
for (int i = 0; i < 5; i++) {
    cout << i << endl;
}

int i = 0;
while (i < 5) {
    cout << i << endl;
    i++;
}

Hangisinin daha okunabilir olduğu açık — sayaçlı durumlarda for tercih edilir.


do-while — En Az Bir Kere Çalış

do-while döngüsünün while'dan tek farkı: koşul sonda kontrol edilir. Bu da gövdenin en az bir kere çalışacağını garanti eder.

do {
    // en az bir kere çalışan kod
} while (koşul);  // Noktalı virgül unutma!
#include <iostream>
using namespace std;

int main() {
    int secim;

    do {
        cout << "\n=== MENÜ ===" << endl;
        cout << "1. Yeni Oyun" << endl;
        cout << "2. Ayarlar" << endl;
        cout << "3. Çıkış" << endl;
        cout << "Seçiminiz: ";
        cin >> secim;

        switch (secim) {
            case 1: cout << "Oyun başlıyor..." << endl; break;
            case 2: cout << "Ayarlar açılıyor..." << endl; break;
            case 3: cout << "Güle güle!" << endl; break;
            default: cout << "Geçersiz seçim!" << endl; break;
        }
    } while (secim != 3);

    return 0;
}

Menü en az bir kere gösterilmeli — kullanıcı daha seçim yapmadan koşul kontrol edilemez. İşte do-while tam bu durumlar için tasarlanmıştır.

⚠️ Dikkat: do-while sonundaki noktalı virgülü (;) unutma! Bu çok yaygın bir söz dizimi hatasıdır. while (koşul); — o noktalı virgül gerekli.

do-while Ne Zaman Kullanılır?

  • Menü sistemleri (menü en az bir kere gösterilmeli)

  • Giriş doğrulama (kullanıcıdan en az bir kere girdi al)

  • Oyun döngüleri (oyun en az bir tur oynamalı)

// Giriş doğrulama — geçerli değer girene kadar sor
int yas;
do {
    cout << "Yaşınız (1-120): ";
    cin >> yas;
} while (yas < 1 || yas > 120);

cout << "Yaşınız: " << yas << endl;

Range-based for — Modern C++ Döngüsü

C++11 ile gelen range-based for döngüsü, bir koleksiyonun (dizi, vector, string vb.) tüm elemanları üzerinde gezmeyi çok kolaylaştırır. İndeks yönetimiyle uğraşmana gerek kalmaz.

for (tip değişken : koleksiyon) {
    // her eleman için çalışan kod
}
#include <iostream>
#include <vector>
#include <string>
using namespace std;

int main() {
    // Vector ile
    vector<int> sayilar = {10, 20, 30, 40, 50};

    for (int sayi : sayilar) {
        cout << sayi << " ";
    }
    cout << endl;
    // Çıktı: 10 20 30 40 50

    // String ile — her karakter üzerinde gezme
    string mesaj = "Merhaba";
    for (char c : mesaj) {
        cout << c << "-";
    }
    cout << endl;
    // Çıktı: M-e-r-h-a-b-a-

    // C-style dizi ile
    int dizi[] = {1, 2, 3, 4, 5};
    for (int x : dizi) {
        cout << x << " ";
    }
    cout << endl;

    return 0;
}

auto ile Tip Çıkarımı

Koleksiyondaki elemanların tipini yazmak yerine auto kullanabilirsin — derleyici tipi senin için çıkarır.

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

int main() {
    vector<double> fiyatlar = {29.99, 49.50, 15.75, 99.00};

    // auto ile — tip otomatik çıkarılır
    for (auto fiyat : fiyatlar) {
        cout << fiyat << " TL" << endl;
    }

    return 0;
}

Referans ile Gezme — Elemanları Değiştirme

Normal range-based for, elemanların kopyasını alır. Elemanları değiştirmek istiyorsan referans (&) kullanmalısın.

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

int main() {
    vector<int> notlar = {60, 75, 80, 45, 90};

    // Değer ile — kopyayı değiştirir, orijinal etkilenmez
    for (auto not_degeri : notlar) {
        not_degeri += 5;  // Kopyayı artırıyor, orijinal aynı kalır
    }

    // Referans ile — orijinali değiştirir
    for (auto& not_degeri : notlar) {
        not_degeri += 5;  // Orijinal değer artıyor
    }

    // const referans ile — okuma amaçlı, kopyalama maliyeti yok
    for (const auto& not_degeri : notlar) {
        cout << not_degeri << " ";
    }
    cout << endl;
    // Çıktı: 65 80 85 50 95

    return 0;
}

💡 İpucu: Performans için büyük nesneleri (string, struct vb.) const auto& ile gez. Küçük tipler (int, char, double) için fark etmez ama alışkanlık olarak const auto& kullanmak iyi bir pratiktir.


İç İçe Döngüler

Bir döngünün içine başka bir döngü koyabilirsin. Buna nested loop (iç içe döngü) denir. Dış döngünün her turu için iç döngü tamamen çalışır.

Bunu bir saat gibi düşün: dakika ibresi (iç döngü) 60 tur atıyor, saat ibresi (dış döngü) 1 tur atıyor. Dakika 60'a ulaştığında sıfırlanır ve saat bir ilerler.

#include <iostream>
using namespace std;

int main() {
    // Çarpım tablosu (1-5)
    for (int i = 1; i <= 5; i++) {
        for (int j = 1; j <= 5; j++) {
            cout << i * j << "\t";
        }
        cout << endl;
    }

    return 0;
}

Çıktı:

1	2	3	4	5
2	4	6	8	10
3	6	9	12	15
4	8	12	16	20
5	10	15	20	25

Dış döngü satırları, iç döngü sütunları kontrol eder. i=1 iken j 1'den 5'e gider (ilk satır), sonra i=2 olur ve j tekrar 1'den 5'e gider (ikinci satır)...

Yıldız Deseni — Klasik Örnek

#include <iostream>
using namespace std;

int main() {
    int n = 5;

    // Dik üçgen
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= i; j++) {
            cout << "* ";
        }
        cout << endl;
    }

    return 0;
}

Çıktı:

*
* *
* * *
* * * *
* * * * *

⚠️ Dikkat: İç içe döngülerin karmaşıklığı çarpımsal olarak artar. Dış döngü N kez, iç döngü M kez dönüyorsa toplam N×M iterasyon olur. Üç katlı iç içe döngü nadiren gereklidir — gerekiyorsa tasarımını sorgula.


Sonsuz Döngü Kalıpları

Bazen döngünün ne zaman biteceğini önceden belirleyemezsin. Bu durumlarda sonsuz döngü oluşturup içeriden kontrollü çıkış yaparsın.

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

int main() {
    // Yöntem 1: while(true)
    while (true) {
        string komut;
        cout << "> ";
        cin >> komut;

        if (komut == "cikis") {
            break;  // Döngüden çık
        }

        cout << "Komut: " << komut << endl;
    }

    return 0;
}
// Yöntem 2: for(;;) — aynı anlama gelir
for (;;) {
    // sonsuz döngü
    break;  // Bir noktada çıkış olmalı!
}

Sonsuz döngüler şu durumlarda kullanılır:

  • Sunucu döngüleri — istek gelene kadar bekle, işle, tekrar bekle

  • Oyun döngüleri — her frame'i çiz, girdi al, güncelle, tekrar

  • Komut satırı araçları — kullanıcı "çık" diyene kadar çalış

Her sonsuz döngüde bir çıkış koşulu olmalı (break, return veya program sonlandırma). Yoksa program sonsuza kadar çalışır ve kapatmak için Ctrl+C'ye ihtiyacın olur.


Döngü Seçim Rehberi

DurumKullanılacak Döngü
Kaç kez döneceğini biliyorsunfor
Koşula bağlı, 0 veya daha fazla turwhile
En az 1 kere çalışmalıdo-while
Koleksiyon elemanları üzerinde gezmerange-based for
Belirsiz süre, kontrollü çıkışwhile(true) + break

Pratik Örnek — Sayı Tahmin Oyunu

Öğrendiklerimizi bir araya getirelim:

#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;

int main() {
    srand(time(nullptr));
    int hedef = rand() % 100 + 1;  // 1-100 arası rastgele
    int tahmin;
    int deneme = 0;

    cout << "1-100 arası bir sayı tuttum. Tahmin et!" << endl;

    do {
        cout << "Tahminin: ";
        cin >> tahmin;
        deneme++;

        if (tahmin < hedef) {
            cout << "Daha büyük!" << endl;
        } else if (tahmin > hedef) {
            cout << "Daha küçük!" << endl;
        } else {
            cout << "Tebrikler! " << deneme
                 << " denemede buldun!" << endl;
        }
    } while (tahmin != hedef);

    return 0;
}

Bu oyunda do-while kullandık çünkü kullanıcı en az bir tahmin yapmalı. Döngü, doğru tahmin yapılana kadar devam eder.


Özet

  • for döngüsü sayaç tabanlıdır — kaç kere döneceğini bildiğinde kullan, üç parçası var: başlangıç, koşul, artış

  • while koşul doğru olduğu sürece döner — koşul başta kontrol edilir, gövde hiç çalışmayabilir

  • do-while gövdeyi en az bir kere çalıştırır — koşul sonda kontrol edilir, menü ve giriş doğrulama için ideal

  • Range-based for koleksiyonlar üzerinde gezmenin en temiz yoludur — for (auto& x : vec) kalıbını kullan

  • İç içe döngüler çarpımsal karmaşıklık yaratır — gereksiz derinlikten kaçın

  • Sonsuz döngüler (while(true)) kontrollü çıkış ile kullanılır — her zaman bir break veya return noktası olmalı