20. Pola perulangan
Hampir setiap perulangan adalah salah satu dari beberapa bentuk. Beri nama bentuk-bentuk itu dan kamu berhenti menciptakan setiap perulangan dari nol, lalu mengambil yang cocok. Bab ini membahas enam, masing-masing melakukan satu pekerjaan kecil. Akumulasi, hitung, cari, dan tanda memakai rentang angka di sini, dan bentuknya bekerja pada apa pun yang bisa kamu telusuri. Validasi input dan sentinel membaca dari keyboard.
1. Akumulasi: membangun hasil
Pegang sebuah variabel dan ubah setiap putaran. Total berjalan adalah contoh klasiknya:
sum := 0
for i := 1; i <= 10; i++ {
sum += i
}
fmt.Println(sum) // 55Bentuknya selalu: atur nilai awal sebelum perulangan, ubah
di dalam, pakai sesudahnya. Bentuk ini juga membangun
string (mulai dari "", sambung setiap potongan dengan
+=) dan mencari nilai terbesar (mulai dari nilai rendah,
naikkan setiap kali melihat yang lebih besar).
2. Hitung: berapa yang cocok?
Penghitung adalah akumulator yang naik satu, tetapi hanya kalau sebuah pemeriksaan lolos. "Berapa angka dari 1 sampai 30 yang habis dibagi 3?"
hits := 0
for i := 1; i <= 30; i++ {
if i%3 == 0 {
hits++
}
}
fmt.Println(hits) // 10if di dalam perulangan adalah pemeriksaannya;
hits++ adalah penghitungannya.
3. Cari: temukan yang pertama cocok lalu berhenti
Kalau kamu hanya butuh nilai pertama yang cocok,
break begitu menemukannya. Tidak ada gunanya
melanjutkan:
first := -1
for i := 1; i <= 100; i++ {
if i*i > 50 {
first = i
break
}
}
fmt.Println(first) // 8Jawabannya 8, karena 8 × 8 = 64 adalah kuadrat pertama di atas 50.
first butuh nilai awal, dan int di Go selalu berisi
angka. Jadi pilih angka yang tidak mungkin menjadi jawaban sungguhan.
-1 bisa dipakai di sini karena pencarian mulai dari 1, dan
itu jawaban "tidak ditemukan" yang sama dengan yang diberikan
strings.Index di Bab 14. Kalau tidak ada yang cocok,
first tetap -1, dan kamu bisa mengujinya
dengan if first == -1.
4. Tanda: apakah ada putaran yang cocok?
Terkadang kamu ingin jawaban ya atau tidak, bukan nilainya: "apakah
ada angka dari 1 sampai 20 yang habis dibagi 7?" Simpan sebuah bool yang
mulai dari false dan berubah menjadi true
begitu kamu melihat yang cocok:
found := false
for i := 1; i <= 20; i++ {
if i%7 == 0 {
found = true
}
}
fmt.Println(found) // trueProgram mencetak true karena 7 dan 14 ada dalam rentang.
Kalau kamu hanya peduli apakah ada, break saat
tandanya berubah, dan pola ini menjadi pencarian. Tanda dan cari adalah
pola yang bersaudara.
Buka exercises/20/01-patterns.go. File ini mengakumulasi
jumlah 1 sampai 20. Tambahkan pola hitung di bawahnya untuk mencetak
berapa angka genap dalam rentang itu.
5. Validasi input: bertanya sampai jawabannya baik
Bab 18 menunjukkan bahwa for kosong dengan
break berjalan setidaknya sekali. Itu cocok untuk
pertanyaan: tanya, periksa, dan tanya lagi kalau jawabannya tidak baik.
Ini adalah exercises/20/02-validate.go, di dalam
main:
reader := bufio.NewReader(os.Stdin)
var level int
for {
fmt.Print("Level (1 to 99): ")
text, _ := reader.ReadString('\n')
level, _ = strconv.Atoi(strings.TrimSpace(text))
if level >= 1 && level <= 99 {
break
}
fmt.Println("That is not a level from 1 to 99.")
}
fmt.Println("Level set to", level)Contoh sesi:
Level (1 to 99): abc
That is not a level from 1 to 99.
Level (1 to 99): 150
That is not a level from 1 to 99.
Level (1 to 99): 12
Level set to 12
Ada tiga hal di sini:
leveldideklarasikan sebelum perulangan, supaya masih ada setelah perulangan. Di dalamnya,level, _ =memakai=biasa untuk mengubahnya.text, _ :=boleh di dalam perulangan, walaupun berjalan berkali-kali. Setiap putaran adalah jalannya blok yang baru, jadi setiap putaran mendeklarasikantextyang baru.abctertangkap, tetapi bukan karena Go melaporkannya.strconv.Atoimemberikan0, seperti peringatan Bab 15, dan0berada di luar rentang. Jadi rentanglah yang menangkap teks yang salah. Kalau0adalah jawaban yang sah, pemeriksaan ini tidak bisa membedakannya dari teks yang salah. Bab 21 menunjukkan cara membaca laporan error dariAtoi, dan itu memperbaikinya.
Perulangan validasi hanya berakhir dengan jawaban yang baik. Kalau
input habis, misalnya ketika input datang dari file dan bukan dari
keyboard, setiap pembacaan berikutnya memberikan "",
angkanya 0, dan perulangan mencetak pesannya selamanya.
Hentikan dengan Ctrl + C. Membaca nilai kedua dari
ReadString, yang dijelaskan Bab 21, adalah cara program
mengetahui hal ini.
6. Sentinel: membaca sampai nilai khusus
Sering kali kamu tidak tahu berapa banyak nilai yang akan datang.
Sentinel adalah input khusus yang berarti "sudah
semua". Program ini membaca nilai sampai kata done, lalu
mencetak rata-ratanya. Ini adalah
exercises/20/03-sentinel.go, di dalam
main:
reader := bufio.NewReader(os.Stdin)
total := 0
count := 0
for {
fmt.Print("Score from 1 to 100, or done: ")
text, _ := reader.ReadString('\n')
answer := strings.TrimSpace(text)
if answer == "done" {
break
}
score, _ := strconv.Atoi(answer)
if score < 1 || score > 100 {
fmt.Println("Skipped.")
continue
}
total += score
count++
}
if count > 0 {
average := float64(total) / float64(count)
fmt.Printf("%d scores, average %.2f\n", count, average)
} else {
fmt.Println("No scores entered.")
}Contoh sesi:
Score from 1 to 100, or done: 80
Score from 1 to 100, or done: abc
Skipped.
Score from 1 to 100, or done: 91
Score from 1 to 100, or done: 150
Skipped.
Score from 1 to 100, or done: 74
Score from 1 to 100, or done: done
3 scores, average 81.67
Perulangan ini memakai pola yang sudah kamu kenal: mengakumulasi
total dan menghitung dengan count. Tiga hal
lagi:
- Sentinel diperiksa sebelum konversi, karena ia
berupa teks. Ini juga menghindari jebakan: dengan angka seperti
0sebagai sentinel, teks yang salah akan mengakhiri perulangan, karena teks yang salah juga memberikan0. continuedari Bab 18 melewati sisa putaran, jadi nilai yang salah tidak ditambahkan atau dihitung.count > 0menjaga pembagian, seperti di Bab 17.
Rata-rata adalah tempat tipe Go berpengaruh. total dan
count adalah int, jadi total / count adalah
pembagian bilangan bulat dan membuang pecahannya. Konversi keduanya ke
float64 dulu, seperti di Bab 13:
total := 245
count := 3
fmt.Println(total / count) // 81
fmt.Printf("%.2f\n", float64(total)/float64(count)) // 81.67Mencampur pola
Program nyata menggabungkan pola-pola ini. Satu kali jalan bisa mengakumulasi total, menghitung berapa yang cocok dengan suatu aturan, dan menandai apakah sesuatu yang khusus muncul, semuanya sekaligus:
total := 0
evens := 0
hasMultipleOf5 := false
for i := 1; i <= 10; i++ {
total += i // akumulasi
if i%2 == 0 {
evens++ // hitung
}
if i%5 == 0 {
hasMultipleOf5 = true // tanda
}
}
fmt.Println("total", total)
fmt.Println("evens", evens)
fmt.Println("multiple of 5?", hasMultipleOf5)Output:
total 55
evens 5
multiple of 5? true
Satu perulangan, tiga pola, tiga jawaban.
PR
Starter PR ada di exercises/20/homework/. Setiap starter
bisa langsung dijalankan dan mencetak satu baris pengganti.
Soal 1 — Faktorial
Buka exercises/20/homework/01-product.go. Dengan pola
akumulasi, kalikan angka 1 sampai 5 dan cetak hasilnya. (Petunjuk: hasil
kali mulai dari 1, bukan 0, karena apa pun
dikali nol adalah nol.)
Soal 2 — Hitung kelipatan
Buka exercises/20/homework/02-count-multiples.go. Dengan
pola hitung, cetak berapa angka dari 1 sampai 50 yang habis dibagi
7.
Soal 3 — Kuadrat besar pertama
Buka exercises/20/homework/03-first-big.go. Gunakan pola
cari untuk menemukan dan mencetak angka pertama yang kuadratnya di atas
200, dengan memeriksa dari 1 ke atas dan berhenti dengan
break.
Tantangan — Statistik rentang dalam satu jalan
Buka exercises/20/homework/04-stats.go. Dalam satu
perulangan atas 1 sampai 20, hitung dan cetak tiga hal: total
(akumulasi), berapa yang genap (hitung), dan apakah ada angka yang habis
dibagi 9 (tanda).
Stuck atau sudah selesai? Buka halaman solusi PR.