原来sscanf函数可以这么强大

来源:互联网 发布:淘宝店铺地址格式 编辑:程序博客网 时间:2024/05/17 03:59

【sscanf()函数的使用详解】
在看ineedle代码的时候,看到一个C函数sscanf(), 挺熟悉,也觉得挺简单的一个函数,但是此时我愣住了:
看到这样的代码: sscanf(szLine,”%[0-9|_|-|a-z|A-Z|&|*]”,szTemp);
/**********************************************************************************************
* 我晕,什么东东? 代码写错了吧?? 肯定不是啊,所以就搜索sscanf函数的格式控制用法,并进行了简单
* 整理。总结的还不是很全乎,但是现在就找到了这么多!(上传共享,求补充!!)
***********************************************************************************************/
[1] 功能: 从一个字符串中读进与指定格式相符的数据(int float string) -> 非常好用的函数
[2] 原型: int sscanf(const char *str, const char *format, …);
[3] 说明: sscanf与scanf类似都用于输入的,只是后者以屏幕为输入源,前者以固定字符串为输入源
其中的format可以是一个或多个如下格式:
{%[*] [width] [{h | l | I64 | L}]type | ’ ’ | ‘\t’ | ‘\n’ | 非%符号}
%[]类似于一个正则表达式。[a-z]表示读取a-z的所有字符,[^a-z]表示读取除a-z以外的所有字符
[0-9] 表示0-9 的所有数字 [a-z0-9] 可以放到一块使用
Ps:还有其它的表达式…
[4] 注解:
  (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表示满足该条件被过滤掉,不向目标参数写入值
  (7) 支持集合操作:
   %[a-z] 表示匹配a到z中任意字符,贪婪性(尽可能多的匹配)
   %[aB’] 匹配a、B、’中一员,贪婪性
   %[^a] 匹配非a的任意字符,贪婪性
[5] 举例说明:
(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

sscanf(“123456abcdedfBCDEF”,”%[1-9A-Z]”,buf);
printf(“%s\n”,buf);
结果为: 123456
/* 说明匹配到abcdef与A-Z不成功的时候就会停止匹配,而且不会去匹配后边的BCDEF */
(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);
// 首先忽略一个字符串,遇到空格直接跳过去–>匹配到%s->保存buf中的是world
   结果为:world
   注:%*s表示第一个匹配到的%s被过滤掉,即hello,被过滤了,如果没有”空格”则结果为NULL。
   sscanf的功能很类似于正则表达式, 但却没有正则表达式强大
所以如果对于比较复杂的字符串处理,建议使用正则表达式
(8) 综合例子
sscanf(“ABCabcAB=”, “%[A-Z]%[a-z]%[^a-z=]”, buf);
printf(“%s\n”, buf);
结果:AB
1:%只能使用一次,但%可以使用多次,比如在这个实验里面,先用%[A-Z]过滤大写字母,然后用%*[a-z]过滤小写字母
2:^后面可以带多个条件,且这些条件都受^的作用,比如^a-z=表示^a-z且^=(既不是小写字母,也不是等于号)
(9) 发现一个特殊的字符’-‘,自己发现的哦~
sscanf(“201*1b_-cdZA&”, “%[0-9|_|–|a-z|A-Z|&|*]”, buf);
/* 注意|–|中间是2个-符号(特殊符号,2个代表一个) */
printf(“%s\n”, buf); /* 体现了|符号的强大作用:或,只要满足其一就可以匹配成功 */
结果:201*1b_-cdZA&
/* 可以调整201*1b_-cdZA&他们的字符为任意顺序,都可以将它们匹配成功并读取!! */

[6] 简单总结(格式匹配过程)
(1) 该函数从源的前面顺序读取一个或一段字符,并将其与顺序取自格式控制字符串中的字符或字符串进行比较匹配:
(2) 当遇到一个空白字符时,则不比较而跳过(空格呢?–>跳过);
(3) 当遇到一个非空白字符时,进行比较但不存进指针变量内;
(4) 当遇到控制字符时,如果能匹配上,则按照控制字符的意义将从源读取的字符或字符串存入到下一个指针指向地址处;
(5) 不能匹配呢? –> 如果不匹配就会停止匹配过程(参考例子中第(4)个中的下边那个例子)
(6) 特别注意的是:
如果控制字符里有width,则会将最多这么多字符串存进下一个指针指向的地址处;
如果是控制符%[],则将源中字符串自当前位置开始到第一个不符合该控制符规定的匹配字符的所有字符存储到下一个指针指向的地址处。

0 0
原创粉丝点击