算是對boost學習的小結,當然也並沒有完全看完boost,內容很多.只是看了一些常用的內容.
本篇文章將接合對boost正則表達式的學習,完成一個正則表達式測試器.UI藉助了QT的實現.
首先當然是對boost的正則表達式的介紹.
boost有兩個正則表達式解析器.一個是xpressive.還有另外一個叫regex.
沒去了解regex,相比使用方法沒有太大差異.僅就xpressive做簡單的介紹.
xpressive有三個頭文件:
xpressive_static.h : 靜態的正則匹配方式,可以在編譯期完成.本文不做討論.
xpressive_dynamic.h : 動態的正則匹配方式.
xpressive.h : 上面的兩個都包括.
xpressive的三個重要的類 :
basic_regex : 這個模板類是核心,封裝了正則表達式的解析和編譯的動作.但是使用的時候不直接使用這個類.而是使用它的兩個typedef : cregex(char的正則) 和 sregex(string的正則)
match_results : 這個模板類保存正則表達式匹配的結果.使用的時候同樣是使用它的兩個typedef : cmatch(同上) 和 smatch(同上).
sub_match : 這個類只在分詞的時候會用到,作用與match_results類似.
xpressive支持五種基於正則表達式的操作:
匹配 : 即完整匹配.藉助全局函數regex_match來實現.函數原型爲 bool regex_match(string, match_results &, basic_regex &);其中第一個參數爲源數據,第二個參數是保存匹配後的結果.第三個參數就是正則表達式.
這裏着意瞭解一下第二個參數,既然是完全匹配,爲什麼還需要第二個參數來保存結果呢,因爲第二個參數是一個結果集.重載了[], 下標0保存的是完整匹配的內容,從1開始保存的是匹配的子表達式(即通過小括號括起來的正則表達式匹配到的內容).
查找 : 只要部分匹配即返回真.函數原型爲 bool regex_search(string, match_results &, basic_regex &); 參數的含義與匹配是一樣的.
替換 : 使用過sed命令的同學肯定都用過這樣的用法.sed "s/from/to/g" ,在這裏是同樣的意思.需要藉助全局函數 regex_replace(string, basic_regex const &, format);前兩個參數分別是源字符串和正則表達式.最後一個參數format就是需要把basic_regex匹配的內容替換成的字符串.注意可以使用$N來作爲子表達式的佔位符.
迭代 : cregex_iterator 和 sregex_iterator, 藉助的是match_results類.可以迭代正則表達式匹配的結果.用法也很簡單,只要使用其自身的構造函數即可實現迭代.
regex_iterator(string begin, string end, basic_regex&).第一個參數表示字符串的開頭,第二個參數表示字符串的結尾.第三個參數即爲正則表達式.
分詞 : 所謂分詞其實也可以理解成一種迭代.不過它所涉及的範圍更廣,不僅可以迭代匹配的內容,還可以迭代不匹配的內容.在使用的時候只要實例化兩個類中的一個即可:cregex_token_iterator 和 sregex_token_iterator.這個功能也是藉助自身構造函數實現的 : regex_token_iterator(string begin, string end, basic_regex, match_type);前三個參數和迭代是一樣的意思,最後一個參數用來標記分詞的內容(把匹配的分出來還是把不匹配的分出來).
本文只是簡單的對boost的正則表達式做了入門級的介紹,如果同學們想要進一步的學習,推薦大家看一下<<boost程序完全開發指南>>,很不錯的一本書,每一個知識點都有一個對應的小例子,很方便學習.
下面來設計一下正則表達式練習器.
1. 實時性,即一邊輸入一邊顯示結果.
2. 結果的顯示方式以高亮的形式進行顯示.
在上面這兩個簡單的需求下,給出實現的代碼:
mywindow.h :
/******************************************************************************
** Coypright(C) 2014-2024 () technology Co., Ltd
**
** 文件名 : mywindow.h
** 版本號 : 1.0
** 描 述 :
** 作 者 : cp3alai
** 日 期 : 2015.06.11
******************************************************************************/
#include <QObject>
#include <QtGui/QApplication>
#include <QtGui/QDesktopWidget>
#include <QtGui/QWidget>
#include <QtGui/QLabel>
#include <QtGui/QTextEdit>
#include <QtGui/QLineEdit>
#include <QtGui/QPushButton>
#include <QtGui/QGridLayout>
#include <QTextCursor>
#include <QtCore/QTextCodec>
#include <string>
#include <sstream>
#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>
#include <boost/xpressive/xpressive.hpp>
using namespace std;
using namespace boost::filesystem;
using namespace boost::xpressive;
namespace fs = boost::filesystem;
class CMyWindow:public QWidget
{
Q_OBJECT
public slots:
void highlightTextMatched(const QString &str);
public:
CMyWindow(QWidget *parent = 0);
private:
QLineEdit *m_lineEdit;
QTextEdit *m_textEdit;
QPushButton *m_pushButton;
path m_filename;
fs::fstream m_fstream;
};
mywindow.cpp :
高亮部分的代碼借鑑子網絡上的代碼.
/******************************************************************************
** Coypright(C) 2014-2024 () technology Co., Ltd
**
** 文件名 : mywindow.cpp
** 版本號 : 1.0
** 描 述 :
** 作 者 : cp3alai
** 日 期 : 2015.06.11
******************************************************************************/
#include "mywindow.h"
CMyWindow::CMyWindow(QWidget *parent) : QWidget(parent)
{
QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));
m_textEdit = new QTextEdit(this);
m_lineEdit = new QLineEdit(this);
m_pushButton = new QPushButton(this);
QGridLayout *gridlayout = new QGridLayout;
//begin 頁面佈局
m_pushButton->setText("Close");
m_textEdit->setReadOnly(true);
gridlayout->addWidget(m_textEdit, 0, 0, 5, 7);
gridlayout->addWidget(m_lineEdit, 5, 0, 1, 5);
gridlayout->addWidget(m_pushButton, 5, 5, 1, 2);
this->setLayout(gridlayout);
//end 頁面佈局
m_filename = "./reg.txt";
m_fstream.open(m_filename.string().c_str());
stringstream strstream;
strstream<<m_fstream.rdbuf();
string str(strstream.str());
m_textEdit->setPlainText(str.c_str());
m_lineEdit->setFocus();
this->setTabOrder(m_lineEdit, m_pushButton);
connect(m_lineEdit, SIGNAL(textChanged(QString)), this, SLOT(highlightTextMatched(QString)));
connect(m_pushButton, SIGNAL(clicked()), this, SLOT(close()));
}
void CMyWindow::highlightTextMatched(const QString &str)
{
string wholewords = m_textEdit->toPlainText().toStdString();
this->repaint();
m_textEdit->setPlainText(m_textEdit->toPlainText().toStdString().c_str());
if (str.toStdString().empty())
{
return;
}
cout<<str.toStdString().at(str.length() - 1)<<endl;
string checkstr = str.toStdString();
int little = 0;
int middle = 0;
for (unsigned int i = 0; i < checkstr.length(); i++)
{
if (checkstr[i] == '(')
{
if (i == 0 || (i > 0 && checkstr[i - 1] != '\\'))
{
little++;
}
else if (i > 0 && checkstr[i - 1] == '\\')
{
}
}
if (checkstr[i] == '[')
{
if (i == 0 || (i > 0 && checkstr[i - 1] != '\\'))
{
middle++;
}
}
if (checkstr[i] == ')')
{
if (i == 0 || (i > 0 && checkstr[i - 1] != '\\'))
{
if (little == 0)
{
return ;
}
little--;
}
}
if (checkstr[i] == ']')
{
if (i == 0 || (i > 0 && checkstr[i - 1] != '\\'))
{
if (middle == 0)
{
return ;
}
middle--;
}
}
}
if (little != 0 || middle != 0 || str.toStdString().at(str.length() - 1) == '\\')
{
return;
}
sregex regex = sregex::compile(str.toStdString(), icase);
smatch match;
try
{
regex_search(wholewords, match, regex);
cout<<match[0]<<endl;
}
catch (regex_error &e)
{
cout<<e.what()<<endl;
m_lineEdit->clear();
return;
}
QString cQstr = ((string)match[0]).c_str();
cout<<cQstr.toStdString()<<endl;
QPalette palette = m_textEdit->palette();
palette.setColor(QPalette::Highlight, palette.color(QPalette::Active, QPalette::Highlight));
m_textEdit->setPalette(palette);
m_textEdit->find(cQstr);
}
main.cpp :
/******************************************************************************
** Coypright(C) 2014-2024 () technology Co., Ltd
**
** 文件名 : test.cpp
** 版本號 : 1.0
** 描 述 :
** 作 者 : cp3alai
** 日 期 : 2015.06.10
******************************************************************************/
#include "mywindow.h"
int main(int argc, char ** argv)
{
QApplication app(argc, argv);
QDesktopWidget *desk;
CMyWindow *mywindow = new CMyWindow;
mywindow->setWindowTitle(("正則練習器"));
mywindow->resize(500, 500);
mywindow->show();
desk = QApplication::desktop();
mywindow->move((desk->width() - mywindow->width())/2, (desk->height() - mywindow->height())/2);
return app.exec();
}
使用方法:
在當前目錄下建立一個reg.txt的文件,然後隨便填一些內容即可加載.
效果如下:
可能代碼中還存在一些瑕疵,如果哪位同學發現了,還望指教.謝謝!!!