C語言中的scanf()函數(shù)介紹

技術(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

6.參考博客

博客鏈接

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末蜕该,一起剝皮案震驚了整個濱河市犁柜,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌堂淡,老刑警劉巖馋缅,帶你破解...
    沈念sama閱讀 218,386評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異绢淀,居然都是意外死亡萤悴,警方通過查閱死者的電腦和手機爹脾,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,142評論 3 394
  • 文/潘曉璐 我一進店門肴甸,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人穗熬,你說我怎么就攤上這事祭务∧诠罚” “怎么了?”我有些...
    開封第一講書人閱讀 164,704評論 0 353
  • 文/不壞的土叔 我叫張陵义锥,是天一觀的道長柳沙。 經(jīng)常有香客問我,道長拌倍,這世上最難降的妖魔是什么赂鲤? 我笑而不...
    開封第一講書人閱讀 58,702評論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮柱恤,結(jié)果婚禮上数初,老公的妹妹穿的比我還像新娘。我一直安慰自己梗顺,他們只是感情好泡孩,可當(dāng)我...
    茶點故事閱讀 67,716評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著寺谤,像睡著了一般仑鸥。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上变屁,一...
    開封第一講書人閱讀 51,573評論 1 305
  • 那天眼俊,我揣著相機與錄音,去河邊找鬼粟关。 笑死疮胖,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播澎灸,決...
    沈念sama閱讀 40,314評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼院塞,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了击孩?” 一聲冷哼從身側(cè)響起迫悠,我...
    開封第一講書人閱讀 39,230評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎巩梢,沒想到半個月后创泄,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,680評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡括蝠,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,873評論 3 336
  • 正文 我和宋清朗相戀三年鞠抑,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片忌警。...
    茶點故事閱讀 39,991評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡搁拙,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出法绵,到底是詐尸還是另有隱情箕速,我是刑警寧澤,帶...
    沈念sama閱讀 35,706評論 5 346
  • 正文 年R本政府宣布朋譬,位于F島的核電站盐茎,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏徙赢。R本人自食惡果不足惜字柠,卻給世界環(huán)境...
    茶點故事閱讀 41,329評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望狡赐。 院中可真熱鬧窑业,春花似錦、人聲如沸枕屉。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,910評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽搀庶。三九已至拐纱,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間哥倔,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,038評論 1 270
  • 我被黑心中介騙來泰國打工揍庄, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留咆蒿,地道東北人。 一個月前我還...
    沈念sama閱讀 48,158評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像沃测,于是被迫代替她去往敵國和親缭黔。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,941評論 2 355

推薦閱讀更多精彩內(nèi)容