【C/C++】sscanf函数和正则表达式
此文所有的实验都是基于下面的程序: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的地址。
验证代码如下
#if 0
1,sscanf():从一个字符串中读进与指定格式相符的数据.
2,sscanf与scanf类似,都是用于输入的,只是后者以屏幕(stdin)为输入源,前者以固定字符串为输入源。
3,关于正则表达式:
(1)%[..],当字符属于方括号里表达式表示的字符集时继续读取,否则停止.方括号里的和正则表达式差不多,^是"排除..."的意思
(2)%*[..],直接跳过方括号里的字符集并继续读取
#endif
#include <iostream>
using namespace std;
int main()
{
char str[10];
// 这个实验很简单,把源字符串"123456"拷贝到str的前6个字符,并且把str的第7个字符设为null字符,也就是\0
for (int i = 0; i < 10; i++) str[i] = '!';
cout<<str<<endl;
sscanf("123456", "%s", str); // str的值为 "123456\0!!!"
cout<<str<<endl;
// 看到没有,正则表达式的百分号后面多了一个3,这告诉sscanf只拷贝3个字符给str,然后把第4个字符设为null字符。
for (int i = 0; i < 10; i++) str[i] = '!';
sscanf("123456", "%3s", str); // str的值为 "123\0!!!!!!"
cout<<str<<endl;
// 从这个实验开始我们会使用正则表达式,括号里面的a-z就是一个正则表达式,它可以表示从a到z的任意字符,
// 在继续讨论之前,我们先来看看百分号表示什么意思,%表示选择,%后面的是条件,比如实验1的"%s",s是一个条件,表示任意字符,"%s"的意思是:-
// -只要输入的东西是一个字符,就把它拷贝给str。实验2的"%3s"又多了一个条件:只拷贝3个字符。实验3的“%[a-z]”的条件稍微严格一些,输入的-
// -东西不但是字符,还得是一个小写字母的字符,所以实验3只拷贝了小写字母"aaa"给str,别忘了加上null字符。
for (int i = 0; i < 10; i++) str[i] = '!';
sscanf("aaaAAA", "%[a-z]", str); // str的值为 "aaa\0!!!!!!"
cout<<str<<endl;
// 对于所有字符,只要不是小写字母,都满足"^a-z"正则表达式,符号^表示逻辑非。前3个字符都不是小写字符,所以将其拷贝给str,但最后3个字符-
// -也不是小写字母,为什么不拷贝给str呢?这是因为当碰到不满足条件的字符后,sscanf就会停止执行,不再扫描之后的字符。
for (int i = 0; i < 10; i++) str[i] = '!';
sscanf("AAAaaaBBB", "%[^a-z]", str); // str的值为 "AAA\0!!!!!!"
cout<<str<<endl;
/*
// 这个实验的本意是:先把大写字母拷贝给str,然后把小写字母拷贝给str,但很不幸,程序运行的时候会发生段错误,因为当sscanf扫描到字符a时,-
// -违反了条件"%[A-Z]",sscanf就停止执行,不再扫描之后的字符,所以第二个条件也就没有任何意义,这个实验说明:不能使用%号两次或两次以上
for (int i = 0; i < 10; i++) str[i] = '!';
sscanf("AAAaaaBBB", "%[A-Z]%[a-z]", str); // 段错误
cout<<str<<endl;
*/
// 这个实验出现了一个新的符号:%*,与%相反,%*表示过滤满足条件的字符,在这个实验中,%*[A-Z]过滤了所有大写字母,然后再使用%[a-z]把之后-
// -的小写字母拷贝给str。如果只有%*,没有%的话,sscanf不会拷贝任何字符到str,这时sscanf的作用仅仅是过滤字符串。
for (int i = 0; i < 10; i++) str[i] = '!';
sscanf("AAAaaaBBB", "%*[A-Z]%[a-z]", str); // str的值为 "aaa\0!!!!!!"
cout<<str<<endl;
// 做完前面几个实验后,我们都知道sscanf拷贝完成后,还会在str的后面加上一个null字符,但如果没有一个字符满足条件,sscanf不会在str 的后面-
// -加null字符,str的值依然是10个惊叹号。这个实验也说明了,如果不使用%*过滤掉前面不需要的字符,你永远别想取得中间的字符。
for (int i = 0; i < 10; i++) str[i] = '!';
sscanf("AAAaaaBBB", "%[a-z]", str); // str的值为 "!!!!!!!!!!"
cout<<str<<endl;
// 这是一个综合实验,但这个实验的目的不是帮我们复习前面所学的知识,而是展示两个值得注意的地方:
// 注意1:%只能使用一次,但%*可以使用多次,比如在这个实验里面,先用%*[A-Z]过滤大写字母,然后用%*[a-z]过滤小写字母。
// 注意2:^后面可以带多个条件,且这些条件都受^的作用,比如^a-z=表示^a-z且^=(既不是小写字母,也不是等于号)。
for (int i = 0; i < 10; i++) str[i] = '!';
sscanf("AAAaaaBC=", "%*[A-Z]%*[a-z]%[^a-z=]", str); // str的值为 "BC\0!!!!!!!"
cout<<str<<endl;
// 首先,%*[^0-9]过滤前面非数字的字符,然后用%i把数字字符转换成int型的整数,拷贝到变量k,注意参数必须使用k的地址。 cout<<str<<endl;
for (int i = 0; i < 10; i++) str[i] = '!';
int k;
sscanf("AAA123BBB456", "%*[A-Z]%i", &k); // k的值为123
cout<<k<<endl;
return 0;
}
参考:https://www.iteye.com/blog/kmplayer-556293
【C/C++】sscanf函数和正则表达式的更多相关文章
- sscanf函数和正则表达式
看了几篇介绍sscanf函数,真是发现自己好多东西没理解透,详细介绍使用在sscanf中使用正则表达式. 第一篇: 此文所有的实验都是基于下面的程序: char str[10]; for (int i ...
- c语言 sscanf()函数
sscanf()函数用于从字符串中读取指定格式的数据,其原型如下: int sscanf (char *str, char * format [, argument, ...]); [参数]参数 ...
- sscanf函数——强大的C语言库函数
这个函数真的很强大,这篇随笔也将一直更新一些总结,直到涵盖大多数应用: eg1: 今天公司项目中从云端获取了一段字符串---"+CBC: 0,90,4090" 我想获取其中的数字0 ...
- [转载]sscanf函数
来源:http://c.biancheng.net/cpp/html/296.html 头文件:#include <stdio.h> sscanf()函数用于从字符串中读取指定格式的数据, ...
- sscanf()函数的使用及其实例
资料引自: 传送门 sscanf函数原型: Int sscanf( const char * src, const char * format, ...); int scanf( const char ...
- sscanf函数
sscanf函数用法举例 #include <stdio.h> #include <string.h> #define N 512 int main() { char buf[ ...
- C语言sprintf与sscanf函数[总结]
sprintf函数 sprintf函数原型为 int sprintf(char *str, const char *format, ...).作用是格式化字符串,具体功能如下所示: (1)将数字变量转 ...
- sscanf 函数
sscanf 函数: 从一个字符串中读进与指定格式相符的数据. 头文件: #include<stdio.h> 返回值: sscanf("1 2 3","%d ...
- php sscanf() 函数使用
定义和用法 sscanf() 函数根据指定的格式解析来自一个字符串的输入. 如果只向该函数传递两个参数,数据将以数组的形式返回.否则,如果传递了额外的参数,那么被解析的数据会存储在这些参数中.如果区分 ...
- 关于sscanf函数的各种详细用法
看书的时候碰到sscanf函数,就上网查了很多资料,并加以自己的整理,希望对大家有所帮助. (因为参考的博客太多太散,就不一一注明,望大神们见谅) sscanf() :从一个字符串中读进与指定格式相 ...
随机推荐
- 结合 element -Plus组件库,压缩图片大小,限制图片格式
业务背景:业务上需求满足上传的图片不能太大,但是有时候上传的图片确实超过了限制大小,所以前端这边可以将图片压缩再上传,亦或者是上传给后端接口的图片只能是指定格式,我们前端需要将图片后缀转化,也可以处理 ...
- ChatGPT 沦为了我的打工仔
大家好,我是老章 最近在折腾之前搞的R-bookdown网站.Jekyll博客,还有刚上了Astro做的周刊.Astro Starlight做的文档站 R2ML:https://r2ml.zhangl ...
- Linux SNMP监控配置
1, 安装SNMP服务 [root@zlm log]# yum -y install net-snmp net-snmp-utils 2, 编辑SNMP配置文件[root@zlm log]# vim ...
- Head First 的学习之道
<Head First 设计模式>是一本好书,正如书的封面上说的那样,这是一本重视大脑的学习指南.里面提到了一些学习方法,可以尝试下,看看哪些对你有用: 1. 慢一点,理解的越多,需要记得 ...
- 云小课|RDS实例连接又失败?看我祭出杀手锏!
摘要:自从购买了RDS实例,连接失败的问题就伴随着我,我真是太难了.不要害怕,不要着急,跟着小云妹,读了本文,让你风里雨里,实例连接自此畅通无阻! 顺着以下几个方面进行排查,问题就可以迎刃而解~ 本文 ...
- 论文解读丨LayoutLM: 面向文档理解的文本与版面预训练
摘要:LayoutLM模型利用大规模无标注文档数据集进行文本与版面的联合预训练,在多个下游的文档理解任务上取得了领先的结果. 本文分享自华为云社区<论文解读系列二十五:LayoutLM: 面向文 ...
- Solon 编译打包怎样保持参数名不变?
1.Java 项目 Java maven 项目 <plugin> <groupId>org.apache.maven.plugins</groupId> <a ...
- H-ui JQuery 给单选按纽赋值不生效
H-ui JQuery 给单选按纽赋值不生效 $("#sex-1").attr('checked',true) 原因,iradio-blue 样式的原因 把下面代码注释掉就可以了 ...
- App备案与iOS云管理式证书 ,公钥及证书SHA-1指纹的获取方法
iOS 备案查看信息 iOS平台Bundle ID 公钥 证书SHA-1指纹 IOS平台服务器域名 获取 Bundle ID: 或者 https://developer.apple.com/accou ...
- C# WPF 将第三方DLL嵌入 exe
没成功,只是做个记录,后面再研究 希望将第三方的 HandyControl.dll 嵌入到 exe 中,这样不用发多个文件给别人 将第三方DLL.加载到解决方案中 添加引用 将"属性页&qu ...