Meminta pengguna mengetik satu karakter terlihat seperti tugas paling sederhana, tetapi di baliknya ada jebakan klasik yang sering membuat pemula bingung: tombol Enter yang ditekan pengguna juga menghasilkan karakter \n yang tertinggal di buffer stdin. Karakter tersisa ini akan langsung dipakai oleh panggilan input berikutnya, sehingga program seolah-olah melewatkan satu prompt. Pada chapter ini kita akan mempelajari cara membaca karakter tunggal dengan getchar, cara membuang sisa buffer stdin, serta bagaimana menggabungkan keduanya dalam loop menu interaktif. Kita juga akan membahas singkat tentang getch yang tidak termasuk dalam standar C.

Membaca Karakter dengan getchar #

Fungsi getchar membaca satu karakter dari stdin dan mengembalikannya sebagai int, bukan char. Mengapa int? Karena getchar perlu bisa mengembalikan nilai khusus EOF (biasanya -1) untuk menandakan end-of-file, yang berada di luar rentang char bertanda. Jika kita menyimpan hasilnya ke variabel char, pemeriksaan ch == EOF bisa keliru true untuk karakter tertentu.

c
#include <stdio.h>

int main(void) {
    printf("Masukkan satu karakter: ");
    int ch = getchar();
    printf("Anda menekan: '%c'\n", ch);
    printf("Kode ASCII  : %d\n", ch);

    /* Karakter berikutnya di buffer */
    int next = getchar();
    printf("Karakter berikutnya: '%c' (kode %d)\n", next, next);
    return 0;
}

Output yang Dihasilkan (input: Ab):

text
Masukkan satu karakter: Anda menekan: 'A'
Kode ASCII  : 65
Karakter berikutnya: 'b' (kode 98)

Mari kita telaah baris-baris kode di atas:

  1. Baris 4 (int ch = getchar();): membaca satu karakter dari stdin dan menyimpannya di variabel int ch. Pemilihan tipe int (bukan char) sangat penting agar kita bisa membandingkan dengan EOF secara benar.
  2. Baris 5 (printf("Anda menekan: '%c'\n", ch);): %c mencetak karakter yang sesuai dengan kode ASCII ch. Karena ch bernilai 65, output adalah huruf 'A'.
  3. Baris 6 (printf("Kode ASCII : %d\n", ch);): %d mencetak nilai integer ch, yaitu 65. Inilah salah satu kekuatan menyimpan karakter sebagai int: kita bisa mencetak sebagai karakter atau sebagai angka.
  4. Baris 9 (int next = getchar();): panggilan kedua getchar membaca karakter berikutnya yang masih tersisa di buffer. Karena input pengguna adalah "Ab\n" (huruf A, huruf b, lalu Enter), karakter kedua yang dibaca adalah b.
  5. Baris 10 (printf("Karakter berikutnya: '%c' (kode %d)\n", next, next);): mencetak karakter kedua dan kode ASCII-nya. Output b (kode 98) menunjukkan bahwa karakter tersisa di buffer bisa langsung dibaca oleh getchar berikutnya.

Membersihkan Buffer stdin #

Karakter newline \n yang tertinggal di buffer setelah getchar sering menjadi sumber bug. Bayangkan kita meminta pengguna mengetik huruf, lalu di langkah berikutnya meminta nama lengkap memakai fgets. Tanpa pembersihan, fgets akan langsung membaca karakter newline tersisa dan menganggap pengguna menekan Enter tanpa mengetik apa-apa. Solusinya: setelah membaca karakter utama, buang semua karakter sampai dan termasuk newline.

c
#include <stdio.h>

int main(void) {
    printf("Masukkan satu karakter: ");
    int ch = getchar();

    /* Bersihkan sisa newline dan karakter lain di buffer stdin */
    int c;
    while ((c = getchar()) != '\n' && c != EOF) {
        /* Buang karakter */
    }

    printf("Karakter yang dibaca : '%c'\n", ch);
    printf("Buffer sudah bersih. Tekan enter untuk keluar...\n");

    /* Sekarang getchar berikutnya akan menunggu input baru */
    getchar();
    return 0;
}

Output yang Dihasilkan (input: Hello):

text
Masukkan satu karakter: Karakter yang dibaca : 'H'
Buffer sudah bersih. Tekan enter untuk keluar...

Mari kita telaah baris-baris kode di atas:

  1. Baris 5 (int ch = getchar();): membaca karakter pertama dari input, yaitu H. Karakter sisanya (ello\n) tetap berada di buffer stdin.
  2. Baris 9 (int c;): variabel sementara untuk menyimpan karakter yang akan dibuang.
  3. Baris 10 (while ((c = getchar()) != '\n' && c != EOF)): loop terus memanggil getchar sampai menemukan karakter newline \n atau EOF. Setiap karakter yang dibaca diabaikan (tidak dipakai). Setelah loop selesai, buffer stdin sudah bersih.
  4. Baris 13 (printf("Karakter yang dibaca : '%c'\n", ch);): mencetak karakter utama H yang sudah disimpan sebelum pembersihan.
  5. Baris 15 (getchar();): karena buffer sudah bersih, panggilan getchar ini akan menunggu input baru dari pengguna. Dalam mode interaktif, program berhenti di sini sampai pengguna menekan Enter lagi. Pada output di atas, program berakhir setelah input pipa habis.

Loop Menu Interaktif #

Dengan pembersihan buffer, kita bisa membangun menu interaktif yang meminta pengguna memasukkan karakter berulang kali. Berikut contoh menu yang meminta huruf, mengonversinya ke huruf besar, lalu menanyakan apakah pengguna ingin lanjut. Header <ctype.h> menyediakan fungsi isalpha (apakah huruf) dan toupper (konversi ke huruf besar).

c
#include <stdio.h>
#include <ctype.h>

int main(void) {
    char lanjut;
    do {
        printf("Masukkan satu huruf: ");
        int ch = getchar();

        /* Bersihkan sisa baris */
        int c;
        while ((c = getchar()) != '\n' && c != EOF) {}

        if (isalpha(ch)) {
            printf("Huruf yang dimasukkan: %c\n", toupper(ch));
            printf("Kode ASCII: %d\n", ch);
        } else {
            printf("Itu bukan huruf (kode ASCII %d).\n", ch);
        }

        printf("Lanjut (y/n)? ");
        lanjut = (char)getchar();
        while ((c = getchar()) != '\n' && c != EOF) {}
    } while (lanjut == 'y' || lanjut == 'Y');

    printf("Sampai jumpa!\n");
    return 0;
}

Output yang Dihasilkan (input berturut-turut: a, y, b, y, z, n):

text
Masukkan satu huruf: Huruf yang dimasukkan: A
Kode ASCII: 97
Lanjut (y/n)? Masukkan satu huruf: Huruf yang dimasukkan: B
Kode ASCII: 98
Lanjut (y/n)? Masukkan satu huruf: Huruf yang dimasukkan: Z
Kode ASCII: 122
Lanjut (y/n)? Sampai jumpa!

Mari kita telaah baris-baris kode di atas:

  1. Baris 6 (char lanjut;): variabel untuk menyimpan jawaban pengguna apakah ingin melanjutkan. Meskipun getchar mengembalikan int, kita bisa menyimpannya ke char di sini karena kita sudah tahu karakter input adalah huruf kecil, bukan EOF.
  2. Baris 9 (int ch = getchar();): membaca karakter pertama dari setiap iterasi. Variabel ch bertipe int agar bisa kita periksa EOF jika perlu.
  3. Baris 12 (while ((c = getchar()) != '\n' && c != EOF) {}): pembersihan buffer stdin. Loop ini membuang seluruh karakter sampai newline. Tanpa pembersihan ini, newline tersisa akan langsung dipakai oleh getchar di iterasi berikutnya.
  4. Baris 14 (if (isalpha(ch))): isalpha mengembalikan nilai bukan nol jika ch adalah huruf alfabet. Pemeriksaan ini memisahkan jalur logika untuk huruf versus karakter lain.
  5. Baris 15 (printf("Huruf yang dimasukkan: %c\n", toupper(ch));): toupper(ch) mengembalikan huruf besar jika ch adalah huruf kecil. Perhatikan kode ASCII yang dicetak tetap nilai asli ch (huruf kecil) — toupper hanya mengubah tampilan, bukan nilai variabel.
  6. Baris 21 (lanjut = (char)getchar();): membaca karakter jawaban (y atau n) lalu meng-cast ke char karena tipe variabelnya char.
  7. Baris 22 (while ((c = getchar()) != '\n' && c != EOF) {}): pembersihan buffer lagi setelah membaca jawaban, agar iterasi berikutnya dimulai dengan buffer bersih.
  8. Baris 23 (} while (lanjut == 'y' || lanjut == 'Y');): loop do-while berhenti ketika pengguna menekan selain y atau Y.