解决Boost.Regex对中文支持不好的问题

  解决Boost.Regex对中文支持不好的问题收藏

新一篇: 内容折叠 | 旧一篇: 具有历史意义的一脚就此踩下了!

<script>function StorePage(){d=document;t=d.selection?(d.selection.type!='None'?d.selection.createRange().text:''):(d.getSelection?d.getSelection():'');void(keyit=window.open('http://www.365key.com/storeit.aspx?t='+escape(d.title)+'&u='+escape(d.location.href)+'&c='+escape(t),'keyit','scrollbars=no,width=475,height=575,left=75,top=20,status=no,resizable=yes'));keyit.focus();}</script>

解决Boost.Regex对中文支持不好的问题

k.m.Cao
v0.1


问题的提出:


Boost.Regex作为Boost对正则表达式的实践,是C++开发中常用模式匹配工具。但在这次使用过程中发现,它他对中文的支持并不好。当我们指定/w匹配时,包含“数”或“节”等字的字符串就会出现匹配失败的问题。

解决方案:


思路:把字符都转换成宽字符,然后再匹配。
需要用到以下和宽字符有关的类:
1、wstring:
作为STL中和string相对应的类,专门用于处理宽字符串。方法和string都一样,区别是value_type是wchar_t。wstring类的对象要赋值或连接的常量字符串必须以L开头标示为宽字符。
2、wregex:
和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匹配。



boost::Regex正则表达式怎么匹配中文啊? [已结贴,结贴人:zkezhon]
进入用户个人空间
加为好友
发送私信
在线聊天
  • zkezhon
  • 等级:
  • 可用分等级:
  • 总技术专家分:
  • 总技术专家分排名:
  • 揭帖率:
发表于:2008-05-13 18:38:30 楼主
网上查的都说是[/u4e00-/u9fa5] ,但是用起来根本不灵,到底是为何呢?
30  修改 删除 举报 引用 回复
style="height: 0pt;" id="Topic_Zone" marginwidth="0" marginheight="0" src="http://topic.csdn.net/u/AD/Topic_Zone.aspx" frameborder="0" height="0" scrolling="no" width="100%">
进入用户个人空间
加为好友
发送私信
在线聊天
  • cyblueboy83
  • 等级:
  • 可用分等级:
  • 总技术专家分:
  • 总技术专家分排名:
发表于:2008-05-13 18:49:391楼 得分:0
mark
修改 删除 举报 引用 回复
进入用户个人空间
加为好友
发送私信
在线聊天
  • mscf
  • 等级:
  • 可用分等级:
  • 总技术专家分:
  • 总技术专家分排名:
发表于:2008-05-13 20:10:132楼 得分:3
就楼主说的方法比较常见,在脚本中曾经用过直接使用中文的方法
修改 删除 举报 引用 回复
进入用户个人空间
加为好友
发送私信
在线聊天
  • zkezhon
  • 等级:
  • 可用分等级:
  • 总技术专家分:
  • 总技术专家分排名:
发表于:2008-05-13 20:31:343楼 得分:0
引用 2 楼 mscf 的回复:
就楼主说的方法比较常见,在脚本中曾经用过直接使用中文的方法
我在问该怎么匹配!!!!
修改 删除 举报 引用 回复
进入用户个人空间
加为好友
发送私信
在线聊天
  • yuzl32
  • 等级:
  • 可用分等级:
  • 总技术专家分:
  • 总技术专家分排名:
发表于:2008-05-13 23:44:544楼 得分:27
http://blog.csdn.net/K_M_Cao/archive/2007/11/07/1871065.aspx
修改 删除 举报 引用 回复
进入用户个人空间
加为好友
发送私信
在线聊天
  • zkezhon
  • 等级:
  • 可用分等级:
  • 总技术专家分:
  • 总技术专家分排名:
发表于:2008-05-14 09:53:385楼 得分:0
引用 4 楼 yuzl32 的回复:
http://blog.csdn.net/K_M_Cao/archive/2007/11/07/1871065.aspx
C/C++ code
            
            
void CDlgProductInfo::OnEnKillfocusEditNamecn() { // TODO: 在此添加控件通知处理程序代码 std::wstring regstr = L " [//u4e00-//u9fa5]+ " ; boost::wregex expression(regstr); boost::wcmatch result; CString value; ((CEdit * )GetDlgItem(IDC_EDIT_NAMECN)) -> GetWindowText(value); if ( ! boost::regex_match((LPCTSTR)value,result,expression)) { // m_TipNAMECN.UpdateTipText(_T("您的输入不合法!"),GetDlgItem(IDC_EDIT_NAMECN)); MessageBox(_T( " 您的输入不合法! " )); } }
为什么这样改正之后,只要是英文字幕都可以匹配,只要是中文或者标点符号都不可以匹配,这是为什么?




求2个正则: 1:网址URL正则表达式 要求不能输入“http://www.sohu”这样的URL http://([/w-]+/.)+[/w-]+(/[/w-/.?%=]*)?这样是不能实现的,在网上找了好多都不正确. 2:比较两个texbox1和texbox2(texbox中可以混合输入中文、英文、数字),要求用正则判断texbox2中的文字是否包含在texbox1的文字中,举例: texbox1中:“在要给分的回复后的文本框中填写分数” texbox2中:“给分的回复” 上面两个TEXBOX中输入的为正确的内容!! 呵呵!!晕了!!晕了!!晕了!! 不过谢谢 "lxcnn(过客) "^http(s)?://(?!([/w-]+/.[/w-]+$))([/w-]+/.)+[/w-]+(/[/w- ./?%&=]*)?$符合我的要求了!! http://topic.csdn.net/u/20070307/14/87e6b878-800e-4a88-830e-7d0eeeaba891.html?1498822639
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值