sscanf,scanf,fscanf与正则表达式(转帖)
表头文件 #include(stdio.h )
定义函数 int sscanf (const char *str,const char * format,........);
函数说明 sscanf()会将参数str的字符串根据参数format字符串来转换并格式化数据。格式转换形式请参考scanf()。转换后的结果存于对应的参数内。
返回值 成功则返回参数数目,失败则返回-1,错误原因存于errno中。
# 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] = {0};
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] = {0};
sscanf(sourceStr, "%*s%s", buf); //%*s表示第一个匹配到的%s被过滤掉,即hello被过滤了
cout << buf<< endl;
结果为:world
支持集合操作:
%[a-z] 表示匹配a到z中任意字符,贪婪性(尽可能多的匹配)
%[aB'] 匹配a、B、'中一员,贪婪性
%[^a] 匹配非a的任意字符,贪婪性
1. 常见用法。
以下是引用片段:
charstr[ 512] = { 0} ;
sscanf( "123456" , "%s" , str) ;
printf( "str=%s" , str) ;
2. 取指定长度的字符串。如在下例中,取最大长度为4字节的字符串。
以下是引用片段:
sscanf( "123456" , "%4s" , str) ;
printf( "str=%s" , str) ;
3. 取到指定字符为止的字符串。如在下例中,取遇到空格为止字符串。
以下是引用片段:
sscanf( "123456abcdedf" , "%[^]" , str) ;
printf( "str=%s" , str) ;
4. 取仅包含指定字符集的字符串。如在下例中,取仅包含1到9和小写字母的字符串。
以下是引用片段:
sscanf( "123456abcdedfBCDEF" , "%[1-9a-z]" , str) ;
printf( "str=%s" , str) ;
5. 取到指定字符集为止的字符串。如在下例中,取遇到大写字母为止的字符串。
以下是引用片段:
sscanf( "123456abcdedfBCDEF" , "%[^A-Z]" , str) ;
printf( "str=%s" , str) ;
搜集一些特殊用法:
% [ ] 的用法:% [ ] 表示要读入一个字符集合, 如果[ 后面第一个字符是”^”,则表示反意思。[ ] 内的字符串可以是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个字符
% [ ^ = ] 读取字符串直到碰到’= ’号,’^’后面可以带更多字符, 如:
char s[ ] = "notepad=1.0.0.1001" ;
char szfilename [ 32] = "" ;
int i = sscanf ( s, "%[^=]" , szfilename ) ;
// szfilename=notepad
如果参数格式是:% [ ^ = : ] ,那么也可以从 notepad: 1. 0. 0. 1001读取notepad
应用实例:Rinex星历数据读入
以下是Rinex星历数据的片断:
2 10 1 16 2 0 0.0 2.159508876503D-04 4.320099833421D-12 0.000000000000D+00
9.500000000000D+01 1.165625000000D+01 5.293791936254D-09-3.076667279839D+00
7.841736078262D-07 9.284008061513D-03 4.578381776810D-06 5.153754629135D+03
5.256000000000D+05-1.527369022369D-07 1.733543031426D+00 1.303851604462D-08
9.397921470752D-01 2.780625000000D+02 2.941268779788D+00-8.269273019842D-09
1.892935991239D-10 1.000000000000D+00 1.566000000000D+03 0.000000000000D+00
2.000000000000D+00 0.000000000000D+00-1.722946763039D-08 9.500000000000D+01
5.184000000000D+05
观察可以发现,有的数据连在了一起,没有空格分隔,如第二行5.293791936254D-09-3.076667279839D+00。这时应该如何提取出相应的数据呢?代码如下:
#include <stdafx.h> #include <stdio.h> #include <stdlib.h> #include <string.h> int _tmain(int argc, _TCHAR* argv[]) { int wn,year,month,day,hour,prn,minute; float second; char t1[30],t2[30],t3[30],t4[30],t5[30],temp[10]; double f1,f2,f3,f4,d1,d2,d3,d4; FILE *RinexEPP_file; if ((RinexEPP_file = fopen("e:\data.txt", "rt")) == NULL) { fprintf(stderr, "Cannot open input file.\n"); exit(1); } rewind(RinexEPP_file); if(fscanf(RinexEPP_file,"%d %d %d %d %d %d\n", &prn,&year,&month,&day, &hour,&minute)==EOF) return 1; fscanf(RinexEPP_file,"%4f",&second); fscanf(RinexEPP_file,"%[^D]",t1); //读到D字符为止 fscanf(RinexEPP_file,"%4s",temp); //截取D后面的四个字符 strcat(t1,temp); //将D前后两段相连 d1=atof(t1); d2=atof(t2); d3=atof(t3); d4=atof(t4); }将其整理成一个函数如下:
char *myscanf(FILE *RinexEPP_file); char *myscanf(FILE *RinexEPP_file) { char t1[30],temp[10]; fscanf(RinexEPP_file,"%[^D]",t1); //一直读到为D字符为止 fscanf(RinexEPP_file,"%4s",temp); strcat(t1,temp); return t1; }