【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() :从一个字符串中读进与指定格式相 ...
随机推荐
- Python——第五章:Zipfile模块
Zipfile模块 zipfile 模块是 Python 中用于处理 ZIP 文件的标准库模块.它提供了创建.读取和写入 ZIP 文件的功能. zipfile 模块在写入文件时,如果要将文件写入子目录 ...
- python异步编程之asyncio高阶API
asyncio 高阶API列表 asyncio中函数可以分为高阶函数和低阶函数.低阶函数用于调用事件循环.linux 套接字.信号等更底层的功能,高阶函数是屏蔽了更多底层细节的任务并发,任务执行函数. ...
- zabbix-server 报错记录
数据库磁盘满导至zabbix挂了 登陆zabbix页面提示错误信息,查看系统磁盘: /目录已满,导致mariadb数据库无法正常运行,如果有介质将会一直收取: 解决方法:扩容/目录,达到理想值,重启m ...
- SQL Server系列:系统函数之日期和时间函数
1.current_timestamp :获取数据库系统时间戳 --获取数据库系统时间戳 select current_timestamp go 2.getdate() :获取数据库系统时间戳 --获 ...
- LeetCode283移动零、11盛最多的水
283. 移动零 给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序. 示例: 输入: [0,1,0,3,12] 输出: [1,3,12,0,0] 说明: 必 ...
- 神经网络基础篇:梯度下降法(Gradient Descent)
梯度下降法 梯度下降法可以做什么? 在 测试集上,通过最小化代价函数(成本函数)\(J(w,b)\)来训练的参数\(w\)和\(b\), 如图,在第二行给出和之前一样的逻辑回归算法的代价函数(成本函数 ...
- 毕业季 | 程序员初入职场必备软件开发神器,华为云Astro带你开启新篇章
摘要:5分钟写出应用,10分钟开发大屏,新手程序员必学技能之华为云Astro,快来get. 本文分享自华为云社区<毕业季 | 程序员初入职场必备软件开发神器,华为云Astro带你开启新篇章> ...
- 容器、Docker、虚拟机,别再傻傻分不清
摘要:容器技术起源于Linux,是一种内核虚拟化技术,提供轻量级的虚拟化,以便隔离进程和资源.尽管容器技术已经出现很久,却是随着Docker的出现而变得广为人知. 容器技术起源于Linux,是一种内核 ...
- 数据库面试要点:关于MySQL数据库千万级数据查询和存储
摘要:百万级.千万级数据处理,核心关键在于数据存储方案设计,存储方案设计的是否合理,直接影响到数据CRUD操作.总体设计可以考虑一下几个方面进行设计考虑: 数据存储结构设计:索引设计:数据主键设计:查 ...
- 1500万员工轻松管理,云原生数据库GaussDB让HR办公更高效
摘要: 云原生数据库GaussDB助力"2号人事部"打造高品质HR效率软件 本文分享自华为云社区<1500万员工轻松管理,云原生数据库GaussDB让HR办公更高效>, ...