Menu

Perulangan While di C: Sintaks, Contoh, dan Kesalahan Umum

Cara while loop di C mengulang sampai sebuah kondisi berubah: aturan kondisi-dicek-dulu, perulangan dengan sentinel, membaca input sampai EOF, while(1), dan mengubah for menjadi while atau sebaliknya.

Halaman ini dilengkapi editor yang bisa dijalankan. Edit, jalankan, dan lihat output-nya seketika.

Mengulang Tanpa Hitungan

for loop adalah alat yang tepat jika kamu tahu, atau bisa menghitung, berapa putaran yang dibutuhkan. Banyak pekerjaan yang tidak datang dengan hitungan. Baca setiap baris sebuah file sampai habis. Terus minta password sampai benar. Bagi dua sebuah bilangan sampai mencapai 1. Untuk kasus seperti ini, pertanyaannya bukan "berapa kali" tetapi "sampai kapan", dan itulah persis yang dinyatakan while.

Tidak ada yang menghitung "tujuh" sebelumnya. Perulangannya hanya terus berjalan selama kondisinya terpenuhi.

Sintaks dan Aturan Kondisi Dicek Lebih Dulu

while (condition) {
    // body - runs while the condition is nonzero
}

Kondisinya diuji sebelum setiap putaran, termasuk putaran pertama. Ada tiga akibatnya:

  • Perulangan yang kondisinya sejak awal bernilai salah berjalan nol kali. while (0) { ... } tidak pernah menjalankan badannya.
  • Apa pun yang diuji kondisinya harus diinisialisasi sebelum perulangan, atau kamu sedang menguji nilai sampah.
  • Ada sesuatu di dalam badan perulangan yang pada akhirnya harus membuat kondisinya bernilai salah, atau perulangannya tidak akan pernah berhenti.

Seperti if, tanda kurungnya wajib dan tidak ada titik koma sesudahnya. Titik koma nyasar itu adalah versi perulangan dari bug yang sama:

/* BUG: the empty statement is the body - this spins forever */
while (i < 10);
{
    printf("%d\n", i);
    i++;
}

i tidak pernah ditambah, jadi kondisinya tidak pernah berubah. gcc -Wall menandai badan perulangan yang kosong.

Aturan nilai benar dan salah di C berlaku di sini persis seperti di if/else: perulangannya berlanjut selama ekspresinya bernilai bukan nol, dan berhenti saat bernilai nol.

Bentuk Standar: Inisialisasi, Uji, Perbarui

Hampir setiap while loop yang benar punya tiga bagian yang tersebar di tiga tempat:

Itulah tiga bagian yang sama yang ada di header for, hanya saja tidak dikumpulkan dalam satu baris. Dan itulah jawaban jujur untuk "for atau while?": jika ketiga bagiannya menyangkut satu penghitung, for menaruhnya di tempat yang bisa dicek pembaca sekaligus. Jika pembaruannya tersebar di badan yang panjang, atau kondisinya bukan soal hitungan, while adalah bentuk yang lebih jelas.

Lupa bagian ke-3 adalah bug while loop yang paling klasik. Jika sebuah perulangan macet, hal pertama yang perlu dicek adalah apakah badannya benar-benar mengubah apa yang dibaca kondisinya.

Perulangan dengan Sentinel

Sentinel adalah nilai khusus yang berarti "berhenti". Jumlahkan bilangan sampai pengguna memasukkan 0:

99 setelah 0 tidak pernah dijangkau, karena sentinel sudah mengakhiri perulangannya. Perhatikan bahwa jumlah bilangannya tidak pernah diketahui sebelumnya, dan itulah persis alasan ini menjadi while.

String di C bekerja dengan cara yang sama: diakhiri sentinel '\0', jadi menelusurinya adalah contoh while yang klasik:

Membaca Input Sampai EOF

Pemakaian while paling umum di dunia nyata adalah membaca input sampai habis. Aturannya adalah uji nilai kembalian fungsi input-nya, bukan nilai yang disimpannya.

getchar mengembalikan karakter berikutnya, atau konstanta EOF saat input habis:

Dua detail yang penting. c bertipe int karena EOF adalah nilai negatif yang tidak muat di char pada banyak sistem; mendeklarasikannya sebagai char bisa membuat perbandingannya tidak pernah berhasil. Selain itu, assignment-nya berada di dalam kondisi: (c = getchar()) != EOF membaca sebuah karakter, menyimpannya, dan membandingkannya dalam satu langkah. Tanda kurung bagian dalam itu wajib, karena != mengikat lebih kuat daripada =; tanpanya, kamu akan menyimpan hasil perbandingannya ke c. Ini salah satu dari sedikit tempat di mana assignment di dalam kondisi adalah idiom, bukan bug.

Bentuk yang sama bekerja dengan scanf, yang nilai kembaliannya adalah jumlah item yang berhasil dikonversi:

int n;
while (scanf("%d", &n) == 1) {
    /* n holds a valid number */
}

Perulangannya berakhir di akhir file dan pada input pertama yang bukan angka, dan biasanya itulah yang kamu inginkan.

Yang tidak boleh kamu tulis adalah while (!feof(f)). feof melaporkan apakah sebuah pembacaan sudah gagal, jadi nilainya masih salah saat kamu berada di item terakhir, badan perulangannya berjalan sekali lagi, dan pembacaannya gagal, sehingga data lama ikut diproses. Uji pembacaannya langsung.

while (1) dan break

Kadang kondisi keluarnya baru diketahui di tengah badan perulangan: setelah membaca, tetapi sebelum memproses. Jawaban idiomatisnya adalah perulangan yang sengaja dibuat tak berujung, dengan jalan keluar yang eksplisit:

while (1) selalu bernilai benar, jadi satu-satunya jalan keluar adalah break (atau return, atau exit). Kamu juga akan melihat for (;;) dipakai untuk tujuan yang sama; keduanya menghasilkan kode yang sama, dan mana yang dipilih sebuah codebase hanyalah soal gaya.

Pakai bentuk ini jika pengujian keluarnya memang seharusnya berada di tengah badan perulangan. Jika pengujiannya pas diletakkan di atas, taruh di kondisi supaya terlihat oleh pembaca. while (1) yang satu-satunya break-nya ada di pernyataan pertama hanyalah kondisi yang menyamar.

Mengubah for Menjadi while dan Sebaliknya

Setiap for loop bisa ditulis sebagai while loop, dan sebaliknya. Pemetaannya mekanis:

/* for */                          /* equivalent while */
for (init; cond; update) {         init;
    body;                          while (cond) {
}                                      body;
                                       update;
                                   }

Jadi kedua kode ini mencetak hal yang sama:

Satu-satunya tempat kesetaraan ini bocor adalah continue. Di for loop, continue melompat ke pembaruan di header, jadi penghitungnya tetap bertambah. Di versi while, continue langsung melompat kembali ke kondisi dan melewati i++ di akhir badan perulangan, sehingga langsung terjadi infinite loop:

/* BUG: continue skips i++, so the loop spins forever on the first even number */
int i = 0;
while (i < 10) {
    if (i % 2 == 0) {
        continue;
    }
    printf("%d ", i);
    i++;
}

Jika sebuah while loop memakai continue, pastikan pembaruannya terjadi sebelumnya, atau pakai for, di mana header-nya menjamin pembaruan itu.

Jebakan Umum

  • Tidak ada yang memperbarui kondisi. Badan perulangan harus mengubah apa yang dibaca kondisinya. Jika program macet, cek di sini dulu.
  • Titik koma setelah header. while (cond); membuat pernyataan kosong menjadi badannya.
  • Menguji variabel yang tidak pernah diinisialisasi. Kondisinya dijalankan sebelum badannya, jadi nilai yang dibacanya harus sudah ada.
  • char alih-alih int untuk getchar. EOF tidak muat di char; akibatnya perbandingannya bisa tidak pernah bernilai benar, atau byte yang sah bisa dikira EOF.
  • while (!feof(f)). Mengulang satu kali terlalu banyak. Uji pembacaannya.
  • Menganggap badannya pasti dijalankan setidaknya sekali. Tidak. Jika kamu butuh satu putaran yang dijamin, misalnya mencetak menu sebelum mengecek pilihan, itulah gunanya do-while loop.

Pertanyaan yang sering diajukan

Bagaimana cara menulis while loop di C?

while (condition) { body }. Kondisinya diuji sebelum setiap putaran, jadi badannya hanya dijalankan selama kondisinya bernilai bukan nol, dan sama sekali tidak dijalankan jika sejak awal bernilai salah. Ada sesuatu di dalam badan perulangan yang harus mengubah kondisinya pada akhirnya, atau perulangannya tidak akan pernah berhenti.

Apa perbedaan for dan while di C?

Keduanya sama kuatnya: setiap for bisa ditulis ulang sebagai while. Pakai for jika sebuah penghitung, batasnya, dan langkahnya memang satu kesatuan dalam satu header, dan while jika kondisi berhentinya bukan hitungan: membaca sampai akhir file, mencoba ulang sampai berhasil, atau mengulang sampai sebuah flag berubah.

Bagaimana cara membaca input sampai EOF di C?

Uji nilai kembalian fungsi input-nya, bukan nilai yang dibacanya: while (scanf("%d", &n) == 1) { ... } berhenti di akhir file atau pada input pertama yang bukan angka, dan while ((c = getchar()) != EOF) { ... } membaca karakter demi karakter. Jangan pernah mengulang dengan while (!feof(f)), karena perulangannya berjalan satu kali lebih banyak setelah akhir file.

Kenapa while loop saya tidak pernah berhenti di C?

Biasanya karena tidak ada yang mengubah nilai yang diuji kondisinya di dalam badan perulangan, atau karena ada titik koma nyasar setelah header (while (i < 10);) yang membuat pernyataan kosong menjadi badannya. Keduanya bisa di-compile tanpa masalah, jadi pastikan badan perulangannya benar-benar memperbarui variabel yang diuji kondisi.

Ilustrasi bahasa pemrograman di Coddy

Belajar coding dengan Coddy

Mulai