此文所有的实验都是基于下面的程序:

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的地址。

验证代码如下

  1. #if 0
  2. 1,sscanf():从一个字符串中读进与指定格式相符的数据.
  3. 2,sscanfscanf类似,都是用于输入的,只是后者以屏幕(stdin)为输入源,前者以固定字符串为输入源。
  4. 3,关于正则表达式:
  5. (1)%[..],当字符属于方括号里表达式表示的字符集时继续读取,否则停止.方括号里的和正则表达式差不多,^是"排除..."的意思
  6. (2)%*[..],直接跳过方括号里的字符集并继续读取
  7. #endif
  8. #include <iostream>
  9. using namespace std;
  10. int main()
  11. {
  12. char str[10];
  13. // 这个实验很简单,把源字符串"123456"拷贝到str的前6个字符,并且把str的第7个字符设为null字符,也就是\0
  14. for (int i = 0; i < 10; i++) str[i] = '!';
  15. cout<<str<<endl;
  16. sscanf("123456", "%s", str); // str的值为 "123456\0!!!"
  17. cout<<str<<endl;
  18. // 看到没有,正则表达式的百分号后面多了一个3,这告诉sscanf只拷贝3个字符给str,然后把第4个字符设为null字符。
  19. for (int i = 0; i < 10; i++) str[i] = '!';
  20. sscanf("123456", "%3s", str); // str的值为 "123\0!!!!!!"
  21. cout<<str<<endl;
  22. // 从这个实验开始我们会使用正则表达式,括号里面的a-z就是一个正则表达式,它可以表示从a到z的任意字符,
  23. // 在继续讨论之前,我们先来看看百分号表示什么意思,%表示选择,%后面的是条件,比如实验1的"%s",s是一个条件,表示任意字符,"%s"的意思是:-
  24. // -只要输入的东西是一个字符,就把它拷贝给str。实验2的"%3s"又多了一个条件:只拷贝3个字符。实验3的“%[a-z]”的条件稍微严格一些,输入的-
  25. // -东西不但是字符,还得是一个小写字母的字符,所以实验3只拷贝了小写字母"aaa"给str,别忘了加上null字符。
  26. for (int i = 0; i < 10; i++) str[i] = '!';
  27. sscanf("aaaAAA", "%[a-z]", str); // str的值为 "aaa\0!!!!!!"
  28. cout<<str<<endl;
  29. // 对于所有字符,只要不是小写字母,都满足"^a-z"正则表达式,符号^表示逻辑非。前3个字符都不是小写字符,所以将其拷贝给str,但最后3个字符-
  30. // -也不是小写字母,为什么不拷贝给str呢?这是因为当碰到不满足条件的字符后,sscanf就会停止执行,不再扫描之后的字符。
  31. for (int i = 0; i < 10; i++) str[i] = '!';
  32. sscanf("AAAaaaBBB", "%[^a-z]", str); // str的值为 "AAA\0!!!!!!"
  33. cout<<str<<endl;
  34. /*
  35. // 这个实验的本意是:先把大写字母拷贝给str,然后把小写字母拷贝给str,但很不幸,程序运行的时候会发生段错误,因为当sscanf扫描到字符a时,-
  36. // -违反了条件"%[A-Z]",sscanf就停止执行,不再扫描之后的字符,所以第二个条件也就没有任何意义,这个实验说明:不能使用%号两次或两次以上
  37. for (int i = 0; i < 10; i++) str[i] = '!';
  38. sscanf("AAAaaaBBB", "%[A-Z]%[a-z]", str); // 段错误
  39. cout<<str<<endl;
  40. */
  41. // 这个实验出现了一个新的符号:%*,与%相反,%*表示过滤满足条件的字符,在这个实验中,%*[A-Z]过滤了所有大写字母,然后再使用%[a-z]把之后-
  42. // -的小写字母拷贝给str。如果只有%*,没有%的话,sscanf不会拷贝任何字符到str,这时sscanf的作用仅仅是过滤字符串。
  43. for (int i = 0; i < 10; i++) str[i] = '!';
  44. sscanf("AAAaaaBBB", "%*[A-Z]%[a-z]", str); // str的值为 "aaa\0!!!!!!"
  45. cout<<str<<endl;
  46. // 做完前面几个实验后,我们都知道sscanf拷贝完成后,还会在str的后面加上一个null字符,但如果没有一个字符满足条件,sscanf不会在str 的后面-
  47. // -加null字符,str的值依然是10个惊叹号。这个实验也说明了,如果不使用%*过滤掉前面不需要的字符,你永远别想取得中间的字符。
  48. for (int i = 0; i < 10; i++) str[i] = '!';
  49. sscanf("AAAaaaBBB", "%[a-z]", str); // str的值为 "!!!!!!!!!!"
  50. cout<<str<<endl;
  51. // 这是一个综合实验,但这个实验的目的不是帮我们复习前面所学的知识,而是展示两个值得注意的地方:
  52. // 注意1:%只能使用一次,但%*可以使用多次,比如在这个实验里面,先用%*[A-Z]过滤大写字母,然后用%*[a-z]过滤小写字母。
  53. // 注意2:^后面可以带多个条件,且这些条件都受^的作用,比如^a-z=表示^a-z且^=(既不是小写字母,也不是等于号)。
  54. for (int i = 0; i < 10; i++) str[i] = '!';
  55. sscanf("AAAaaaBC=", "%*[A-Z]%*[a-z]%[^a-z=]", str); // str的值为 "BC\0!!!!!!!"
  56. cout<<str<<endl;
  57. // 首先,%*[^0-9]过滤前面非数字的字符,然后用%i把数字字符转换成int型的整数,拷贝到变量k,注意参数必须使用k的地址。 cout<<str<<endl;
  58. for (int i = 0; i < 10; i++) str[i] = '!';
  59. int k;
  60. sscanf("AAA123BBB456", "%*[A-Z]%i", &k); // k的值为123
  61. cout<<k<<endl;
  62. return 0;
  63. }

参考:https://www.iteye.com/blog/kmplayer-556293

【C/C++】sscanf函数和正则表达式的更多相关文章

  1. sscanf函数和正则表达式

    看了几篇介绍sscanf函数,真是发现自己好多东西没理解透,详细介绍使用在sscanf中使用正则表达式. 第一篇: 此文所有的实验都是基于下面的程序: char str[10]; for (int i ...

  2. c语言 sscanf()函数

    sscanf()函数用于从字符串中读取指定格式的数据,其原型如下:    int sscanf (char *str, char * format [, argument, ...]); [参数]参数 ...

  3. sscanf函数——强大的C语言库函数

    这个函数真的很强大,这篇随笔也将一直更新一些总结,直到涵盖大多数应用: eg1: 今天公司项目中从云端获取了一段字符串---"+CBC: 0,90,4090" 我想获取其中的数字0 ...

  4. [转载]sscanf函数

    来源:http://c.biancheng.net/cpp/html/296.html 头文件:#include <stdio.h> sscanf()函数用于从字符串中读取指定格式的数据, ...

  5. sscanf()函数的使用及其实例

    资料引自: 传送门 sscanf函数原型: Int sscanf( const char * src, const char * format, ...); int scanf( const char ...

  6. sscanf函数

    sscanf函数用法举例 #include <stdio.h> #include <string.h> #define N 512 int main() { char buf[ ...

  7. C语言sprintf与sscanf函数[总结]

    sprintf函数 sprintf函数原型为 int sprintf(char *str, const char *format, ...).作用是格式化字符串,具体功能如下所示: (1)将数字变量转 ...

  8. sscanf 函数

    sscanf 函数: 从一个字符串中读进与指定格式相符的数据. 头文件: #include<stdio.h> 返回值:  sscanf("1 2 3","%d ...

  9. php sscanf() 函数使用

    定义和用法 sscanf() 函数根据指定的格式解析来自一个字符串的输入. 如果只向该函数传递两个参数,数据将以数组的形式返回.否则,如果传递了额外的参数,那么被解析的数据会存储在这些参数中.如果区分 ...

  10. 关于sscanf函数的各种详细用法

    看书的时候碰到sscanf函数,就上网查了很多资料,并加以自己的整理,希望对大家有所帮助. (因为参考的博客太多太散,就不一一注明,望大神们见谅) sscanf()  :从一个字符串中读进与指定格式相 ...

随机推荐

  1. C#如何对List中的Object进行排序

    首先定义一个List类,这个类里面包含了Name和Total两个属性变量,下面就是针对这两个变量进行排序. public class Player { public string Name { get ...

  2. idea2020.1.3汉化包报错问题

    已解决:idea2020.1.3汉化包报错问题 问题描述:插件市场提供的版本不对.不兼容,所以需要手动下载安装 这里附上文件 https://wwsi.lanzouq.com/b03czdtwf 密码 ...

  3. 一键式调试工具—Reqable 使用指南

    简介 Reqable是一款跨平台的专业HTTP开发和调试工具,在全平台支持HTTP1.HTTP2和HTTP3(QUIC)协议,简单易用.功能强大.性能高效,助力程序开发和测试人员提高生产力!本产品需要 ...

  4. Caffeine Cache缓存

    SpringBoot 集成 Caffeine Caffeine 和 Spring Cache 依赖,使用注解方法实现缓存 依赖 <!--提供 Spring Boot 中的缓存支持--> & ...

  5. 从热爱到深耕,全国Top10开源软件出品人探索“开源云上行”

    本文分享自华为云社区<[先锋开发者云上说]从热爱到深耕,全国Top10开源软件出品人探索"开源云上行">,作者:华为云社区精选. <2022-2023 中国开源开 ...

  6. JavaScript回调函数的高手指南

    摘要:本文将会解释回调函数的概念,同时帮你区分两种回调:同步和异步. 回调函数是每个前端程序员都应该知道的概念之一.回调可用于数组.计时器函数.promise.事件处理中. 本文将会解释回调函数的概念 ...

  7. Nacos是什么?

    摘要:Nacos是 Dynamic Naming and Configuration Service的首字母简称,相较之下,它更易于构建云原生应用的动态服务发现.配置管理和服务管理平台. 本文分享自华 ...

  8. AOC萌新探索:搭建和体验在线AOC环境

    摘要:AOC是一个做网络设备自动化运维以及三方设备纳管的一个能力平台. 本文分享自华为云社区<AOC萌新探索之旅第一期--在线AOC环境初体验>,作者:oysterzz. 接触AOC没多久 ...

  9. 从原理带你掌握Spring MVC拦截处理器知识

    摘要:SpringWebMVC的处理器拦截器,类似于Servlet开发中的过滤器Filter,用于处理器进行预处理和后处理. 本文分享自华为云社区<不讲废话,全程干货,0基础带你学习Spring ...

  10. 火山引擎 ByteHouse:TB 级数据下,如何实现高效、稳定的数据导入

    更多技术交流.求职机会,欢迎关注字节跳动数据平台微信公众号,回复[1]进入官方交流群 近期,火山引擎开发者社区.火山引擎数智平台(VeDI)联合举办以<数智化转型背景下的火山引擎大数据技术揭秘& ...