sscanf学习

以前特别点的字符串解析都自己写,虽然有点麻烦,但总算不太复杂,而且量也不多,就这么过去了。

最近又要写,头疼。本想用正则,想想没多大必要,总感觉sscanf就能搞定,google一下,果然有惊喜。

两个常用例子:

url地址解析

bool paser_url(const char *url, char proto[16],host[256],file[256],param[256])

{

   //  一般的http://www.website.com/mainpage?param=d&dkad
   if(sscanf(url, "%[^:]://%[^/]/%[^?]?%s", proto,host,file,param)>=2)

      return true;

 

  // 特别点的ftp://user:[email protected]/file

   if(sscanf(url, "%[^:]://%*[^@]@%[^/]/%[^?]?%s", proto,host,file,param)>=2)

     return true;

 

   return false;

}

 

email地址识别

bool isemail(const char *email)

{
   if(email==NULL || strlen(email)>256)
      return false;

 

   char user[256],host[256];
   if(sscanf(email, "%[a-zA-Z0-9._-]@%s", user,host)==2) {

      char domain[256];

       while(sscanf(host, "%[a-zA-Z0-9_-].%s", domain, host)==2 && domain[0]!='-');

       if(strcmp(domain, host)==0)

           return true;

  }

  return false;

}

 

附上MSDN的说明

A format specification has the following form:

% [* ] [width ] [{h | l | I64 | L }]type

The format argument specifies the interpretation of the input and can contain one or more of the following:

  • White-space characters: blank (' '); tab ('/t'); or newline ('/n'). A white-space character causes scanf to read, but not store, all consecutive white-space characters in the input up to the next non–white-space character. One white-space character in the format matches any number (including 0) and combination of white-space characters in the input.
  • Non–white-space characters, except for the percent sign (% ). A non–white-space character causes scanf to read, but not store, a matching non–white-space character. If the next character in stdin does not match, scanf terminates.
  • Format specifications, introduced by the percent sign (% ). A format specification causes scanf to read and convert characters in the input into values of a specified type. The value is assigned to an argument in the argument list.

The format is read from left to right. Characters outside format specifications are expected to match the sequence of characters in stdin ; the matching characters in stdin are scanned but not stored. If a character in stdin conflicts with the format specification, scanf terminates, and the character is left in stdin as if it had not been read.

When the first format specification is encountered, the value of the first input field is converted according to this specification and stored in the location that is specified by the first argument . The second format specification causes the second input field to be converted and stored in the second argument , and so on through the end of the format string.

An input field is defined as all characters up to the first white-space character (space, tab, or newline), or up to the first character that cannot be converted according to the format specification, or until the field width (if specified) is reached. If there are too many arguments for the given specifications, the extra arguments are evaluated but ignored. The results are unpredictable if there are not enough arguments for the format specification.

Each field of the format specification is a single character or a number signifying a particular format option. The type character, which appears after the last optional format field, determines whether the input field is interpreted as a character, a string, or a number.

The simplest format specification contains only the percent sign and a type character (for example, %s ). If a percent sign (% ) is followed by a character that has no meaning as a format-control character, that character and the following characters (up to the next percent sign) are treated as an ordinary sequence of characters, that is, a sequence of characters that must match the input. For example, to specify that a percent-sign character is to be input, use %% .

An asterisk (* ) following the percent sign suppresses assignment of the next input field, which is interpreted as a field of the specified type. The field is scanned but not stored.

 

google到的文章原文http://baike.baidu.com/view/1364018.htm

sscanf

   名称:
   sscanf () - 从一个 字符 中读进与指定格式相符的数据.
   函数原型:
  Int sscanf ( string str, string fmt, mixed var1, mixed var2 ... );
  int scanf( const char *format [,argument]... );
   说明:
   sscanf 与scanf类似,都是用于输入的,只是后者以键盘(stdin)为输入源,前者以固定 字符 为输入源。
  其中的format可以是一个或多个 {%[*] [width] [{h | l | I64 | L}]type | ' ' | '/t' | '/n' | 非%符号}
   注:
  1、 * 亦可用于格式中, (即 %*d 和 %*s) 加了星号 (*) 表示跳过此数据不读入. (也就是不把此数据读入参数中)
  2、{a|b|c}表示a,b,c中选一,[d],表示可以有d也可以没有d。
  3、width表示读取宽度。
  4、{h | l | I64 | L}:参数的size,通常h表示单字节size,I表示2字节 size,L表示4字节size(double例外),l64表示8字节size。
  5、type :这就很多了,就是%s,%d之类。
  6、特别的:%*[width] [{h | l | I64 | L}]type 表示满足该条件的被过滤掉,不会向目标参数中写入值
   支持集合操作:
  %[a-z] 表示匹配a到z中任意 字符 ,贪婪性(尽可能多的匹配)
  %[aB'] 匹配a、B、'中一员,贪婪性
  %[^a] 匹配非a的任意 字符 ,贪婪性  

[ 编辑本段 ]
例子:

  1. 常见用法。
  char buf[512] = ;
   sscanf ("123456 ", "%s", buf);
  printf("%s/n", buf);
  结果为:123456
  2. 取指定长度的 字符 。如在下例中,取最大长度为4字节的 字符
   sscanf ("123456 ", "%4s", buf);
  printf("%s/n", buf);
  结果为:1234
  3. 取到指定 字符 为止的 字符 。如在下例中,取遇到空格为止 字符
   sscanf ("123456 abcdedf", "%[^ ]", buf);
  printf("%s/n", buf);
  结果为:123456
  4. 取仅包含指定 字符 集的 字符 。如在下例中,取仅包含1到9和小写字母的 字符
   sscanf ("123456abcdedfBCDEF", "%[1-9a-z]", buf);
  printf("%s/n", buf);
  结果为:123456abcdedf
  5. 取到指定 字符 集为止的 字符 。如在下例中,取遇到大写字母为止的 字符
   sscanf ("123456abcdedfBCDEF", "%[^A-Z]", buf);
  printf("%s/n", buf);
  结果为:123456abcdedf
  6、给定一个 字符 iios/12DDWDFF@122,获取 / 和 @ 之间的 字符 ,先将 "iios/"过滤掉,再将非'@'的一 内容送到buf中
   sscanf ("iios/12DDWDFF@122", "%*[^/]/%[^@]", buf);
  printf("%s/n", buf);
  结果为:12DDWDFF
  7、给定一个 字符 ““hello, world”,仅保留world。(注意:“,”之后有一空格)
   sscanf (“hello, world”, "%*s%s", buf);
  printf("%s/n", buf);
  结果为:world
  %*s表示第一个匹配到的%s被过滤掉,即hello被过滤了
  如果没有空格则结果为NULL。
   sscanf 的功能很类似于正则表达式, 但却没有正则表达式强大,所以如果对于比较复杂的 字符 处理,建议使用正则表达式.
  //-------------------------------------------------------
   sscanf ,表示从 字符 中格式化输入
  上面表示从str中,输入数字给x,就是32700
  久以前,我以为c没有自己的split string函数,后来我发现了 sscanf ;一直以来,我以为 sscanf 只能以空格来界定 字符 ,现在我发现我错了。
   sscanf 是一个运行时函数,原形很简单:
  int sscanf (
  const char *buffer,
  const char *format [,
  argument ] ...
  );
  它强大的功能体现在对format的支持上。
  我以前用它来 分隔 类似这样的 字符 2006:03:18:
  int a, b, c;
   sscanf ("2006:03:18", "%d:%d:%d", a, b, c);
  以及2006:03:18 - 2006:04:18:
  char sztime1[16] = "", sztime2[16] = "";
   sscanf ("2006:03:18 - 2006:04:18", "%s - %s", sztime1, sztime2);
  但是后来,我需要处理2006:03:18-2006:04:18
  仅仅是取消了‘-’两边的空格,却打破了%s对 字符 的界定。
  我需要重新设计一个函数来处理这样的情况?这并不复杂,但是,为了使所有的代码都有统一的风格,我需要改动很多地方,把已有的 sscanf 替换成我自己的分割函数。我以为我肯定需要这样做,并伴随着对 sscanf 的强烈不满而入睡;一觉醒来,发现其实不必。
  format-type中有%[]这样的type field。如果读取的 字符 ,不是以空格来 分隔 的话,就可以使用%[]。
  %[]类似于一个正则表达式。[a-z]表示读取a-z的所有 字符 ,[^a-z]表示读取除a-z以外的所有 字符
  所以那个问题也就迎刃而解了:
   sscanf ("2006:03:18 - 2006:04:18", "%[0-9,:] - %[0-9,:]", sztime1, sztime2);
  在softmse (Jake) 的问题贴http://community.csdn.net/Expert/topic/4843/4843294.xml?temp=.4321558中 ,周星星给出了一个很cool的 sscanf 用例,而后通过学习,发现 sscanf 真棒,现做一总结。
  原问题:
  iios/12DDWDFF@122
  获取/和@之间的 字符 怎么做
  C程序里面有什么函数吗?
  周星星的代码:
  #include <stdio.h>
  int main()
  {
  const char* s = "iios/12DDWDFF@122";
  char buf[20];
   sscanf ( s, "%*[^/]/%[^@]", buf );
  printf( "%s/n", buf );
  return 0;
  }
  结果为:12DDWDFF
   sscanf 与scanf类似,都是用于输入的,只是后者以屏幕(stdin)为输入源,前者以固定 字符 为输入源。
  函数原型:
  int scanf( const char *format [,argument]... );
  其中的format可以是一个或多个 {%[*] [width] [{h | l | I64 | L}]type | ' ' | '/t' | '/n' | 非%符号},
  注:{a|b|c}表示a,b,c中选一,[d],表示可以有d也可以没有d。
  width:宽度,一般可以忽略,用法如:
  const char sourceStr[] = "hello, world";
  char buf[10] = ;
   sscanf (sourceStr, "%5s", buf); //%5s,只取5个 字符
  cout << buf<< endl;
  结果为:hello
  {h | l | I64 | L}:参数的size,通常h表示单字节size,I表示2字节 size,L表示4字节size(double例外),l64表示8字节size。
  type :这就很多了,就是%s,%d之类。
  特别的:
  %*[width] [{h | l | I64 | L}]type 表示满足该条件的被过滤掉,不会向目标参数中写入值。如:
  const char sourceStr[] = "hello, world";
  char buf[10] = ;
   sscanf (sourceStr, "%*s%s", buf); //%*s表示第一个匹配到的%s被过滤掉,即hello被过滤了
  cout << buf<< endl;
  结果为:world
  支持集合操作:
  %[a-z] 表示匹配a到z中任意 字符 ,贪婪性(尽可能多的匹配)
  %[aB'] 匹配a、B、'中一员,贪婪性
  %[^a] 匹配非a的任意 字符 ,贪婪性
  是不是感觉眼熟了啊,不错,这和正则表达式很相似,而且仍然支持过滤,即可以有%*[a-z].如:
  星星大哥例子回顾:
  const char* s = "iios/12DDWDFF@122";
  char buf[20];
   sscanf ( s, "%*[^/]/%[^@]", buf );
  printf( "%s/n", buf );
  由例子3-》取到指定 字符 为止的 字符 。如在下例中,取遇到空格为止 字符
   sscanf ("123456 abcdedf", "%[^ ]", buf);
  printf("%s/n", buf);
  结果为:123456
  所以周星星的代码总结应该为:
  const char* s = "iios/12DDWDFF@122";
  char buf[20];
   sscanf ( s, "%*[^/]/%[^@]", buf );
  printf( "%s/n", buf );
  先将 "iios/"过滤掉,再将到 字符 '@'为止的一 12DDWDFF(由例3可得此 到@为止,把@122舍掉)内容即是:12DDWDFF送到buf中,得到结果。
  PS: 向星星大哥和softmse (Jake) 致谢了,有了你们才有它啊

你可能感兴趣的:(sscanf学习)