Bir Döngünün Akışını Değiştirmenin İki Yolu
Bir döngünün koşulu ne zaman biteceğine karar verir, ama bazen asıl cevap gövdenin ortasında ortaya çıkar. Bir dizide arama yapıyorsunuz ve aradığınızı üçüncü elemanda buluyorsunuz - kalan 997'yi neden kontrol edesiniz? Ya da bir listeyi işliyorsunuz ve bir kayıt boş - onu atlayıp devam edin.
C'nin her durum için bir anahtar kelimesi var:
break- döngüden şimdi çık. Yürütme, ondan sonraki ilk deyimden devam eder.continue- yalnızca bu geçişi terk et. Bir sonrakine geç.
İlk döngü 1 2 3 4 yazdırır ve durur. İkincisi 1 2 3 4 6 7 8 9 10 yazdırır - bir değeri atladı ve devam etti.
Bir Döngüde break
Klasik kullanım, başarır başarmaz duran bir aramadır:
found, break'ten önce ayarlandığı için döngüden sonraki kod "buldum" ile "elemanlar bitti" arasındaki farkı anlayabilir. Bu eşleşme - bir sonuç değişkeni artı bir break - standart C arama deyimidir. Döngü sayacının kendisi, başlıkta bildirildiğinde sonrasında kullanılamaz, çünkü kapanış parantezinde kapsam dışına çıkar.
break her zaman bir döngüden çıkar: onu saran en yakın for, while, do-while ya da switch.
Bir Döngüde continue
continue, işi durdurmak yerine atlanması gereken kayıtlar içindir:
continue'nun nereye atladığı döngüye bağlıdır:
for -> baslikteki guncelleme kismina (sayac yine de ilerler)
while -> kosul testine (govdede baska hicbir sey calismaz)
do-while -> asagidaki kosul testine
Bu fark teorik değildir. Bir for döngüsünde continue, sayaç artırımını asla atlayamaz, çünkü artırım başlıktadır. Bir while döngüsünde atlayabilir:
/* HATA: continue i++'ı atlar, yani ilk çift sayıda takılır */
int i = 0;
while (i < 10) {
if (i % 2 == 0) {
continue;
}
printf("%d ", i);
i++;
}
Ya i++'ı continue'nun üstüne taşıyın, ya da bunu, başlığın yanlış yapmayı imkânsız kıldığı bir for döngüsü olarak yazın.
switch İçindeki break, Döngüdeki break Değildir
break, kendisini saran en yakın döngüyü ya da switch'i bitirir - hangisi daha yakınsa. Bir döngünün içine switch koyun, içindeki her break switch'e aittir:
q komutu mesajını yazdırır ve döngü cc üzerinden dönmeye devam eder. Çıkışın döngüyü bitirmesi gerekiyorduysa, o break bunu yapmadı. Çözümler bir bayrak, bir goto ya da döngüyü bir fonksiyona taşıyıp return kullanmaktır - hepsi aşağıda.
İç İçe Döngülerden Kaçış
Tek bir break bir seviyeden çıkar. İç içe iki döngüde yalnızca içtekini bitirir ve dış döngü hiçbir şey olmamış gibi bir sonraki geçişine başlar.
C'de break 2 yoktur, etiketli break de yoktur. Üç dürüst seçenek:
Bir bayrak. Taşınabilir, açık ve biraz gürültülü:
Bayrak iki yerde görünür - dış koşulda ve atamada - ve bedeli budur. Üç seviye iç içelikte gerçekten can sıkıcı hâle gelir.
goto. C'nin çok yerilen atlaması ve deneyimli C programcılarının özür dilemeden kullandığı tek durum budur:
Döngülerin hemen ardındaki bir etikete ileri doğru bir goto, başka dillerde etiketli bir break'in yapacağı şeyi tek satırda ve senkron tutulacak bir bayrak olmadan yapar. goto'nun ünü, gerçekten okunmaz bir denetim akışı üreten geri atlamalar ve başka blokların ortasına yapılan atlamalarla kazanılmıştır. İç içe döngülerden tek bir ileri atlama bunlardan değildir. Linux çekirdeği temizlik yolları için aynı kalıbı kullanır. Bilinçli ve az kullanın; tabunun sizi okunması daha zor, üç bayraklı bir alternatife itmesine izin vermeyin.
Bir fonksiyon ve return. Genellikle en iyi cevap, çünkü bir arama bir isim hak eder:
return, fonksiyondaki her döngüyü çözer, ne bayrak ne etiket ister ve arama kodunun artık bir ismi vardır, tek başına test edilebilir. İç içelik, ondan kaçmanın sorun olacağı kadar derinleştiyse, bu çoğu zaman o bloğun zaten bir fonksiyon olmak istediğinin işaretidir.
Ne Zaman Yardım Ederler, Ne Zaman Zarar Verirler
break ve continue, tüm gövdeyi bir if içine sarmak yerine bir döngünün "bu durum bitti" demesini en tepede, bir kez sağladıklarında yerlerini hak ederler. Karşılaştırın:
/* continue ile: asıl iş girintili değil */
for (int i = 0; i < n; i++) {
if (!isValid(a[i])) continue;
if (isDuplicate(a[i])) continue;
process(a[i]);
}
/* onsuz: her koruma bir seviye ekler */
for (int i = 0; i < n; i++) {
if (isValid(a[i])) {
if (!isDuplicate(a[i])) {
process(a[i]);
}
}
}
Sayıları çoğaldığında zarar verirler. Dağınık beş break ve üç continue içeren bir döngünün, hiçbir yerde yazılı olmayan bir çıkış koşulu vardır - okuyanın, ne zaman durduğunu bilmek için tüm gövdeyi zihninde canlandırması gerekir. İyi çalışan iki kural: continue korumalarını gövdenin en tepesinde bir arada tutun ve bir döngüde birden ya da ikiden fazla break varsa, o işi başlıktaki koşulun yapması gerekip gerekmediğini düşünün.
İki küçük tuzak daha. Bir do-while içinde continue, zaten sıradaki şey olan alttaki teste atlar - zararsız, ama insanları şaşırtır. Ve herhangi bir döngü ya da switch dışındaki break bir derleme hatasıdır; burada derleyicinin sizin için yakaladığı tek hata odur.
Sıkça Sorulan Sorular
C'de break ile continue arasındaki fark nedir?
break döngüyü tamamen bitirir ve yürütme döngüden sonra devam eder. continue yalnızca mevcut geçişi terk eder ve bir sonrakine geçer - bir for döngüsünde güncellemeye, bir while ya da do-while içinde doğrudan koşul testine.
C'de iç içe bir döngüden nasıl çıkarım?
Tek bir break yalnızca en içteki döngüden çıkar. İkisinden birden çıkmak için ya bir bayrak kurup dış döngünün koşulunda test edin, ya döngülerden sonraki bir etikete atlamak için goto kullanın, ya da - genellikle en temizi - döngüleri bir fonksiyona taşıyıp return yapın.
break döngüden mi yoksa yalnızca switch'ten mi çıkar?
Onu en sıkı saran hangisiyse ondan. Bir döngünün içindeki bir switch'in içindeki break yalnızca switch'i bitirir; döngü devam eder. Bir switch'in içinden döngüden çıkmak için bir bayrağa, bir goto'ya ya da bir return'e ihtiyacınız var.
while döngümde continue neden sonsuz döngüye yol açıyor?
Çünkü continue koşula atlar ve gövdenin geri kalanını - sonda duruyorsa sayaç artırımı dahil - atlar. Bir for döngüsünde güncelleme başlıkta durur, dolayısıyla her zaman çalışır; bir while döngüsünde güncellemeyi continue'nun üstüne taşıyın ya da bir for kullanın.