18.28 getchar()函数与缓冲区问题
一個關于使用鏈表增加刪除人名的小程序,在使用getchar()函數,得到輸入的菜單選項時,出現了問題,現記錄如下:
【菜單部分代碼如下:】
#include <stdio.h>int main(int argc, char * argv [ ]) {char cOpt;while(1){ print();cOpt = getchar();switch(cOpt) /* switch里的變量只能是整型或字符型 */{case 'l':{list_name();break; }case 'a':{add_name();break;}case 'd':{del_name();break;}case 'x':{return 0;break;}default:{break;}}}return 0; }【錯誤現象:】
?
輸入菜單選項時,多輸出一次菜單。
【解決問題過程:】
1.我在每一個語句后增加的打印語句。
printf("1. test\n");
發現每次都會多執行一次default語句。
2.查看cOpt輸出結果
cOpt = getchar(); printf("1. cOpt = 0x%x\n", cOpt); switch(cOpt) {… }?
發現cOpt的值有0xa,這是換行符的ASCII碼。
通過對緩沖區的研究發現以下結論:
我的輸入被放入了輸入緩沖區,這里的回車操作,既有確定作用又是字符,所以回車'\n'它也跟著進了緩沖區,這個時候getchar()會從stdin流緩沖區中讀取剛才的輸入,一次只讀一個字符,所以字符‘l’就被拿出來了,賦值給了cOpt,然后使用switch選擇菜單項執行,這是第1次顯示菜單欄。字符‘l’被取出的同時,也被緩沖區釋放了,而此時緩沖區還有回車('\n')。所以在while(1)第2次循環時,根本不需要輸入就讀出了回車('\n')字符,賦值給cOpt,在switch里判斷后回車('\n')字符屬于未定義的,必然要執行default分支。此時,回車字符也被緩沖區釋放了,所以再次調用getchar時,程序就等著用戶按鍵。
所以,getchar的調用就是直接讀取緩沖區中的字符,直到緩沖區中的字符讀完后,才等待用戶按鍵。
【解決方案:】
【法1:】知道原因后,我在switch前的cOpt = getchar();后增加下列語句
if (cOpt == '\n') {cOpt = getchar(); }【法2:】
#include <stdio.h>int main(int argc, char * argv [ ]) {char cOpt;while(1){ print();/* 解決方案2 */do{cOpt = getchar();}whiel((cOpt != 'l') && (cOpt != 'a') && (cOpt != 'd') && (cOpt != 'x'))if (cOpr == 'l'){list_name();}else if (cOpr == 'a'){ShowPrePage(); }else if (cOpr == 'd'){del_name(); }else if (cOpr == 'x'){return 0; }}return 0; }
目的是為了釋放回車字符,使程序跳過對回車字符的操作。
?補充:
緩沖區分為三種類型:全緩沖、行緩沖和不帶緩沖。
1、全緩沖
在這種情況下,當填滿標準I/O緩存后才進行實際I/O操作。全緩沖的典型代表是對磁盤文件的讀寫。
2、行緩沖
在這種情況下,當在輸入和輸出中遇到換行符時,執行真正的I/O操作。這時,我們輸入的字符先存放在緩沖區,等按下回車鍵換行時才進行實際的I/O操作。典型代表是鍵盤輸入數據。
3、不帶緩沖
也就是不進行緩沖,標準出錯情況stderr是典型代表,這使得出錯信息可以直接盡快地顯示出來。
緩沖區的刷新
緩沖區會在以下三種情況下被刷新:
1、緩沖區滿
2、執行flush刷新緩沖區的語句
3、程序正常結束。
?
轉載于:https://www.cnblogs.com/baixu/p/11212216.html
總結
以上是生活随笔為你收集整理的18.28 getchar()函数与缓冲区问题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java之hibernate之 casc
- 下一篇: tomcat更改端口