Percabangan switch / case

Perilaku fall-through pada switch, peran label default, dan kapan switch lebih tepat daripada rantai if.

Daftar isi

Percabangan switch memilih satu jalur eksekusi dari banyak kemungkinan nilai yang sudah diketahui. Struktur ini menjadi alternatif rantai else if apabila semua kasus berupa nilai tetap yang dapat didaftarkan satu per satu. Topik ini membahas struktur switch, case, dan default, perilaku fall-through yang muncul ketika break tidak ditulis, serta pertimbangan memilih switch daripada rantai if.

Struktur switch, case, dan default#

Pernyataan switch menguji nilai sebuah ekspresi bilangan bulat, lalu melompat ke label case yang nilainya sama. Label case wajib berupa konstanta, sehingga case 2 sah, sedangkan case nilai_input tidak. Ekspresi yang diuji boleh bertipe int, char, atau tipe bilangan bulat lain, tetapi tidak boleh string ataupun pecahan. Label default menampung semua nilai yang tidak cocok dengan label mana pun dan sifatnya opsional.

Bentuk umumnya dengan break pada setiap kasus tampak seperti berikut.

c Bentuk umum switch dengan break
// tidak-dijalankan
switch (ekspresi) {
case nilai1:
    /* pernyataan untuk nilai1 */
    break;
case nilai2:
    /* pernyataan untuk nilai2 */
    break;
default:
    /* pernyataan untuk nilai lain */
    break;
}

Program berikut menyimulasikan pemilihan layanan pada loket antrean tiket. Nilai pilihan ditetapkan sebelum pengujian, sehingga keluarannya tetap sama setiap kali program dijalankan.

c layanan-loket.c
#include <stdio.h>

int main(void) {
    int pilihan = 2;

    switch (pilihan) {
    case 1:
        printf("Layanan: tiket ekonomi\n");
        break;
    case 2:
        printf("Layanan: tiket eksekutif\n");
        break;
    case 3:
        printf("Layanan: pembatalan tiket\n");
        break;
    default:
        printf("Pilihan tidak tersedia\n");
        break;
    }

    return 0;
}
text Keluaran
Layanan: tiket eksekutif

Kata break di akhir setiap blok menghentikan eksekusi di dalam switch dan melanjutkan program pada pernyataan sesudahnya. Tanpa break, eksekusi jatuh ke pernyataan pada case di bawahnya, perilaku yang disebut fall-through. Perilaku ini bersifat bawaan bahasa C. Bagian berikutnya membahas fall-through beserta akibatnya. Penulisan label case yang sejajar dengan switch mengikuti kebiasaan umum agar daftar kasus mudah dipindai.

Perilaku fall-through#

Perilaku fall-through muncul apabila sebuah blok case tidak diakhiri break, sehingga eksekusi berlanjut ke pernyataan pada case di bawahnya tanpa memeriksa labelnya lagi. Label case hanyalah penanda titik lompatan, bukan pembatas blok. Diagram berikut memperlihatkan jalur eksekusi yang masuk pada label yang cocok, jatuh ke bawah ketika break tidak ada, dan keluar ketika break dijalankan.

switch (ekspresi)lompat ke label yang cocokcase Apernyataan Atanpa break: jatuhcase Bpernyataan BbreakLanjut setelah switchdefaultpernyataan laintidak ada yang cocok
Jalur eksekusi switch dengan fall-through, break, dan default

Program berikut memperlihatkan akibatnya. Blok case 1 sengaja tidak diberi break, sehingga pernyataan milik case 2 ikut terjalankan.

c lupa-break.c
#include <stdio.h>

int main(void) {
    int pilihan = 1;

    switch (pilihan) {
    case 1:
        printf("Membeli tiket\n");
        /* break sengaja tidak ditulis */
    case 2:
        printf("Membatalkan tiket\n");
        break;
    default:
        printf("Pilihan tidak tersedia\n");
        break;
    }

    return 0;
}
text Keluaran
Membeli tiket
Membatalkan tiket

Keluaran memperlihatkan dua baris padahal pilihan bernilai 1. Eksekusi masuk melalui case 1, mencetak baris pertama, lalu jatuh ke pernyataan pada case 2 tanpa memedulikan labelnya. Kekeliruan semacam ini mudah terlewat saat kode dibaca cepat karena strukturnya tampak lengkap.

Fall-through juga dapat dimanfaatkan secara sengaja. Beberapa label case boleh ditumpuk tanpa pernyataan di antaranya sehingga beberapa nilai berbagi satu blok pernyataan. Program berikut mengelompokkan nomor bulan ke dalam kuartal dengan pola tersebut.

c kuartal-bulan.c
#include <stdio.h>

int main(void) {
    int bulan = 8;

    switch (bulan) {
    case 1:
    case 2:
    case 3:
        printf("Kuartal pertama\n");
        break;
    case 4:
    case 5:
    case 6:
        printf("Kuartal kedua\n");
        break;
    case 7:
    case 8:
    case 9:
        printf("Kuartal ketiga\n");
        break;
    case 10:
    case 11:
    case 12:
        printf("Kuartal keempat\n");
        break;
    default:
        printf("Nomor bulan tidak valid\n");
        break;
    }

    return 0;
}
text Keluaran
Kuartal ketiga

Nilai 8 melompat langsung ke label case 8, menemukan tidak ada pernyataan di sana, lalu jatuh ke pernyataan printf yang berbagi tiga label tersebut. Pada pola ini, jatuhnya memang disengaja dan mudah dikenali karena labelnya bertumpuk tanpa pernyataan di antaranya. Kompilator tidak menandai label kosong seperti ini sebagai fall-through yang bermasalah.

Peran label default#

Label default dijalankan apabila tidak ada satu pun label case yang cocok dengan ekspresi yang diuji. Perannya menyerupai else pada percabangan if, yaitu menampung semua nilai di luar daftar. Nilai pilihan 5 atau 0 pada program layanan loket jatuh ke default dan menampilkan pesan bahwa pilihan tidak tersedia. Tanpa default, nilai yang tidak cocok membuat seluruh switch dilewati tanpa efek apa pun, keadaan yang sering luput dari pengujian.

Posisi default yang lazim adalah di ujung bawah, setelah semua case, tetapi bahasa C memperbolehkan default ditulis di posisi mana pun. Apabila default diletakkan di tengah, sediakan break pada akhirnya agar eksekusi tidak jatuh ke case berikutnya. Satu switch hanya boleh memiliki satu label default. Apabila satu pengujian memerlukan penanganan untuk dua kelompok nilai yang berbeda, pecah masalahnya menjadi dua pernyataan switch yang berurutan atau gabungkan nilainya sebelum diuji. Kombinasi daftar case yang lengkap dan default yang menampung sisanya membuat kasus yang terlewat cepat ketahuan saat program diuji.

Memilih switch atau rantai if#

Keputusan memilih switch atau rantai else if sebaiknya didasarkan pada bentuk nilainya, bukan pada kebiasaan. Keduanya menghasilkan keputusan yang sama, sehingga pilihan menyangkut keterbacaan dan bentuk syaratnya. Tabel berikut merangkum perbedaan keduanya.

AspekswitchRantai else if
Nilai yang diujiBilangan bulat atau karakter, dibandingkan kesamaan dengan konstantaEkspresi apa pun yang bernilai benar atau salah
Bentuk syaratDaftar nilai tetap yang diskritRentang nilai atau gabungan beberapa kondisi
KeterbacaanDaftar kasus tersusun rapi untuk pilihan yang banyakMembengkak apabila kasusnya banyak dan seragam
Perilaku tanpa breakJatuh ke case berikutnyaTidak ada padanannya karena setiap blok terpisah

switch unggul apabila program harus membedakan banyak nilai tetap, misalnya nomor menu atau kode layanan, karena daftar kasusnya terbaca seperti tabel. Rantai else if tetap diperlukan apabila syaratnya berupa rentang, misalnya nilai >= 70, atau gabungan beberapa variabel. Kompilator juga dapat menerjemahkan switch yang kasusnya rapat menjadi tabel lompatan (jump table), sehingga waktu pencarian kasusnya tidak bertambah seiring jumlah label. Meskipun demikian, pilih struktur yang paling jelas menyatakan maksud program karena perbedaan kinerja pada program kecil jarang berarti.

Ringkasan#

  • switch melompat ke label case yang nilainya sama dengan ekspresi bilangan bulat yang diuji.
  • Tanpa break, eksekusi jatuh ke case berikutnya, perilaku yang disebut fall-through.
  • Label bertumpuk tanpa pernyataan adalah pola fall-through yang disengaja untuk mengelompokkan nilai.
  • default menampung nilai yang tidak cocok dengan label mana pun dan sebaiknya selalu disediakan.

Referensi#