scanf(),gets(),getchar()

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

| 問題描述一:(分析scanf()和getchar()讀取字符)? |

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

scanf(), getchar()等都是標準輸入函數(shù),一般人都會覺得這幾個函數(shù)非常簡單,沒什么特殊的。但是有時候卻就是因為使用這些函數(shù)除了問題,卻找不出其中的原因。下面先看一個很簡單的程序:

程序1:

? ? ? ? int main()

? ? ? ? {

? ? ? ? ? ? ? char ch1, ch2;

? ? ? ? ? ? ? scanf("%c", &ch1);

? ? ? ? ? ? ? scanf("%c", &ch2);

? ? ? ? ? ? ? printf("%d? %d\n", ch1, ch2);

? ? ? ? ? ? ? return 0;

? ? ? ? }

程序2:

? ? ? ? int main()

? ? ? ? {

? ? ? ? ? ? ? char ch1, ch2;

? ? ? ? ? ? ? ch1 = getchar();

? ? ? ? ? ? ? ch2 = getchar();

? ? ? ? ? ? ? printf("%d? %d\n", ch1, ch2);

? ? ? ? ? ? ? return 0;

? ? ? ? }

? 程序的本意很簡單,就是從鍵盤讀入兩個字符,然后打印出這兩個字符的ASCII碼值??墒菆?zhí)行程序后會發(fā)現(xiàn)除了問題:當從鍵盤輸入一個字符后,就打印出了 結(jié)果,根本就沒有輸入第二個字符程序就結(jié)束了。例如用戶輸入字符'a', 打印結(jié)果是97,10。這是為什么呢?

【分析】:

? ? 首先我們呢看一下輸入操作的原理, 程序的輸入都建有一個緩沖區(qū),即輸入緩沖區(qū)。一次輸入過程是這樣的,當一次鍵盤輸入結(jié)束時會將輸入的數(shù)據(jù)存入輸入緩沖區(qū),而cin函數(shù)直接從輸入緩沖區(qū)中 取數(shù)據(jù)。正因為cin函數(shù)是直接從緩沖區(qū)取數(shù)據(jù)的,所以有時候當緩沖區(qū)中有殘留數(shù)據(jù)時,cin函數(shù)會直接取得這些殘留數(shù)據(jù)而不會請求鍵盤輸入,這就是例子 中為什么會出現(xiàn)輸入語句失效的原因!

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

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

|? 問題描述二:(分析scanf()和gets()讀取字符串)? |

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

首先我們看一下scanf()讀取字符串的問題:

程序3:

? ? ? ? int main()

? ? ? ? {

? ? ? ? ? ? ? char str1[20], str2[20];

? ? ? ? ? ? ? scanf("%s",str1);

? ? ? ? ? ? ? printf("%s\n",str1);? ?

? ? ? ? ? ? ? scanf("%s",str2);?

? ? ? ? ? ? ? printf("%s\n",str2);?

? ? ? ? ? ? ? return 0;

? ? ? ? }

程序的功能是讀入一個字符串輸出,在讀入一個字符串輸出??晌覀儠l(fā)現(xiàn)輸入的字符串中不能出現(xiàn)空格,例如:

測試一輸入:

Hello world!

輸出:

Hello

world!

【分 析】到此程序執(zhí)行完畢,不會執(zhí)行第二次的讀取操作!這個問題的原因跟問題一類似,第一次輸入Hello world!后,字符串Hello world!都會被讀到輸入緩沖區(qū)中,而scanf()函數(shù)取數(shù)據(jù)是遇到回車、空格、TAB就會停止,也就是第一個scanf()會取出"Hello", 而"world!"還在緩沖區(qū)中,這樣第二個scanf會直接取出這些數(shù)據(jù),而不會等待從終端輸入。

測試二:

Hello[Enter]

Hello[輸出]

world[Enter]

world[輸出]

【分析】程序執(zhí)行了兩次從鍵盤讀入字符串,說明第一次輸入結(jié)束時的回車符被丟棄!即:scanf()讀取字符串會舍棄最后的回車符!

我們再看一下gets()讀取字符串的情況:

用scanf來讀取一個字符串時,字符串中是不可以出現(xiàn)空格的,一旦出現(xiàn)空格,后面的數(shù)據(jù)就會舍棄殘留在緩沖區(qū)中。其實有另外一個函數(shù)是可以接受空格的,那就是gets(),下面我們看一下這個函數(shù)的應(yīng)用,我們把程序3改動一下:

? ? int main()

? ? {

? ? ? ? ? char str1[20], str2[20];

? ? ? ? ? gets(str1);

? ? ? ? ? printf("%s\n",str1);? ?

? ? ? ? ? gets(str2);?

? ? ? ? ? printf("%s\n",str2);?

? ? ? ? ? return 0;

? ? }

【分析】顯然與上一個程序的執(zhí)行情況不同,這次程序執(zhí)行了兩次從鍵盤的讀入,而且第一個字符串取了Hello world! 接受了空格符,而沒有像上一個程序那樣分成了兩個字符串!所以如果要讀入一個帶空格符的字符串時因該用gets(), 而不宜用scanf()!

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

| 問題描述三:(getchar()暫停程序,查看程序執(zhí)行結(jié)果)|

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

? ? 不知道大家有沒有遇到過這樣的問題,有的編譯器程序執(zhí)行完后的結(jié)果界面不會停下而是一閃就沒了,以至于看不到執(zhí)行結(jié)果。所以很多人在程序最后加上 getchar()語句,目的是想讓程序執(zhí)行完后停下來,等待從終端接收一個字符再結(jié)束程序??墒前l(fā)現(xiàn)有時候這樣根本沒用,程序照樣跳出去了。這是為什么 呢?

【分析】原因跟上面例子講的一樣,是因為輸入緩沖區(qū)中還有數(shù)據(jù),所以getchar()會成果讀到數(shù)據(jù),所以就跳出了!

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

|? 【總結(jié)】? |

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

第一:要注意不同的函數(shù)是否接受空格符、是否舍棄最后的回車符的問題!

讀取字符時:

scanf()以Space、Enter、Tab結(jié)束一次輸入,不會舍棄最后的回車符(即回車符會殘留在緩沖區(qū)中);

getchar()以Enter結(jié)束輸入,也不會舍棄最后的回車符;

讀取字符串時:

scanf()以Space、Enter、Tab結(jié)束一次輸入

gets()以Enter結(jié)束輸入(空格不結(jié)束),接受空格,會舍棄最后的回車符!

第二:為了避免出現(xiàn)上述問題,必須要清空緩沖區(qū)的殘留數(shù)據(jù),可以用以下的方法解決:

方法1:C語言里提供了函數(shù)清空緩沖區(qū),只要在讀數(shù)據(jù)之前先清空緩沖區(qū)就沒問題了!

? ? ? 這個函數(shù)是fflush(stdin)。

方法2:自己取出緩沖區(qū)里的殘留數(shù)據(jù)。

(說實話這個語句我也沒看懂,呵呵!為什么格式控制是這樣的!希望高手指點一下!)

? ? ? scanf("%[^\n]",string);

————————————————

版權(quán)聲明:本文為CSDN博主「zqixiao_09」的原創(chuàng)文章,遵循 CC 4.0 BY-SA 版權(quán)協(xié)議,轉(zhuǎn)載請附上原文出處鏈接及本聲明。

原文鏈接:https://blog.csdn.net/zqixiao_09/article/details/50189477

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • C/C++輸入輸出流總結(jié) 前兩天寫C++實習作業(yè),突然發(fā)現(xiàn)I/O是那么的陌生,打了好長時間的文件都沒有打開,今天終...
    LuckTime閱讀 1,804評論 0 6
  • 在C語言中,五種基本數(shù)據(jù)類型存儲空間長度的排列順序是: A)char B)char=int<=float C)ch...
    夏天再來閱讀 3,995評論 0 2
  • 一、輸入和輸出流 C 語言的標準輸入輸出函數(shù)都是獨立于設(shè)備的,不需要考慮如何在特定設(shè)備上傳輸數(shù)據(jù);C 語言的庫函數(shù)...
    seraphzxz閱讀 1,215評論 0 51
  • 頭文件stdio.hc語言的標準輸入輸出,常用printf;scanfiostreamc++語言的標準輸入輸出,重...
    bobobe閱讀 2,618評論 0 2
  • 程序是人機交互的媒介,有輸出必然也有輸入,第三章我們講解了如何將數(shù)據(jù)輸出到顯示器上,本章我們開始講解如何從鍵盤輸入...
    夢凡塵閱讀 1,635評論 0 2

友情鏈接更多精彩內(nèi)容