hakeの日記

Windows環境でプログラミングの勉強をしています。

C++でQTアプリ(その3) 正規表現

Rubyほどの機能は無いようだけれども、QTでもQRegExpクラスを用いることで正規表現によるパターンマッチングが可能みたい。下のプログラムではRegExp欄に正規表現、String欄に文字列を入力してボタンを押すとマッチした文字列を表示する。
QTの正規表現の詳細はリファレンスを参照。このクラスは日本語の文字も認識してくれるのは便利です、ただし\sで全角スペースの認識は無理だけど。。。


それとは別に、結果を表示する為の関数printを定義して日本語と半角英数字を別に出力させると、まず英数字が全部まとめて出力されてから日本語がまとめて出力というように順番が狂って出力されてしまった、原因は不明???
そのため日本語と英数字を一個のQStringにしてから出力させるようにしたら上手くいった。

regexp.h
#ifndef REGEXP_H
#define REGEXP_H

#include <qmainwindow.h>
#include <qtextcodec.h>
#include <qfont.h>
#include <qvbox.h>
#include <qlabel.h>
#include <qlineedit.h>
#include <qmultilineedit.h>
#include <qpushbutton.h>
#include <qstring.h>
#include <qregexp.h>

class RegExp : public QMainWindow{
	Q_OBJECT  // これが無いとスロットが作れない?

public:
	RegExp(QWidget *parent = 0, const char *name = 0);
//	~RegExp();

private:
	QVBox *v;

	QHBox *h0;
	QLabel *label0;
	QLineEdit *eb0;
	QHBox *h1;
	QLabel *label1;
	QLineEdit *eb1;

	QMultiLineEdit *eb;
	QPushButton *pb;

	int pline;

private:
	void print( QString str, int ret);

private slots:
	void slot_check();
};

#endif //REGEXP_H
regexp.cpp
#include "regexp.h"

RegExp::RegExp(QWidget *parent, const char *name)
		: QMainWindow(parent, name)
{
	setCaption("RegExp Test");
	QFont f("lcfont",18);
	setFont(f);              // Widget内のフォント設定

	v = new QVBox( this );
	setCentralWidget(v);

	h0 = new QHBox( v );     // 正規表現入力欄
	label0 = new QLabel("RegExp: ", h0);
	eb0 = new QLineEdit( h0 );
	eb0->clear();

	h1 = new QHBox( v );     // 文字列入力欄
	label1 = new QLabel("String: ", h1);
	eb1 = new QLineEdit( h1 );
	eb1->clear();

	eb = new QMultiLineEdit(v); // 結果表示欄
	eb->clear();
	eb->setFocusPolicy( QWidget::NoFocus );
	eb->setReadOnly( true );

	pb = new QPushButton(tr("パターンマッチ確認"), v);
	connect( pb, SIGNAL(clicked()), this, SLOT(slot_check()) );

	pline = 0;
}


// ebに出力、ret=1で改行
void RegExp::print( QString str , int ret = 0)
{
	int col;
	eb->getCursorPosition( &pline, &col);
	pline++;

	if( ret == 1 ){      // ret=1で改行する
		str += "\n";
	}
	eb->insertAt( str, pline, 0);
}


// パターンマッチ確認
void RegExp::slot_check()
{
	QString str0 = eb0->text();
	QString str1 = eb1->text();
	
	if(str0.isEmpty() || str1.isEmpty() ){
		print( tr("入力欄が空です\n\n") );
		return;
	}
	
	QRegExp r( str0 );   // eb0の内容にマッチする正規表現
	int len = 0, idx = 0;
	uint length = str1.length();

	QString s;
	s = tr("正規表現   :");
	s += str0;
	print( s, 1);
	s = tr("入力文字列  :");
	s += str1;
	print( s, 1);

	int i = 0;
	while( (uint)idx < length){
		idx = r.match( str1, idx, &len); // マッチした位置と長さを取得
		if( idx == -1 ) break;
		if(len == 0){
			print( tr("文字にマッチしていません\n") );
			i++;
			break;
		}
		s = tr("マッチした文字:");
		s += str1.mid(idx, len);     // マッチした文字列を取得
		print( s, 1);
		idx += len;
		i++;
	}
	if( i == 0) print( tr("マッチしません\n") );
	print( "\n" );
}

/*		// 以下の方法だと日本語が後でまとめて出力されてしまう
		print( tr("正規表現: ") );
		print( str0, 1);
		print( tr(" 文字列: ") );
		print( str1, 1);
		print( tr("マッチした文字: ") );
		QString s = str1.mid(idx, len);
		print( s, 1);
		print( "\n" );
 */