Percabangan if dan else

Kondisi, if bersarang, dan bentuk C++17 if dengan initializer.

Daftar isi

Percabangan menentukan jalur eksekusi yang ditempuh program berdasarkan hasil pengujian kondisi. Topik ini membahas pernyataan if beserta else dan rantai else if, bentuk if bersarang, serta bentuk C++17 if dengan initializer yang membatasi lingkup variabelnya. Setiap mekanisme disertai program utuh beserta keluaran aslinya, sehingga perilakunya dapat diuji ulang dengan compiler g++ apa adanya.

Kondisi pada pernyataan if#

Pernyataan if mengeksekusi blok pernyataannya hanya apabila kondisinya bernilai true. Kondisi tersebut berupa ekspresi yang dapat dikonversi menjadi bool, biasanya hasil operator perbandingan seperti >= atau ==. Apabila kondisi bernilai false, program melompati blok if dan melanjutkan eksekusi pada pernyataan berikutnya. Bentuk else menyediakan jalur cadangan yang dijalankan hanya ketika kondisi if tidak terpenuhi. Rantai else if menguji beberapa kondisi secara berurutan, dan C++ berhenti pada kondisi pertama yang terpenuhi, sehingga urutan pengujian ikut menentukan hasilnya.

Program berikut mengklasifikasikan nilai ujian ke dalam kategori A sampai D. Pengujian disusun dari ambang tertinggi ke ambang terendah, sehingga nilai 78 teruji terhadap batas 85 lebih dahulu, gagal, kemudian teruji terhadap batas 70 dan terpenuhi. Pola menyusun rentang dari atas ke bawah semacam ini menghindari tumpang tindih antara kategori.

cpp klasifikasi-nilai.cpp
#include <iostream>

int main() {
    int nilai = 78;

    if (nilai >= 85) {
        std::cout << "Kategori: A\n";
    } else if (nilai >= 70) {
        std::cout << "Kategori: B\n";
    } else if (nilai >= 55) {
        std::cout << "Kategori: C\n";
    } else {
        std::cout << "Kategori: D\n";
    }
    return 0;
}
text Keluaran
Kategori: B

Keluaran menunjukkan kategori B karena kondisi nilai >= 85 bernilai false dan kondisi nilai >= 70 bernilai true. Apabila urutan kedua kondisi itu dibalik, nilai apa pun di atas 70 akan teruji terhadap batas 70 lebih dahulu dan kategori A tidak pernah tercapai. Kesalahan logika semacam ini lolos dari pemeriksaan compiler karena sintaksnya sah.

if bersarang#

Sebuah if dapat ditempatkan di dalam blok if lain, dan susunan ini disebut if bersarang. Pemisahan yang tepat menempatkan syarat umum pada tingkat luar dan pengecekan rinci pada tingkat dalam, sehingga kondisi dalam hanya diuji ketika syarat luarnya terpenuhi. Urutan itu juga menghemat pengujian karena kondisi dalam tidak pernah dievaluasi ketika syarat luarnya gagal. Contoh berikut mengatur peminjaman buku perpustakaan, yaitu jumlah buku diperiksa lebih dahulu, kemudian lama pinjamnya.

Program berikut menerapkan pola tersebut dengan dua tingkat pengujian. Kedua tingkatnya menggunakan tanda kurung kurawal meskipun isinya hanya satu pernyataan. Kebiasaan ini menuntaskan keraguan tentang batas blok pada tingkat mana pun.

cpp peminjaman-buku.cpp
#include <iostream>

int main() {
    int jumlahBuku = 2;
    int lamaPinjam = 5;

    if (jumlahBuku <= 3) {
        if (lamaPinjam <= 7) {
            std::cout << "Peminjaman disetujui\n";
        } else {
            std::cout << "Lama pinjam melebihi batas\n";
        }
    } else {
        std::cout << "Jumlah buku melebihi batas\n";
    }
    return 0;
}
text Keluaran
Peminjaman disetujui

Nilai jumlahBuku bernilai 2 sehingga kondisi luar terpenuhi, kemudian kondisi dalam menguji lamaPinjam dan mencetak persetujuannya. Apabila jumlah buku sudah melebihi 3, kondisi dalam tidak pernah diuji sama sekali dan pesan pada else luar yang tampil. Pemisahan dua tingkat ini juga menghasilkan pesan yang lebih spesifik dibanding satu kondisi gabungan seperti jumlahBuku <= 3 && lamaPinjam <= 7. Satu kondisi gabungan hanya mampu menyatakan tolak atau terima, sedangkan bentuk bersarang dapat menjelaskan penyebab penolakan.

if dengan initializer (C++17)#

Sejak C++17, pernyataan if menerima satu pernyataan inisialisasi sebelum kondisinya dengan bentuk if (inisialisasi; kondisi). Variabel yang dideklarasikan pada bagian inisialisasi hidup sepanjang keseluruhan if beserta blok else-nya, kemudian musnah setelah percabangan selesai. Lingkup yang sempit itu menguntungkan karena variabel sementara tidak bocor ke kode di luar percabangan dan tidak mungkin diakses pada tempat yang tidak memerlukannya. Bentuk yang sama juga tersedia pada switch dengan kaidah lingkup yang identik.

Program berikut mencari petugas piket pada tabel hari yang disimpan dalam std::map milik pustaka standar. Pencarian dilakukan dengan fungsi anggota find. Fungsi ini mengembalikan iterator, yaitu penunjuk posisi elemen di dalam map, atau iterator end() apabila tidak ada data yang cocok. Kedua pencarian pada program ini menggunakan nama variabel cari yang sama karena masing-masing hanya hidup pada pernyataan if-nya sendiri.

cpp cari-piket.cpp
#include <iostream>
#include <map>
#include <string>

int main() {
    std::map<std::string, std::string> piket{
        {"Senin", "Ali"}, {"Rabu", "Budi"}, {"Jumat", "Citra"}};

    if (auto cari = piket.find("Rabu"); cari != piket.end()) {
        std::cout << "Petugas piket: " << cari->second << '\n';
    } else {
        std::cout << "Tidak ada piket terjadwal\n";
    }

    if (auto cari = piket.find("Selasa"); cari != piket.end()) {
        std::cout << "Petugas piket: " << cari->second << '\n';
    } else {
        std::cout << "Tidak ada piket terjadwal\n";
    }
    return 0;
}
text Keluaran
Petugas piket: Budi
Tidak ada piket terjadwal

Pada percabangan pertama, find menemukan kunci “Rabu” sehingga kondisi cari != piket.end() bernilai true dan nama petugasnya dicetak melalui cari->second. Percabangan kedua mencari “Selasa” yang tidak ada dalam tabel, sehingga blok else menampilkan pesan cadangan. Perbandingan terhadap end() merupakan cara standar membedakan hasil pencarian yang ditemukan dan yang gagal.

Kesalahan umum#

Kesalahan berikut sering muncul pada penulisan percabangan dan sebagian besar tidak menghasilkan pesan error. Pola semacam ini berbahaya karena program tetap terkompilasi, sedangkan alurnya menyimpang dari maksud penulisnya. Flag peringatan seperti -Wall membantu menangkap sebagiannya saat kompilasi.

  1. Operator penugasan = dipakai pada tempat perbandingan ==. Ekspresi if (nilai = 0) menugaskan 0 kepada nilai, kemudian mengujinya sebagai false, sehingga jalur program berubah tanpa pesan apa pun. Perbaikannya adalah penulisan == secara eksplisit disertai kompilasi dengan -Wall agar pola serupa terdeteksi sejak awal.
  2. Tanda titik koma tepat setelah kondisi. Penulisan if (kondisi); mengakhiri pernyataan dengan badan kosong, sehingga blok yang tampak sebagai isinya justru selalu dijalankan. Perbaikannya adalah penghapusan titik koma tersebut.
  3. else berpasangan dengan if terdalam yang masih terbuka. Pada if bersarang tanpa tanda kurung kurawal, else dapat berpindah pasangan ke if yang tidak dimaksud, dan hasilnya berupa logika yang berubah tanpa error kompilasi. Menuliskan kurung kurawal pada setiap tingkat menuntaskan keraguan semacam ini.

Ringkasan#

  • if mengeksekusi bloknya apabila kondisi bernilai true, sedangkan else if dan else menyediakan jalur alternatif yang dievaluasi berurutan dari atas ke bawah.
  • if bersarang menguji syarat umum di tingkat luar dan pengecekan rinci di tingkat dalam, dengan tanda kurung kurawal menjaga pasangan else tetap jelas.
  • Bentuk C++17 if (inisialisasi; kondisi) menempatkan variabel sementara pada lingkup yang berakhir bersama percabangannya, sehingga tidak ada kebocoran nama ke kode lain.

Referensi#