加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

Qt实现实时正则表达式测试器

发布时间:2020-12-14 01:12:03 所属栏目:百科 来源:网络整理
导读:算是对boost学习的小结,当然也并没有完全看完boost,内容很多.只是看了一些常用的内容. 本篇文章将接合对boost正则表达式的学习,完成一个正则表达式测试器.UI借助了QT的实现. 首先当然是对boost的正则表达式的介绍. boost有两个正则表达式解析器.一个是xpress

算是对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. 实时性,即一边输入一边显示结果.

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,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的文件,然后随便填一些内容即可加载.

效果如下:

可能代码中还存在一些瑕疵,如果哪位同学发现了,还望指教.谢谢!!!

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读