首页 > 代码库 > C++ Tr1中的正則表達式

C++ Tr1中的正則表達式

要使用正則表達式,首先要有类库支持,C++曾经不像Java或者C#有完整的类库使用,可是在Tr1中早已提供了正则库,仅仅是非常少被人们注意罢了

 

TR1中包括了一个正则库,来自Boost的 regex,已经纳入了0x新标准,可是新标准遥遥无期。即便如此,如今非常多编译器也已经支持了,特别是微软,步伐最快!

尽管如今新标准还未全然支持,可是早点了解一下也是好的:

#include <iostream>
#include <regex>

int _tmain(int argc, _TCHAR* argv[])
{
	
	 std::locale loc("");  
    std::wcout.imbue(loc);  
  
    std::wstring text(_T("我的IP地址是:109.168.0.1."));  
    std::wstring newIP(_T("127.0.0.1"));  
    std::wstring regString(_T("(\\d+)\\.(\\d+)\\.(\\d+)\\.(\\d+)"));  
  
    // 表达式选项 - 忽略大写和小写   
    std::regex_constants::syntax_option_type fl = std::regex_constants::icase;  
      
    // 编译一个正則表達式语句   
    std::wregex regExpress(regString, fl);  
  
    // 保存查找的结果   
    std::wsmatch ms;  
  
    // 推断是否全行匹配   
    if(std::regex_match(text, ms, regExpress))  
    {  
        std::wcout<<_T("正則表達式:")<<regString<<_T("匹配:")<<text<<_T("成功.")<<std::endl;  
    }  
    else  
    {  
        std::wcout<<_T("正則表達式:")<<regString<<_T("匹配:")<<text<<_T("失败.")<<std::endl;  
    }  
  
    // 查找   
    if(std::regex_search(text, ms, regExpress))  
    {  
        std::wcout<<_T("正則表達式:")<<regString<<_T("查找:")<<text<<_T("成功.")<<std::endl;  
        for(size_t i= 0; i < ms.size(); ++i)  
        {  
            std::wcout<<_T("第")<<i<<_T("个结果:\"")<<ms.str(i)<<_T("\" - ");  
            std::wcout<<_T("起始位置:")<<ms.position(i)<<_T("长度")<<ms.length(i)<<std::endl;  
        }  
        std::wcout<<std::endl;  
  
        // 替换1   
        text = text.replace(ms[0].first, ms[0].second, newIP);  
        std::wcout<<_T("替换1后的文本:")<<text<<std::endl;  
    }  
    else  
    {  
        std::wcout<<_T("正則表達式:")<<regString<<_T("查找:")<<text<<_T("失败.")<<std::endl;  
    }  
  
    // 替换2   
    newIP = _T("255.255.0.0");  
    std::wstring newText = std::regex_replace( text, regExpress, newIP);  
    std::wcout<<_T("替换2后的文本:")<<newText<<std::endl;  
  
    // 结束   
    std::wcout<<_T("按回车键结束...");  
    std::wcin.get();  
	
	return 0;
}


[代码说明]
1. 创建正則表達式对象,有3中方法:
(1) 使用构造函数
std::regex_constants::syntax_option_type fl = std::regex_constants::icase; // 语法选项,能够设置使用哪种风格的正則表達式语法等.
std::wregex regExpress(regString, fl);
(2) 使用赋值运算符,缺点是不能指定语法选项,并且也比較低效.
std::wregex regExpress;
regExpress = regString;
(3) 使用assign方法.
std::wregex regExpress;
regExpress.assign(regString, fl);
构造正则对象的过称就是所谓的"编译".

2. regex_match() 和 regex_search()
regex_match()仅仅有在整个字符串匹配正則表達式时才返回 true, 而 regex_search()在子串匹配就返回 true.

3. 匹配结果对象 std::wsmatch.
熟悉Perl正則表達式的人都知道,匹配成功后能够用 $1 $2 ... $N 来获得子串的指, tr1 regex库把匹配结果保存在一个 std::wsmatch(UNICODE) / std::smatch(ANSI) 对象中.
std::wsmatch 是一个由若干个 std::wssub_match 对象构成的数组. 而 std::wssub_match 派生自 pair.
由std::wssub_match::first保存子串的起始位置指针(事实上说是迭代器比較准确一点).
由std::wssub_match::second保存子串的结束位置 +1 的指针(STL的通用原则,半开区间).
所以 [std::wssub_match::first,std::wssub_match::second) 就是子串的所有内容.
当然, std::wsmatch (match_result模版的提前定义类) 提供了一些简便的方法用于訪问子串:
(1) str(idx) 方法返回相应的子串的 std::string / std::wstring 对象. 仅仅是最经常使用的.
(2) position(idx) 方法返回相应子串的起始偏移量.(不是指针,是相对于首字节地址或者begin()的偏移量).
(3) length(idx) 返回子串的长度.

4. 替换子串.
前面说到 std::wssub_match::first / second 保存了子串的起始/结束位置,那么我们当然能够用这个指针(迭代器)来替换文本(见代码中的 "替换1").
或者用 std::regex_replace() 也能够达到目的(见代码中的"替换2").

 

 

 

使用的VC2010,一般2008 sp1以上都支持正則表達式,想要接触tr1的能够看 《C++标准程序库扩展权威指南》,这本书没什么销量,缘故大约是tr1鲜为人知吧,我买的书还在路上勒,到了之后再深入学习下!