算是对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,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,basic_regex,match_type);前三个参数和迭代是一样的意思,最后一个参数用来标记分词的内容(把匹配的分出来还是把不匹配的分出来).
本文只是简单的对boost的正则表达式做了入门级的介绍,如果同学们想要进一步的学习,推荐大家看一下<<boost程序完全开发指南>>,很不错的一本书,每一个知识点都有一个对应的小例子,很方便学习.
下面来设计一下正则表达式练习器.
1. 实时性,即一边输入一边显示结果.
在上面这两个简单的需求下,给出实现的代码:
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,5,7); gridlayout->addWidget(m_lineEdit,1,5); gridlayout->addWidget(m_pushButton,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()),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的文件,然后随便填一些内容即可加载.
效果如下:
可能代码中还存在一些瑕疵,如果哪位同学发现了,还望指教.谢谢!!!
原文链接:https://www.f2er.com/regex/360201.html