Sayı Olmadan Tekrarlamak
Bir for döngüsü, kaç geçişe ihtiyacınız olduğunu bildiğinizde - ya da hesaplayabildiğinizde - doğru araçtır. Pek çok iş bir sayıyla gelmez. Bir dosyanın her satırını bitene dek okuyun. Doğru olana dek parola sormaya devam edin. Bir sayıyı 1'e ulaşana dek yarılayın. Bunlar için soru "kaç kez" değil "ne zamana kadar"dır ve while'ın ifade ettiği tam olarak budur.
Kimse önceden "yedi"yi hesaplamadı. Döngü yalnızca koşul geçerli olduğu sürece devam ediyor.
Söz Dizimi ve Önce-Koşul Kuralı
while (kosul) {
// gövde - koşul sıfırdan farklı olduğu sürece çalışır
}
Koşul ilk geçiş dahil her geçişten önce test edilir. Üç sonuç:
- Koşulu baştan yanlış olan bir döngü sıfır kez çalışır.
while (0) { ... }gövdeyi hiç çalıştırmaz. - Koşulun test ettiği şeye döngüden önce ilk değer verilmelidir, yoksa çöp bir değeri test ediyorsunuzdur.
- Gövdedeki bir şey eninde sonunda koşulu yanlış yapmalıdır, yoksa döngü hiç bitmez.
if gibi parantezler zorunludur ve onlardan sonra noktalı virgül yoktur. O başıboş noktalı virgül, aynı hatanın döngü sürümüdür:
/* HATA: boş deyim gövdedir - bu sonsuza dek döner */
while (i < 10);
{
printf("%d\n", i);
i++;
}
i hiç artırılmaz, dolayısıyla koşul hiç değişmez. gcc -Wall boş gövdeyi işaretler.
C'nin doğruluk kuralı burada tam olarak if/else'te olduğu gibi geçerlidir: döngü, ifade sıfırdan farklı olduğu sürece devam eder ve sıfır olduğunda durur.
Standart Biçim: İlk Değer, Test, Güncelleme
Neredeyse her doğru while döngüsünün üç yere yayılmış üç parçası vardır:
Bunlar bir for başlığının tuttuğu aynı üç parçadır, yalnızca tek satırda toplanmamıştır. "for mu while mi?" sorusunun dürüst cevabı da budur: üç parça da tek bir sayaçla ilgiliyse bir for onları okuyucunun birlikte denetleyebileceği yere koyar. Güncelleme uzun bir gövdeye dağılmışsa ya da koşul bir sayıdan başka bir şeyle ilgiliyse while daha açık biçimdir.
- parçayı unutmak tek while döngüsü hatasıdır. Bir döngü takılırsa kontrol edilecek ilk şey, gövdenin koşulun okuduğu şeyi gerçekten değiştirip değiştirmediğidir.
Nöbetçi Döngüleri
Nöbetçi, "dur" anlamına gelen özel bir değerdir. Kullanıcı 0 girene dek sayıları toplayın:
0'dan sonraki 99'a hiç ulaşılmaz - nöbetçi döngüyü bitirdi. Sayıların adedinin hiçbir zaman önceden bilinmediğine dikkat edin; tam olarak bu yüzden bu bir while'dır.
C metinleri de aynı şekilde çalışır: bir '\0' nöbetçisiyle biterler, dolayısıyla birini dolaşmak ders kitabı bir while'dır:
EOF'a Kadar Girdi Okumak
Gerçek dünyadaki en yaygın while, girdi kalmayana dek okur. Kural, girdi fonksiyonunun dönüş değerini test etmektir, sakladığı değeri değil.
getchar sonraki karakteri ya da girdi tükendiğinde EOF sabitini döndürür:
Önemli iki ayrıntı. c bir int'tir, çünkü EOF pek çok sistemde bir char'a sığmayan negatif bir değerdir - onu char bildirmek karşılaştırmanın hiç başarılı olmamasına yol açabilir. Ve atama koşulun içinde durur: (c = getchar()) != EOF, bir karakter okur, saklar ve tek adımda karşılaştırır. İçteki parantezler zorunludur, çünkü !=, ='den daha sıkı bağlanır; onlar olmadan karşılaştırmanın sonucunu c'ye saklardınız. Bu, koşul içindeki atamanın bir hata değil deyimsel olduğu birkaç yerden biridir.
Aynı biçim, dönüş değeri başarıyla dönüştürülen öğe sayısı olan scanf ile de çalışır:
int n;
while (scanf("%d", &n) == 1) {
/* n geçerli bir sayı tutuyor */
}
Döngü, dosya sonunda ve sayı olmayan ilk girdide biter ki bu genellikle istediğiniz şeydir.
Yazmamanız gereken şey while (!feof(f))'tir. feof, bir okumanın çoktan başarısız olup olmadığını bildirir, dolayısıyla son öğenin üzerinde otururken hâlâ yanlıştır, döngü gövdesi bir kez daha çalışır ve okuma başarısız olur - bayat veri işlenir. Okumanın kendisini test edin.
while (1) ve break
Bazen çıkış koşulu yalnızca gövdenin ortasında bilinir - okuduktan sonra, ama işlemeden önce. Deyimsel cevap, açık bir çıkışı olan kasıtlı bir sonsuz döngüdür:
while (1) her zaman doğrudur, dolayısıyla tek çıkış yolu break'tir (ya da return ya da exit). Aynı amaçla kullanılan for (;;) de göreceksiniz; aynı şeye derlenirler ve bir kod tabanının hangisini tercih ettiği bir tarz sorusudur.
Bu biçimi, çıkış testi gerçekten gövdenin ortasına ait olduğunda kullanın. Test doğal olarak tepeye sığdığında onu okuyucunun görebileceği koşula koyun - tek break'i ilk deyim olan bir while (1), kılık değiştirmiş bir koşuldan ibarettir.
for ile while Arasında Dönüşüm
Her for döngüsü bir while döngüsü olarak ve tersi şekilde yazılabilir. Eşleme mekaniktir:
/* for */ /* eşdeğer while */
for (ilk; kosul; guncelle) { ilk;
govde; while (kosul) {
} govde;
guncelle;
}
Dolayısıyla bu ikisi aynı şeyi yazdırır:
Eşdeğerliğin sızdığı tek yer continue'dur. Bir for döngüsünde continue, başlıktaki güncellemeye atlar, dolayısıyla sayaç yine ilerler. while sürümünde continue doğrudan koşula geri atlar ve gövdenin sonundaki i++'ı atlar - anlık bir sonsuz döngü:
/* HATA: continue i++'ı atlar, dolayısıyla döngü ilk çift sayıda sonsuza dek döner */
int i = 0;
while (i < 10) {
if (i % 2 == 0) {
continue;
}
printf("%d ", i);
i++;
}
Bir while döngüsü continue kullanıyorsa, güncellemenin ondan önce gerçekleştiğinden emin olun - ya da başlığın bunu garanti ettiği bir for kullanın.
Sık Yapılan Hatalar
- Hiçbir şey koşulu güncellemiyor. Gövde, koşulun okuduğu şeyi değiştirmelidir. Bir program takılırsa önce buraya bakın.
- Başlıktan sonra noktalı virgül.
while (kosul);boş deyimi gövde yapar. - Hiç ilk değer verilmemiş bir değişkeni test etmek. Koşul gövdeden önce çalışır, dolayısıyla okuduğu değerin çoktan var olması gerekir.
getchariçinintyerinechar.EOFbirchar'a sığmaz; karşılaştırma o zaman hiç doğru olamayabilir ya da geçerli bir baytEOFsanılabilir.while (!feof(f)). Bir kez fazla döner. Okumayı test edin.- Gövdenin en az bir kez çalışacağını varsaymak. Çalışmaz. Bir garantili geçişe ihtiyacınız olduğunda - seçimi denetlemeden önce bir menü yazdırmak - bu bir do-while döngüsüdür.
Sıkça Sorulan Sorular
C'de bir while döngüsü nasıl yazılır?
while (kosul) { govde }. Koşul her geçişten önce test edilir, dolayısıyla gövde yalnızca koşul sıfırdan farklıyken çalışır ve baştan yanlışsa hiç çalışmaz. Gövdenin içindeki bir şey eninde sonunda koşulu değiştirmelidir, yoksa döngü hiç bitmez.
C'de for ile while arasındaki fark nedir?
Eşit derecede güçlüdürler - her for bir while olarak yeniden yazılabilir. Bir sayaç, sınırı ve adımı tek bir başlıkta bir arada durduğunda for, durma koşulu bir sayı olmadığında while kullanın: dosya sonuna kadar okumak, başarana dek yeniden denemek ya da bir bayrak dönene dek döngü kurmak.
C'de EOF'a kadar nasıl girdi okurum?
Okunan değeri değil, girdi fonksiyonunun dönüş değerini test edin: while (scanf("%d", &n) == 1) { ... }, dosya sonunda ya da ilk sayısal olmayan girdide durur ve while ((c = getchar()) != EOF) { ... } karakter karakter okur. Asla while (!feof(f)) ile döngü kurmayın - sonun ötesinde fazladan bir kez çalışır.
while döngüm neden sonsuz?
Genellikle gövdede koşulun test ettiği değeri değiştiren hiçbir şey olmadığı ya da başlıktan sonraki başıboş bir noktalı virgül (while (i < 10);) boş deyimi gövde yaptığı için. İkisi de tertemiz derlenir, dolayısıyla gövdenin koşulun değişkenini gerçekten güncellediğini kontrol edin.