Loop yang sudah kita kuasai bekerja pada satu dimensi: satu baris deret, satu daftar nilai. Tetapi banyak data kehidupan nyata berdimensi dua — tabel perkalian, papan catur, sel di layar, koordinat baris-kolom pada matriks. Untuk mengunjungi setiap sel, kita perlu loop yang berjalan di dalam loop lain: loop luar mengatur baris, loop dalam mengatur kolom. Pola nested loop ini sederhana strukturnya, tetapi menyimpan dua hal yang wajib dipahami sejak awal: jumlah iterasi yang berlipat kali, dan fakta bahwa break dari Chapter break dan continue hanya tembus satu lapis. Keduanya kita bedah lewat contoh nyata di Chapter ini.
Struktur Loop di Dalam Loop #
Program berikut mencetak grid perkalian 3x3. Loop luar mengurus baris, loop dalam mengurus kolom, dan setiap sel diisi hasil perkaliannya:
#include <iostream>
int main() {
for (int baris = 1; baris <= 3; ++baris) {
for (int kolom = 1; kolom <= 3; ++kolom) {
std::cout << baris * kolom;
if (kolom < 3) {
std::cout << " ";
}
}
std::cout << "\n";
}
return 0;
}Output yang Dihasilkan:
1 2 3
2 4 6
3 6 9Mari kita ikuti eksekusinya:
- Baris 6 (loop luar):
barisdimulai dari 1. SEMUA pekerjaan untuk baris 1 harus selesai dulu sebelumbarisnaik ke 2 — itulah makna loop di dalam loop. - Baris 7 (loop dalam): untuk baris 1, loop dalam berputar tiga kali memproses kolom 1, 2, 3 — mencetak
1, lalu2, lalu3, dengan pemisah dua spasi di antaranya (dilewati di kolom terakhir agar baris tidak berakhiran spasi). - Baris 12 (
std::cout << "\n";): baris baru ini MILIK loop luar — perhatikan indentasinya. Ia berjalan sekali setiap kali loop dalam selesai, sehingga setiap baris grid tampil pada baris teksnya sendiri. - Putaran berikutnya:
barisnaik ke 2, loop dalam dimulai lagi dari kolom 1, dan siklus berulang hingga baris 3 selesai.
Perhatikan bahwa kedua loop memakai nama variabel berbeda — baris dan kolom. Menamai keduanya i dan j lazim di kode nyata, tetapi nama deskriptif membuat kesalahan seperti menulis baris di tempat kolom jauh lebih mudah terdeteksi.
Iterasi Berlipat: 3 x 3 = 9 #
Grid di atas terlihat ringan, tetapi biayanya tersembunyi: total putaran adalah HASIL KALI jumlah putaran kedua loop. Kita buktikan dengan counter — program yang sama, kali ini dicatat setiap langkahnya:
#include <iostream>
int main() {
int hitungan = 0;
for (int baris = 1; baris <= 3; ++baris) {
for (int kolom = 1; kolom <= 3; ++kolom) {
++hitungan;
std::cout << "Iterasi " << hitungan
<< ": baris " << baris
<< ", kolom " << kolom << "\n";
}
}
std::cout << "Total iterasi: " << hitungan << "\n";
return 0;
}Output yang Dihasilkan:
Iterasi 1: baris 1, kolom 1
Iterasi 2: baris 1, kolom 2
Iterasi 3: baris 1, kolom 3
Iterasi 4: baris 2, kolom 1
Iterasi 5: baris 2, kolom 2
Iterasi 6: baris 2, kolom 3
Iterasi 7: baris 3, kolom 1
Iterasi 8: baris 3, kolom 2
Iterasi 9: baris 3, kolom 3
Total iterasi: 9Jejaknya memperlihatkan urutan yang khas: kolom berputar cepat (1, 2, 3) untuk setiap baris yang berputar lambat. Totalnya 9 = 3 x 3 — dan di sinilah lipatan itu terasa: bila loop luar 1000 kali dan loop dalam 1000 kali, badan dalam berjalan 1.000.000 kali. Dua lapis lagi (nested tiga tingkat) membuatnya satu miliar. Estimasi kasar ini perlu dilakukan SEBELUM menulis nested loop: jumlah dimensi mengalikan biaya, dan topik ini kita kaji ulang secara formal pada Section Performa dan Optimasi.
break Hanya Tembus Satu Lapis #
Kini kejutan yang dijanjikan. Ketika break dijalankan di dalam loop dalam, loop yang berhenti hanyalah loop DALAM — loop luar tidak tahu apa-apa dan melanjutkan putarannya. Contoh berikut mencetak pola segitiga; break di dalam loop dalam memotong baris sesuai panjangnya, dan perhatikan bahwa loop luar tetap berjalan penuh tiga kali:
#include <iostream>
int main() {
for (int baris = 1; baris <= 3; ++baris) {
for (int kolom = 1; kolom <= 3; ++kolom) {
if (kolom > baris) {
break; // keluar dari loop DALAM saja, loop luar lanjut
}
std::cout << kolom;
if (kolom < baris) {
std::cout << " ";
}
}
std::cout << "\n";
}
return 0;
}Output yang Dihasilkan:
1
1 2
1 2 3Untuk baris 1, loop dalam mencetak kolom 1 lalu break saat kolom mencapai 2. Yang mengejutkan pemula: loop luar TIDAK berhenti — baris 2 dan 3 tetap diproses, masing-masing dengan loop dalam barunya. break selalu menunjuk ke struktur kendali terdekat yang melingkupinya, dan struktur itu hanyalah loop dalam. Lalu bagaimana bila kita butuh berhenti dari SEMUA loop? Ada tiga jalan yang layak, dari yang paling kita sarankan:
- Fungsi dengan
return— pola terbaik bila tujuannya “cari sesuatu, selesai”: pindahkan nested loop ke dalam fungsi kecil, danreturnmengakhiri semua lapis sekaligus (seperticariAkarKuadratpada Chapter return). - Flag plus
breakbertingkat — gunakan variabelboolsebagai sinyal, lalu periksa di kedua loop seperti berikut. goto— ada di bahasa ini dan secara teknis bisa melompat keluar semua lapis, tetapi kita tidak menyarankannya: lompatan bebas membuat alur program sulit dilacak, dan dua cara di atas memenuhi kebutuhan nyata dengan lebih rapi.
Berikut pola flag dalam aksi: mencari pasangan angka yang jumlahnya 7, dan berhenti total begitu ketemu:
#include <iostream>
int main() {
bool ditemukan = false;
for (int a = 1; a <= 5 && !ditemukan; ++a) {
for (int b = 1; b <= 5; ++b) {
std::cout << "Menguji " << a << " + " << b << "\n";
if (a + b == 7) {
std::cout << "Ditemukan pasangan: " << a << " + " << b << " = 7\n";
ditemukan = true;
break; // keluar dari loop dalam
}
}
}
if (!ditemukan) {
std::cout << "Tidak ada pasangan\n";
}
return 0;
}Output yang Dihasilkan:
Menguji 1 + 1
Menguji 1 + 2
Menguji 1 + 3
Menguji 1 + 4
Menguji 1 + 5
Menguji 2 + 1
Menguji 2 + 2
Menguji 2 + 3
Menguji 2 + 4
Menguji 2 + 5
Ditemukan pasangan: 2 + 5 = 7Kuncinya di header loop luar: a <= 5 && !ditemukan membuat loop luar menolak putaran baru begitu flag menyala. Mekanismenya dua langkah — break menghentikan loop dalam seketika; loop luar kemudian selesai secara alami pada pemeriksaan kondisi berikutnya. Jejak output membuktikan efisiensinya: setelah “Menguji 2 + 5” menemukan 7, tidak ada satu pun baris “Menguji 3 + …” yang tercetak. Referensi formal for yang mendukung kondisi majemuk seperti ini ada di cppreference
.
Nested loop menuntaskan perulangan dua dimensi — tetapi semua variabel yang kita pakai selama ini (baris, kolom, hitungan) diam-diam menaikkan satu pertanyaan: di mana saja sebuah nama boleh dipakai, dan sampai kapan nilainya bertahan? Chapter terakhir section ini, Scope dan Lifetime Variabel, menjawabnya secara sistematis.