Flush Buffer – fflush(stdin)

Posted on   Februari 4, 2018   |   Last Modified   Mei 31, 2018
fflush stdin

Saya yakin, 99% newbie yang baru belajar bahasa pemrograman C/C++ pasti pernah mengalami masalah ketika data berupa integer selesai diinput kemudian data berupa string yang akan diinput berikutnya terlewat begitu saja (saya sendiri juga mengalaminya ketika baru belajar bahasa C :D). Untuk lebih jelasnya perhatikan source code di bawah.

C

#include <stdio.h>
 
int main() {
    int angka1, angka2;
    char kalimat[100];
     
    printf("Masukkan sebuah angka     : ");
    scanf("%d", &angka1);
     
    printf("Masukkan sebuah kalimat   : ");
    gets(kalimat);
     
    printf("Masukkan sebuah angka lagi: ");
    scanf("%d", &angka2);
     
    printf("Angka pertama: %d\n", angka1);
    printf("Kalimat      : %s\n", kalimat);
    printf("Angka kedua  : %d\n", angka2);
     
    return 0;
}

C++

#include <iostream>
#include <cstring>
 
int main() {
    int angka1, angka2;
    std::string kalimat;
     
    std::cout << "Masukkan angka pertama : ";
    std::cin >> angka1;
     
    std::cout << "Masukkan sebuah kalimat: ";
    std::getline(std::cin, kalimat);
     
    std::cout << "Masukkan angkat kedua  : ";
    std::cin >> angka2;
     
    std::cout << "Angka pertama: " << angka1 << '\n';
    std::cout << "Kalimat      : " << kalimat << '\n';
    std::cout << "Angka kedua  : " << angka2 << '\n';
     
    return 0;
}

Kedua source code di atas akan menghasilkan output seperti berikut.

Masukkan sebuah angka     : 1
Masukkan sebuah kalimat   : Masukkan sebuah angka lagi: 2
Angka pertama: 1
Kalimat      :
Angka kedua  : 2

Mengapa hal tersebut bisa terjadi?

Hal ini terjadi karena fungsi scanf() dan std::cin adalah fungsi input buffered, artinya input yang diketikkan melalui keyboard tidak akan langsung disimpan ke variabel melainkan disimpan ke buffer terlebih dahulu.

Sekarang muncul pertanyaan kedua, Apa itu buffer?

Dalam computer science, buffer adalah area memori yang digunakan untuk penyimpanan sementara ketika data dipindahkan dari satu tempat ke tempat lain. Ketika kita membuat sebuah program dengan bahasa pemrograman C/C++ untuk menginput data, data yang diketikkan melalui keyboard tidak akan langsung disimpan ke dalam variabel. Data tersebut akan melalui buffer sebelum disimpan ke dalam variabel.

Baca :   Sejarah Bahasa Pemrograman

Karena secara default fungsi scanf dan std::cin tidak membaca karakter newline (‘\n’) yang diinput langsung dari keyboard, maka setelah selesai melakukan input angka1, karakter newline tersebut tetap berada di dalam buffer. Selanjutnya karakter tersebut dibaca oleh input kalimat setelah input angka1.

Asumsikan input untuk angka1 adalah 12[enter]. Ketika tombol enter ditekan, data yang input akan dikirim ke buffer. Kemudian compiler akan memeriksa satu per satu karakter data yang diinput apakah input yang dilakukan sah sesuai dengan tipe data variabel yang akan menampung input tersebut. Dari input tersebut, angka 1 dan 2 adalah sah sebagai integer, maka akan disimpan ke dalam variabel. Sementara karakter enter (newline) akan tetap tertinggal di dalam buffer. Kemudian pada saat input kalimat, karena masih ada karakter yang tertinggal di dalam buffer, maka karakter tersebut akan diperiksa oleh compiler apakah dapat disimpan di dalam variabel kalimat atau tidak. Karena tipe data char dapat menyimpan karakter newline, maka karakter newline tersebut akan langsung disimpan ke dalam variabel kalimat. Akibatnya input untuk kalimat terlewatkan.

Bagaimana cara mengatasi masalah tersebut?

Kebanyakan buku-buku dan dosen mengajarkan cara instan, yaitu dengan menambahkan fungsi fflush(stdin) yang terdapat pada library stdio.h (C/C++) atau cstdio (C++) sebelum input kalimat seperti berikut.

C

#include <stdio.h>
 
int main() {
    int angka1, angka2;
    char kalimat[100];
 
    printf("Masukkan sebuah angka: ");
    scanf("%d", &angka1);
 
    fflush(stdin);
     
    printf("Masukkan sebuah kalimat: ");
    gets(kalimat);
 
    printf("Masukkan sebuah angka lagi: ");
    scanf("%d", &angka2);
 
    printf("Angka pertama: %d\n", angka1);
    printf("Kalimat      : %s\n", kalimat);
    printf("Angka kedua  : %d\n", angka2);
 
    return 0;
}

C++

#include <iostream>
#include <cstring>
#include <cstdio>
 
int main() {
    int angka1, angka2;
    std::string kalimat;
     
    std::cout << "Masukkan angka pertama : ";
    std::cin >> angka1;
     
    fflush(stdin);
     
    std::cout << "Masukkan sebuah kalimat: ";
    std::getline(std::cin, kalimat);
     
    std::cout << "Masukkan angkat kedua  : ";
    std::cin >> angka2;
     
    std::cout << "Angka pertama: " << angka1 << '\n';
    std::cout << "Kalimat      : " << kalimat << '\n';
    std::cout << "Angka kedua  : " << angka2 << '\n';
     
    return 0;
}

Kedua source code di atas akan menghasilkan output sebagai berikut.

Masukkan sebuah angka: 1
Masukkan sebuah kalimat: hello world
Masukkan sebuah angka lagi: 2
Angka pertama: 1
Kalimat      : hello world
Angka kedua  : 2

Sekarang program sudah berjalan sesuai dengan keinginan. Jadi apa yang salah? Saya yakin buku ataupun dosen Anda tidak akan memberikan penjelasan apa sebenarnya fungsi dari fflush(stdin).

Berikut fungsi fflush() menurut standar C11 7.21.5.2

“For output streams (and for update streams on which the last operation was output), writes any unwritten data from the stream’s buffer to the associated output device.

For input streams (and for update streams on which the last operation was input), the behavior is UNDEFINED.

Dari keterangan di atas, untuk output streams, fflush() digunakan untuk menulis data yang belum tertulis dari buffer ke perangkat output (seperti layar). Sementara untuk input streams, adalah tidak terdefinisikan atau tidak diketahui.

Baca :   Kenapa Bjarne Stroustrup Menciptakan C++

Jadi, penggunaan fflush() dengan stdin (standard input streams) adalah cara yang kurang tepat karena dapat menghasilkan sesuatu yang tidak diketahui. Alasan kedua adalah karena fflush(stdin) tidak portable karena hanya berjalan di Windows.

Lalu bagaimana cara yang benar untuk melakukan flushing buffer?

Salah satu cara yang sering disarankan adalah menggunakan looping while dan fungsi getchar(). Berikut contoh source code dalam bahasa C.

#include <stdio.h>
 
int main() {
    int angka1, angka2;
    char kalimat[100];
 
    printf("Masukkan sebuah angka: ");
    scanf("%d", &angka1);
 
    while(gechar() != '\n');
     
    printf("Masukkan sebuah kalimat: ");
    gets(kalimat);
 
    printf("Masukkan sebuah angka lagi: ");
    scanf("%d", &angka2);
 
    printf("Angka pertama: %d\n", angka1);
    printf("Kalimat      : %s\n", kalimat);
    printf("Angka kedua  : %d\n", angka2);
 
    return 0;
}

Looping while dan getchar() berfungsi untuk mengosongkan karakter-karakter yang tersimpan di dalam buffer sampai ketemu karakter newline (‘\n’).

Untuk C++, Anda dapat melakukan cara yang sama seperti di atas dengan include library stdio.h atau cstdio. Pada C++, cara lain untuk melakukan flushing buffer adalah dengan mengunakan std::cin.ignore(). Berikut contoh source code dalam bahasa C++.

#include <iostream>
#include <cstring>
#include <cstdio>
 
int main() {
    int angka1, angka2;
    std::string kalimat;
     
    std::cout << "Masukkan angka pertama : ";
    std::cin >> angka1;
     
    std::cin.ignore();
     
    std::cout << "Masukkan sebuah kalimat: ";
    std::getline(std::cin, kalimat);
     
    std::cout << "Masukkan angkat kedua  : ";
    std::cin >> angka2;
     
    std::cout << "Angka pertama: " << angka1 << '\n';
    std::cout << "Kalimat      : " << kalimat << '\n';
    std::cout << "Angka kedua  : " << angka2 << '\n';
     
    return 0;
}

std::cin.ignore() berfungsi mengabaikan karakter yang ada pada input streams. Secara default, std::cin.ginore() hanya mengabaikan satu karakter yang ada pada input streams. Anda dapat menambahkan parameter, seperti std::cin.ignore(256, ‘\n’). Nilai 256 adalah jumlah maksimum karakter yang akan diabaikan dan karakter ‘\n’ adalah delimeter (pembatas). Jadi meskipun belum ketemu sampai 256 karakter jika ketemu karakter ‘\n’, maka karakter-karakter tersebut akan diabaikan.


Tinggalkan Balasan

Alamat email Anda tidak akan dipublikasikan. Ruas yang wajib ditandai *