sscanf_s 使用问题

在使用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的使用,可以看出后者对缓冲区安全有了更多的考虑,从而避免了许多不经意的烦恼。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值