定义函数 int sscanf (const char *str,const char * format,........);
函数说明 sscanf()会将参数str的字符串根据参数format字符串来转换并格式化数据。格式转换形式请参考scanf()。转换后的结果存于对应的参数内。返回值 成功则返回匹配成功的参数数目,失败则返回-1,错误原因存于errno中。范例 #include<stdio.h>main(){ int i;unsigned int j;char input[ ]=”10 0x1b aaaaaaaa bbbbbbbb”;char s[5];sscanf(input,”%d %x %5[a-z] %*s %f”,&i,&j,s,s);printf(“%d %d %s\n”,i,j,s);} charstr[512] = {0}; sscanf("123456 ", "%s", str); printf("str=%s\n", str); |
sscanf("123456 ", "%4s", str); printf("str=%s\n", str); |
sscanf("123456 abcdedf", "%[^ ]s", str); printf("str=%s\n", str); |
sscanf("123456abcdedfBCDEF", "%[1-9a-z]s", str); printf("str=%s\n", str); |
sscanf("123456abcdedfBCDEF", "%[^A-Z]s", str); printf("str=%s\n", str); |
先看一下%[] 格式:
(1)-: 表示范围,如:%[1-9]表示只读取1-9这几个数字 %[a-z]表示只读取a-z小写字母,类似地 %[A-Z]只读取大写字母(2)^: 表示不取,如:%[^1]表示读取除‘1‘以外的所有字符 %[^/]表示除/以外的所有字符(3),: 范围可以用","相连接 如%[1-9,a-z]表示同时取1-9数字和a-z小写字母 (4)原则:从第一个在指定范围内的数字开始读取,到第一个不在范围内的数字结束%s 可以看成%[] 的一个特例 %[^ ](注意^后面有一个空格!)这样使用sscanf+%[]可以轻松的分析字符串,很多字符串问题便迎刃而解了。
以hrbeu3001为例(不是完整代码,没有要求的格式)只需2个sscanf函数,就能完成题目的要求,代码非常简洁。#include <stdio.h>#include <string.h>int main(int argc, char *argv[])
{ char buf[1024],str1[100],str2[100],str3[100],str4[100],temp[100]="<default>"; int count; scanf("%d",&count); while(count--) { str1[0]=‘\0‘; str2[0]=‘\0‘; str3[0]=‘\0‘; str4[0]=‘\0‘; scanf("%s",buf); sscanf(buf,"%[^:]://%[^:,/]:%[,1-9]",str1,str2,str3,str4); sscanf(buf,"%[^:]://%[^:,/]/%[a-z,A-Z,/,~]",str1,str2,str4); if(str3[0]==‘\0‘)strcpy(str3,temp); if(str4[0]==‘\0‘)strcpy(str4,temp); printf("%s\n%s\n%s\n%s\n",str1,str2,str3,str4); } return 0;}
========================================================
此文所有的实验都是基于下面的程序:
char str[10];
for (int i = 0; i < 10; i++) str[i] = '!';
执行完后str的值为
str = "!!!!!!!!!!"
我们把str的每个字符都初始化为惊叹号,当str的值发生变化时,使用printf打印str的值,对比先前的惊叹号,这样就可以方便的观察str发生了怎样的变化。下面我们做几个小实验,看看使用sscanf和正则表达式格式化输入后,str有什么变化。
实验1:
sscanf("123456","%s",str); ---------str的值为 "123456\0!!!"
这个实验很简单,把源字符串"123456"拷贝到str的前6个字符,并且把str的第7个字符设为null字符,也就是\0
实验2:
sscanf("123456","%3s",str); ---------str的值为 "123\0!!!!!!"
看到没有,正则表达式的百分号后面多了一个3,这告诉sscanf只拷贝3个字符给str,然后把第4个字符设为null字符。
实验3:
sscanf("aaaAAA","%[a-z]",str); ---------str的值为 "aaa\0!!!!!!"
从这个实验开始我们会使用正则表达式,括号里面的a-z就是一个正则表达式,它可以表示从a到z的任意字符,
在 继续讨论之前,我们先来看看百分号表示什么意思,%表示选择,%后面的是条件,比如实验1的"%s",s是一个条件,表示任意字符,"%s"的意思是:只 要输入的东西是一个字符,就把它拷贝给str。实验2的"%3s"又多了一个条件:只拷贝3个字符。实验3的“%[a-z]”的条件稍微严格一些,输入的 东西不但是字符,还得是一个小写字母的字符,所以实验3只拷贝了小写字母"aaa"给str,别忘了加上null字符。
实验4:
sscanf("AAAaaaBBB","%[^a-z]",str); ---------str的值为 "AAA\0!!!!!!"
对 于所有字符,只要不是小写字母,都满足"^a-z"正则表达式,符号^表示逻辑非。前3个字符都不是小写字符,所以将其拷贝给str,但最后3个字符也不 是小写字母,为什么不拷贝给str呢?这是因为当碰到不满足条件的字符后,sscanf就会停止执行,不再扫描之后的字符。
实验5:
sscanf("AAAaaaBBB","%[A-Z]%[a-z]",str); ---------段错误
这 个实验的本意是:先把大写字母拷贝给str,然后把小写字母拷贝给str,但很不幸,程序运行的时候会发生段错误,因为当sscanf扫描到字符a时,违 反了条件"%[A-Z]",sscanf就停止执行,不再扫描之后的字符,所以第二个条件也就没有任何意义,这个实验说明:不能使用%号两次或两次以上
实验6:
sscanf("AAAaaaBBB","%*[A-Z]%[a-z]",str); ---------str的值为 "aaa\0!!!!!!"
这 个实验出现了一个新的符号:%*,与%相反,%*表示过滤满足条件的字符,在这个实验中,%*[A-Z]过滤了所有大写字母,然后再使用%[a-z]把之 后的小写字母拷贝给str。如果只有%*,没有%的话,sscanf不会拷贝任何字符到str,这时sscanf的作用仅仅是过滤字符串。
实验7:
sscanf("AAAaaaBBB","%[a-z]",str); ---------str的值为 "!!!!!!!!!!"
做 完前面几个实验后,我们都知道sscanf拷贝完成后,还会在str的后面加上一个null字符,但如果没有一个字符满足条件,sscanf不会在str 的后面加null字符,str的值依然是10个惊叹号。这个实验也说明了,如果不使用%*过滤掉前面不需要的字符,你永远别想取得中间的字符。
实验8:
sscanf("AAAaaaBC=","%*[A-Z]%*[a-z]%[^a-z=]",str); ---------str的值为 "BC\0!!!!!!!"
这是一个综合实验,但这个实验的目的不是帮我们复习前面所学的知识,而是展示两个值得注意的地方:
注意1:%只能使用一次,但%*可以使用多次,比如在这个实验里面,先用%*[A-Z]过滤大写字母,然后用%*[a-z]过滤小写字母。
注意2:^后面可以带多个条件,且这些条件都受^的作用,比如^a-z=表示^a-z且^=(既不是小写字母,也不是等于号)。
实验9:
int k;
sscanf("AAA123BBB456", "%*[^0-9]%i", &k); ---------k的值为123
首先,%*[^0-9]过滤前面非数字的字符,然后用%i把数字字符转换成int型的整数,拷贝到变量k,注意参数必须使用k的地址。
==================================================================
以前只是简单是使用sscanf,却没发现其还有如此强大的功能
char str0[100],str1[100],str2[100],str3[100]; sscanf("abcde abc 123 aaa","%s %s %s %s",str0,str1,str2,str3); 结果:str0="abcde" str1="abc" str2 = "123" str3="aaa" sscanf("abcde abc 123 aaa","abc%s %s %*d %s",str0,str1,str3); 结果:str0="abcde" str1="abc" str3="aaa" sscanf("abc123 efg456","%4s",str0); 结果:str0="abc1" sscanf("abc123 efg456a4","%[a-z 1-5]",str0); 结果:str0="abc123 efg45" sscanf("abc123 efg456a4","%[a-z1-5]",str0); 结果:str0="abc123" sscanf("ABCTabcZ123 efg456","%[A-P]",str0); 结果:str0="ABC" sscanf("abc 12345","%[^ ]",str0); 结果:str0="abc" sscanf("abc 12345","%[^4]",str0); 结果:str0="abc 123" sscanf("fdaBs 52aB1asdf","%[^4-0]",str0); 结果:str0="fdaBs 5" sscanf("abc 12345","%[^ ]%[^3]",str0,str1); 结果:str0="abc" str1="12" sscanf("abc301abc2345","%*[^9-0]%s",str0); 结果:str0="301abc2345" sscanf("); 结果:str0="123efg4"