sscanf() - 从一个字符串中读进与指定格式相符的数据.
函数原型:
Int sscanf( string str, string fmt, mixed var1, mixed var2 ... );
int scanf( const char *format [,argument]... );说明: sscanf与scanf类似,都是用于输入的
sscanf以固定字符串为输入源 scanf以固定字符串为输入源。
**其中的format可以是一个或多个 {%[*] [width] [{h | l | I64 | L}]type | ' ' | '\t' | '\n' | 非%符号}
支持集合操作:
%[a-z] 表示匹配a到z中任意字符,贪婪性(尽可能多的匹配)
%[aB'] 匹配a、B、'中一员,贪婪性
%[^a] 匹配非a的任意字符,贪婪性
例子:
1. 常见用法。
char buf[512] = {0};
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、给定一个字符串Dejan/12DDWDF@12,获取 / 和 @ 之间的字符串,先将 "Dejan/"过滤掉,再将非"@的一串内容送到buf中 。
sscanf("Dejan/12DDWDF@12", "%*[^/]/%[^@]", 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。
8、 scanf的format中出现的非转换字符(%之前或转换字符之后的字符),即此例中的1234用来跳过输入中的相应字符;‘[ ]’的含义与正则表达式中相同,表示匹配其中出现的字符序列;^表示相反。使用[ ]时接收输入的变量必须是有足够存储空间的char、signed char、unsigned char数组。记住 [ 也是转换字符,所以没有s了。 (跳开1 遇到2停下 跳开234 遇到5停下)
char *s="1try234delete5";sscanf(s, "1%[^2]234%[^5]", s1, s2);
char s1[16]={0};
char s2[16]={0};
char *s="1try234delete5";
sscanf(s, "1%[^2]234%[^5]", s1, s2);
printf("%s\n", s1);
printf("%s\n", s2);
9、一个提取用户个人资料中邮件地址的例子
关键是"%*[^:]:%[^;]"和"%*[^:]:%s"这两个参数的问题 %*[^:] 表示满足"[]"里的条件将被过滤掉,不会向目标参数中写入值。这里的意思是在 第一个':'之前的字符会在写入时过滤掉,'^'是表示否定的意思,整个参数翻译 成白话就是:将在遇到第一个':'之前的(不为':'的)字符全部过滤掉。 : 自然就是跳过':'的意思。 %[^;] 拷贝字符直到遇到';'
#include
#include
using namespace std;
int main()
{
char a[20]={0};
char b[20]={0};
//假设email地址信息以';'结束
sscanf("email:[email protected];","%*[^:]:%[^;]",a);
//假设email地址信息没有特定的结束标志
sscanf("email:[email protected]","%*[^:]:%s",b);
printf("%s\n",a);
printf("%s\n",b);
system("pause");
return 0;
}
补充:
%[ ]
%[ ]表示要读入一个字符集合, 如果[ 后面第一个字符是”^”,则表示反意思。
[ ]内的字符串可以是1或更多字符组成。空字符集(%[])是违反规定的,可导致不可预知的结果。%[^]也是违反规定的。
%[a-z]
读取在 a-z 之间的字符串,如果不在此之前则停止,如char s[]="hello, my friend”
注意: ,逗号在不 a-z之间 , sscanf( s, “%[a-z]”, string ) ; // string=hello
%[^a-z]
读取不在 a-z 之间的字符串,如果碰到a-z之间的字符则停止,如
char s[ ]="HELLOkitty” ; // 注意: ,逗号在不 a-z之间
sscanf( s, “%[^a-z]”, string ) ; // string 》》》HELLO
%*[^=]
前面带 * 号表示不保存变量。跳过符合条件的字符串。
char s[ ]="notepad=1.0.0.1001" ;
char szfilename [32] = "" ;
int i = sscanf( s, "%*[^=]", szfilename ) ; // szfilename=NULL,因为没保存
int i = sscanf( s, "%*[^=]=%s", szfilename ) ; // 遇到=停下,跳过=,输出到最后
// szfilename=1.0.0.1001
%40c
读取40个字符,运行时库不会自动附加空终止符到字符串,也不会读取 40 个字符自动终止 scanf() 函数。 因为库使用缓冲输入,您必须按 ENTER 键终止字符串扫描。 如果您之前按 ENTER,scanf() 读取40个字符,正常显示,并且库继续提示额外的输入直到它读到 40 个字符
%[^=]
读取字符串直到碰到’=’号,’^’后面可以带更多字符,如:
char s[]="notepad=1.0.0.1001" ;
char szfilename [32] = "" ;
int i = sscanf( s, "%[^=]", szfilename ) ; // szfilename=notepad
//如果参数格式是:%[^=:] ,那么也可以从 notepad:1.0.0.1001读取notepad
char s[]="notepad=1.0.0.1001" ;
char szname [32] = "" ;
char szver [32] = "" ;
sscanf( s, "%[^=]=%s", szname , szver ) ; // szname=notepad, szver=1.0.0.1001
注意:%[]有很大的功能,但是并不是很常用到,主要因为:
1、许多系统的 scanf 函数都有漏洞. (典型的就是 TC 在输入浮点型时有时会出错).
2、用法复杂, 容易出错.
3、编译器作语法分析时会很困难, 从而影响目标代码的质量和执行效率.