Click here to Skip to main content
15,891,136 members
Articles / Desktop Programming / MFC

Adding Regular Expressions to Your App with Regex++

Rate me:
Please Sign up or sign in to vote.
4.67/5 (20 votes)
17 Jun 2002CPOL10 min read 439K   3.1K   93  
A tutorial to demonstrate adding regular expressions to your project using Regex++ from boost.org.
// RegexTestDlg.cpp : implementation file
//

#include "stdafx.h"
#include "RegexTest.h"
#include "RegexTestDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

using namespace boost;

/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About

class CAboutDlg : public CDialog
{
public:
	CAboutDlg();

// Dialog Data
	//{{AFX_DATA(CAboutDlg)
	enum { IDD = IDD_ABOUTBOX };
	//}}AFX_DATA

	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CAboutDlg)
	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
	//}}AFX_VIRTUAL

// Implementation
protected:
	//{{AFX_MSG(CAboutDlg)
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
	//{{AFX_DATA_INIT(CAboutDlg)
	//}}AFX_DATA_INIT
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CAboutDlg)
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
	//{{AFX_MSG_MAP(CAboutDlg)
		// No message handlers
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CRegexTestDlg dialog

CRegexTestDlg::CRegexTestDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CRegexTestDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CRegexTestDlg)
		// NOTE: the ClassWizard will add member initialization here
	//}}AFX_DATA_INIT
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CRegexTestDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CRegexTestDlg)
	DDX_Control(pDX, IDC_EDIT_TYPE, m_typeEdit);
	DDX_Control(pDX, IDC_EDIT1, m_mainEdit);
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CRegexTestDlg, CDialog)
	//{{AFX_MSG_MAP(CRegexTestDlg)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(IDC_BUTTON_TRY_IT, OnButtonTryIt)
	ON_BN_CLICKED(IDC_BUTTON_BROWSE, OnButtonBrowse)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CRegexTestDlg message handlers

BOOL CRegexTestDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// Add "About..." menu item to system menu.

	// IDM_ABOUTBOX must be in the system command range.
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		CString strAboutMenu;
		strAboutMenu.LoadString(IDS_ABOUTBOX);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon
	
	// TODO: Add extra initialization here
	m_typeEdit.SetFocus();
	
	return TRUE;  // return TRUE  unless you set the focus to a control
}

void CRegexTestDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialog::OnSysCommand(nID, lParam);
	}
}

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CRegexTestDlg::OnPaint() 
{
	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting

		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

		// Center icon in client rectangle
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// Draw the icon
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
	}
}

// The system calls this to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CRegexTestDlg::OnQueryDragIcon()
{
	return (HCURSOR) m_hIcon;
}

void CRegexTestDlg::OnButtonTryIt() 
{
	CString tmpBuf;
	this->m_typeEdit.GetWindowText(tmpBuf);
	if(tmpBuf.IsEmpty())
	{
		MessageBox("Enter a filename before trying it.");
		return;
	}
	ParseFile(tmpBuf);
	
}


void CRegexTestDlg::OnOK()
{
	OnButtonTryIt();
	m_typeEdit.SetFocus();
}


void CRegexTestDlg::OnButtonBrowse() 
{
	CFileDialog fd(TRUE, NULL, NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT);
	if(fd.DoModal() == IDOK)
	{
		this->m_typeEdit.SetWindowText(fd.GetPathName());
	}
}

BOOL CRegexTestDlg::ParseFile(CString filename)
{
	if (filename.IsEmpty()){
		return FALSE;
	}
	CString finalstring;


	this->m_mainEdit.SetWindowText("");

	CStdioFile htmlfile;
	CString inString = "";
	CString wholeFileString = "";
	std::string wholeFileStr = "";

	// Read entire file into a string.
	try{
		if (htmlfile.Open(filename,CFile::modeRead | CFile::typeText, NULL))
		{
			while (htmlfile.ReadString(inString))
			{
				wholeFileString += inString;
			}
			htmlfile.Close();
		}
	}
	catch (CFileException e)
	{
		MessageBox("The file " + filename + " could not be opened for reading", "File Open Failed", MB_ICONHAND|MB_ICONSTOP|MB_ICONERROR );
		return FALSE;
	}

	// Need to convert string to a STL string for use in RegEx
	wholeFileStr = wholeFileString.GetBuffer(10);

	// Create our regular expression object
	boost::RegEx expr("(<\\s*(textarea|input|select)\\s[^>]+>[^<>]*(</(select|textarea)>)?)", TRUE);

	// Create a vector to hold all matches
	std::vector<std::string> v;

	// Pass the vector and the STL string that hold the file contents
	// to the RegEx.Grep method.
	expr.Grep(v, wholeFileStr);

	// Create char array to hold actual type (e.g. input, select, textarea).
	char actualType[100];

	// vector v is now full of all matches. We iterate through them.
	for(int i = 0; i < v.size(); i++)
	{
		// Get the object at the current index and typecast to string
		std::string line = (std::string)v[i];

		// Get a pointer to the beginning of the string
		const char *buf = line.c_str();

		// Creeate some temporary variables
		char name[100];
		char typeName[100];

		// Build output string.
		finalstring += "input, textarea, select?: ";
		GetActualType(buf, actualType);
		finalstring += actualType;
		finalstring += " -- ";
		GetValue("name", buf, name);
		finalstring += "name: ";
		finalstring += name;
		finalstring += " -- ";
		finalstring += "input type is: ";

		// If it's an input, get the type of input (e.g. text, password, checkbox, radio, etc.)
		if(_stricmp("input", actualType) == 0)
		{
			GetValue("type", buf, typeName);
			finalstring += typeName;
		}
		// Otherwise, it doesn't apply.
		else
		{
			finalstring += "N/A";
		}
		finalstring += "\r\n";
		
	}


	// Populate text field with items
	this->m_mainEdit.SetWindowText(finalstring);

	return TRUE;

}

/**

  GetActualType - Gets the tag for the current line. It could be
  "input", "select", or "textarea". Returns TRUE on success.

  */
BOOL CRegexTestDlg::GetActualType(const char *line, char *type)
{
	// Create a pattern to look for.
	char* pattern = "<\\s*((input|textarea|select))\\s*";
	// Create RegEx object with pattern.
	RegEx exp(pattern, TRUE);
	// Search for the pattern.
	if(exp.Search(line))
	{
		// If found, copy the text of the first expression match to the
		// type variable.
		strcpy(type, exp[1].c_str());
		return TRUE;
	
	}
	// We didn't find anything. Just copy an empty string.
	strcpy(type, "");
	return FALSE;

}


/**
	GetValue - Given key, copy the value to the val variable. If
	str = "<input type="text" name="email">", when you pass the key
	"name", you'll get "email" in val.
*/
void CRegexTestDlg::GetValue(char *key, const char *str, char *val)
{
	char* tmpStr = NULL;

	tmpStr = "\\s*=\\s*\\\"?([^\"<>]+)\\\"?";

	char final[100];
	// We need to build the string so we know exactly what we're looking for.
	strcpy(final, key);
	strcat(final, tmpStr);

	// Create the RegEx object with the pattern.
	RegEx exp(final);
	// Search for the
	if(exp.Search(str))
	{
		// If found, copy what we found.
		strcpy(val, exp[1].c_str());
	}
	else
	{
		// Otherwise copy a string with the no<key> where <key> is the key passed in.
		sprintf(val, "no%s", key);
	}


}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Web Developer
United States United States
Matt Long is the Director of Technology for Skye Road Systems, Inc. in Colorado Springs, Colorado. He provides software architecture consulting services to small businesses. To contact Matt ( perlmunger ) send an email to matt@skyeroadsystems.com.

Comments and Discussions