技術(shù)交流QQ群:1027579432呀闻,歡迎你的加入鸿秆!
1.scanf函數(shù):讀取從鍵盤輸入的數(shù)據(jù)
- 在C語言中肥隆,有多個函數(shù)可以從鍵盤獲得用戶輸入:
- scanf():和 printf() 類似觉既,scanf() 可以輸入多種類型的數(shù)據(jù)
- getchar()待笑、getche()、getch():這三個函數(shù)都用于輸入單個字符
- gets():獲取一行數(shù)據(jù)摔踱,并作為字符串處理
- scanf函數(shù)詳解:意思是格式化掃描虐先,也就是從鍵盤獲得用戶輸入,和printf的功能正好相反。實例如下:
#include "iostream" #include "cstdio" #include "cstdlib" using namespace std; int main(){ // scanf函數(shù)介紹 int a = 0, b = 0, c = 0, d=0; scanf("%d", &a); scanf("%d", &b); printf("a+b = %d\n", a+b); scanf("%d %d", &c, &d); printf("c*d = %d\n", c*d); return 0; }
- 從鍵盤輸入12派敷,按下回車鍵蛹批,scanf()就會讀取輸入數(shù)據(jù)并賦值給變量 a;本次輸入結(jié)束篮愉,接著執(zhí)行下一個 scanf()函數(shù)腐芍,再從鍵盤輸入 60,按下回車鍵潜支,就會將60賦值給變量b甸赃,都是同樣的道理柿汛。scanf("%d %d", &c, &d);scanf()有兩個以空格分隔的%d冗酿,后面還跟著兩個變量,這要求我們一次性輸入兩個整數(shù)络断,并分別賦值給c和d裁替。注意"%d %d"之間是有空格的,所以輸入數(shù)據(jù)時也要有空格貌笨。對于scanf()弱判,輸入數(shù)據(jù)的格式要和控制字符串的格式保持一致。
- 其實scanf和printf非常相似锥惋,只是功能相反罷了昌腰。它們都有格式控制字符串,都有變量列表膀跌。不同的是遭商,scanf的變量前要帶一個&符號。&稱為取地址符捅伤,也就是獲取變量在內(nèi)存中的地址劫流。
scanf("%d %d", &a, &b); // 獲取用戶輸入的兩個整數(shù),分別賦值給變量 a 和 b print("%d %d", a, b); // 將變量 a 和 b 的值在顯示器上輸出
- 再來看一個scanf函數(shù)的例子:
#include "iostream" #include "cstdio" #include "cstdlib" using namespace std; int main(){ // scanf函數(shù)的實例2 int a_, b_, c_; scanf("%d %d", &a_, &b_); printf("a_+b_=%d\n", a_+b_); scanf("%d %d", &a_, &b_); printf("a_+b_=%d\n", a_+b_); scanf("%d, %d, %d", &a_, &b_, &c_); printf("a_+b_+c_=%d\n", a_+b_+c_); scanf("%d is bigger than %d", &a_, &b_); printf("a_-b_=%d\n", a_- b_); return 0; }
- 第一個scanf()的格式控制字符串為"%d %d"丛忆,中間有一個空格祠汇,而我們卻輸入了10 20,中間有多個空格熄诡。第二個scanf()的格式控制字符串為"%d %d"可很,中間有多個空格,而我們卻輸入了100 200凰浮,中間只有一個空格我抠。這說明scanf()對輸入數(shù)據(jù)之間的空格的處理比較寬松姜骡,并不要求空格數(shù)嚴格對應(yīng),多幾個少幾個無所謂屿良,只要有空格就行圈澈。
- 第三個scanf()的控制字符串為"%d, %d, %d",中間以逗號分隔尘惧,所以輸入的整數(shù)也要以逗號分隔康栈。第四個scanf()要求整數(shù)之間以is bigger than分隔。用戶每次按下回車鍵喷橙,程序就會認為完成了一次輸入操作啥么,scanf()開始讀取用戶輸入的內(nèi)容,并根據(jù)格式控制字符串從中提取有效數(shù)據(jù)贰逾,只要用戶輸入的內(nèi)容和格式控制字符串匹配悬荣,就能夠正確提取。本質(zhì)上講疙剑,用戶輸入的內(nèi)容都是字符串氯迂,scanf()完成的是從字符串中提取有效數(shù)據(jù)的過程。
2.連續(xù)輸入
- 第一個實例中都是一個一個地輸入變量 a言缤、b嚼蚀、c、d 的值管挟,每輸入一個值就按一次回車鍵〗问铮現(xiàn)在改變輸入方式,將四個變量的值一次性輸入僻孝,如下所示:
12 60 10 23↙ a+b=72 c*d=230
- 可以發(fā)現(xiàn)导帝,兩個scanf()都能正確讀取。合情合理的猜測是穿铆,第一個scanf()讀取完畢后沒有拋棄多余的值您单,而是將它們保存在了某個地方,下次接著使用悴务。如果多輸入一個整數(shù)睹限,會怎樣呢?
12 60 10 23 99↙ a+b=72 c*d=230
- 這次多輸入了一個 99讯檐,發(fā)現(xiàn)scanf()仍然能夠正確讀取羡疗,只是99沒用罷了。如果少輸入一個整數(shù)别洪,又會怎樣呢叨恨?
12 60 10↙ a+b=72 23↙ c*d=230
- 輸入三個整數(shù)后,前兩個scanf()把前兩個整數(shù)給讀取了挖垛,剩下一個整數(shù)10痒钝,而第三個scanf()要求輸入兩個整數(shù)秉颗,一個單獨的10并不能滿足要求,所以還得繼續(xù)輸入送矩,湊夠兩個整數(shù)以后蚕甥,第三個scanf()才能讀取完畢。
-
從本質(zhì)上講栋荸,從鍵盤輸入的數(shù)據(jù)并沒有直接交給scanf()菇怀,而是放入了緩沖區(qū)中,直到按下回車鍵晌块,scanf()才到緩沖區(qū)中讀取數(shù)據(jù)爱沟。如果緩沖區(qū)中的數(shù)據(jù)符合scanf()的要求,那么就讀取結(jié)束匆背;如果不符合要求呼伸,那么就繼續(xù)等待用戶輸入,或者干脆讀取失敗钝尸。注意括享,如果緩沖區(qū)中的數(shù)據(jù)不符合scanf()的要求,要么繼續(xù)等待用戶輸入蝶怔,要么就干脆讀取失敗奶浦,上面演示了“繼續(xù)等待用戶輸入”的情形兄墅,下面對代碼稍作修改踢星,演示“讀取失敗”的情形。
#include "iostream" #include "cstdio" #include "cstdlib" using namespace std; int main(){ // scanf函數(shù)實例3 int a2 = 2, b2 = 3,c2 = 4, d2 = 5; // 給變量賦予不同的初始值 scanf("%d", &a2); scanf("%d", &b2); printf("a2=%d,b2=%d\n", a2, b2); scanf("%d", &c2); scanf("%d", &d2); printf("c2=%d, d2=%d\n", c2, d2); return 0; }
- 運行結(jié)果:
12 60 a10↙ a2=12, b2=60 c2=3, d2=4
- 前兩個整數(shù)被正確讀取后隙咸,剩下了a10沐悦,而第三個scanf()要求輸入兩個十進制的整數(shù),a10無論如何也不符合要求五督,所以只能讀取失敗藏否。輸出結(jié)果也證明了這一點,c2和d2的值并沒有被改變充包。這說明scanf()不會跳過不符合要求的數(shù)據(jù)副签,遇到不符合要求的數(shù)據(jù)會讀取失敗,而不是再繼續(xù)等待用戶輸入基矮。
-
總而言之淆储,正是由于緩沖區(qū)的存在,才使得我們能夠多輸入一些數(shù)據(jù)家浇,或者一次性輸入所有數(shù)據(jù)本砰,這可以認為是緩沖區(qū)的一點優(yōu)勢。然而钢悲,緩沖區(qū)也帶來了一定的負面影響点额,甚至?xí)?dǎo)致很奇怪的行為舔株,請看下面的代碼:
#include "iostream" #include "cstdio" #include "cstdlib" using namespace std; int main(){ // scanf函數(shù)實例4 int a1_ = 111, b1_=222; scanf("a1_=%d", &a1_); scanf("b1_=%d", &b1_); printf("a1_=%d, b1_=%d\n", a1_, b1_); return 0; }
- 輸入示例:
a1_=99↙ a1_=99, b1_=222
- 輸入a1_=99,按下回車鍵还棱,程序竟然運行結(jié)束了载慈,只有第一個scanf()成功讀取了數(shù)據(jù),第二個scanf()仿佛沒有執(zhí)行一樣珍手,根本沒有給用戶任何機會去輸入數(shù)據(jù)娃肿。如果換一種輸入方式呢?
a1_=99b1_=200↙ a1_=99, b1_=200
- 這樣a1 和b1_都能夠正確讀取了,注意:a1_=99b1_=200中間是沒有任何空格的珠十。如果a1_=99b1_=200兩個數(shù)據(jù)之間有空格又會怎么樣呢料扰?不妨試一下:
a1_=99 b1_=200↙ a1_=99, b1_=222 // 第二個 scanf() 又讀取失敗了!原因和緩沖區(qū)有關(guān)
3.輸入其他數(shù)據(jù)
- 除了輸入整數(shù)焙蹭,scanf()還可以輸入單個字符晒杈、字符串、小數(shù)等孔厉,請看下面的演示:
#include "iostream" #include "cstdio" #include "cstdlib" using namespace std; int main(){ // scanf函數(shù)實例5 char name; int age; char url[30]; float price; scanf("%c", &name); scanf("%d", &age); scanf("%s", url); // 可以加&也可以不加& scanf("%f", &price); printf("26個英文字母的最后一個是%c\n", name); printf("博客已經(jīng)寫了%d月,網(wǎng)址是%s,贊賞是%f", age, url, price); return 0; }
- scanf()和printf()雖然功能相反拯钻,但是格式控制符是一樣的,單個字符撰豺、整數(shù)粪般、小數(shù)、字符串對應(yīng)的格式控制符分別是 %c污桦、%d亩歹、%f、%s凡橱。
4.對讀取字符串的說明
- 字符串的兩種定義形式小作,它們分別是:
char str1[]="www.baidu.com"; char *str2="百度";
- 這兩種形式其實是有區(qū)別的,第一種形式的字符串所在的內(nèi)存既有讀取權(quán)限又有寫入權(quán)限稼钩,第二種形式的字符串所在的內(nèi)存只有讀取權(quán)限顾稀,沒有寫入權(quán)限。printf()坝撑、puts()等字符串輸出函數(shù)只要求字符串有讀取權(quán)限静秆,而scanf()、gets()等字符串輸入函數(shù)要求字符串有寫入權(quán)限巡李,所以抚笔,第一種形式的字符串既可以用于輸出函數(shù)又可以用于輸入函數(shù),而第二種形式的字符串只能用于輸出函數(shù)击儡。
- 另外塔沃,對于第一種形式的字符串,在[]里面要指明字符串的最大長度,如果不指明蛀柴,也可以根據(jù)=后面的字符串來自動推算螃概,此處,就是根據(jù)"www.baidu.com"的長度來推算的鸽疾。但是在前一個例子中吊洼,開始只是定義了一個字符串,并沒有立即給它賦值制肮,所以沒法自動推算冒窍,只能手動指明最大長度,這也就是為什么一定要寫作char url[30]豺鼻,而不能寫作char url[]的原因综液。
- scanf("%s", url);這行代碼用來輸入字符串。上面說過儒飒,scanf()讀取數(shù)據(jù)時需要的是數(shù)據(jù)的地址谬莹,整數(shù)、小數(shù)桩了、單個字符都要加&取地址符附帽,這很容易理解;但是對于此處的url字符串井誉,并沒有加&蕉扮,這是因為,字符串的名字會自動轉(zhuǎn)換為字符串的地址颗圣,所以不用再多此一舉加&了喳钟。當(dāng)然,你也可以加上欠啤,這樣雖然不會導(dǎo)致錯誤荚藻,但是編譯器會產(chǎn)生警告。int洁段、char、float 等類型的變量用于scanf() 時都要在前面添加&共郭,而數(shù)組或者字符串用于 scanf() 時不用添加&祠丝,它們本身就會轉(zhuǎn)換為地址。
-
最后需要注意的一點是除嘹,scanf()讀取字符串時以空格為分隔写半,遇到空格就認為當(dāng)前字符串結(jié)束了,所以無法讀取含有空格的字符串尉咕,請看下面的例子:
#include "iostream" #include "cstdio" #include "cstdlib" using namespace std; int main(){ // scanf函數(shù)實例6 char author[30], lang[30], urls[30]; scanf("%s %s", author, lang); printf("author:%s\n lang:%s\n", author, lang); scanf("%s", urls); printf("urls:%s\n", urls); return 0; }
- 對于第一個scanf()叠蝇,它將空格前邊的字符串賦值給author,將空格后邊的字符串賦值給lang年缎;很顯然悔捶,第一個字符串遇到空格就結(jié)束了铃慷,第二個字符串到了本行的末尾結(jié)束了。
5.scanf()格式控制符匯總
scanf格式符匯總.png