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 ...
随机推荐
- UIGestureRecognizer和UITouch
UIGestureRecognizer和UITouch是分别判断的,如果判定了是手势,那就不再触发UITouch事件,如果两者并存,则会先执行UITouch事件,之后如果确认是手势,不再执行UITou ...
- flask操作简章
https://blog.csdn.net/u011054333/article/details/70151857
- MySQL字符集设置及字符转换(latin1转utf8)
MySQL字符集设置及字符转换(latin1转utf8) http://blog.chinaunix.net/uid-25266990-id-3344584.html MySQL字符集设置及字符转换 ...
- CSS 基础知识
CSS 实例(CSS声明总是以分号(;)结束,声明组以大括号({})括起来:) CSS 规则由两个主要的部分构成:选择器,以及一条或多条声明: 选择器通常是您需要改变样式的 HTML 元素. 每条声明 ...
- 怎么获得当前点击的按钮的id名?
<body> <input id="t1" type="button" value='fff'> <input id=" ...
- spring的bean容器加载
1.在单独使用的时候可以通过ClassPathXmlApplicationContext(“配置文件.xml”);来启动容器. 2.在MVC下是通过启动servlet容器,初始化DispatcherS ...
- Tomcat重启session失效
在Tomcat的目录下找到context.xml,取消掉<Manager pathname="" /> 这句的注释.
- [LeetCode] 345. Reverse Vowels of a String_Easy tag:Two Pointers
Write a function that takes a string as input and reverse only the vowels of a string. Example 1: In ...
- [LeetCode] 196. Delete Duplicate Emails_Easy tag: SQL
Write a SQL query to delete all duplicate email entries in a table named Person, keeping only unique ...
- javascript按字节截取标题中字符串
在网页展示中经常会碰到,标题过长,需要截取字符串,用CSS的实现的话各种兼容问题,下面为大家介绍下javascript如何按字节截取字符串 做为一个前端开发人员在网页展示中经常会碰到,标题过长,需要截 ...