1. 程式人生 > >清除緩衝區的幾種方法

清除緩衝區的幾種方法


一、緩衝區的作用

  • 一般緩衝區的作用是為了防止頻繁的讀寫。
    • A:往緩衝區裡寫,這裡會有一個寫的等待時間,並不總是有資料需要寫;
    • B: 從緩衝區裡讀,這裡就有一個讀間(沒有資料或資料不全)的等待時間;

使用緩衝區可以減小程式輸入時的等待,程式執行緒可以騰出CPU時間做其它的工作;


二、緩衝區的問題

緩衝區在提升了程式效率的同時,也帶來了一些問題。
在專案的編寫的工程中,很多時候並不需要使用者的輸入,這時如果使用者輸入,輸入的資訊就會被存入緩衝區中,當程式真的需要輸入時,這些之前輸入的資訊,會被傳入程式。造成程式獲取錯誤資訊,甚至是崩潰。


三、解決方案

1.使用fflush(stdin)

  • 優點:使用這種方法清除緩衝區,簡單快捷,只需將這條語句放入程式的輸入語句的前面。
  • 缺陷:但是這個方法有很大缺陷,因為在c語言得標準中沒有明確規定這種用法,所以並不是所有的編譯器都支援。
    • 如果編譯器支援,那麼清除緩衝區就很簡單了。
    • 如果編譯器不支援,它並不會報錯,只是執行完這條語句後,緩衝區的內容依然存在。

2.getch()的連續獲取

while(getchar()!='\n')
    continue;
  • 優點:使用這種方法進行緩衝區的清除,通用性好,任何系統和編譯器都支援。
  • 缺陷:緩衝區清除的不徹底,這種緩衝區清除方法,依據判斷獲取字元為“換行符”來停止。
    • 如果緩衝區中有換行符,但不是最後一個字元,這時緩衝區中第一個換行符之前(包括換行符)被清掉,但是第一個換行符的後面字元不會被清掉。
    • 如果緩衝區中沒有換行符,那麼while會進入死迴圈,程式會停下來,這時只有按下回車鍵,程式才會向後執行,這樣很影響使用者體驗。
    • 在無法判斷是否需要清除緩衝區時,無法使用這個方法,因為這會導致程式無故停頓等待使用者輸入回車鍵

3.setbuf()

  • 原理:使stdin輸入流由預設緩衝區轉為無緩衝區。
  • 優點:使用這種方法清除緩衝區,簡單快捷,只需將這條語句放入程式的輸入語句的前面。
  • 缺陷:通用性不好,這種方法只適用於Windows的大部分編譯器,linux和Windows的少量編譯器使用時沒有反應。

4.scanf(“%*[^\n]%*c”)

原理:%*〔^\n〕將逐個讀取緩衝區中的’\n’字元之前的其它字元,%後面的*表示將讀取的這些字元丟棄,前遇到’\n’字元時便停止讀取操作,此時,緩衝區中尚有一個’\n’字元遺留,所以後面的%*c將讀取並丟棄這個遺留的換行符,這裡的星號和前面的星號作用相同。由於所有從鍵盤的輸入都是以回車結束的,而回車會產生一個’\n’字元,所以將’\n’連同它之前的字元全部讀取並丟棄之後,也就相當於清除了輸入緩衝區。

  • 優點:使用這種方法進行緩衝區的清除,通用性好,任何系統和編譯器都支援。
  • 缺陷:緩衝區清除的不徹底,這種緩衝區清除方法,依據判斷獲取字元為“換行符”來停止。
    • 在無法判斷是否需要清除緩衝區時,無法使用這個方法,因為這會導致程式無故停頓等待使用者輸入回車鍵

5.判斷鍵盤輸入

while (_kbhit())
{
    getch();
}

kbhit()是一個C和C++函式,用於非阻塞地響應鍵盤輸入事件。

這是一個我自己發現的一個清緩衝區方法:
* 使用kbhit()判斷是否有鍵盤輸入,即判斷緩衝區內是否有內容。
* 如果緩衝區有內容,就使用getch()去獲取,直到緩衝區內的所有輸入都被清掉。
ps:使用這種方法,簡單快捷,只需把這幾行復制到需要的輸入的程式碼之前,應對使用者的各種詭異輸入,都可以清除乾淨。同時它可以自動判斷是否需要進行清除操作,避免了程式的意外停止。很好用!!!