1. 程式人生 > >c--getchar() 清空快取

c--getchar() 清空快取

getchar()

該函式的原型為:

# include <stdio.h>
int getchar(void);

功能是從緩衝區中讀取一個字元。這個函式非常簡單,連引數都沒有,非常好用。下面用 scanf 給字元變數賦值和吸收回車的程式用 getchar() 修改一下:

 
  1. # include <stdio.h>
  2. int main(void)
  3. {
  4. int a;
  5. char ch;
  6. while (1)
  7. {
  8. printf("請輸入一個數字:");
  9. scanf("%d", &a);
  10. printf("a = %d\n", a);
  11. printf("您想繼續嗎(Y/N):");
  12. getchar(); /*用getchar吸收回車, 簡單、方便、好用, 都不需要定義變數用來儲存獲取的回車符*/
  13. ch = getchar(); //用getchar從緩衝區中讀取一個字元賦給字元變數ch
  14. if (('Y' == ch) || ('y' == ch))
  15. {
  16. ;
  17. }
  18. else
  19. {
  20. break; // 跳出本層迴圈體
  21. }
  22. }
  23. return 0;
  24. }

輸出結果是:
請輸入一個數字:10
a = 10您想繼續嗎(Y/N):y
請輸入一個數字:5
a = 5您想繼續嗎(Y/N):y
請輸入一個數字:333
a = 333您想繼續嗎(Y/N):n

在程式中,“ch=getchar();”這句之前我們先用 getchar() 清空緩衝區,然後重新從鍵盤輸入一個字元。同樣,必須按回車 getchar() 才會進去取這個字元。這時候需要注意的是,同 scanf 一樣,按的這個回車也會被遺留在緩衝區中,大家要注意。

這時有人會說,如果前面有多個 scanf 給 int 型變數賦值,那麼每個 scanf 都會遺留一個回車,那這時是不是有幾個 scanf 就要用幾個 getchar() 呢?

回答是“不需要”,仍然只需要一個 getchar()!前面說過,當 scanf 用 %d 取緩衝區資料的時候,如果遇到空格、回車或 Tab 鍵就跳過去。不僅如此,這些被跳過去的空白符都被釋放了。所以假如前面有三個 scanf 給 int 型變數賦值,那麼第一個 scanf 輸入回車後把回車遺留在了緩衝區,而第二個 scanf 取值時會越過第一個 scanf 遺留在緩衝區中的回車,那麼這個回車就會從緩衝區中釋放。但第二個 scanf 取完值後也在緩衝區中留下了一個回車,而當第三個 scanf 到緩衝區中取值時會跳過第二個 scanf 遺留的回車,這個回車同樣也會從緩衝區中釋放,所以歸根結底最後緩衝區中只有一個回車,也就是說,緩衝區中永遠不可能遺留多個回車。

下面來寫一個程式驗證一下:

 
  1. # include <stdio.h>
  2. int main(void)
  3. {
  4. int a, b, c, d;
  5. char ch;
  6. printf("請輸入第一個數:");
  7. scanf("%d", &a);
  8. printf("請輸入第二個數:");
  9. scanf("%d", &b);
  10. printf("請輸入第三個數:");
  11. scanf("%d", &c);
  12. printf("您想繼續嗎(Y/N):");
  13. getchar(); //只需要用一個getchar吸收回車
  14. ch = getchar(); //用getchar獲取一個字元賦給ch
  15. if (('Y' == ch) || ('y' == ch))
  16. {
  17. printf("請輸入密碼:");
  18. scanf("%d", &d);
  19. printf("恭喜成功獲得密碼%d\n", d);
  20. }
  21. return 0;
  22. }

輸出結果是:
請輸入第一個數:1
請輸入第二個數:2
請輸入第三個數:3
您想繼續嗎(Y/N):y
請輸入密碼:5678
恭喜成功獲得密碼5678

由此我們知道,當用 %d 獲取輸入流中的資料的時候,如果遇到字元(空格、回車、Tab 除外),則直接從輸入流中退出來,什麼都不取。但如果是用 %c 獲取,那麼任何資料都會被當作一個字元。所以如果你要從輸入流中取一個字元,但在之前使用過 scanf,那麼此時就必須要先用 getchar() 吸收回車。否則取到的將不是你想要的字元,而是 scanf 遺留在輸入流中的回車。如果你要從輸入流中取的不是字元,那就不需要用 getchar() 吸收回車了。

以上詳細分析了什麼時候需要吸收回車,什麼時候不需要。但實際程式設計中,程式往往很長,我們很難預測到下一次到緩衝區中取資料的是 %d 還是 %c 或者是 gets()、fgets()。所以為了避免忘記吸收回車或耗費精力考慮回車的問題,習慣上 scanf 後面都加上 getchar()。

fflush(stdin)

前面介紹了使用 getchar() 吸收回車的方法,除此之外還有一個更強大、更直接的方法,就是直接將輸入緩衝區全部清空。

清空緩衝區只需加一句 fflush(stdin) 即可。fflush 是包含在檔案 stdio.h 中的函式。stdin 是“標準輸入”的意思。std 即 standard(標準),in 即 input(輸入),合起來就是標準輸入。fflush(stdin) 的功能是:清空輸入緩衝區。下面將前面的一個程式修改一下:

 
  1. # include <stdio.h>
  2. int main(void)
  3. {
  4. int a;
  5. char i;
  6. while (1)
  7. {
  8. printf("請輸入一個數字:");
  9. scanf("%d", &a); //因為讀取的是數字, 所以不需要清空緩衝區
  10. printf("a = %d\n", a);
  11. printf("您想繼續嗎, Y想, N不想:");
  12. fflush(stdin);
  13. scanf("%c", &i);
  14. if ('Y'==i || 'y'==i)
  15. {
  16. ;
  17. }
  18. else
  19. {
  20. break; // 跳出本層迴圈體
  21. }
  22. }
  23. return 0;
  24. }

輸出結果是:
請輸入一個數字:10safa
a = 10
您想繼續嗎, Y想, N不想:Y
請輸入一個數字:58jlkj\*&**^
a = 58
您想繼續嗎, Y想, N不想:N

fflush 一般用於清除使用者前面遺留的垃圾資料,提高程式碼的健壯性。因為如果是自己程式設計的話,一般都會按要求輸入。但對於使用者而言,難免會有一些誤操作,多輸入了一些其他沒有用的字元,如果程式中不對此進行處理的話可能會導致程式癱瘓。所以程式設計時一定要考慮到各種情況,提高程式碼的健壯性和容錯性。使用 fflush 就可以將使用者輸入的垃圾資料全部清除。

但是 fflush 有一個問題,就是可移植性。並不是所有的編譯器都支援 fflush,比如 gcc 就不支援。那麼此時怎麼辦?還是用 getchar()。

getchar()的高階用法

while (getchar() != '\n');

這種用法其實在前面也使用過,它可以完全代替 fflush(stdion) 來清空緩衝區。不管使用者輸入多少個沒用的字元,他最後都得按回車,而且只能按一次。只要他按回車那麼回車之前的字元就都會被 getchar() 取出來。只要 getchar() 取出來的不是回車 ('\n') 那麼就會一直取,直到將使用者輸入的垃圾字元全部取完為止。q