當前位置:
首頁 > 知識 > C+中三種正則表達式比較

C+中三種正則表達式比較

工作需要用到C++中的正則表達式,有比較才有傷害!看看哪種傷害更大吧!

1、C regex

/* write by xingming * time:2012年10月19日15:51:53 * for: test regex * */

#include

#include

#include

#include

#include

#include

using namespace std;

const int times = 1000000;

int main(int argc,char** argv) {

char pattern[512]="finance.sina.cn|stock1.sina.cn|3g.sina.com.cn.*(channel=finance|_finance$|ch=stock|/stock/)|dp.sina.cn/.*ch=9&";

const size_t nmatch = 10;

regmatch_t pm[10];

int z ;

regex_t reg;

char lbuf[256]="set",rbuf[256];

char buf[3][256] = {"finance.sina.cn/google.com/baidu.com.google.sina.cndddddddddddddddddddddda.sdfasdfeoasdfnahsfonadsdf",

"3g.com.sina.cn.google.com.dddddddddddddddddddddddddddddddddddddddddddddddddddddbaidu.com.sina.egooooooooo",

"http://3g.sina.com.cn/google.baiduchannel=financegogo.sjdfaposif;lasdjf.asdofjas;dfjaiel.sdfaosidfj"};

printf("input strings:
");

timeval end,start;

gettimeofday(&start,NULL);

regcomp(?,pattern,REG_EXTENDED|REG_NOSUB);

for(int i = 0 ; i < times; ++i)

{

for(int j = 0 ; j < 3; ++j)

{

z = regexec(?,buf[j],nmatch,pm,REG_NOTBOL);

/* if(z==REG_NOMATCH) printf("no match
"); else printf("ok
"); */

}

}

gettimeofday(&end,NULL);

uint time = (end.tv_sec-start.tv_sec)*1000000 + end.tv_usec - start.tv_usec;

cout

return 0 ;

}

使用正則表達式可簡單的分成幾步:

1.編譯正則表達式

2.執行匹配

3.釋放內存

首先,編譯正則表達式

int regcomp(regex_t *preg, const char *regex, int cflags);

reqcomp()函數用於把正則表達式編譯成某種格式,可以使後面的匹配更有效。

preg: regex_t結構體用於存放編譯後的正則表達式;

regex: 指向正則表達式指針;

cflags:編譯模式

共有如下四種編譯模式:

REG_EXTENDED:使用功能更強大的擴展正則表達式

REG_ICASE:忽略大小寫

REG_NOSUB:不用存儲匹配後的結果

REG_NEWLINE:識別換行符,這樣『$』就可以從行尾開始匹配,『^』就可以從行的開頭開始匹配。否則忽略換行符,把整個文本串當做一個字元串處理。

其次,執行匹配

int regexec(const regex_t *preg, const char *string, size_t nmatch, regmatch_t pmatch[], int eflags);

preg: 已編譯的正則表達式指針;

string:目標字元串;

nmatch:pmatch數組的長度;

pmatch:結構體數組,存放匹配文本串的位置信息;

eflags:匹配模式

共兩種匹配模式:

REG_NOTBOL:The match-beginning-of-line operator always fails to match (but see the compilation flag REG_NEWLINE above). This flag may be used when different portions of a string are passed to regexec and the beginning of the string should not be interpreted as the beginning of the line.

REG_NOTEOL:The match-end-of-line operator always fails to match (but see the compilation flag REG_NEWLINE above)

最後,釋放內存

void regfree(regex_t *preg);

當使用完編譯好的正則表達式後,或者需要重新編譯其他正則表達式時,一定要使用這個函數清空該變數。

其他,處理錯誤

size_t regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size);

當執行regcomp 或者regexec 產生錯誤的時候,就可以調用這個函數而返回一個包含錯誤信息的字元串。

errcode: 由regcomp 和 regexec 函數返回的錯誤代號。

preg: 已經用regcomp函數編譯好的正則表達式,這個值可以為NULL。

errbuf: 指向用來存放錯誤信息的字元串的內存空間。

errbuf_size: 指明buffer的長度,如果這個錯誤信息的長度大於這個值,則regerror 函數會自動截斷超出的字元串,但他仍然會返回完整的字元串的長度。所以我們可以用如下的方法先得到錯誤字元串的長度。

當然我在測試的時候用到的也比較簡單,所以就直接用了,速度一會再說!

2、C++ regex

/* write by xingming * time:2012年10月19日15:51:53 * for: test regex * */

#include

#include

#include

#include

using namespace std;

int main(int argc,char** argv) {

regex pattern("[[:digit:]]",regex_constants::extended);

printf("input strings:
");

string buf;

while(cin>>buf)

{

printf("*******
%s
********
",buf.c_str());

if(buf == "quit")

{

printf("quit just now!
");

break;

}

match_results result;

printf("run compare now! %s
", buf.c_str());

bool valid = regex_match(buf,result,pattern);

printf("compare over now! %s
", buf.c_str());

if(!valid)

printf("no match!
");

else

printf("ok
");

}

return 0 ;

}

C++這個真心不想多說它,測試過程中發現 字元匹配的時候 『a』 是可以匹配的,a+也是可以的,[[:w:]]也可以匹配任意字元,但[[:w:]]+就只能匹配一個字元,+號貌似不起作用了。所以後來就乾脆放棄了這偉大的C++正則,如果有大牛知道這裡面我錯在哪裡了,真心感謝你告訴我一下,謝謝。

3、boost regex

/* write by xingming

* for:test boost regex

* time:2012年10月23日11:35:33

* */ #include #include #include

#include "boost/regex.hpp"

using namespace std;

using namespace boost;

const int times = 10000000;

int main()

{

regex pattern("finance\.sina\.cn|stock1\.sina\.cn|3g\.sina\.com\.cn.*(channel=finance|_finance$|ch=stock|/stock/)|dp\.s ina\.cn/.*ch=9&");

cout

timeval start,end;

gettimeofday(&start,NULL);

string input[] = {"finance.sina.cn/google.com/baidu.com.google.sina.cn",

"3g.com.sina.cn.google.com.baidu.com.sina.egooooooooo",

"http://3g.sina.com.cn/google.baiduchannel=financegogo"};

for(int i = 0 ;i < times; ++ i)

{

for(int j = 0 ; j < 3;++j)

{

//if(input=="quit")

// break;

//cout

cmatch what;

if(regex_search(input[j].c_str(),what,pattern)) ;

// cout

else ;

// cout

}

}

gettimeofday(&end,NULL);

uint time = (end.tv_sec-start.tv_sec)*1000000 + end.tv_usec - start.tv_usec;

cout

return 0 ;

}

boost正則不用多說了,要是出去問,C++正則怎麼用啊?那90%的人會推薦你用boost正則,他實現起來方便,正則庫也很強大,資料可以找到很多,所以我也不在闡述了。

4、對比情況

總結

C regex的速度讓我吃驚啊,相比boost的速度,C regex的速度幾乎要快上3倍,看來正則引擎的選取上應該有著落了!

上面的表格中我用到的正則和字元串是一樣的(在代碼中C regex的被我加長了),速度相差幾乎有3倍,C的速度大約在30+w/s , 而boost的速度基本在15-w/s ,所以對比就出來了!

在這裡Cregex的速度很讓我吃驚了已經,但隨後我的測試更讓我吃驚。

我以前在.net正則方面接觸的比較多,就寫了一個.net版本的作為對比

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Text.RegularExpressions;

namespace 平常測試

{

class Program

{

static int times = 1000000;

static void Main(string[] args) {

Regex reg = new Regex(@"(?>finance.sina.cn|stock1.sina.cn|3g.sina.com.cn.*(?:channel=finance|_finance$|ch=stock|/stock/)|dp.sina.cn/.*ch=9&)",RegexOptions.Compiled);

string[] str = new string[]{@"finance.sina.cn/google.com/baidu.com.google.sina.cn",

@"3g.com.sina.cn.google.com.baidu.com.sina.egooooooooo",

@"http://3g.sina.com.cn/google.baiduchannel=financegogo"};

int tt = 0;

DateTime start = DateTime.Now;

for (int i = 0; i < times; ++i)

{

for (int j = 0; j < 3; ++j)

{

if (reg.IsMatch(str[j])) ;

//Console.WriteLine("OK!");

//else

//Console.WriteLine("Error!");

}

}

DateTime end = DateTime.Now;

Console.WriteLine((end - start).TotalMilliseconds);

Console.WriteLine(tt);

Console.ReadKey();

}

}

}

結果發現,正則在不進行RegexOptions.Compiled 的時候,速度和C regex的基本一樣,在編譯只會,速度會比C regex快上一倍,這不由得讓我對微軟的那群人的敬畏之情油然而生啊。

但隨後我去查看了一下該博客上面C regex的描述,發現我可以再申明正則的時候加入編譯模式,隨後我加入了上面代碼里的 REG_NOSUB(在先前測試的時候是沒有加入的),結果讓我心理面很激動的速度出來了,C regex 匹配速度竟然達到了 300+w/s,也就是比原來的(不加入REG_NOSUB)的代碼快了將近10倍。

之後我變換了匹配的字元串,將其長度生了一倍,達到每個100字元左右(代碼裡面所示),匹配速度就下來了,但是也能達到 100w/s左右,這肯定滿足我們現在的需求了。

結果很顯然,當然會選擇C regex了。

點擊展開全文

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 程序源 的精彩文章:

Redis高性能模型
40歲的程序員你該怎麼辦?
使用 C+的StringBuilder 提升 4350% 的性能
Java後台開發精選知識圖譜
Java開發中異常處理的最佳實踐

TAG:程序源 |

您可能感興趣

宇宙中三種極有趣的現象
八字中三種能一夜暴富的組合
面相中三種命不好的鼻子,中年運勢差,一生勞碌奔波!
色彩中三種常見花卉的畫法
種草8種襯衫的花式穿法,get其中三種,讓你秒變街頭焦點!
風水中三種不同的定向方法!
海賊王中最神奇的五種外掛,其中三種使路飛獲益匪淺
VMware中三種網路連接的區別
盤點火影中殺馬特最愛的五個髮型,其中三種都來自於宇智波一族!
金庸眼中三種劍法稱王,六脈神劍排不上位,最後一種劍法最厲害
火影忍者:大蛇丸共有5種形態,其中三種超影級,第五種是恥辱!
盤點海賊王中三種特殊能力的果實,網友:傻子才會選第三種!
奧特曼中三種無法想像的合體技能,最後一個一招將貝利亞打回原形
上個世紀的零食,能認出其中三種,現在肯定都奔三了吧
Science:甲狀腺激素水平竟調節人視網膜中三種視錐細胞的產生
海賊王中三種稀有又強大的幻獸系果實,百分之九十的人會選第三種
《火影忍者》中三種最強的眼,但最無敵的還要數輪迴眼
最新出爐的絕地求生五種憋屈死法,沒中三種的都不好意思說玩過這個遊戲!
這四種水果是世界上最貴的水果,簡直就是天價,其中三種來自日本
全球五大滅絕生物,第一種備受爭議,其中三種或許倖存!