今天遇到一个格式化字符串输入函数如下:
char *pcUserHdr = “abc[username][interface]”;
sscanf(pcUserHdr, "%*[^[][%[^]]][%[^]]",acUserName,acInterface);
对此学习了下,输出一个总结:
1. sscanf函数原型不多做解释,直接以一个例子开始;
sscanf(buf, "GET /%[^ ]", buf_rev);
基本格式为 %[set],表示将接收一个由set指定格式的字符串,其中set表示可接受的字符集合。
set一般有两种情况:
一种是"^set"表示非, 即在输入的字符串中将匹配所有不在set中出现的字符,遇到set中的字符时停止匹配。
另一种是"set"表示在输入的字符串中将匹配所有在set中出现的字符,遇到非set中的字符时停止匹配。
如:
scanf("%[^&]",buf); //当输入的字符中出现"&"时停止匹配,如果输入hello&world,则buf=hello;
scanf("%[^290#*]",buf); //当输入aidc#ad时,则buf=aidc,
特殊情况:
(1)如果要匹配"^"时,当然不能直接放在[]中,所以可以用%[ab^cd]这种方式,
(2)当要匹配右方括号"]"时,应把其放在set中第一个位置,如"%[]abc]"表示匹配的字符集为{], a, b, c},又如"%[^]abc]"表示匹配所有非"], a, b, c"中的字符,另外,还可以使用"-" 如%[a-z]表示只匹配abcd....yz等小写的字母; %[0-9]表示只匹配0,1,2...9等数字;
(3) * 表示跳过。
2. 举例:
例1:
#gcc test2.c -o test
#./test
name = aaaa,number = bbbb
#vi test2.c
#include <stdio.h>
#include <string.h>
int main()
{
char *str = "999:aaaa][bbbb]";
char name[10] = {0};
char number[10] = {0};
sscanf(str,"%*[^:]:%[^]]][%[^]]",name,number);
printf("name = %s,number = %s\n",name,number);
return 0;
}
解释:
sscanf(str,"%*[^:]:%[^]]][%[^]]",name,number);
1. %*[^:]:%[^]]][%[^]] 可分为3部分理解:①%*[^:] ②:%[^]] ③][%[^]]
1.1 ①%*[^:] 表示:%*跳过,[^:]到哪里结束,结合起来理解就是跳过直到匹配到第一个:即结合上面的程序就是跳过了999。
1.2 ②:%[^]]表示::%从:开始,[^]]到哪里结束,结合起来理解就是从:开始到直到匹配到]结束,即结合上面的程序就是从:开始到]结束,即值为aaaa。
1.3 ③][%[^]]表示:][%从][开始,[^]]到哪里结束,结合起来理解就是从][开始到直到匹配到]结束,即结合上面的程序就是从][到]结束,即值为bbbb。
例 2:
#gcc test2.c -o test
#./test
user = liman,host = host,cmd = 34234,msg = hello
#vi test2.c
#include <stdio.h>
#include <string.h>
int main()
{
char buf[100]="123:asdfasd:2342342:liman:host:34234:hello";
char user[20]="";
char host[20]="";
char msg[20]="";
int cmd = 0;
sscanf(buf, "%*d:%*[^:]:%*[^:]:%[^:]:%[^:]:%d:%s", user, host, &cmd, msg);
printf("user = %s,host = %s,cmd = %d,msg = %s\n",user,host,cmd,msg);
return 0;
}
解释:
sscanf(buf, "%*d:%*[^:]:%*[^:]:%[^:]:%[^:]:%d:%s", user, host, &cmd, msg);
1. %*d:%*[^:]:%*[^:]:%[^:]:%[^:]:%d:%s有上面的基础,这个也拆成7部分理解:
1.1 %*d 跳过第一个整数。 //跳过123
1.2 :%*[^:]从:开始跳过直到遇到下一个:之间的值。 //跳过asdfasd
1.3:%*[^:]从:开始跳过直到遇到下一个:之间的值。 //跳过2342342
1.4 :%[^:]取出从:开始直到下一个:之间的值。//取出liman
1.5:%[^:]取出从:开始直到下一个:之间的值。//取出host
1.6 :%d取出从:开始的一个整数值。//取出34234
1.7:%s取出从:开始的一个字符串的值。//取出hello
那么再回头看sscanf(pcUserHdr, "%*[^[][%[^]]][%[^]]",acUserName,acInterface);就不是那么难了。
可以很快看出跳过从开始到第一个[之间的值,拿出从[开始到下一个匹配到]的值,拿出从][开始到匹配到下一个]的值。
3. 正则表达式基本用法:
1、“.”为通配符,表示任何一个字符,例如:“a.c”可以匹配“anc”、“abc”、“acc”;
2、“[]”,在[]内可以指定要求匹配的字符,例如:“a[nbc]c”可以匹配“anc”、“abc”、"acc";但不可以匹配“ancc”,a到z可以写成[a-z],0到9可以写成[0-9];
3、数量限定符号,表示匹配次数(或者叫做长度)的符号,包括:
“*” 0次或者多次
“+” 1次或者多次
“?” 0次或者1次
“{n}” 匹配n次,n为整数
“{n,m}” 匹配从n到m之间的某个数的次数;n和m都是整数;
“{n,}” 匹配n到无穷次之间任意次数;
“{,m}” 匹配0到m之间任意次数;
数量限定符号放到匹配格式的后面,例如:电话号码:024-84820482,02484820482(假设前面3或者4位,后面7或者8位,并且中间的减号可有可无),都是符合规定的,那么可以用如下格式来匹配:[0-9]{3,4} \-? [0-9]{7,8};注意:“\”为转义字符,因为“-”在正则表达式用有代表一个范围的意义,例如:前面所说的[0-9],所以它需要转义字符“\”进行转义才可使用;
4、^为否符号,表示不想匹配的符号,例如:[^z][a-z]+可以匹配所有除"z"开头的以外的所有字
如果^放到[]的外边则表示以[]开头的字符串;^[az][a-z]+表示a或者z开头的长度大于等于2的英文字符串;
关于介绍正则表达式的文章很多,有的较为详细,由于个人只是在遇到问题时稍作学习,因此还有很多的用法未明白也不做陈述,此文只供入门的同学参考下。