bcb6 中安裝 boost
正則表達(dá)式是一種模式匹配形式,它通常用在處理的文本程序中。比如我們經(jīng)常使用的grep工具,還是perl語(yǔ)言都使用了正則表達(dá)式。傳統(tǒng)的C++處理正則表達(dá)式是非常麻煩的,這也成為很多其他語(yǔ)言愛(ài)好者的笑柄,現(xiàn)在情況不一樣了,因?yàn)橛辛薭oost。
Boost是一個(gè)基于Template的開(kāi)發(fā)源代碼庫(kù),在這個(gè)庫(kù)中有很多子庫(kù)用來(lái)高效處理各方面的問(wèn)題,比如字符串拆分,格式化,線程等等,Boost對(duì)于每一個(gè)C++愛(ài)好者都是應(yīng)該了解的,對(duì)于C++ Builder用戶如果能在熟練使用VCL的情況下再熟練使用Boost,我想一定如虎添翼。
一般來(lái)說(shuō),使用Boost是非常簡(jiǎn)單,和使用其他STL庫(kù)沒(méi)有太大區(qū)別,但使用Boost的正則表達(dá)式庫(kù)則不那么容易,因?yàn)檫@個(gè)庫(kù)還需要我們單獨(dú)編譯,下面我將詳細(xì)介紹如何使用。
如果你還不知道或者還沒(méi)有Boost的話,你可以去www.boost.org下載最新版本,作者使用的是1.30版本。將下載下來(lái)的zip包[1]解壓到任何你喜歡的目錄,比如D:\boost。
編譯正則表達(dá)式庫(kù)
前面已經(jīng)提到,這個(gè)庫(kù)需要我們單獨(dú)編譯才能使用,為什么不編譯好一起發(fā)布呢?主要是考慮到不同的編譯器需要不同的鏈接庫(kù)文件和鏈接庫(kù)太大了。在命令行下,進(jìn)入[%Boost]\Libs\RegEx\Build目錄,直接敲入make –fbcb6.mak命令開(kāi)始編譯,這里請(qǐng)大家注意了,如果你的計(jì)算機(jī)上同時(shí)安裝了BCB5,請(qǐng)一定要把path設(shè)置成為BCB6的bcc32.exe程序所在的目錄,否則可能使用BCB5的make程序,這樣雖然能編譯但最后不能使用。
編譯過(guò)程相當(dāng)耗時(shí),你需要耐心等待,最終編譯完成,會(huì)在[%Boost]\Libs\RegEx\Build目錄生成一個(gè)BCB6目錄,在這個(gè)目錄生成了很多l(xiāng)ib文件和dll文件,把所有dll文件復(fù)制到windows系統(tǒng)目錄,所以lib文件復(fù)制到bcb6\lib目錄。如果你不想這么麻煩的復(fù)制文件,可以在編譯時(shí)加入install參數(shù),就像這樣make –fBcb6.mak install,不過(guò)作者還是比較喜歡前一種方式,這樣我可以知道到底生成了什么文件。現(xiàn)在編譯已經(jīng)完成了,你可以體現(xiàn)boost的神奇魅力了。
編譯過(guò)程相當(dāng)耗時(shí),你需要耐心等待,最終編譯完成,會(huì)在[%Boost]\Libs\RegEx\Build目錄生成一個(gè)BCB6目錄,在這個(gè)目錄生成了很多l(xiāng)ib文件和dll文件,把所有dll文件復(fù)制到windows系統(tǒng)目錄,所以lib文件復(fù)制到bcb6\lib目錄。如果你不想這么麻煩的復(fù)制文件,可以在編譯時(shí)加入install參數(shù),就像這樣make –fBcb6.mak install,不過(guò)作者還是比較喜歡前一種方式,這樣我可以知道到底生成了什么文件。現(xiàn)在編譯已經(jīng)完成了,你可以體現(xiàn)boost的神奇魅力了。
#include<deque>
#include<iostream>
#include<algorithm>
#include<boost/regex.hpp>
int main()
{
using namespace boost;
using namespace std;
regex expression("\\s+href\\s*=\\s*\"([^\"]*)\"",regbase::normal|regbase::icase);
string s="<a href=\"index.html\"><img src=\"logo.gif\"></a>";
deque<string> result;
regex_split(std::back_inserter(result),s,expression);
copy(result.begin(),result.end(),ostream_iterator<string>(cout,"\n"));
int c;
cin>>c;
return 0;
}
#include<iostream>
#include<algorithm>
#include<boost/regex.hpp>
int main()
{
using namespace boost;
using namespace std;
regex expression("\\s+href\\s*=\\s*\"([^\"]*)\"",regbase::normal|regbase::icase);
string s="<a href=\"index.html\"><img src=\"logo.gif\"></a>";
deque<string> result;
regex_split(std::back_inserter(result),s,expression);
copy(result.begin(),result.end(),ostream_iterator<string>(cout,"\n"));
int c;
cin>>c;
return 0;
}
設(shè)置BCB6 Project屬性的Lib Path和Include Path為你安裝boost的目錄,運(yùn)行你會(huì)看到結(jié)果:
index.html
可以看到index.html已經(jīng)從字符串中提出出來(lái)了,那么為什么會(huì)是這樣呢?
代碼的核心部分是:
regex expression("\\s+href\\s*=\\s*\"([^\"]*)\"",regbase::normal|regbase::icase);
它用來(lái)設(shè)置如何匹配字符串,上面亂七八糟的字符串很難看懂,如果不了解正則表達(dá)式的書(shū)寫(xiě)規(guī)則,上
面代碼可以和天書(shū)媲美。
regbase::normal|regbase::icase 是解析參數(shù)設(shè)置,具體可以參考boost幫助文檔。
正則表達(dá)式的書(shū)寫(xiě)規(guī)則
具體的書(shū)寫(xiě)規(guī)則,大家可以參看boost的文檔,我這里做一下簡(jiǎn)要說(shuō)明:
. (dot)
用來(lái)匹配任何一個(gè)字符,但不包括新行上的字符
*
閉包,任意有限次的自重復(fù)連接
+
有限次自重復(fù)連接,但至少出現(xiàn)一次
{}
指定可能的重復(fù)次數(shù)
例如:
ba* 匹配 b ba baa baaa等
ba+ 匹配 ba baa baaaaaaaaa等
ba{1,5} 匹配 ba baa baaa baaaa baaaaa
\
轉(zhuǎn)義字符,有很多用途,根據(jù)參數(shù)設(shè)置而變化,最常見(jiàn)的就是類似于c語(yǔ)言\的用法
\s
匹配空格
\w
匹配一個(gè)單詞
\d
匹配數(shù)字
()
有兩種用法:
1是合并的作用,例如(ab)*匹配ab abab ababab等
2是確定匹配,也就是說(shuō)在()中的字符將被最終拆解出來(lái)
根據(jù)上面這張表,我們可以很容易知道前面的那段天書(shū)如何解釋。
index.html
可以看到index.html已經(jīng)從字符串中提出出來(lái)了,那么為什么會(huì)是這樣呢?
代碼的核心部分是:
regex expression("\\s+href\\s*=\\s*\"([^\"]*)\"",regbase::normal|regbase::icase);
它用來(lái)設(shè)置如何匹配字符串,上面亂七八糟的字符串很難看懂,如果不了解正則表達(dá)式的書(shū)寫(xiě)規(guī)則,上
面代碼可以和天書(shū)媲美。
regbase::normal|regbase::icase 是解析參數(shù)設(shè)置,具體可以參考boost幫助文檔。
正則表達(dá)式的書(shū)寫(xiě)規(guī)則
具體的書(shū)寫(xiě)規(guī)則,大家可以參看boost的文檔,我這里做一下簡(jiǎn)要說(shuō)明:
. (dot)
用來(lái)匹配任何一個(gè)字符,但不包括新行上的字符
*
閉包,任意有限次的自重復(fù)連接
+
有限次自重復(fù)連接,但至少出現(xiàn)一次
{}
指定可能的重復(fù)次數(shù)
例如:
ba* 匹配 b ba baa baaa等
ba+ 匹配 ba baa baaaaaaaaa等
ba{1,5} 匹配 ba baa baaa baaaa baaaaa
\
轉(zhuǎn)義字符,有很多用途,根據(jù)參數(shù)設(shè)置而變化,最常見(jiàn)的就是類似于c語(yǔ)言\的用法
\s
匹配空格
\w
匹配一個(gè)單詞
\d
匹配數(shù)字
()
有兩種用法:
1是合并的作用,例如(ab)*匹配ab abab ababab等
2是確定匹配,也就是說(shuō)在()中的字符將被最終拆解出來(lái)
根據(jù)上面這張表,我們可以很容易知道前面的那段天書(shū)如何解釋。
一個(gè)實(shí)際的例子
前一段時(shí)間在CSDN上有一篇帖子,問(wèn)題是有一種文件結(jié)構(gòu)如(類似):
@People{
Age=19
Speek=”Hay,{name},how are you”
}
問(wèn)如何拆分字符串得到@后面的名字,=兩邊的屬性名和屬性值,引號(hào)里{}種的名字。
解決這個(gè)問(wèn)題用正則表達(dá)式再合適不過(guò)了。
根據(jù)分析,我們可以這樣構(gòu)造匹配規(guī)則:
"@(.*?)\s*\\{" 匹配@開(kāi)始的字符創(chuàng),后面兩種類型如何構(gòu)造匹配規(guī)則留給大家思考吧。
這樣我們可以輕易拆解這個(gè)例子。
前一段時(shí)間在CSDN上有一篇帖子,問(wèn)題是有一種文件結(jié)構(gòu)如(類似):
@People{
Age=19
Speek=”Hay,{name},how are you”
}
問(wèn)如何拆分字符串得到@后面的名字,=兩邊的屬性名和屬性值,引號(hào)里{}種的名字。
解決這個(gè)問(wèn)題用正則表達(dá)式再合適不過(guò)了。
根據(jù)分析,我們可以這樣構(gòu)造匹配規(guī)則:
"@(.*?)\s*\\{" 匹配@開(kāi)始的字符創(chuàng),后面兩種類型如何構(gòu)造匹配規(guī)則留給大家思考吧。
這樣我們可以輕易拆解這個(gè)例子。
性能分析
通過(guò)上面的討論,大家已經(jīng)了解到boost的強(qiáng)大威力,那個(gè)性能又如何呢?為此我們?cè)賹?shí)際來(lái)拆分一個(gè)
復(fù)雜的html代碼,看看到底需要花費(fèi)多少時(shí)間。
為了節(jié)省篇幅,這里就不列出html代碼了,不過(guò)可以告訴大家,這是一個(gè)又Word生成的大小為186K
的html文件,這個(gè)文件中用到了很多<table>標(biāo)簽,所以我這里測(cè)試就來(lái)拆分所有<table>標(biāo)簽的
width屬性。測(cè)試代碼如下:
通過(guò)上面的討論,大家已經(jīng)了解到boost的強(qiáng)大威力,那個(gè)性能又如何呢?為此我們?cè)賹?shí)際來(lái)拆分一個(gè)
復(fù)雜的html代碼,看看到底需要花費(fèi)多少時(shí)間。
為了節(jié)省篇幅,這里就不列出html代碼了,不過(guò)可以告訴大家,這是一個(gè)又Word生成的大小為186K
的html文件,這個(gè)文件中用到了很多<table>標(biāo)簽,所以我這里測(cè)試就來(lái)拆分所有<table>標(biāo)簽的
width屬性。測(cè)試代碼如下:
#include<deque>
#include<iostream>
#include<algorithm>
#include<boost/regex.hpp>
#include<vcl.h>
int main()
{
using namespace boost;
using namespace std;
TStringList* html=new TStringList();
html->LoadFromFile("D:\\1.htm");
regex expression("\\s+width=([^\"]*)\s+",regbase::normal|regbase::icase);
DWORD start=GetTickCount();
for(int n=0;n<html->Count;n++)
{
string s=html->Strings[n].c_str();
deque<string> result;
regex_split(std::back_inserter(result),s,expression);
copy(result.begin(),result.end(),ostream_iterator<string>(cout,"\n"));
result.clear();
}
start=GetTickCount()-start;
delete html;
cout<<start;
int c;
cin>>c;
return 0;
}
#include<iostream>
#include<algorithm>
#include<boost/regex.hpp>
#include<vcl.h>
int main()
{
using namespace boost;
using namespace std;
TStringList* html=new TStringList();
html->LoadFromFile("D:\\1.htm");
regex expression("\\s+width=([^\"]*)\s+",regbase::normal|regbase::icase);
DWORD start=GetTickCount();
for(int n=0;n<html->Count;n++)
{
string s=html->Strings[n].c_str();
deque<string> result;
regex_split(std::back_inserter(result),s,expression);
copy(result.begin(),result.end(),ostream_iterator<string>(cout,"\n"));
result.clear();
}
start=GetTickCount()-start;
delete html;
cout<<start;
int c;
cin>>c;
return 0;
}
輸出結(jié)果為671毫秒,拆分得到1072個(gè)width屬性值,我們可以看到boost的效率是非常高的,雖然與一些角本語(yǔ)言比起來(lái)解析速度還是慢,但已經(jīng)可以滿足大多數(shù)編程要求了。另外作者的計(jì)算機(jī)配置并不是非常高,相信拿到現(xiàn)在任何一臺(tái)主流配置的計(jì)算機(jī)上都會(huì)優(yōu)于作者的結(jié)果。
結(jié)束語(yǔ)
結(jié)束語(yǔ)
其實(shí)上面的強(qiáng)大威力只是boost的冰山一角,如果你不自己去體會(huì),你很難想象到boost的強(qiáng)大威力。在boost里還有很多使用的庫(kù),比如格式化輸出,字符串拆解,類型轉(zhuǎn)換等,這些庫(kù)使用起來(lái)也比較方便,大家可以自行參考boost文檔。在這些庫(kù)中還有兩個(gè)庫(kù)需要自行編譯,他們是Python和thread庫(kù),而且這些庫(kù)的編譯需要專門(mén)的工具Jam,所以我們?cè)诰幾g這些庫(kù)的時(shí)候還要編譯jam工具,而編譯jam工具也不是一件快樂(lè)的事情,麻煩同樣出現(xiàn)在如果你安裝了多個(gè)編譯器,如果讀者有興趣可以自己試一下。
不過(guò)BCB6并不支持全部boost庫(kù),從boost提供的編譯器支持表可以看到[2],BCB6還是有相當(dāng)多的庫(kù)不支持的,支持最好的是gcc/g++的編譯器,但也不是全部支持。希望borland下一個(gè)將要發(fā)布的C++編譯器可以支持更多C++標(biāo)準(zhǔn)。
[1] 其實(shí)還有其他類型的包,但在windows系統(tǒng)下,你最好下載zip包
[2] Boost提供的編譯器支持表是針對(duì)BCB5的,對(duì)于BCB6的支持作者并沒(méi)有詳細(xì)測(cè)試,如果讀者有興趣可以自己測(cè)試boost附帶的測(cè)試代碼。
posted on 2008-12-07 21:22 john 閱讀(884) 評(píng)論(0) 編輯 收藏 所屬分類: C++ builder