在vs2010中寫了一行scanf(“%s",name); 調式時 提示warning , 提示修改為scanf()使用可能會存在不安全,建議使用scanf_s() 但是我修改成scanf_s("%s",name)之后,正常運行沒有問題,也沒有了warning ,但是遇到scanf_s("%s",name)這句話時,我輸入了一個name, Enter 一下就報如下錯誤:
0xC0000005: Access violation writing location 0x00000000
在MS系統中錯誤代號:0xC0000005 表示訪問不存在的內存
原來,ANSI C中沒有scanf_s() , 只有scanf(), scanf()在讀取數據時不檢查邊界,所以可能會造成內在泄露。所以MS在vs2005及更高級版本中提供了scanf_s(),但是在調用它時,必須提供一個數字表明最多讀取多少位字符。
[官方文檔:http://msdn.microsoft.com/zh-cn/library/w40768et%28VS.80%29.aspx ]
之所以出現:0xC0000005這樣的錯,是因為在調用的時候沒有為它申請到內存,所以報訪問內存不存在,因為我輸入了字符串,這些字符串在buffer是有一個地址代表它們存在的位置的,但是調用scanf_s()時因為沒有指定讀取多少位字符, 所以它無法去讀取內存buffer中的字符串,所以報內存不可讀取的錯誤。 如果我們改成如下形式,給scanf_s()指定讀取例如10個字符,即可順利完成讀取任務:
scanf_s("%s",name,10);
因為scanf() 在讀取數據時不檢查邊界,由此可能造成安全隱患, 所以MS在vs2005版本及更高級版本中就建議使用scanf_s()來代替scanf()函數, 但是如果你堅持要使用scanf()函數的話,一般也不會出現什么問題, 不過vs在編譯時會給出warning提示, 如果要消除這個提示, 只要在使用了scanf()的文件最開始的地方加入如下語句即可:
#pragma warning(disable:4996)
scanf_s函數也是從標准輸入流中讀取數據並把它們格式化寫入到指定的變量中, 不像scanf()函數, scanf_s()函數在讀取輸入的字符時必須要為其指定一個緩沖區大小,這個緩沖區大小將作為一個附加參數在讀取字符時 立即傳入到scanf_s()函數。例如讀取一個字符串,容納這個字符串的緩沖區大小就被作為附加參數傳入到scanf_s()中。
char s[10];
scanf_s("%9s",s,10);
注:這個緩沖區大小包括了結束符NULL,讀取指令將使用這個緩沖區大小去讀取相應長度的字符到緩沖區中,如果沒有指定緩沖區大小,或者要讀取的字符(即從鍵盤輸入的字符)大於指定的緩沖區大小,那么什么也不會寫入到緩沖區中。 注意上面說的緩沖區包括了后面的結束符NULL ,是在字符串中而言。
讀取一個字符
char c;
scanf_s("%c",&c,1);
讀取多字節不帶null結束的字符串時,整型可以用如下方式讀取:
char c[4];
scanf_s("%4c",&c,4);
如果你需要在不同的編譯器中去編譯的話, 那么采用條件編譯是最好的選擇:
#define MS2010
double getNumber(const char* prompt)
{
double inputNumber = 0.0;
puts(prompt);
#ifdef MS2010
while((scanf_s("%lf",&inputNumber)) != 1)
#else
while((scanf("%lf",&inputNumber)) != 1)
#endif
{
while(getchar() != '\n');
printf("You must enter a NUMBER --%s",prompt);
}
while(getchar() != '\n');
return (inputNumber);
}
[參考鏈接:http://faculty.edcc.edu/paul.bladek/CS131/scanf_s.htm]