Bir Sayacınız Olmadığında
for döngüsü, önceden ayarladığınız bir sayacın etrafında kurulur. Ama net bir sayımı olmayan bir sürü döngü vardır: girdi bitene kadar sayı okumaya devam etmek, doğru olana kadar parola sormaya devam etmek, 1'e ulaşana kadar bir değeri yarıya bölmeye devam etmek. Bunlar için while döngüsü doğal bir seçimdir; bir koşul doğru kaldığı sürece basitçe tekrar eder.
Bir while döngüsü koşulunu her geçişten önce, en ilk geçiş dahil, kontrol eder. Koşul en başta yanlışsa, gövde hiç çalışmaz.
count > 0 koşulu önce kontrol edilir; doğruysa gövde çalışır, sonra başa döner ve tekrar kontrol ederiz. count-- satırı, koşulu eninde sonunda yanlış yapan şeydir; onu kaldırırsanız döngü sonsuza dek çalışır.
Bir while Döngüsünün Anatomisi
Onu zaten bildiğiniz üç parçalı for döngüsüyle karşılaştırın. Bir while döngüsü bu üç işi birbirinden ayırır: kurulumu döngüden önce yaparsınız, koşul parantezlerin içine gider ve güncelleme gövdenin içinde yaşar.
int i = 0; // ilklendirme - döngüden önce
while (i < 5) { // koşul - her geçişte kontrol edilir
cout << i << "\n";
i++; // güncelleme - bunu kendiniz hatırlamalısınız
}
İşin püf noktası o son kısımdır. Bir for döngüsünde güncelleme koşulun hemen yanında durur, bu yüzden unutmak zordur. Bir while döngüsünde ise gövdedeki başka bir ifadeden ibarettir; en sık görülen hata onu atlamak ve programı kilitlemektir.
Yeni başlayanları ısıran bir C++ tuzağı: koşulun hemen ardındaki başıboş bir noktalı virgül, gövdeyi boş bir ifadeye dönüştürür.
int i = 0;
while (i < 5); // <-- bu noktalı virgül tüm döngü gövdesidir
{
cout << i << "\n";
i++;
}
Bu, sonsuza dek hiçbir şey yapmadan döner, çünkü ; gövdenin kendisidir ve i hiç değişmez. Süslü parantezlerdeki blok ise tam olarak bir kez çalışır. Derleyici sizi durdurmaz; bu tamamen geçerli bir koddur, sadece kastettiğiniz şey değildir.
do-while: Gövdeyi En Az Bir Kez Çalıştır
Bazen gövdenin, tekrar edip etmeyeceğinize bile karar verebilmenizden önce bir kez çalışmasına ihtiyaç duyarsınız. do-while döngüsü koşulunu sonda kontrol eder, böylece gövde her zaman en az bir kez yürütülür:
Girdinin geçerli olup olmadığını bilmeden önce en az bir kez sorup okumanız gerekir, ki do-while'ın size tam olarak verdiği şey budur. while (...)'dan sonraki noktalı virgüle dikkat edin; C++'ta do-while için zorunludur ve onu unutmak sık görülen bir derleme hatasıdır.
Düz bir while ile fark, koşul en baştan yanlış başladığında açıkça ortaya çıkar:
Yalnızca do-while body yazdırılır. while döngüsü gövdesini tamamen atlar çünkü x < 5 ilk kontrolden önce yanlıştı.
cin Başarısız Olana Kadar Döngü
Klasik bir while kullanımı, girdi durana kadar okumaktır; sayaç yoktur, akış size durmanızı söyleyene kadar devam edersiniz. C++'ta cin >> value, akışın kendisi olarak değerlendirilir; okuma başarılı olduğu sürece doğru (truthy), girdinin sonuna ya da bir tip uyuşmazlığına çarpar çarpmaz yanlış (falsy). Bu da onu temiz bir döngü koşulu yapar:
Koşul çifte görev yapar: tek bir adımda hem okur hem de test eder. Bunu bir nöbetçi değerle karşılaştırın; diyelim ki 0 gelince durmak. Orada, koşulun her zaman taze girdiyi test etmesi için döngüden önce bir kez ve her geçişin sonunda yeniden okumanız gerekir:
Gövdenin içindeki ikinci okumayı unutursanız, value hiç değişmez ve elinizde bir sonsuz döngü olur. while (cin >> value) biçimi, okumayı koşulun içine katlayarak bundan kaçınır.
while Döngülerinde break ve continue
break ve continue burada bir for döngüsündekiyle aynı şekilde çalışır. break döngüden anında çıkar; continue doğrudan koşul kontrolüne atlar ve mevcut geçişin geri kalanını atlar:
Bu, 1 3 5 7 9 yazdırır. while (true) kasıtlı olarak kendiliğinden asla durmaz; break tek çıkıştır. Bir while döngüsünde continue ile dikkatli olun: güncelleme gövdenin parçası olduğu için, sayacınızı ilerletmeden önce continue ile başa atlamak, döngüyü sessizce kilitlemenin bir yoludur. Yukarıdaki örnekte n++ önce çalışır, bu yüzden güvenlidir.
Sonsuz Döngülere Dikkat Edin
Koşulun eninde sonunda yanlış hale gelmesi gerekir ve bu tamamen gövdenin içindeki bir şeyin değişmesine bağlıdır. İki olağan suçlu, güncellemeyi unutmak ve çıkış değerinin üzerinden atlayacak şekilde güncellemektir:
int i = 0;
while (i < 5) {
cout << i << "\n"; // i hiç değişmez -> sonsuza dek çalışır
}
int i = 0;
while (i != 10) {
i += 3; // 0, 3, 6, 9, 12... tam 10'un üzerinden atlar -> sonsuza dek çalışır
}
Birincisi takılır çünkü i hiç güncellenmez. İkincisi takılır çünkü sayaç, koşulun aradığı tam değerin üzerinden adımlar; adım tam olarak denk gelmeyebilecekse != yerine < ya da <= tercih edin. Bir while (true), garantili bir break'i varsa sorun değildir; kazara olanı ise sadece bir hatadır. Ve daha önceki boş gövdeli while (...); tuzağını hatırlayın; yanlış yerleştirilmiş bir noktalı virgül, ilk bakışta doğru görünen bir sonsuz döngü üretir.
Sırada: Aralık Tabanlı for Döngüsü
Bir koşul değişene kadar döngü kurduğunuzda ve net bir sayım olmadığında doğru araç while döngüsüdür. Ama yalnızca bir kabın her elemanını (bir vector, bir dizi, bir string) yönetilecek bir indeks ve koşul olmadan dolaşmak istediğinizde, modern C++'ın daha temiz bir şeyi vardır: aralık tabanlı for döngüsü (for (auto x : container)). Bir sonraki sayfanın konusu bu.
Sıkça Sorulan Sorular
C++'ta while ile do-while arasındaki fark nedir?
Bir while döngüsü koşulunu ilk geçişten önce kontrol eder, dolayısıyla gövde sıfır kez çalışabilir. Bir do-while döngüsü gövdeyi önce bir kez çalıştırır, ardından koşulu sonda kontrol eder, böylece her zaman en az bir kez çalışır. İş, tekrar edip etmeyeceğine karar vermeden önce gerçekleşmek zorundaysa do-while kullanın; örneğin girdi istemek ve sonra onu doğrulamak gibi. do-while'ın kapanış while (...) ifadesinden sonra noktalı virgül gerektirdiğini unutmayın.
C++'ta for döngüsü yerine ne zaman while döngüsü kullanmalıyım?
Net bir sayacınız olmadığında ve sadece bir koşul değişene kadar tekrar etmek istediğinizde bir while döngüsü kullanın: cin başarısız olana kadar girdi okumak, bir değer hazır olana kadar yoklamak ya da bir kuyruğu boşalana kadar işlemek gibi. Yineleme sayısını bildiğinizde ya da sayılacak bariz bir indeks olduğunda for döngüsüne yönelin.
C++'ta sonsuz bir while döngüsü nasıl durdurulur?
Gövdenin içindeki bir şeyin eninde sonunda koşulu yanlış (false) hale getirdiğinden emin olun (bir sayacı azaltmak, bir işaretçiyi ilerletmek, bir bayrak ayarlamak). Bilinçli bir while (true) döngüsü için, bir if ile korunan bir break yerleştirin. Bir döngü takılırsa, olağan neden koşulun bağlı olduğu değişkeni güncellemeyi unutmaktır.