天天看點

關于利用scanf()函數做為do-while循環條件的分析

首先來看一段測試程式:

#include <stdio.h>

#include <ctype.h>

int main(void)

{

    char flag;            //設定标志位

    int loop_var=0;       //輸出變量

    do

    {

        printf("loop %d \n",loop_var++);  

        printf("繼續下次循環 (y/n)?\n"); //提示使用者輸入選擇

        scanf("%c",&flag);

    }while(toupper(flag)=='Y');//如果輸入y或Y進行下次循環

    return 0;

}

這段程式在首次運作以後,會立刻輸出:

loop0

繼續下次循環 (y/n)?

來提示使用者進行選擇,如果使用者輸入的是y或Y,那會進入下次循環,并輸出:

loop1 

繼續下次循環 (y/n)?

但是第二次循環一過,程式運作結束。這個程式本意,應該是隻要使用者輸入的是y或Y,應該可以持續循環下去。可是第二次循環後就退出程式了。為什麼會這樣呢,通過分析利用重定向符進行字元輸入後得到的結果,個人認為是這樣:當使用者輸入y或Y以後,按下回車确定輸入結束,這樣,相當于輸入了兩次字元一個y或Y和回車符,是以進行第三次判斷由于輸入的不y或Y,while的條件不成立,是以程式結束運作。

通過此次小程式的測試,得到的結論為:在do-while循環裡,用scanf()函數得到的使用者輸入做為條件判斷時,條件成立的情況下,也隻能再循環一次,因為回車會被算做第二次輸入判斷的條件。

解決方法:由于scanf()函數做為輸入條件的判斷,是以問題本身是出在這個函數上。通過了解scanf()函數,得知,scanf()函數獲得的資料是儲存在鍵盤緩沖區中,并且是在鍵盤緩沖區查找輸入資料,而不是直接從鍵盤上讀取資料,使用者輸入的所有資料都會儲存在緩沖區裡,是以第二次循環的條件會直接從緩沖區讀取資料。因為第一次使用者的輸入是字元加回車。是以回車符成為了第二次循環條件判斷的字元。明白了問題所在,那麼要讓程式達到本意,就可以這麼做,在取得使用者輸入後,清除緩沖區。标準輸入和輸出有兩個緩沖區:stdin用于輸入,stdout用于輸出。要清除鍵盤輸入緩沖區,隻要清除stdin就可以了,如何清除呢?使用函數fflush(),這個函數包含在stdio.h裡。

下面是更改後的代碼:

#include <stdio.h>

#include <ctype.h>

int main(void)

{

    char flag;            //設定标志位

    int loop_var=0;       //輸出變量

    do

    {

        printf("loop %d \n",loop_var++);  

        printf("繼續下次循環 (y/n)?\n"); //提示使用者輸入選擇

        scanf("%c",&flag);

        fflush(stdin);  //清除鍵盤資料緩沖區

    }while(toupper(flag)=='Y');//如果輸入y或Y進行下次循環

    return 0;

}

----------------------------------------------------------------------

參考書籍:C語言入門經典第四版