C 【printf 和 scanf 函式的使用】
阿新 • • 發佈:2018-12-23
對於printf函式,我們主要要掌握printf函式的輸出格式。
而對於scanf函式,我們則要知道幾個輸入過程中的錯誤輸入情況和scanf函式的實現原理。
- (1)printf 函式
- printf 中 格式控制 部分 的完整格式:
- "% - 0 m.n l或h 格式字元"
- 下面對組成格式說明的各項加以說明:
- ① % 表示格式說明的起始符號,不可缺少。
- ② - 有-表示左對齊輸出(右側補空格),如省略表示右對齊輸出(左側補空格)。
- ③ 0 有0表示指定空位填0,如省略表示指定空位不填。
- ④ m.n m指域寬,即對應的輸出項在輸出裝置上所佔的字元數。n指精度。用於說明輸出的實型數的小數位數。對數值型的來說,未指定n時,隱含的精度為n=6位。
- ⑤ l或h l對整型指long型,對實型指double型。h用於將整型的格式字元修正為short型。
- ⑥ 格式字元(格式字元用於 指定輸出項的 資料型別 和
輸出格式) :
- d格式:用來輸出十進位制整數。有以下幾種用法:
- %d %hd %ld
- o格式:以無符號八進位制形式輸出整數
- x格式:以無符號十六進位制形式輸出整數
- u格式:以無符號十進位制形式輸出整數
- c格式:輸出一個字元
- s格式:用來輸出一個串。有幾種用法列舉:
- ① %s 例如:printf("%s","CHINA")輸出"CHINA"字串(不包括雙引號)。
- ② %ms 輸出的字串佔m列,如字串本身長度大於m,則突破獲m的限制,將字串全部輸出。若串 長小於m,則左補空格。
- ③ %-ms 如果串長小於m,則在m列範圍內,字串向左靠,右補空格。
- (以下④⑤條中的 m和n 的含義不同於上面)
- ④ %m.ns 輸出佔m列,但只取字串中 左端 n個字元。這n個字元輸出在m列的右側,左補空格。 注意:如果n未指定,預設為0。如果n>m,則m自 動取n的值,即保證n個字元正常輸出。
- ⑤ %-m.ns 其中m、n含義同上,n個字元輸出在m列範圍的左側,右補空格。 注意:如果n未指定,預設為0。如果n>m,則m自動取n的值,即保證n個字元正常輸出。
- (2)scanf 函式
- scanf是一個阻礙式函式,程式在執行過程中會停在scanf函數出現的地方,直到接收資料時才會執行後面的程式碼。
- scanf使用時注意的幾個點:
- ① 如果在控制檯輸入時,輸入了多個空格、回車、Tab都會被系統忽略的(這其中包括輸入多個實型常量 和 整型常量時如果其間輸入了多餘的空格、回車、Tab也是都會被系統忽略的)
- ② 當 字元型常量 與 整型常量 或 實型常量 混合輸入的時候,要注意新增分隔符,來避免無意輸入 空格 造成的錯誤
- ③ 在scanf中,儘量不要使用\n,因為會造成在輸入的時候無限換行。如果使用了\n,那麼在輸入的時候一定要原樣輸入“\n”才可以解決
- scanf的實現原理:系統會將使用者在控制檯輸入的內容放入輸入緩衝區,scanf會從輸入緩衝區內逐個取出內容賦值給格式符,如果型別不一致的話不會修改原有資料。並且如果輸入緩衝區中不為空,那麼再次使用scanf時scanf會一直從緩衝區中獲取值,而不會要求使用者再次輸入。
- 接下來一段程式碼會將上面 需要注意的幾個點 和 實現原理 相結合為大家展示:
#include <stdio.h> int main(int argc, const char * argv[]) { int intValue1 = 1; char charValue1 = '1'; int intValue2 = 2; char charValue2 = '2'; int intValue3 = 3; printf("-----第一次輸入:-----\n"); scanf("%d%c%d", &intValue1, &charValue1, &intValue2); printf("\n-----第一次輸出:-----\n"); printf("intValue1 = %d,charValue1 = %c,intValue2 = %d\n", intValue1, charValue1, intValue2); printf("\n-----第二次輸入:-----\n"); scanf("%c%d", &charValue2, &intValue3); printf("\n-----第二次輸出:-----\n"); printf("charValue2 = %c,intValue3 = %d\n\n", charValue2, intValue3); return 0; } /* * 執行結果: -----第一次輸入:----- 19 s 32 -----第一次輸出:----- intValue1 = 19,charValue1 = ,intValue2 = 2 -----第二次輸入:----- -----第二次輸出:----- charValue2 = s,intValue3 = 32 */
-
執行結果分析:
首先看輸入部分,第一次看似輸入了3個值,實則不然,我們輸入了5個。分別是:19 空格 s 空格 32
再看第二次輸入,直接被跳過了。
其次看輸出部分,一次輸入(只按了一次回車),兩次結果都打印出來了:
intValue1 = 19,charValue1 = ,intValue2 = 2,charValue2 = s,intValue3 = 32
經上面的分析,我們一共在控制檯手動輸入了5個值,也就是讓scanf去輸入緩衝區去取5次值,第一次輸入scanf將前三個值取出來,也就是取出 19、空格、s,並將他們賦給intValue1、charValue1、intValue2,前兩個正常賦值,但是第三個值 s 和 intValue2的型別不匹配,所以輸入快取區裡的值 s 並沒有被取走,而intValue2顯示的就是它初始化時被賦予的值 2。
試想一下,現在輸入快取區中還存在三個值,那就是第一次沒被取走的 s 以及 空格 和 32。所以說第二次控制檯輸入不會執行,而是繼續在輸入快取區中取值。自然 s 賦給了 charValue2,又因為 空格 換行 tab 遇到 非char型別的值時會被忽略,所以說 空格 就被忽略了。那麼最後一個值 32 就被賦給intValue3了。
- 接下來一個小問題,來加深理解這部分內容:
#include <stdio.h> void test1(); int main(int argc, const char * argv[]) { int a = 0; int b = 0; int c = 0; int d = 0; int e = 0; int f = 0; printf("第一次輸入:\n"); scanf("%i,%i,%i", &a, &b, &c); printf("-----第一次輸入結束-----\n"); printf("第一次輸出結果---%i,%i,%i,%i,%i,%i\n", a, b, c, d, e, f); // setbuf(stdin, NULL); // 清空輸入快取區的快取資料 printf("第二次輸入:\n"); scanf("%i,%i,%i", &d, &e, &f); printf("-----第二次輸入結束-----\n"); printf("第二次輸出結果---%i,%i,%i,%i,%i,%i\n", a, b, c, d, e, f); return 0; } /* * 執行結果: 第一次輸入: 1,2,3,4,5,6 -----第一次輸入結束----- 第一次輸出結果---1,2,3,0,0,0 第二次輸入: -----第二次輸入結束----- 第二次輸出結果---1,2,3,0,0,0 */
- 執行結果分析:
和上面的程式一樣,一次性輸入多個值,那麼會在快取區裡儲存未賦值的資料。那為什麼第二次輸入的時候d、e、f的值還是0呢?不應該是4,5,6嗎?這是因為在輸入的時候我們加上了逗號作為分隔符,而一次輸入6個值時,c與d之間是沒有逗號作為分隔符的,但我們卻多輸入了一個逗號,那麼逗號就會從快取區中取出並依次賦給d、e、f,但型別不匹配,所以說賦值失敗,於是輸出結果d、e、f還是0。
-
/* * 如果是按下面的方式進行輸出,空格去替代3和4之間的逗號,那麼賦值時空格遇到非char型別的資料自動忽略,所以後面的4、5、6成功賦值 * 執行結果: 第一次輸入: 1,2,3 4,5,6 -----第一次輸入結束----- 第一次輸出結果---1,2,3,0,0,0 第二次輸入: -----第二次輸入結束----- 第二次輸出結果---1,2,3,4,5,6 */