scanf這個函數--論壇裏的一個帖子

原帖地址:http://topic.csdn.net/u/20110423/19/a1e4c5ae-5b44-4e94-8f2c-55f7ba6486de.html

 

int a;
char b;
printf("請輸入a的值");
scanf("%d",&a);
getchar()//假如這裏不加getchar,那麼後面的輸入都直接無效了
printf("請輸入b的值:");
scanf("%c",&b);


大家看看這個程序,假如把輸入字符放在輸入整數之前,那麼不用加getchar(),否則必須加getchar(),這到底是怎麼回事??

 

 

處理空白符的問題,當 scanf 中的輸入格式說明符 (Format specifiers) 是 "%c"的時候,那麼空白字符 (whitespace) 將會被正常讀入,不再起到分隔符的作用。這個時候要注意處理緩衝區中殘留的空白符

 

那爲什麼將scanf("%c",&b)與scanf("%d",&a)交換過來就不會出現這樣的情況,不是也有個換行符在緩衝區中嗎??

 

引用 3 樓 mmothermother 的回覆:

那爲什麼將scanf("%c",&b)與scanf("%d",&a)交換過來就不會出現這樣的情況,不是也有個換行符在緩衝區中嗎??


當 scanf 中的輸入格式說明符 (Format specifiers) 不是 "%c"的時候,那麼空白字符 (whitespace) 將起到分隔符的作用。把分隔好的兩個數據分別賦值到各自定義好的變量或數組中去,兩個數據之間的 whitespace 被從緩衝區讀出但是不起任何作用,當然最後一個 '/n' 會被留在緩衝區內,除非用 getchar(); 或 scanf("%c",&ch); 把它讀出來。

 

引用 8 樓 mmothermother 的回覆:

引用 6 樓 delphiwcdj 的回覆:
引用 3 樓 mmothermother 的回覆:

那爲什麼將scanf("%c",&b)與scanf("%d",&a)交換過來就不會出現這樣的情況,不是也有個換行符在緩衝區中嗎??

當 scanf 中的輸入格式說明符 (Format specifiers) 不是 "%c"的時候,那麼空白……


仔細看下6L的解釋 注意什麼時候把空白字符當成分隔符什麼時候不當

 

想象輸入設備(鍵盤)連接着一個叫“緩衝”的東西,把緩衝認爲是一個字符數組。當你的程序執行到scanf時,會從你的緩衝區讀東西,如果緩衝區是空的,就阻塞住,等待你從鍵盤輸入。 現在假設你的緩衝區裏有: abcd/n1234/n (其中/n是回車符) 執行: scanf("%s",name); 的時候,由於scanf是讀數據直到看見空白符(空白符:指空格符、製表符、回車符)就停止的輸入函數。所以執行後,把abcd存到了name中。緩衝區於是變成了 /n1234/n 接下來的執行就有問題了,如果遇到了: scanf("%d",&number); 怎麼辦?因爲遇到了回車符,它並不是一個數字,所以應該拋出錯誤,讓程序死掉?不對吧,明明是編程序的你讓用戶輸入完名字回車的(不然怎麼提示用戶該輸入數字了?),怎麼能出爾反爾地報錯呢? 所以scanf還有一個特性,就是忽略先導的空白符。不管是有幾百個回車也好,幾萬個空格也罷,只要它們連續地出現在緩衝區的開頭,就統統忽略他們。然後再讀有意義的字符。於是1234被讀入number。 回到剛剛,當緩衝區還是: /n1234/n 的時候,如果遇到了: scanf("%c",&sex); 應該怎麼辦呢?你說,那好辦呀,不是說了忽略前導空白符嗎?跳過回車讀'1'呀! 想法是好的,可這隻針對你的程序這一種情況。如果我編寫的程序就是統計用戶輸入了多少個回車呢?緩衝裏明明有回車符,卻讀不出來,你不是忽悠我嗎? 所以對scanf來講跳過前導空白符有個例外,當參數是%c的時候,就把緩衝區的第一個字符返回回去,不管是什麼。 這樣的設計就有個問題,scanf對不同的參數表現出來的特性不一樣。 得承認,這是個缺陷,但不是說這樣不好。 這樣的設計至少把發現所有字符的機會交給了用戶, 設計者這樣想: 如果程序員使用了scanf("%c",..),那他就有必要知道這函數能把回車符讀出來,至於程序員對回車符感不感興趣,那就看他了,不感興趣的話,程序員也一定知道該怎麼處理。 回到你的程序裏。 當執行scanf("%s",name)的時候,要求你從鍵盤輸入, 於是你輸入了"abc",然後“回車”。 緩衝區裏自然而然地是: abc/n scanf把abc拿走了,留下了/n,緩衝區裏現在就剩下/n 於是,下一個scanf ("%c",&sex); 想當然地讀取了/n 明白了? 關於scanf忽略前導空白符這一點,可以這樣驗證: 寫個程序,用scanf()讀數據,只要不是%c就行。 然後輸入的時候,隨便輸入回車、空格、製表符,然後“回車”確認。 會發現程序依然提示等待你輸入。 就是因爲它忽略掉所有前導空白符之後發現緩衝區是空的!於是乖乖地阻塞住,等待你輸入。關於scanf是直到看見空白符結束讀取這一點,如果你是初學C的話,那麼很快你就會遇到另一個函數,叫gets()。 程序裏如果我們想一次讀入一個英文句子: I am a student. 如果你用scanf讀的話,只能讀出"I",想讀出後面的東西要不斷調scanf。 此時需要用gets,這個函數不管是什麼一律讀進來,直到遇到回車符才停下。 總之,各有各的用途,全都熟悉之後,才能在恰當的時候恰當地使用。
本文來自CSDN博客,轉載請標明出處:
http://blog.csdn.net/wangyadong/archive/2009/04/23/4103774.aspx
的卻,如果人人都用萬能鑰匙,那天下就沒有鑰匙了

 

 

發佈了36 篇原創文章 · 獲贊 5 · 訪問量 20萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章