C++ 解决Boost正则中文支持欠佳
之前,项目中需要解析TXT文本格式做字符分割,以空格和制表符作为分隔符分割字符串…但是文档中文本格式不规范,相当多的地方采取四个空格来替代制表符,导致分割出来的子串里面存在相当多的空白字符串…
最初的处理方案是遍历分解出来的子串,当子串为空则剔除掉…个人认为这并非长久之计…
于是思前想后,决定使用正则表达式,找出所有的连续空白字符串,然后使用一个空格替代连续的空白字符串,这样还能顺便整理不规范文档…
最开始的时候,使用boost::regex库做处理,但是很快遇到问题…boost对于国际化的支持真的不是一般的差啊…
代码如下:
void Test()
{
std::string s = _T("一 二 三 t四t 五tt六t t七t t八");
boost::regex expr("\s+");
s= boost::regex_replace(s,expr," ");
cout < < s << endl;
}
// 结果为:
// ???
这个结果也太坑爹了吧…
传进去的中文最终就剩几个问号了…
于是在网上搜索了大半天,总算找到了一个解决方案,将char全部转换成wchar…
代码如下:
//解决boost::regex中文乱码问题
std::string CTextFileDate::ReplaceString_boost(std::string strLine)
{
// 先把string转换成wstring
std::wstring wstrLine = s2ws(strLine);
// 去掉连续的空白字符
boost::wregex exp(_T(L"s+"));
wstrLine = boost::regex_replace(wstrLine, exp, _T(L" "));
// 将wstring转换成string
return ws2s(wstrLine);
}
//Converting a WChar string to a Ansi string
std::string CTextFileDate::WChar2Ansi(LPCWSTR pwszSrc)
{
// 获取字符串长度
int nLen = WideCharToMultiByte(CP_ACP, 0, pwszSrc, -1, NULL, 0, NULL, NULL);
if (nLen<= 0)
return std::string("");
char* pszDst = new char[nLen];
if (NULL == pszDst)
return std::string("");
WideCharToMultiByte(CP_ACP, 0, pwszSrc, -1, pszDst, nLen, NULL, NULL);
pszDst[nLen -1] = 0;
std::string strTemp(pszDst);
delete [] pszDst;
return strTemp;
}
std::string CTextFileDate::ws2s(std::wstring& inputws)
{
return WChar2Ansi(inputws.c_str());
}
//Converting a Ansi string to WChar string
std::wstring CTextFileDate::Ansi2WChar(LPCSTR pszSrc, int nLen)
{
int nSize = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)pszSrc, nLen, 0, 0);
if(nSize <= 0)
return NULL;
WCHAR *pwszDst = new WCHAR[nSize+1];
if( NULL == pwszDst) return NULL;
MultiByteToWideChar(CP_ACP, 0,(LPCSTR)pszSrc, nLen, pwszDst, nSize);
pwszDst[nSize] = 0;
if( pwszDst[0] == 0xFEFF) // skip Oxfeff
for(int i = 0; i < nSize; i ++)
pwszDst[i] = pwszDst[i+1];
std::wstring wcharString(pwszDst);
delete pwszDst;
return wcharString;
}
std::wstring CTextFileDate::s2ws(const std::string& s)
{
return Ansi2WChar(s.c_str(),s.size());
}
使用此方法,即可将待转换的字符串转为Wchar的形式,用于boost的解析…然后解析完成后,再转换成char输出…如果不考虑性能,这倒是个完美的结局方案…哈哈…
如果考虑到性能,这种方法已然很坑爹…继续寻觅,终于找到了一个名为deelx的库…开源免费用于正则表达式…
完全采用模版的方式编写…只有一个头文件,不像boost,用个正则表达式还要包一个lib…但是该库作者承认,效率比boost慢2-5倍…
不过我觉得deelx最好的地方是支持cstring…boost因为使用了base_string,所以只支持std::string…对于VC编程的我,我最讨厌string和cstring互转了…哈哈…