fscanf_s函數
在文件操作中經常會用到fscanf這個函數,但是在VC和VS中會有警告
意思是編譯器覺得fscanf不安全,叫你考慮用一下fscanf_s這個函數來代替fscanf,fscanf_s比fscanf多使用了一個參數
fscanf函數原型:
int fscanf( FILE *stream, const char *format [, argument ]...
fscanf_s函數原型:
int fscanf_s( FILE *stream, const char *format [, argument ]...
fscanf_s的第四個參數是最多讀取的字符數(注意:這個最多讀取的字符數的大小是包括的末尾的('\0')NULL的),下面我們來簡單測試一下第四個參數,先上代碼:
FILE *fp; char ss[10]; fp = fopen("E:\\ww.txt", "r+"); fscanf_s(fp , "%s", ss, 10); printf("%s", ss);
ww.txt文件中的內容為
運行結果為:
第四個參數10指的是最多讀取的字符數,是包含了字符串末尾的'\0'的,所以實際上最多可以讀取的字符只有10-1=9個字符,如果讀取的字符串長度大於9,那么fscanf_s不會向ss數組中讀入任何內容,只
將數組第一個元素賦值為'\0',下面來測試一下
將ww.txt中的內容改為
運行結果:
可以使用斷點調試來觀察數組ss的的值
還有一點必須要注意,第四個參數是無符號類型的
意思是:0 <= 第四個參數 <= 數組的長度,意思是下面這種寫法是不允許的
char ss[10]; fscanf_s(fp , "%s", ss, 11);
編譯階段不會報錯,但是無法運行(無論讀取內容的是否大於緩沖區大小)
在微軟的官方手冊中有這樣一段話
當輸入的數據太大時,除非指定了寬度的大小否則不會向緩沖區寫入任何數據
意思是有一種方法可以讓fscanf_s在讀取超過最多讀取的字符數的內容時,仍然只讀取指定了寬度大小的數據,方法如下
fscanf_s(fp , "%5s", ss, 10);
與上面不同的是,我們在格式控制符%s這個加了一個寬度控制,意思是最多讀取5個字符
此時ww.txt的內容為明顯文本文件的字符數大於了10,但是由於我們加了寬度控制,fscanf_s仍然會讀取5個字符到ss數組中
運行效果:
scanf_s函數
scanf_s的第四個參數也是最多讀取的字符數,這和fscanf_s完全一樣這里就不再贅述了,讀者可以看一微軟官方文檔中對buffer size的描述
重點:一、buffer size包括了末尾的NULL
二、buffer size參數描述的允許讀取的最大的字符數,而不是字節數
因為是最大的字符數,建議在使用這個參數的時候使用_countof這個宏,而不是sizeof,在對char類型的數組限制最大字符數時sizeof和_countof都可以,但是在對寬字符wchar_t類型的數組使用時就不能使用sizeof了,
應該用_countof,最好在前面加上(unsigned)強制轉換為無符號數
_countof
_countof是定義在stdlib.h中的一個宏
_countof作用是計算靜態數組中的元素個數,常見的使用方法如下
1 char ss[10]; 2 scanf_s("%s", ss, (unsigned)_countof(ss));
如果對指針使用_countof,則會產生錯誤的結果,因為數組在作為參數傳遞時會退化為指針,這意味着在函數內部不能直接使用_countof來得到數組中元素的個數
補充:對於fscanf_s中第四個參數以及寬度控制參數的測試
1、無寬度控制,有緩沖區控制
1 char ss[10]; 2 fscanf_s(fp, "%s", ss, (unsigned)_countof(ss));
2、有寬度控制,有緩沖區控制
寬度控制大小 < 緩沖區大小
char ss[10]; fscanf_s(fp, "%5s", ss, (unsigned)_countof(ss));
寬度控制大小 = 緩沖區大小
char ss[10]; fscanf_s(fp, "%10s", ss, (unsigned)_countof(ss));
寬度控制大小 > 緩沖區大小
char ss[10]; fscanf_s(fp, "%12s", ss, (unsigned)_countof(ss));
測試結果: