黑馬程式設計師 C語言基礎之 scanf函式

2022-07-17 12:39:09 字數 4065 閱讀 6860

寫**的時候,我們可以看得出,幾乎每乙個c程式都會包括輸入輸出。輸入輸出是程式中最基本的操作之一。

c語言本身並不提供輸入輸出的語句,輸入輸出操作是由c標準函式庫中的函式來實現的。今天就先說說輸入:scanf函式。

scanf 函式與printf函式一樣,都不是c語言的關鍵字,而只是函式庫的名字,它們被定義在stdio.h裡,因此在使用scanf函式時要 加 上#include。

它是格式輸入函式,即按使用者指定的格式從鍵盤上把資料輸入到指定的變數之中,其關鍵字最末乙個字 母f 即為「格式」(format)之意。

int scanf(char *format[,argument,...]);

「格式控制」的是用雙引號括起來 字串,稱「轉換控制字串」,簡稱「格式字串」,它包含兩個資訊:

(1)、格式宣告:由%和格式字元組成,作用是將輸入的資料轉變為指定的格式後輸入,總是由%字元開始的;

(2)、普通字元:即是需要在輸出時原樣輸入的字元。

「位址表列」是由若干個位址組成的表列,可以是變數的位址,或字串首位址或表示式。

scanf()函式返回成功賦值的資料項數,出錯時則返回eof。

/*

例:使用scanf函式輸入資料

*/#include

void

main()

格式字元說明

%a,%a 讀入乙個浮點值(僅c99有效) 

%c 讀入乙個字元

%d 讀入十進位制整數

%i 讀入十進位制,八進位制,十六進製制整數

%o 讀入八進位制整數

%x,%x 讀入十六進製制整數

%s 讀入乙個字串,遇空格、製表符或換行符結束

%f,%f,%e,%e,%g,%g 用來輸入實數,可以用小數形式或指數形式輸入

%p 讀入乙個指標

%u 讀入乙個無符號十進位制整數

%n 至此已讀入值的等價字元數

% 掃瞄字元集合

%% 讀%符號

附加格式說明字元表修飾符說明 

l/l 長度修飾符 輸入"長"資料

h 長度修飾符 輸入"短"資料

w 整型常數 指定輸入資料所佔寬度

* 表示本輸入項在讀入後不賦值給相應的變數

scanf的返回值

scanf的返回值有後面的引數決定

scanf("

%d%d

", &a, &b);

(1)如果a和b都被成功讀入,那麼scanf的返回值就是2

(2)如果只有a被成功讀入,返回值為1

(3)如果a和b都未被成功讀入,返回值為0

(4)如果遇到錯誤或遇到end of file,返回值為eof,且返回值為int型.

使用scanf函式時應該注意的問題

(1)sacnf()中的變數必須使用位址 

(2)scanf()的格式控制串可以使用其它非空白字元,但在輸入時必須輸入這些字元

(3)在用"%c"輸入時,空格和「轉義字元」均作為有效字元

下面讓我們來舉例說明一下scanf

函式的具體使用以及使用過程中遇到的一些問題:

/*

問題一:scanf()函式不能正確接受有空格的字串?如: i love you!

*/#include

intmain()

scanf()函式接收輸入資料時,遇以下情況結束乙個資料的輸入:(不是結束該scanf函式,scanf函式僅在每乙個資料域均有資料,並按回車後結束)

(1)遇空格、「回車」、「跳格」鍵

(2)遇寬度結束

(3)遇非法輸入

因此, 上述程式並不能達到預期目的,scanf()掃瞄到"i"後面的空格就認為對str的賦值結束,並忽略後面的"love you!".

這裡要注 意 是"love you!"還在鍵盤緩衝區(關於這個問題,網上我所見的說法都是如此,但是,我經過除錯發現,其實這時緩衝區字串首尾指標已經相等 了,

也就是說緩衝區清空了,scanf()函式應該只是掃瞄stdin流,這個殘存資訊是在stdin中)。

我們改動一下上面的程式來驗證一下:

#include int

main()

執行結果是:

ilove

you!

現在原因知道了,那麼scanf()函式能不能完成這個任務?回答是:能!別忘了scanf()函式還有乙個 % 格式控制符(如果對%不了解的請檢視本文的上篇)

請看下面的程式:

#include "

stdio.h

"int

main()

此時程式就行正確的輸出i love you!啦!

/*

問題二:鍵盤緩衝區殘餘資訊問題

*/#include

intmain()

while(c!='n'

);}

scanf("%c",&c); 這句不能正常接收字元,什麼原因呢?我們用printf("c=%d/n",c);將c用int表示出來,

啟用 printf("c=%d/n",c); 這一句,看看scanf()函式賦給c到底是什麼,結果是c=10 ,ascii值為10是什麼?換行即/n.對了,我們每擊打一下"enter"鍵,

向鍵盤緩衝區發去乙個「回車」(/r),乙個「換行"(/n),在這裡 /r被scanf()函式處理掉了(姑且這麼認為吧^_^),

而/n被 scanf()函式「錯誤」地賦給了c.解決辦法:可以在兩個scanf()函式之 後加個fflush(stdin);,還有加 getch() , getchar()也可以,

但是要視具體scanf()語句加那個,這裡就不分析了,讀者自己去摸索吧。但是加 fflush(stdin);不管什麼情況都可行。

#include int

main()while(c!='n'

);}

這裡再給乙個用「空格符」來處理緩衝區殘餘資訊的示例:執行出錯的程式:

#include int

main()

}

使用了空格控制符後:

#include int

main()

}

可以執行看看兩個程式有什麼不同哦~~

/*

問題三: 如何處理scanf()函式誤輸入造成程式死鎖或出錯?

*/#include

intmain()

如上程式,如果正確輸入a,b的值,那麼沒什麼問題,但是,你不能保證使用者每一次都能正確輸入,一旦輸入了錯誤的型別,你的程式不是死鎖,就是得到一 個錯誤的結果。

解決方法:scanf()函式執行成功時的返回值是成功讀取的變數數,也就是說,你這個scanf()函式有幾個變數,如果scanf()函式全部正常讀取,它就返回幾。

但這裡還要注意另乙個問題,如果輸入了非法資料,鍵盤緩衝區就可能 還個有殘餘資訊問題。正確的例程:

#include int

main()

補充: fflush(stdin)這個方法在gcc下不可用。(在vc6.0下可以),以下是 c99 對 fflush 函式的定義:

int fflush(file *stream);

如果stream指向輸出流或者更新流(update stream),並且這個更新流最近執行的操作不是輸入,那麼fflush函式將把任何未被寫入的資料寫入stream指向的

檔案(如標準輸出檔案stdout)。否則,fflush函式的行為是不確定的。fflush(null)清空所有輸出流和上面提到的更新流。

如果發生寫錯誤,fflush函式會給那些流打上錯誤標記,並且返回eof,否則返回0。

由此可知,如果 stream指向輸入流(如 stdin),那麼 fflush函式的行為是不確定的。故而使用fflush(stdin) 是不正確的,至少是移植性不好的。可採用如下方法:

/*

此函式可以和scanf函式一起使用,但使用%c輸入時要注意,即此函式只能用於緩衝區非空的情況

*/void

flush()

#include

intmain()

黑馬程式設計師 C語言基礎

ios培訓 android培訓 期待與您交流!一 c語言的流程控制 1 順序結構 按照程式的書寫順序執行每一條語句 2 選擇結構 對給定的條件進行判斷,再根據判斷結果來決定執行哪一段 2.1 if語句 1 if的第一種結構 if 條件 eg include int main return 0 2 i...

黑馬程式設計師 C語言基礎

asp.net unity開發 net培訓 期待與您交流!c語言算數運算子 1.2.3.4.5.int a 10,b 20 printf 兩個差 d b a printf 兩個和 d b a printf 兩個積 d b a printf 兩個商 d b a printf 兩個餘 d b a 小技巧...

黑馬程式設計師 C語言基礎

asp.net unity開發 net培訓 期待與您交流!簡介 c語言於1972年發明,首次使用是用於重寫uinx作業系統。隨著unix作業系統的成功,c語言也得到了大幅度地推廣,是世界上最流行 使用最廣泛的高階程式語言之一。基礎語法 關鍵字 1 關鍵字就是c語言提供的有特殊含義的符號,也叫做 保留...