scanf、sscanf和sscanf_s

http://blog.csdn.net/shellching/article/details/4958518

在使用VS2005編譯一個程序時,出現了很多警告,說是用的函數是不安全的,應當使用安全版本,即函數名稱增加“_s”的版本。
 
 警告內容:
 warning C4996: 'sscanf': This function or variable may be unsafe. Consider using sscanf_s instead.
 
據瞭解,“_s”版本函數是微軟後來對c++做得擴展,用來替代原先不安全的函數,例如:printf、scanf、strcpy、fopen等等。

 

詳細參考:
ms-help://MS.VSCC.v80/MS.MSDN.v80/MS.VisualStudio.v80.chs/dv_vccrt/html/d9568b08-9514-49cd-b3dc-2454ded195a3.htm

 

原來安全版本的函數,對參數和緩衝邊界做了檢查,增加了返回值和拋出異常。這樣增加了函數的安全性,減少了出錯的機率。
同時這也意味着在使用這些函數時,有時你不得不輸入更多的關於緩衝區大小的參數,多敲幾下鍵盤能換來更少的麻煩,值得!

 

下面總結了sscanf的以及sscanf_s的常用方法,也體現了“_s”版本函數與原函數的特別之處:

 

1、sscanf和scanf的不同是輸入來源,前者是一個字符串,後者則是標準輸入設備

 

2、sscanf的使用,以解析時間字符串爲例,將字符串“2009-01-02_11:12:13”解析爲整型年月日時分秒

 

//定義
 char cc;
 tm tm_temp={0};
 string stime("2009-01-02_11:12:13");

 

//(1) 必須嚴格按照分隔符形式匹配填寫,若遇到不匹配項則終止解析


 sscanf(stime.c_str(), "%4d-%2d-%2d_%2d:%2d:%2d",
  &tm_temp.tm_year,
  &tm_temp.tm_mon,
  &tm_temp.tm_mday,
  &tm_temp.tm_hour,
  &tm_temp.tm_min,
  &tm_temp.tm_sec
  );
  
//(2) 可以不按照分割符號形式填寫,字符數必須一致,例如可以正確解析“2009/01/02_11:12:13”


 sscanf(stime.c_str(), "%4d%c%2d%c%2d%c%2d%c%2d%c%2d",
  &tm_temp.tm_year, &cc,
  &tm_temp.tm_mon, &cc,
  &tm_temp.tm_mday, &cc,
  &tm_temp.tm_hour, &cc,
  &tm_temp.tm_min, &cc,
  &tm_temp.tm_sec
  );
 
//(3) 可以不按照分割符號形式填寫,字符數必須一致,同上,%1s可以等同於%c


 sscanf(stime.c_str(), "%4d%1s%2d%1s%2d%1s%2d%1s%2d%1s%2d",
  &tm_temp.tm_year, &cc,
  &tm_temp.tm_mon, &cc,
  &tm_temp.tm_mday, &cc,
  &tm_temp.tm_hour, &cc,
  &tm_temp.tm_min, &cc,
  &tm_temp.tm_sec
  );

 

//(4) 可以不按照分割符形式和數量填寫,類型必須一致,例如可以正確解析“2009/01/02___11:12:13”
//這裏使用了sscanf的正則表達式,與通用的正則表示類似但不完全相同,%*c表示忽略連續多個字符


 sscanf(stime.c_str(), "%4d%*c%2d%*c%2d%*c%2d%*c%2d%*c%2d",
  &tm_temp.tm_year,
  &tm_temp.tm_mon,
  &tm_temp.tm_mday,
  &tm_temp.tm_hour,
  &tm_temp.tm_min,
  &tm_temp.tm_sec
  );
  
3、sscanf_s的使用

 

 //定義
 char cc[2];
 tm tm_temp={0};
 string stime("2009-01-02_11:12:13");

 

//(1) 與sscanf第一種方法相同,可以使用"%4d-%2d-%2d_%2d:%2d:%2d"格式匹配解析


 sscanf_s(stime.c_str(), "%4d-%2d-%2d_%2d:%2d:%2d",
   &tm_temp.tm_year,
   &tm_temp.tm_mon,
   &tm_temp.tm_mday,
   &tm_temp.tm_hour,
   &tm_temp.tm_min,
   &tm_temp.tm_sec
   );
  
//(2) 使用%c格式對數據解析時,必須對相應的緩衝區增加長度參數,否則將會出錯


 sscanf_s(stime.c_str(), "%4d%c%2d%c%2d%c%2d%c%2d%c%2d",
  &tm_temp.tm_year, &cc, 1,
  &tm_temp.tm_mon, &cc, 1,
  &tm_temp.tm_mday, &cc, 1,
  &tm_temp.tm_hour, &cc, 1,
  &tm_temp.tm_min, &cc, 1,
  &tm_temp.tm_sec
  );
  
//(3) 使用%s格式對數據解析時,緩衝長度必須大於字符串長度,否則不予解析


 sscanf_s(stime.c_str(), "%4d%1s%2d%1s%2d%1s%2d%1s%2d%1s%2d",
   &tm_temp.tm_year, &cc, 2,
   &tm_temp.tm_mon, &cc, 2,
   &tm_temp.tm_mday, &cc, 2,
   &tm_temp.tm_hour, &cc, 2,
   &tm_temp.tm_min, &cc, 2,
   &tm_temp.tm_sec
   );

 

//(4) 與sscanf一樣,sscanf_s同樣支持正則表達式


 sscanf_s(stime.c_str(), "%4d%*c%2d%*c%2d%*c%2d%*c%2d%*c%2d",
  &tm_temp.tm_year,
  &tm_temp.tm_mon,
  &tm_temp.tm_mday,
  &tm_temp.tm_hour,
  &tm_temp.tm_min,
  &tm_temp.tm_sec
  );
  
通過以上對比sscanf與sscanf_s的使用,可以看出後者對緩衝區安全有了更多的考慮,從而避免了許多不經意的煩惱。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章