New FAMILUG

Sunday, 8 January 2012

C Programming - fflush function and output stream!

Ai đã từng lập trình C hẳn rất quen thuộc với hàm fflush. Nhưng các bạn thường hiểu nhầm công dụng của nó.
fflush là hàm "chỉ" dùng để xóa bộ đệm dòng ra(output stream), khi sử dụng với dòng vào(input stream) thì sẽ gây ra sự vận hành không xác định của các chương trình(behave undefine). Nhưng thường thì chúng ta lại dùng để xóa dòng vào chuẩn(stdin) với suy nghĩ loại bỏ những thứ không mong đợi được đưa vào từ bàn phím khi chạy chương trình.

vd: fflush(stdin); fgets(name); đó là một sai lầm rất ngớ ngẩn vì đơn giản fflush không dùng cho các dòng vào và có thể gây ra những lỗi không ngờ tới.
Để giải thích công dụng của fflush mình xin đưa ra một đoạn code đơn giản sau:
Trường hợp 1:
#include "stdio.h"
#include "stdlib.h"

int main(void)
{
int i;
for(i = 0;i < 10; i++)
{
printf("%d", i);
sleep(1);
}
return 0;
}

Trường hợp 2: Vẫn đoạn code đó nhưng thêm hàm fflush(stdout); ngay sau hàm print.

Trường hợp 3: Bỏ hàm fflush(stdout) và thay hàm printf thành printf("%d\n", i);

Chạy 3 đoạn chương trình đó và bạn sẽ thấy sự khác biệt rất thú vị. Hàm sleep(1) dùng để dừng chương trình 1s(không làm gì trong 1s này cả). Ở trường hợp thứ nhất, tất cả kí tự được in ra cùng 1 lúc sau 10s chạy chương trình, lí do là hàm printf chỉ đơn giản đưa các kí tự cần in ra màn hình vào stdout và chỉ in ra màn hình khi stdout được làm đầy hoặc không còn kí tự nào được đưa vào stdout nữa khi chương trình kết thúc, hoặc gặp kí tự xuống dòng(trường hợp 3). Ở trường hợp 2, hàm fflush(stdout) đưa tất cả kí tự được chứa trong stdout ra màn hình(làm sạch stdout).

9 comments:

  1. ấy , bây giờ mới để ý stdin ,stdout là stream vào và ra .

    Cám ơn Hiệp đã nhắc và gợi mở kiến thức .

    ReplyDelete
  2. mà hàm sleep() trong thư viện dos.h thì phải

    ReplyDelete
  3. bớt thì phải đi nhá Chung.
    cái này biết lâu rồi. Vote up :D

    ReplyDelete
  4. @Chung: Đoạn code trên có include cái thư viện nào gọi là "dos.h" không? sleep là hàm trong thư viện stdlib.h

    ReplyDelete
  5. Nhưng mà trên win thì fflush(stdin) có tác dụng thật là sao ? Tại complie KHÔNG chuẩn à?

    ReplyDelete
  6. Cậu có ví dụ cụ thể nào cho fflush(stdin) để minh họa nó bất lực không :D

    ReplyDelete
  7. Biên dịch đoạn code sau và chạy:
    ...
    main()
    {
    char c;
    sleep(5);
    printf("Nhap:");
    fflush(stdin);
    c = fgetc(stdin);
    return 0;
    }

    Sau khi chạy chương trình ấn bừa các phím và hàm fgetc sẽ bị trôi, nhưng mà nhớ là phải biên dịch bằng trình biên dịch C chuẩn đấy, còn không chuẩn thì tớ không biết :)).

    ReplyDelete
  8. Mà nhớ phải ấn enter nữa, vì khi chưa ấn enter thì kí tự chưa được chuyển đến bộ đệm.

    ReplyDelete