zoukankan      html  css  js  c++  java
  • scanf和sscanf中关于正则表达式的技巧

    首先scanf和sscanf的区别在于sscanf是可以以字符串为输入流的方式。
    
    例如:
    
    1)去空格读取字符
    char *buf="hello world";
    char str[100];
    sscanf(buf,"%s",s);
    结果s="hello"
    2)将一串字符传化为数字
    若出现一串未知的表达式时;
    char *buf="232442 + 13214144";
    int a,b;
    sscanf(buf,"%d+%d",&a,&b);
    结果a=232442 b=13214144;
    sscanf()函数可以很轻松的在字符和数组中间转换。对应的也有个函数叫sprintf();
    
    2,关于正则表达式;
    对于这个概念我们无需过多理解看例子
    
    int scanf( const char *format [,argument]... );
    其中的format可以是一个或多个 {%[*] [width] [{h | l | I64 | L}]type | ' ' | '	' | '
    ' | 非%符号}
    
    第一篇:
    
    此文所有的实验都是基于下面的程序:
    
    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!!!"
    
    这个实验很简单,把源字符串"123456"拷贝到str的前6个字符,并且把str的第7个字符设为null字符,也就是
    
    实验2:
    
    sscanf( "123456" , "%3s" , str) ; ---------str的值为 "123!!!!!!"
    
    看到没有,正则表达式的百分号后面多了一个3,这告诉sscanf只拷贝3个字符给str,然后把第4个字符设为null字符。
    
    实验3:
    
    sscanf( "aaaAAA" , "%[a-z]" , str) ; ---------str的值为 "aaa!!!!!!"
    
    从这个实验开始我们会使用正则表达式,括号里面的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!!!!!!"
    
    对于所有字符,只要不是小写字母,都满足"^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!!!!!!"
    
    这个实验出现了一个新的符号:%*,与%相反,%*表示过滤 满足条件的字符,在这个实验中,%*[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!!!!!!!"
    
    这是一个综合实验,但这个实验的目的不是帮我们复习前面所学的知识,而是展示两个值得注意的地方:
    
    注意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的地址。



  • 相关阅读:
    PHP通过日志来发现问题
    php环境重启
    排行榜的实现
    git相关使用技巧和问题
    lua State加载部分库
    c++ 解析json
    查看某个进程允许打开的最大文件描述符
    glog安装与使用
    ubuntu update-alternatives
    gcc安装多个版本
  • 原文地址:https://www.cnblogs.com/leejuen/p/5547491.html
Copyright © 2011-2022 走看看