Perulangan menjalankan sekumpulan pernyataan berulang kali selama sebuah kondisi masih terpenuhi. Bahasa C menyediakan tiga bentuk perulangan, yaitu for, while, dan do-while, yang ketiganya bertumpu pada penghitung dan kondisi penghenti. Topik ini membahas cara kerja ketiga bentuk tersebut, konvensi penghitung perulangan, serta error off-by-one yang menggeser jumlah putaran satu kali.
Perulangan while#
Pernyataan while menguji kondisinya lebih dahulu, lalu menjalankan tubuh perulangan selama kondisi bernilai benar. Apabila kondisi bernilai salah sejak awal, tubuh tidak dijalankan sama sekali. Aturan nol dan selain nol berlaku sama seperti pada if, yaitu nol dianggap salah dan nilai selain nol dianggap benar. Sebuah perulangan yang berjalan benar membutuhkan tiga unsur, yaitu inisialisasi nilai awal sebelum while, kondisi penghenti, dan pembaruan di dalam tubuh agar kondisi pernah bernilai salah. Bila salah satu unsur hilang, hasilnya perulangan tak terbatas (infinite loop), yaitu perulangan yang tidak pernah berhenti.
Program berikut menghitung mundur dari lima sampai satu menggunakan while. Variabel detik berperan sebagai penghitung, yaitu variabel yang nilainya berubah pada setiap putaran untuk mengendalikan perulangan.
#include <stdio.h>
int main(void) {
int detik = 5;
while (detik > 0) {
printf("%d\n", detik);
detik = detik - 1;
}
printf("Selesai\n");
return 0;
}5
4
3
2
1
SelesaiBaris detik = detik - 1 merupakan pembaruannya, dan kelupaan menulis baris itu membuat detik > 0 tetap benar selamanya. Perhatikan pula bahwa printf("Selesai\n") berada di luar kurung kurawal, sehingga pernyataan itu baru dijalankan setelah perulangan berakhir. Menempatkan pernyataan di luar tubuh tanpa sengaja merupakan kekeliruan yang lazim. Apabila sebuah pernyataan tidak ikut berulang, periksa posisi kurung kurawalnya. Pola inisialisasi, pengujian, dan pembaruan inilah yang kemudian dipadatkan oleh for pada bagian berikutnya.
Perulangan for#
Pernyataan for memadatkan ketiga unsur perulangan pada satu baris kepala, yaitu inisialisasi, kondisi, dan pembaruan yang dipisahkan tanda titik koma. Bentuk ini tepat digunakan apabila jumlah putaran sudah diketahui atau dapat dihitung. Variabel penghitung boleh dideklarasikan langsung di dalam kepala for, dan sejak C99 deklarasi itu hanya berlaku di dalam perulangan tersebut.
Diagram berikut menunjukkan urutan eksekusi for dari inisialisasi, pengujian kondisi, tubuh, hingga pembaruan yang kembali menguji kondisi.
Untuk mengamati urutan itu secara bertahap, jalankan demo berikut. Tekan tombol Satu langkah berulang kali dan amati nilai i serta jumlah pada setiap fase, mulai dari pengujian kondisi, penjumlahan di tubuh, sampai pembaruan penghitung.
Contoh program berikut menjumlahkan bilangan 1 sampai 10 dengan penghitung i dan akumulator jumlah.
#include <stdio.h>
int main(void) {
int jumlah = 0;
for (int i = 1; i <= 10; i = i + 1) {
jumlah = jumlah + i;
}
printf("Jumlah 1 sampai 10 = %d\n", jumlah);
return 0;
}Jumlah 1 sampai 10 = 55Kepala for dieksekusi dengan urutan yang tetap. Inisialisasi int i = 1 dijalankan sekali, kemudian kondisi i <= 10 diuji sebelum setiap putaran, dan pembaruan i = i + 1 dijalankan setelah tubuh. Dengan demikian, tubuh berjalan tepat sepuluh kali, dari i bernilai 1 sampai 10, dan berhenti ketika i mencapai 11. Notasi i = i + 1 lazim diganti dengan i++ yang artinya sama, dan keduanya akan ditemui pada kode C mana pun.
Perulangan do-while#
Pernyataan do-while membalik urutan pengujian, yaitu tubuh dijalankan lebih dahulu dan kondisi diuji sesudahnya. Akibatnya, tubuh selalu dieksekusi minimal satu kali, sekalipun kondisi bernilai salah sejak awal. Bentuk ini cocok untuk interaksi yang memang harus terjadi sekali sebelum dapat divalidasi, misalnya menampilkan pertanyaan dan membaca jawaban pengguna.
Program berikut meminta nomor antrean dan mengulang permintaannya selama masukan berada di luar rentang 1 sampai 3. Program ini membaca masukan lewat scanf. Agar tidak perlu mengetik secara langsung, masukan disalurkan melalui pipe pada perintah kompilasi dan eksekusi berikut.
// tidak-dijalankan
#include <stdio.h>
int main(void) {
int pilihan;
do {
printf("Pilih nomor antrean 1-3: ");
scanf("%d", &pilihan);
if (pilihan < 1 || pilihan > 3) {
printf("Nomor harus di antara 1 dan 3.\n");
}
} while (pilihan < 1 || pilihan > 3);
printf("Nomor antrean %d diproses.\n", pilihan);
return 0;
}# kompilasi program validasi
gcc validasi-pilihan.c -o validasi-pilihan
# beri masukan 7, 0, dan 2 lewat pipe agar tidak menunggu ketikan
printf "7\n0\n2\n" | ./validasi-pilihanPilih nomor antrean 1-3: Nomor harus di antara 1 dan 3.
Pilih nomor antrean 1-3: Nomor harus di antara 1 dan 3.
Pilih nomor antrean 1-3: Nomor antrean 2 diproses.Keluaran memperlihatkan tubuh dijalankan sebelum kondisi sempat diuji, sehingga pertanyaan pertama selalu muncul. Masukan 7 dan 0 gagal memenuhi kondisi akhir pilihan >= 1 && pilihan <= 3, sehingga permintaan diulang. Masukan 2 lolos, kondisi bernilai salah, dan eksekusi berlanjut ke pernyataan sesudah perulangan. Struktur while tidak cocok untuk pola ini tanpa penyesuaian karena kondisi penghentinya baru dapat dihitung setelah masukan pertama dibaca. Apabila masukan habis sebelum angka valid diperoleh, scanf tidak mengisi pilihan, sehingga program yang tangguh memeriksa nilai kembalian scanf sebelum nilai pilihan dipakai.
Error off-by-one#
Error off-by-one adalah kekeliruan yang menggeser jumlah putaran satu kali, lebih banyak atau lebih sedikit dari yang dimaksudkan. Penyebabnya hampir selalu ada pada batas kondisi, misalnya menukar < dengan <=, atau pada titik mulai penghitung yang tertukar antara 0 dan 1. Istilah ini muncul karena selisihnya memang tepat satu. Error semacam ini tidak memicu pesan apa pun, sehingga hanya terlihat dari keluaran yang berlebih atau kurang.
Program berikut dimaksudkan mencetak sepuluh baris, tetapi kondisinya sengaja ditulis keliru sehingga berjalan sebelas kali.
#include <stdio.h>
int main(void) {
/* dimaksudkan mencetak sepuluh baris, tetapi berjalan sebelas kali */
for (int i = 0; i <= 10; i = i + 1) {
printf("Baris %d\n", i);
}
return 0;
}Baris 0
Baris 1
Baris 2
Baris 3
Baris 4
Baris 5
Baris 6
Baris 7
Baris 8
Baris 9
Baris 10Kondisi i <= 10 tetap benar hingga i bernilai 10, sehingga tubuh dijalankan sebelas kali untuk i dari 0 sampai 10. Perbaikannya adalah i < 10, yang menjalankan tubuh tepat sepuluh kali. Kaidah yang dapat dipegang: apabila penghitung dimulai dari 0 dan putaran yang diinginkan sebanyak n, tuliskan i < n, sedangkan apabila dimulai dari 1, tuliskan i <= n. Perhatikan pula bahwa pada for (int i = 0; ...), penghitung i tidak dapat dibaca lagi setelah perulangan selesai karena lingkup deklarasinya terbatas pada perulangan tersebut. Kebiasaan menulis i < n untuk penghitung berbasis nol juga membuat kode C dari berbagai sumber terbaca dengan cara yang sama.
Ringkasan#
whilemenguji kondisi sebelum tubuh, sedangkando-whilemengujinya sesudah tubuh sehingga tubuh minimal berjalan sekali.formemadatkan inisialisasi, kondisi, dan pembaruan dalam satu kepala perulangan.- Penghitung perulangan harus diperbarui agar kondisi pernah bernilai salah, kalau tidak perulangan berjalan tak terbatas.
- Kaidah
i < nuntuk penghitung berbasis nol menjaga jumlah putaran tetap tepat dan mencegah error off-by-one.
Referensi#
- while loop — Cppreference — Kaidah perulangan while beserta evaluasi kondisinya.
- for loop — Cppreference — Kaidah klausa inisialisasi, kondisi, dan pembaruan pada for, termasuk lingkup deklarasi sejak C99.
- do-while loop — Cppreference — Kaidah perulangan do-while yang menguji kondisi setelah tubuhnya.