sscanf

    技术2022-05-20  70

    在使用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(), "M----_-:-:-",   &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(), "M%c-%c-%c-%c-%c-",   &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(), "M%1s-%1s-%1s-%1s-%1s-",   &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(), "M%*c-%*c-%*c-%*c-%*c-",   &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第一种方法相同,可以使用"M----_-:-:-"格式匹配解析

     sscanf_s(stime.c_str(), "M----_-:-:-",    &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(), "M%c-%c-%c-%c-%c-",   &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(), "M%1s-%1s-%1s-%1s-%1s-",    &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(), "M%*c-%*c-%*c-%*c-%*c-",   &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)