C++ 新特性学习(三) — Regex库

C++ STL终于会放点实用的东西了。可喜可贺。

这个,显然是正则表达式库,作为一个强大而又NB的库,我表示对其理解甚少,只能先研究下基本用法,更具体的用法要等实际应用中用到的时候在细看了。 PS:正则表达式的资料见 http://www.regexlab.com/ 更多资料见 https://www.owent.net/2011/264.html

就这样吧,开始。 正则表达式这玩意是用自动机搞出来的,效率当然就是自动机的效率了。当然不同的实现效率是不一样的,至于STL的效率。我就不清楚了,不过姑且相信STL吧。

第一个注意:使用正则表达式的转义的时候,不要忘了C/C++的斜杠也是要转义的 正则表达式主要函数有三 std::regex_search std::regex_match std::regex_replace 第三个好说,看函数名就知道什么意思,但是前两个呢? 直接报答案吧,第一个是不完全匹配,第二个是完全匹配。

同时,在正则表达式库里还有两个重要的类 enum std::regex_constants::match_flag_type 这个看名字就能知道是设置匹配选项的,具体选项看内容就很容易看懂,也不用多解释了。 另一个是类模版std::match_results,传进去的类型是类的迭代器 如以下从VC里抄来的

typedef basic_regex<char> regex;
typedef basic_regex<wchar_t> wregex;
typedef match_results<const char> cmatch;
typedef match_results<const wchar_t> wcmatch;
typedef match_results<string::const_iterator> smatch;
typedef match_results<wstring::const_iterator> wsmatch;

这都是默认定义 这个用于记录匹配结果,匹配如果成功,它里面会有多个std::sub_match对象,分别指向匹配的结果 std::sub_match里有matched成员表示该项是否匹配成功,还有first和second成员分别指向匹配的目标的起始位置和结束位置,str()函数可以获取匹配的值 而同时std::match_results的prefix()和suffix()函数分别指向整个匹配式的头和尾。返回的类型也是std::sub_match,内容和上面的类似

这里有第二个注意:匹配结果里的数据是共享的,只是指针不同,所以要注意不要随意释放资源。 另外有第三个注意:匹配返回真的时候才会对传入的匹配项的变量修改,如果返回false,传入的std::match_results是不会变化的

接下来就是std::regex_replace了,说到这个还涉及到std::match_results的format函数,这是一个表示筛选匹配项的的东东 具体的嘛,看下面(只是把BOOST里的东西简单翻译以下,没有boost扩展的部分,并且只留下了VC++里tr1包含的功能,他说是Perl风格的)

      占位符 |           含义 |

—————-|—————| \$& | 整个匹配值 | \$MATCH | 和 \$& 一样 | \${^MATCH} | 和 \$& 一样 | \$| 被匹配字符串去除匹配目标后的结果(即) | \$PREMATCH | 和 \$ 一样 | \${^PREMATCH} | 和 \$` 一样 | \$’ | 当前匹配位置之后的全部文本(不包括匹配的字符串) | \$POSTMATCH | 和 \$’ 一样 | \${^POSTMATCH} | 和 \$’ 一样 | \$\$ | 字符 ‘$’ | $n | 第n和被匹配项的值 |

我表示boost的功能更强大不过这些已经够了。 另外转义字符如下

     Escape |           Meaning |

—————-|——————-| \a | Outputs the bell character: ‘\a’. | \e | Outputs the ANSI escape character (code point 27). | \f | Outputs a form feed character: ‘\f’ | \n | Outputs a newline character: ‘\n’. | \r | Outputs a carriage return character: ‘\r’. | \t | Outputs a tab character: ‘\t’. | \v | Outputs a vertical tab character: ‘\v’. | \xDD | Outputs the character whose hexadecimal code point is 0xDD | \x{DDDD} | Outputs the character whose hexadecimal code point is 0xDDDDD | \cX | Outputs the ANSI escape sequence “escape-X”. | \D | If D is a decimal digit in the range 1-9, then outputs the text that matched sub-expression D. | \l | Causes the next character to be outputted, to be output in lower case. | \u | Causes the next character to be outputted, to be output in upper case. | \L | Causes all subsequent characters to be output in lower case, until a \E is found. | \U | Causes all subsequent characters to be output in upper case, until a \E is found. | \E | Terminates a \L or \U sequence. |

这个就懒得翻译和测试了,都是很简单的东西。

接下来std::regex_replace里的format也是传入这种东西,返回的就是替换后的字符串了。

另外正则表达式错误,会抛出异常,当然你也可以配合std::regex_constants::match_flag_type做一些变化。

最后,贴出代码和结

#include <string>
#include <iostream>
#include <algorithm>
#include <regex>
#include <cstdio>



int main() {
    using namespace std;

    regex reg("(http|https)://([\\w\\./]*)");
    string strIn;
    std::smatch res;
    bool isUrl;

    // 查找
    getline(cin, strIn);
    isUrl = std::regex_search(strIn, res, reg, std::regex_constants::match_not_null);
    cout<< (isUrl? "It's a url": "It's not a url")<< endl;
    // 输入 MyBlog is http://www.owent.net/ 匹配成功
    // 匹配结果里有三项,分别是整个匹配表达式和两个子表达式
    // 以下代码输出
    // 这个时候千万不能执行类似strIn = "" 改变strIn内容的操作,
    // 因为其和res指针指向的内存是共享的,如果对其进行就该会出现RE
    for (std::smatch::size_type i = 0; i < res.size(); i ++) {
        cout<< "第"<< i + 1<< "条匹配项first地址 => "<< &(res[i].first)<< endl;
        cout<< "第"<< i + 1<< "条匹配项second地址 => "<< &(res[i].second)<< endl;
        cout<< "第"<< i + 1<< "条匹配值为 => "<< res[i].str()<< endl<< endl;
    }

  
    // 匹配
    isUrl = std::regex_match(strIn, res, reg);
    cout<< isUrl<< " <= Matched? ,Size =>"<<res.size()<< endl;
    // 输入 MyBlog is http://www.owent.net/ 匹配失败,但是没有修改res的值
    // 所以会输出上一次匹配的结果: 3
   
    // 替换
    string strRule = "<a href=\"$&\">$&</a><br />\nScheme is $1\nAddress is $2";
    string strOut = std::regex_replace(strIn, reg, strRule);
    cout<< strOut<< endl;
    return 0;
}

//以下是输入“MyBlog is http://www.owent.net/ ”的输出结果:
//It's a url
//第1条匹配项first地址 => 0032EB70
//第1条匹配项second地址 => 0032EB7C
//第1条匹配值为 => http://www.owent.net/
//
//第2条匹配项first地址 => 0032EB8C
//第2条匹配项second地址 => 0032EB98
//第2条匹配值为 => http
//
//第3条匹配项first地址 => 0032EBA8
//第3条匹配项second地址 => 0032EBB4
//第3条匹配值为 => www.owent.net/
//
//0 <= Matched? ,Size =>3
//MyBlog is <a href="http://www.owent.net/">http://www.owent.net/</a><br />
//Scheme is http
//Address is www.owent.net/

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏大史住在大前端

javascript基础修炼(2)——What's this(上)

this是javascript关键字之一,是javascript能够实现面向对象编程的核心概念。用得好能让代码优雅高端,风骚飘逸,用不好也绝对是坑人坑己利器。我...

9910
来自专栏程序员互动联盟

【编程基础】main函数,你知道多少?

近期学习时对这个问题产生了迷惑,看到了这篇文章,感觉挺好。 在C/C++的学习过程中,一个很常见的问题就是void main和int main有什么区别呢?本文...

37580
来自专栏PPV课数据科学社区

零基础到精通Python,从这篇文章开始

关键词:Python,入门 正文: 本文由rever4433, Tocy, Tony, 南宫冰郁, 透过树叶的光等协作翻译,发表于开源中国。 什么是 Pytho...

31360
来自专栏带你撸出一手好代码

编程语言函数多返回值处理方式排名

一个函数一个返回值 , 这好像跟祖宗定下的规则似的,各个时代主流编程语言几乎都严格遵守着。然而, 在实际情况下, 程序员写代码经常会碰到一个函数会返回多个返回值...

42970
来自专栏AI研习社

新手必看:手把手教你入门 Python

“Python是一种高级编程语言,它的核心设计思想是代码可读性和允许程序员用几行代码来表达观点的语法。”

10030
来自专栏怀英的自我修炼

Java漫谈8

今天我们来聊聊字符串。 字符串,在Java中一个最接近与8大数据类型的存在。甚至于由于它太好用了,以至于在编写代码的时候都快忘了有个叫char的基本数据类型了。...

384100
来自专栏MyBlog

Effective.Java 读书笔记(10)关于toString

针对于java.lang.Object已经帮我们实现好了的toString方法,当我们自己定义出来的类使用这古老的toString方法的时候,通常不会返回给你一...

14440
来自专栏编程

Java8新特性第3章

Stream作为Java8的新特性之一,他与Java IO包中的InputStream和OutputStream完全不是一个概念。Java8中的Stream是对...

21970
来自专栏小樱的经验随笔

Vijos P1785 同学排序【模拟】

同学排序 描述 现有m位同学,第1位同学为1号,第2位同学为2号,依次第m位同学为m号。要求双号的学生站出来,然后余下的重新组合,组合完后,再次让双号的学生站出...

27740
来自专栏灯塔大数据

每周学点大数据 | No.8基础数据结构之线性表

No.8期 基础数据结构之线性表 Mr. 王:为了以后的知识描述方便,这里简单介绍一下数据结构的概念。数据结构是一个广泛存在于计算机科学中的概念。曾经有一位计...

382110

扫码关注云+社区

领取腾讯云代金券