關於c語言char類型輸入輸出的一個bug


題目

輸入一個整數n,接下來n行每一行輸入兩個用一個空格分隔的字符。

對每一對字符,比較其大小關系並輸出比較的結果:1、0、-1.

解決的代碼如下:

#include<stdio.h>

int main()
{
    int N,i;
    char c1=' ',c2=' ';
    scanf("%d",&N);
    getchar();
    for(i=0;i<N;i++)
    {
        scanf("%c %c",&c1,&c2);
        getchar();
        if(c1>c2) printf("1\n");
        else if(c1<c2) printf("-1\n");
        else printf("0\n");
    }
    return 0;
}

這個地方最需要注意的是char變量其實在輸入時讀取的是鍵盤緩沖區的內容。上面的寫法只是一個變通的寫法,安全的寫法是清空鍵盤緩沖區的內容。

 

參見:http://bbs.bccn.net/thread-248420-1-1.html

 

清空鍵盤緩沖區的一種好方法!

用  rewind(stdin);  語句可以達到很好的清空鍵盤緩沖區的作用。不用考慮太多其他因素。這是我在一本名為《軟件開發:編程與設計(C語言版)》中所了解到的,作者是USA的David Conger。
    以前也了解到其他的清空鍵盤緩沖區的方法,如:用getchar();fflush(stdin);等。但感覺很麻煩,不好用,也不容易理解。而rewind(stdin)簡單好用,而且是一種可移植的方法。

舉個例子:

 1 #include <stdio.h>
 2 
 3 int main()
 4 {
 5     int i;
 6     char aString[3];
 7 
 8     printf("Please enter some characters:");   /*先向鍵盤緩沖區里輸入無用字符*/
 9 
10     getchar();
11 
12     rewind(stdin);                             /*清空鍵盤緩沖區里的無用字符*/
13 
14     printf("Please enter 'OK': ");             /*輸入字符串“OK”*/
15     
16     for(i=0;i<2;i++)                           /*字符串aString接受字符串“OK”*/
17     {
18         aString[i]=getchar();
19     }
20     aString[i]='\0';
21 
22     puts(aString);                             /*輸出字符串aString*/
23 
24     return(0);
25 }
View Code

Microsof Visual C++下調試結果:

輸入:abcdefghijk回車OK回車
輸出:OK

之前緩沖區里的abcdefghijk垃圾字符都被清空了。

下面向新手解釋一下rewind(stdin);的工作原理。

C語言把鍵盤,顯示器等設備當做文件來處理,也就是說從鍵盤輸入相當於從一個文件中讀入,向顯示器輸出相當於向一個文件寫出。
而stdin是C標准庫定義的標准文件之一,它與鍵盤相關聯。我一般把它理解為指向鍵盤這個“文件”的指針。
而rewind()函數的作用是把文件的當前位置指針指向文件頭。
兩者結合,rewind(stdin);的作用也就是把“指向鍵盤(一個文件)的指針從當前位置挪到鍵盤(一個文件)開頭”,相當於拋棄了當前鍵盤緩沖區中的數據,重新開始輸入。
雖然並不是真正的把緩沖區里的數據全部清掉,但卻起到了清空鍵盤緩沖區的作用。

 

 

 

也可參考:http://blog.sina.com.cn/s/blog_63c66eb60100sc0o.html

 

 

空鍵盤緩沖區很多種方法,如用fflush(stdin); rewind(stdin);setbuf(stdin, NULL);前兩者僅對windows有用,最后一個則對Linux系統也適用。那么為什么需要清空鍵盤緩沖區呢?

以下幾個實例:

Sample one

 1 #include <stdio.h>  
 2 int main()
 3 {
 4     char ch1;
 5     char ch2;
 6     ch1 = getchar();
 7     ch2 = getchar();
 8     printf("%d  %d", ch1, ch2);
 9     return 0;
10 }

 

 

     程序的本意很簡單,就是從鍵盤讀入兩個字符,然后打印出這兩個字符的ASCII碼值。可是執行程序后會發現出了問題:當從鍵盤輸入一個字 符后,就打印出了結果,根本就沒有輸入第二個字符程序就結束了。例如用戶輸入字符’a', 打印結果是97,10。這是為什么呢?

【分析】:

     scanf()和getchar()函數是從輸入流緩沖區中讀取值的,而並非從鍵盤(也就是終端)緩沖區讀取。而讀取時遇到回車(n)而 結束的,這個n會一起讀入輸入流緩沖區的,所以第一次接受輸入時取走字符后會留下字符n,這樣第二次的讀入函數直接從緩沖區中把n取走了,顯然讀取成功 了,所以不會再從終端讀取!其實這里的10恰好是回車符!這就是為什么這個程序只執行了一次輸入操作就結束的原因!

【解決辦法】:

     清空緩沖區的殘留數據。

     使用 fflush(stdin); 或 rewind(stdin); 均可起到清空鍵盤緩沖區的作用,這兩個函數均包含在stdio.h這個頭文件中

修正后的寫法:
Sample two

 1 #include <stdio.h>
 2 int main()
 3 {
 4     char ch1;
 5     char ch2;
 6     scanf("%c", &ch1);
 7     printf("ch1 = %d", ch1);
 8     fflush(stdin);  
 9     scanf("%c", &ch2);
10     printf("ch2 = %d", ch2);
11     return 0;
12 }

 

 

     上面的實例只適用於Windows系統,在Linux環境下上面兩種寫法都是不起作用的,所以還要換個函數。

Sample three

 1 #include <stdio.h>
 2 int main()
 3 {
 4     char ch1;
 5     char ch2;
 6     scanf("%c",&ch1);
 7     printf("ch1=%d",ch1);
 8     setbuf(stdin,NULL); 
 9     scanf("%c",&ch2);
10     printf("ch2=%d",ch2);
11     return 0;
12 }

(資料來源:http://www.ludou.org/c-clear-buffer-area.html

 
 
參考:http://www.ludou.org/c-clear-buffer-area.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM