C語言中輸入函數(shù)(scanf()、fgets()和gets())的區(qū)別詳解
前言
大家都知道在C語言中,有三種主要的輸入函數(shù):scanf(),fgets()以及gets()。他們的使用方法及注意事項如下:
1.scanf()
它是一種格式化的輸入方式,可一次性按照規(guī)定的格式輸入多個數(shù)據(jù)域。
scanf函數(shù)是一個標(biāo)準(zhǔn)庫函數(shù),它的函數(shù)原型在頭文件“stdio.h”中。與printf函數(shù)相同,C語言也允許在使用scanf函數(shù)之前不必包含stdio.h文件。
scanf函數(shù)的一般形式為:
scanf(“格式控制字符串”, 地址表列);
其中,格式控制字符串的作用與printf函數(shù)相同,但不能顯示非格式字符串,也就是不能顯示提示字符串。地址表列中給出各變量的地址。地址是由地址運算符“&”后跟變量名組成的。
例如:&a、&b分別表示變量a和變量b的地址。
下面以輸入規(guī)定的長度的字符串為例,來說說它的使用方法和容易產(chǎn)生的bug。
要求:定義一個長度為10的個字符數(shù)組,由用戶通過鍵盤為其賦值。
Code:
char name[10]; scanf("%9s",name);
說明:之所以使用%9s是因為我們還需要預(yù)留一個位置給字符串結(jié)束標(biāo)志'\0',所以用戶輸入的名字最長只能為9,且其中不能包含空格類字符(空格,回車,首行縮進符),因為scanf函數(shù)認(rèn)為它們是字符串的結(jié)尾。
危險:當(dāng)用戶輸入的名字超過9個衣服時,系統(tǒng)將會產(chǎn)生段錯誤(segment fault),如果運氣好程序可能不會提示錯誤,如果不好,可能內(nèi)存中重要的數(shù)據(jù)被覆蓋!
2.fgets(char *name, int length, fd)
頭文件:include<stdio.h>
該函數(shù)從文件描述符fd指定的文件獲得length個字符存入從name開始的length個內(nèi)存單元中。由于其形參中規(guī)定了最大接受字符數(shù),故不會發(fā)生像scanf函數(shù)那樣的緩存溢出的問題。
要求:定義一個長度為10的個字符數(shù)組,由用戶通過鍵盤為其賦值。
Code:
char name[10]; fget(name,sizeof(name),stdin);
說明:因為此處name是一個數(shù)組名,雖然它本質(zhì)上是一個指針,但聰明的sizeof函數(shù)會把他區(qū)別于一般的指針變量,從而根據(jù)之前的定義求出數(shù)組的長度。但若是一般的指針變量,sizeof函數(shù)求出的值就是4或是8了。
3.gets()
它通過鍵盤獲得字符串輸入,并且沒有任何字符串長度上的限制和檢測,建議應(yīng)該避免在我們的代碼中使用該函數(shù)!
要求:定義一個長度為10的個字符數(shù)組,由用戶通過鍵盤為其賦值。
Code:
char name[10]; gets(name);
注意:本函數(shù)可以無限讀取,不會判斷上限,所以程序員應(yīng)該確保buffer的空間足夠大,以便在執(zhí)行讀操作時不發(fā)生溢出。為了避免這種情況,我們可以用fgets()來替換gets()。
危險:任何時候均要避免使用該函數(shù),雖然它存在已經(jīng)有很長一段時間了。
區(qū)別:
1.是否對用戶輸入的字符個數(shù)有所限制?
兩者均有所限制,但scanf函數(shù)需要你在格式化說明符中顯示注明,若不注明則無限制,可能會導(dǎo)致溢出事故;fgets函數(shù)則將其作為一個形參予以強制規(guī)定。
2.用戶是否可以同時輸入多個域的數(shù)據(jù)?
scanf函數(shù)可以通過添加多個格式化輸入說明符來實現(xiàn)多域輸入,而fgets函數(shù)每次僅能對一個域賦值。
3.用戶輸入的字符串中可以包含空格類字符嗎?
scanf函數(shù)會把空格符當(dāng)做字符串的結(jié)束符,故不可以在一個字符串中含有空格。而否則可以。
總結(jié)
以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持。
相關(guān)文章
C語言靜態(tài)動態(tài)兩版本通訊錄實戰(zhàn)源碼
這篇文章主要為大家?guī)砹薈語言實現(xiàn)靜態(tài)動態(tài)兩版本的通訊錄實戰(zhàn)源碼,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步2022-02-02C++消息隊列(定義,結(jié)構(gòu),如何創(chuàng)建,發(fā)送與接收)
這篇文章主要介紹了C++消息隊列(定義,結(jié)構(gòu),如何創(chuàng)建,發(fā)送與接收),消息隊列是一種先進先出的隊列型數(shù)據(jù)結(jié)構(gòu),實際上是系統(tǒng)內(nèi)核中的一個內(nèi)部鏈表2022-08-08c++與python實現(xiàn)二分查找的原理及實現(xiàn)
本文介紹了c++與python實現(xiàn)二分查找的原理及實現(xiàn),二分查找指首先將數(shù)組中間值和目標(biāo)值進行比較,如果相等則返回;如果不相等,則選擇中間值左邊的一半或者右邊的一半進行比較;不斷重復(fù)直到檢索完畢,下文相關(guān)資料需要的朋友可以參考一下2022-03-03static_cast,dynamic_cast,reinterpret_cast,const_cast的區(qū)別及用法詳解
以下是對static_cast,dynamic_cast,reinterpret_cast,const_cast的區(qū)別及用法進行了詳細的分析介紹,需要的朋友可以過來參考下2013-09-09