解決Boost.Regex對中文支援不好的問題
第一參考段:
C/C++ code
#include "stdafx.h"
#include <cstdlib>
#include <stdlib.h>
#include <boost/regex.hpp>
#include <string>
#include <iostream>
using namespace std;
//using namespace boost;
boost::wregex expression(L"^\\s*我+\\s*[想|愛|恨|扁]+\\s*你");
int main(int argc, char* argv[]) {
locale loc("Chinese-simplified");
wcout.imbue(loc);
std::wstring in = L"我我我我 愛愛愛愛愛 你";
static boost::wsmatch what;
cout << "enter test string" << endl;
//getline(cin,in);
if (boost::regex_match(in.c_str(), what, expression))
{
for (int i = 0;i < what.size();i++)
wcout << L"str :" << what[i].str() << endl;
}
else {
wcout << L"Error Input" << endl;
}
return 0;
}
============ 為了程式能夠在VC6.0中運行 改為如下所示 ==================
boost::wregex expression(L"^\\s*我+\\s*[想|愛|恨|扁]+\\s*你");
locale loc("Chinese-simplified");
wcout.imbue(loc);
std::wstring in = L"我我我我 愛愛愛愛愛 你";
static boost::wsmatch what;
if (boost::regex_match(in.c_str(), what, expression))
{
for (int i = 0;i < what.size();i++)
{
// string test = (LPCTSTR)what[i].str().c_str();
int iLen= WideCharToMultiByte( CP_ACP, NULL, what[i].str().c_str(), -1, NULL, 0, NULL, FALSE ); // 計算轉換後字串的長度。(包含字串結束符)
char *lpsz= new char[iLen];
WideCharToMultiByte( CP_OEMCP, NULL, what[i].str().c_str(), -1, lpsz, iLen, NULL, FALSE);
}
}
===================================
第二參考段:
k.m.Cao
v0.1
問題的提出:
Boost.Regex作為Boost對Regex的實踐,是C++開發中常用模式比對工具。但在這次使用過程中發現,它他對中文的支援並不好。當我們指定\w匹配時,包含“數”或“節”等字的字串就會出現匹配失敗的問題。
解決方案:
思路:把字元都轉換成寬字元,然後再匹配。
需要用到以下和寬字元有關的類:
1、wstring:
作為STL中和string相對應的類,專門用於處理寬字元串。方法和string都一樣,區別是value_type是wchar_t。wstring類的對象要賦值或串連的常量字串必須以L開頭標示為寬字元。
2、wregex:
和regex相對應,專門處理寬字元的Regex類。同樣可以使用regex_match()和regex_replace()等函數。regex_match()的結果需要放在wsmatch類的對象中。
字元和寬字元的相互轉換:
1、RTL的方法
//把字串轉換成寬字元串
setlocale( LC_CTYPE, "" ); // 很重要,沒有這一句,轉換會失敗。
int iWLen= mbstowcs( NULL, sToMatch.c_str(), sToMatch.length() ); // 計算轉換後寬字元串的長度。(不包含字串結束符)
wchar_t *lpwsz= new wchar_t[iWLen+1];
int i= mbstowcs( lpwsz, sToMatch.c_str(), sToMatch.length() ); // 轉換。(轉換後的字串有結束符)
wstring wsToMatch(lpwsz);
delete []lpwsz;
//把寬字元串轉換成字串,輸出使用
int iLen= wcstombs( NULL, wsm[1].str().c_str(), 0 ); // 計算轉換後字串的長度。(不包含字串結束符)
char *lpsz= new char[iLen+1];
int i= wcstombs( lpsz, wsm[1].str().c_str(), iLen ); // 轉換。(沒有結束符)
lpsz[iLen] = '\0';
string sToMatch(lpsz);
delete []lpsz;
2、Win32 SDK的方法
//把字串轉換成寬字元串
int iWLen= MultiByteToWideChar( CP_ACP, 0, sToMatch.c_str(), sToMatch.size(), 0, 0 ); // 計算轉換後寬字元串的長度。(不包含字串結束符)
wchar_t *lpwsz= new wchar_t [iWLen+1];
MultiByteToWideChar( CP_ACP, 0, sToMatch.c_str(), sToMatch.size(), lpwsz, iWLen ); // 正式轉換。
wsz[iWLen] = L'\0';
//把寬字元串轉換成字串,輸出使用
int iLen= WideCharToMultiByte( CP_ACP, NULL, wsResult.c_str(), -1, NULL, 0, NULL, FALSE ); // 計算轉換後字串的長度。(包含字串結束符)
char *lpsz= new char[iLen];
WideCharToMultiByte( CP_OEMCP, NULL, wsResult.c_str(), -1, lpsz, iLen, NULL, FALSE); // 正式轉換。
sResult.assign( lpsz, iLen-1 ); // 對string對象進行賦值。
樣本:
通過以下程式我們可以看到,對字串做\w匹配時,某些字會引起匹配失敗。通過把字串轉換成寬字元串嘗試解決這個問題。
#include <iostream>
using std::cout;
using std::endl;
#include <string>
using std::string;
using std::wstring;
#include <locale>
#include "boost\tr1\regex.hpp"
using namespace boost;
void MatchWords(string sToMatch)
{
regex rg("(\\w*)");
smatch sm;
regex_match( sToMatch, sm, rg );
cout << "匹配結果:" << sm[1].str() << endl;
}
void MatchWords(wstring wsToMatch)
{
wregex wrg(L"(\\w*)");
wsmatch wsm;
regex_match( wsToMatch, wsm, wrg );
int iLen= wcstombs( NULL, wsm[1].str().c_str(), 0 );
char *lpsz= new char[iLen+1];
int i= wcstombs( lpsz, wsm[1].str().c_str(), iLen );
lpsz[iLen] = '\0';
string sToMatch(lpsz);
delete []lpsz;
cout << "匹配結果:" << sToMatch << endl;
}
void main()
{
string sToMatch("數超限");
MatchWords( sToMatch );
sToMatch = "節點數目超限";
MatchWords( sToMatch );
setlocale( LC_CTYPE, "" );
int iWLen= mbstowcs( NULL, sToMatch.c_str(), sToMatch.length() );
wchar_t *lpwsz= new wchar_t[iWLen+1];
int i= mbstowcs( lpwsz, sToMatch.c_str(), sToMatch.length() );
wstring wsToMatch(lpwsz);
delete []lpwsz;
MatchWords( wsToMatch );
}
編譯執行程式後輸出:
匹配結果:數超限
匹配結果:
匹配結果:節點數目超限
第一行顯示“數超限”匹配成功。但第二行“節點數超限”沒有匹配到任何字元。只有轉換成寬字元串之後才能夠對“節點數超限”成功進行\w匹配。
本文來自CSDN部落格,轉載請標明出處:http://blog.csdn.net/skyremember/archive/2008/09/17/2941295.aspx