Jika printf adalah cara program berbicara kepada pengguna, maka scanf adalah cara program mendengarkan. Fungsi scanf membaca data dari standard input (stdin), memparse sesuai format specifier yang kita berikan, lalu menyimpan hasilnya ke variabel yang ditunjuk melalui pointer. Pada chapter ini kita akan memahami cara kerja scanf, bagaimana membedakan nilai kembalian dari jumlah item yang berhasil dibaca, serta kapan scanf cocok dipakai dan kapan sebaiknya kita memilih alternatif lain seperti fgets. Daftar lengkap format specifier scanf dapat dilihat di dokumentasi cppreference untuk <stdio.h>.

Cara Kerja scanf #

Fungsi scanf menerima sebuah format string dan daftar pointer ke variabel penyimpan hasil. Setiap penanda konversi seperti %d atau %f menyuruh scanf melewatkan whitespace, membaca data sesuai tipe, lalu menulis hasilnya ke alamat yang ditunjuk. Nilai kembalian scanf adalah jumlah item yang berhasil dibaca dan ditugaskan; jika input berakhir lebih awal atau tipe tidak cocok, nilai kembalian bisa lebih kecil dari jumlah penanda.

c
#include <stdio.h>

int main(void) {
    int umur;
    printf("Masukkan umur Anda: ");
    int hasil = scanf("%d", &umur);
    printf("Anda memasukkan: %d\n", umur);
    printf("Jumlah item terbaca: %d\n", hasil);
    return 0;
}

Output yang Dihasilkan (input: 17):

text
Masukkan umur Anda: Anda memasukkan: 17
Jumlah item terbaca: 1

Mari kita telaah baris-baris kode di atas:

  1. Baris 4 (int umur;): variabel umur dideklarasikan tanpa inisialisasi. Nilainya belum tentu nol — bisa berisi sampah memori.
  2. Baris 5 (printf("Masukkan umur Anda: ");): prompt tanpa \n agar kursor tetap di baris yang sama saat pengguna mengetik. Pada output, prompt muncul langsung diikuti input karena input dipipakan.
  3. Baris 6 (int hasil = scanf("%d", &umur);): penanda %d menyuruh scanf membaca sebuah integer. Tanda & memberikan alamat variabel umur agar scanf dapat menulis hasilnya. Nilai kembalian disimpan di hasil.
  4. Baris 7 (printf("Anda memasukkan: %d\n", umur);): mencetak nilai yang baru saja ditulis scanf ke variabel umur.
  5. Baris 8 (printf("Jumlah item terbaca: %d\n", hasil);): menampilkan berapa item yang berhasil dibaca. Untuk input valid 17, hasilnya 1.

Membaca Beberapa Variabel Sekaligus #

scanf mampu membaca beberapa nilai sekaligus dalam satu pemanggilan, dipisahkan oleh whitespace (spasi, tab, atau newline). Pola format specifier %31s %d %f membaca string maksimum 31 karakter, lalu integer, lalu float. Batasan %31s sangat penting untuk mencegah buffer overflow saat pengguna mengetik string lebih panjang dari kapasitas array.

c
#include <stdio.h>

int main(void) {
    char nama[32];
    int umur;
    float tinggi;

    printf("Masukkan nama umur tinggi: ");
    int jumlah = scanf("%31s %d %f", nama, &umur, &tinggi);
    printf("Nama    : %s\n", nama);
    printf("Umur    : %d\n", umur);
    printf("Tinggi  : %.2f\n", tinggi);
    printf("Item terbaca: %d\n", jumlah);
    return 0;
}

Output yang Dihasilkan (input: Budi 17 168.5):

text
Masukkan nama umur tinggi: Nama    : Budi
Umur    : 17
Tinggi  : 168.50
Item terbaca: 3

Mari kita telaah baris-baris kode di atas:

  1. Baris 4 (char nama[32];): array char dengan kapasitas 32 byte, cukup untuk 31 karakter ditambah null terminator.
  2. Baris 8 (int jumlah = scanf("%31s %d %f", nama, &umur, &tinggi);): tiga penanda konversi membaca tiga nilai berturut-turut. Perhatikan bahwa nama tidak butuh & karena nama array sudah otomatis menjadi pointer ke elemen pertama, sementara umur dan tinggi perlu & karena keduanya variabel biasa.
  3. Baris 9 (printf("Nama : %s\n", nama);): %s mencetak string sampai null terminator. %31s di scanf membatasi pembacaan maksimum 31 karakter sehingga null terminator tetap muat di indeks ke-31.
  4. Baris 12 (printf("Item terbaca: %d\n", jumlah);): nilai kembalian 3 berarti ketiga item berhasil dibaca. Jika input kurang lengkap, nilai kembalian akan lebih kecil.

Format Lanjutan: Separator dan Scanset #

Selain whitespace, scanf mendukung separator custom dan scanset untuk membaca pola tertentu. Scanset %[^\n] membaca semua karakter sampai newline, berguna untuk membaca kalimat penuh yang mengandung spasi.

c
#include <stdio.h>

int main(void) {
    int hari, bulan, tahun;

    /* %d memakai separator bebas (whitespace) */
    printf("Masukkan tanggal (dd mm yyyy): ");
    int jml = scanf("%d %d %d", &hari, &bulan, &tahun);
    printf("Tanggal: %02d/%02d/%d\n", hari, bulan, tahun);
    printf("Item terbaca: %d\n", jml);

    /* Membaca sampai karakter tertentu */
    char kalimat[64];
    printf("Masukkan kalimat (sampai newline): ");
    scanf(" %63[^\n]", kalimat);
    printf("Kalimat: %s\n", kalimat);
    return 0;
}

Output yang Dihasilkan (input: 12 8 2024 lalu Belajar bahasa C itu menyenangkan):

text
Masukkan tanggal (dd mm yyyy): Tanggal: 12/08/2024
Item terbaca: 3
Masukkan kalimat (sampai newline): Kalimat: Belajar bahasa C itu menyenangkan

Mari kita telaah baris-baris kode di atas:

  1. Baris 9 (scanf("%d %d %d", ...)): setiap %d otomatis melewatkan whitespace sebelum membaca angka. Pengguna boleh memisahkan tanggal dengan satu spasi, beberapa spasi, tab, atau bahkan baris baru — scanf akan tetap memproses input dengan benar.
  2. Baris 10 (printf("Tanggal: %02d/%02d/%d\n", ...)): %02d menjamin dua digit dengan padding nol di depan. Tanggal 12/08/2024 ditampilkan dengan format konsisten.
  3. Baris 16 (scanf(" %63[^\n]", kalimat);): scanset [^\n] berarti “baca semua karakter kecuali newline”. Spasi sebelum % menyuruh scanf melewatkan whitespace tersisa (termasuk newline dari input tanggal sebelumnya). Batasan 63 mencegah overflow pada kalimat[64].
  4. Baris 17 (printf("Kalimat: %s\n", kalimat);): kalimat penuh dengan spasi tetap terbaca, tidak seperti %s yang berhenti di whitespace pertama.