C++11 正则表达式——实例系统(转载)
一.用正则表达式判断邮箱格式是否正确
1 #include <regex> #include <iostream> #include <string> bool is_email_valid(const std::string& email)
{ const std::regex pattern("(\\w+)(\\.|_)?(\\w*)@(\\w+)(\\.(\\w+))+");
//const std::regex pattern("(\\w+)(\\.|_)?(\\w*)@(\\w+)(\\.|-)?(\\w*)(\\.(\\w+))+");验证最全面 return std::regex_match(email, pattern); } int main() { std::string email1 = "marius.bancila@domain.com"; std::string email2 = "mariusbancila@domain.com"; std::string email3 = "marius_b@domain.co.uk"; std::string email4 = "marius@domain"; std::cout << email1 << " : " << (is_email_valid(email1) ? "valid" : "invalid") << std::endl; std::cout << email2 << " : " << (is_email_valid(email2) ? "valid" : "invalid") << std::endl; std::cout << email3 << " : " << (is_email_valid(email3) ? "valid" : "invalid") << std::endl; std::cout << email4 << " : " << (is_email_valid(email4) ? "valid" : "invalid") << std::endl; return ;
}
运行结果

这里对is_email_valid()函数中的正则表达式做一个简短的说明,如果对于正则表示不是很清楚的同学就能很容易理解了。
const std::regex pattern("(\\w+)(\\.|_)?(\\w*)@(\\w+)(\\.(\\w+))+");
首先注意‘()’表示将正则表达式分成子表达式,每个‘()’之间的内容表示一个子表达式;‘\’是一个转义字符,‘\\’表示扔掉第二个‘\’的转义特
性,‘\w+’表示匹配一个或多个单词,‘+’表示重复一次或者多次,因此第一个子表达式的意思就是匹配一个或者多个单词;接着看第二个子表达式,‘|’
表示选择,出现‘.’或者‘_’,后面的‘?’表示该子表示出现一次或者零次,因此第二个子表示表示‘.’或‘_’出现不出现都匹配。第三个子表达式表示
出现一个单词,‘*’表示任意个字符。后面的子表示根据已经介绍的内容,已经可以容易理解,就不再赘述。通过对正则表达式匹配模式串的分析,可以容易理解
运行结果。
下面一个例子通过正则表达式识别和打印IP地址的各个部分:
#include <regex>
#include <iostream>
#include <string>
void show_ip_parts(const std::string& ip)
{
// regular expression with 4 capture groups defined with
// parenthesis (...)
const std::regex pattern("(\\d{1,3}):(\\d{1,3}):(\\d{1,3}):(\\d{1,3})");
// object that will contain the sequence of sub-matches
std:: match_results<std::string::const_iterator> result;
// match the IP address with the regular expression
bool valid = std:: regex_match(ip, result, pattern);
std::cout << ip << " \t: " << (valid ? "valid" : "invalid")
<< std::endl;
// if the IP address matched the regex, then print the parts
if(valid)
{
std::cout << "b1: " << result[] << std::endl;
std::cout << "b2: " << result[] << std::endl;
std::cout << "b3: " << result[] << std::endl;
std::cout << "b4: " << result[] << std::endl;
}
}
int main()
{
show_ip_parts("1:22:33:444");
show_ip_parts("1:22:33:4444");
show_ip_parts("100:200");
return ;
}
运行结果:

是对正则表达式的模式串做一个说明:首先还是通过‘()’将这个串分成几个子表达式,其中\d表示匹配一个数字,{,}表示数字的个数,例如{1,3}可以理解为匹配一个小于1000的数字(1-3位数都符合匹配要求)。
程序中还使用了match_results类,用来保存匹配的每一个子序列。调用regex_match(ip,result,pattern),表示将ip中与模式串pattern匹配的结果放在result中。
result最后可以通过下标来访问各个匹配的子表达式。
#include <regex>
#include <iostream>
#include <string>
int main()
{
const std::tr1::regex pattern("(\\w+day)");
// the source text
std::string weekend = "Saturday and Sunday";
std::smatch result;
bool match = std::regex_search(weekend, result, pattern);
if(match)
{
for(size_t i = ; i < result.size(); ++i)
{
std::cout << result[i] << std::endl;
}
}
std::cout<<std::endl;
return ;
}
运行结果:

上面这个例子只能返回第一个匹配的项,如果要返回所有匹配的子序列,可以使用下面的方式:
#include <regex>
#include <iostream>
#include <string>
int main()
{
// regular expression
const std::regex pattern("\\w+day");
// the source text
std::string weekend = "Saturday and Sunday, but some Fridays also.";
const std::sregex_token_iterator end; //需要注意一下这里
for (std::sregex_token_iterator i(weekend.begin(),weekend.end(), pattern); i != end ; ++i)
{
std::cout << *i << std::endl;
}
std::cout<<std::endl;
return ;
}
运行结果:

下面的例子将元音字母打头的单词前面的a替换为an:
#include <regex>
#include <iostream>
#include <string>
int main()
{
// text to transform
std::string text = "This is a element and this a unique ID.";
// regular expression with two capture groups
const std::regex pattern("(\\ba (a|e|i|u|o))+");
// the pattern for the transformation, using the second
// capture group
std::string replace = "an $2";
std::string newtext = std::regex_replace(text, pattern, replace);
std::cout << newtext << std::endl;
std::cout << std::endl;
return ;
}
运行结果:

还是来说明一下,这里主要使用了regex_replace(text, pattern, replace),意思是将text的内容按照pattern进行匹配,匹配成功的使用replace串进行替换,并将替换后的结果作为函数值返回。需要 注意的是std::string replace = "an $2"; 这里‘$2’表示模式串的第二个子表达式,
也就是以a,e,i,o,u开头的单词。
三.下面一个例子将进行年月日格式的转换,将DD-MM-YYYY –> YYYY-MM-DD,其中‘.’或者‘/’都能正确识别。
#include <regex>
#include <iostream>
#include <string>
std::string format_date(const std::string& date)
{
// regular expression
const std:: regex pattern("(\\d{1,2})(\\.|-|/)(\\d{1,2})(\\.|-|/)(\\d{4})");
// transformation pattern, reverses the position of all capture groups
std::string replacer = "$5$4$3$2$1";
// apply the tranformation
return std:: regex_replace(date, pattern, replacer);
}
int main()
{
std::string date1 = "1/2/2008";
std::string date2 = "12.08.2008";
std::cout << date1 << " -> " << format_date(date1) << std::endl;
std::cout << date2 << " -> " << format_date(date2) << std::endl;
std::cout << std::endl;
return ;
}
运行结果:

说明,这个例子也很有实用价值,这里用到的正则表达式的匹配模式前面都已经进行过说明就不在分析。
相信通过以上例子,对正则表达式的运用已经有了一个不错的了解,下面再来添加一个实例,加深一下理解。
下面一个例子用来查找给定文本中new的个数和delete的个数是否相等:
#include <iostream>
#include <string>
#include <regex>
int main() {
// "new" and "delete" 出现的次数是否一样?
std::regex reg("(new)|(delete)");
std::smatch m;
std::string s=
"Calls to new must be followed by delete. \
Calling simply new results in a leak!";
int new_counter=;
int delete_counter=;
std::string::const_iterator it=s.begin();
std::string::const_iterator end=s.end();
while (std::regex_search(it,end,m,reg))
{
// 是 new 还是 delete?
m[].matched ? ++new_counter : ++delete_counter;
it=m[].second;
}
if (new_counter!=delete_counter)
std::cout << "Leak detected!\n";
else
std::cout << "Seems ok...\n";
std::cout << std::endl;
}
运行结果:

运行结果表明,new和delete的数量不相等,也就是发生了“内存泄露”。
为了帮助理解,上面对于match_results类型的下标操作的意义,请看ISOIEC14882 C++11的说明:

#include <iostream>
#include <string>
#include <regex>
using namespace std;
class regex_callback {
int sum_;
public:
regex_callback() : sum_() {}
template <typename T> void operator()(const T& what) {
sum_+=atoi(what[].str().c_str());
}
int sum() const {
return sum_;
}
};
int main() {
regex reg("(\\d+),?");
string s="1,1,2,3,5,8,13,21";
sregex_iterator it(s.begin(),s.end(),reg);
sregex_iterator end;
regex_callback c;
int sum=for_each(it,end,c).sum();//for_each返回的是这个函数对象,因此可以调用sum
cout<<sum<<endl;
cout<<endl;
}
运行结果:

#include <iostream>
#include <string>
#include <regex>
using namespace std;
int main()
{
regex reg("/");
vector<std::string> vec;
string s="Split/Vulue/Teather/Neusoft/Write/By/Lanwei";
sregex_token_iterator it(s.begin(),s.end(),reg,-);//// -1逆向匹配,就是匹配除了'/'之外的
sregex_token_iterator end ;
while(it!=end)
vec.push_back(*it++);
copy(vec.begin(),vec.end(),ostream_iterator<std::string>( cout,"\n"));
}
运行结果:

C++11 正则表达式——实例系统(转载)的更多相关文章
- Java-Runoob-高级教程-实例-方法:11. Java 实例 – enum 和 switch 语句使用
ylbtech-Java-Runoob-高级教程-实例-方法:11. Java 实例 – enum 和 switch 语句使用 1.返回顶部 1. Java 实例 - enum 和 switch 语句 ...
- Java-Runoob-高级教程-实例-数组:11. Java 实例 – 删除数组元素
ylbtech-Java-Runoob-高级教程-实例-数组:11. Java 实例 – 删除数组元素 1.返回顶部 1. Java 实例 - 删除数组元素 Java 实例 以下实例演示了如何使用 ...
- Java-Runoob-高级教程-实例-字符串:11. Java 实例 - 字符串性能比较测试
ylbtech-Java-Runoob-高级教程-实例-字符串:11. Java 实例 - 字符串性能比较测试 1.返回顶部 1. Java 实例 - 字符串性能比较测试 Java 实例 以下实例演 ...
- JavaScript学习11 数组排序实例
JavaScript学习11 数组排序实例 数组声明 关于数组对象的声明,以前说过:http://www.cnblogs.com/mengdd/p/3680649.html 数组声明的一种方式: va ...
- c++11 正则表达式基本使用
c++ 11 正则表达式 常用的方法 regex_match regex_search regex_replace 等. regex_match 要求正则表达式必须与模式串完全匹配,例如: strin ...
- C++11 | 正则表达式(4)
C++11还支持正则表达式里的子表达式(也叫分组),用sub_match这个类就行了. 举个简单的例子,比如有个字符串"/id:12345/ts:987697413/user:678254& ...
- 【正则表达式1】C++11正则表达式
https://www.cnblogs.com/pukaifei/p/5546968.html [正则表达式1]C++11正则表达式 头文件 #include <regex> rege ...
- python进阶11 正则表达式
python进阶11 正则表达式 一.概念 #正则表达式主要解决什么问题? #1.判断一个字符串是否匹配给定的格式,判断用户提交的又想的格式是否正确 #2.从一个字符串中按指定格式提取信息,抓取页面中 ...
- 零元学Expression Blend 4 - Chapter 11 用实例了解布局容器系列-「Border」
原文:零元学Expression Blend 4 - Chapter 11 用实例了解布局容器系列-「Border」 将教大家以实做案例认识Blend 4 的布局容器,此章介绍的布局容器是Blend ...
随机推荐
- postgresql+postgis+pgrouting安装步骤图解
1.在此(https://www.bigsql.org/postgresql/installers.jsp/)下载postgresql(开源数据库,gis行业推荐使用); 2.在此(http://wi ...
- Service 的 onStartCommand(Intent, int, int) 返回值
(1)START_NOT_STICKY If the system kills the service after onStartCommand() returns, do not recreate ...
- 实现一个2008serve的IIS的虚拟目录(通过网络路径(UNC)的形式,共享在另外一个2008服务器上
转载:http://www.cnblogs.com/top5/archive/2012/12/10/2812133.html 目的:实现一个2008serve的IIS的虚拟目录(通过网络路径(UNC) ...
- Python第三方库官网
Python第三方库官网 https://pypi.python.org/pypi 包下载后的处理: 下载后放到Python的scripts文件夹中(D:\Python3.5\Scripts),用cm ...
- Unity注意事项
1.尽量避免出现中文路径 2.做2D游戏时,图片最好要与背景图片保持一定距离 以免重叠
- [vue]计算和侦听属性(computed&watch)
先看一下计算属性 vue只有data区的数据才具备响应式的功能. 计算和侦听属性 - v-text里可以写一些逻辑 <div id="example"> {{ mess ...
- PHP操作Redis常用技巧
这篇文章主要介绍了PHP操作Redis常用技巧,结合实例形式总结分析了php针对redis的连接.认证.string.hash等操作技巧与注意事项,需要的朋友可以参考下 本文实例讲述了PHP操作Red ...
- 关于Python类属性与实例属性的讨论
标题名字有点长. 之所以想写这个文章是因为碰巧看到网上一篇关于Pyhon中类属性及实例属性区别的帖子.因为我之前也被这个问题困扰过,今天碰巧看到了这篇帖子,发现帖子的作者只是描述了现象,然后对原因的解 ...
- Sublime Text3(mac)一些插件和快捷键
Sublime Text3(mac)一些插件和快捷键 楚简约 关注 2017.02.24 17:02* 字数 1216 阅读 412评论 0喜欢 2 下载地址http://www.sublimetex ...
- 《ABCNN: Attention-Based Convolutional Neural Network for Modeling Sentence Pairs》
代码: keras:https://github.com/phdowling/abcnn-keras tf:https://github.com/galsang/ABCNN 本文是Wenpeng Yi ...