Chinaunix首页 | 论坛 | 博客
  • 博客访问: 116724
  • 博文数量: 26
  • 博客积分: 10
  • 博客等级: 民兵
  • 技术积分: 122
  • 用 户 组: 普通用户
  • 注册时间: 2012-10-11 10:02
个人简介

分享是一种快乐!

文章分类

全部博文(26)

文章存档

2014年(11)

2013年(15)

我的朋友

分类: C/C++

2014-01-03 12:46:11

#include

 定义函数 int sscanf (const char *str,const char * format,........);

函数说明 
 sscanf()会将参数str的字符串根据参数format字符串来转换并格式化数据。格式转换形式请参考scanf()。转换后的结果存于对应的参数内。

返回值 成功则返回参数数目,失败则返回-1,错误原因存于errno中。 返回0表示失败    否则,表示正确格式化数据的个数    例如:sscanf(str,"%d%d%s", &i,&i2, &s);    如果三个变成都读入成功会返回3。    如果只读入了第一个整数到i则会返回1。证明无法从str读入第二个整数。

   1. 常见用法。

  charstr[512]={0};
  sscanf("123456","%s",str);
  printf("str=%s",str);

  2. 取指定长度的字符串。如在下例中,取最大长度为4字节的字符串。

  sscanf("123456","%4s",str);
  printf("str=%s",str);

  3. 取到指定字符为止的字符串。如在下例中,取遇到空格为止字符串。

  sscanf("123456abcdedf","%[^]",str);
  printf("str=%s",str);

 4. 取仅包含指定字符集的字符串。如在下例中,取仅包含1到9和小写字母的字符串。

  sscanf("123456abcdedfBCDEF","%[1-9a-z]",str);
  printf("str=%s",str);

  5. 取到指定字符集为止的字符串。如在下例中,取遇到大写字母为止的字符串。

  sscanf("123456abcdedfBCDEF","%[^A-Z]",str);
  printf("str=%s",str);

可以用如下代码将字符串形式的ip地址转换为四个整数:

  1. char * inputIp  
  2. int ip[4];  
  3. sscanf_s(inputIp, "%d.%d.%d.%d", &ip[0], &ip[1],&ip[2],&ip[3]); 

  注意sscanf_s,当读入的类型是整数或其它长度可以确定的类型时,不能在类型后面跟上长度,但是对于字符串类型(char *)长度无法得知则必须在类型后面明确指出字符串的最大长度(即可以容纳的空间)。举例如下:

  1. // crt_sscanf_s.c  
  2. // This program uses sscanf_s to read data items  
  3. // from a string named tokenstring, then displays them.  
  4.   
  5. #include   
  6. #include   
  7.   
  8. int main( void )  
  9. {  
  10.    char  tokenstring[] = "15 12 14...";  
  11.    char  s[81];  
  12.    char  c;  
  13.    int   i;  
  14.    float fp;  
  15.   
  16.    // Input various data from tokenstring:  
  17.    // max 80 character string plus NULL terminator  
  18.    sscanf_s( tokenstring, "%s", s, _countof(s) );  
  19.    sscanf_s( tokenstring, "%c", &c, sizeof(char) );  
  20.    sscanf_s( tokenstring, "%d", &i );  
  21.    sscanf_s( tokenstring, "%f", &fp );  
  22.   
  23.    // Output the data read  
  24.    printf_s( "String    = %s\n", s );  
  25.    printf_s( "Character = %c\n", c );  
  26.    printf_s( "Integer:  = %d\n", i );  
  27.    printf_s( "Real:     = %f\n", fp );  
  28. }  

      对于多个字符串读入的情况,代码如下:

  1. sscanf_s(inputString, "%s.%s.%s.%s", s1, s1.length, s2, s2.length, s3, s3.length, s4, s4.length); 

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

阅读(1956) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~