C++ 0x regex实现关键OR敏感字过滤

孤街醉人 提交于 2020-04-24 06:53:30

给出一篇文档,要求把里面的“性爱”都替换成“革命”,“性”都替换成“道德”。删除里面所有的“A片”。在所有的“苍井空来了”前面加上“(表相信)”,后面加上“(这是谣言)”。
要求:考虑周密,设想各种会出现的奇怪情况。因为---我们是国家安全局!宁可错杀一万,不能漏过一个。

首先考虑到肯定要涉及到各种宽字符的过滤故肯定要使用unicode来处理,我们的函数接口不妨设为
static void filter_unicode(std::wstring& ws_text);
然后题目中的三个需求其实都可以概括成将子串A替换为B的操作,故如果没有特殊要求直接三句boost::replace_all即可搞定。
现在来考虑最后的要求中提到的“奇怪情况”,那就需要我们“设身处地”地来思考啦。我们平时想输入敏感字时会用到什么方法呢,无外乎会插入空格或者各种异常标点符号之类,这里会想到用正则表达式岂不正好?符合我们需求的相应函数为std::regex_replace,boost的regex库也有对应函数,这里就用c++ 0x原生的了。
我们的需求是从关键字首字符开始匹配,中间如果只间隔标点符号,且符号结束后的第一个字符与关键字尾字符相匹配,则匹配成功,将此串替换为预设的目标串。要注意到的是c++ 0x和boost中的regex库并不支持unicode库定义,比如\p{L} 之类的定义,不然我们可以简单的使用\p{Punct}来完成这个需求了。详细的符号定义可以参考http://en.wikipedia.org/wiki/Regular_expression我们这里使用到的是\W,可以排除所有字母(包含中文等)和下划线,于是正则表达式可以写成
性\W*爱
再将下划线补充上即可完成需求
性[\W|_]*爱

最终完成的代码如下:

#include <regex> 
#include <locale> 
#include <string> 
#include <iostream> 
 
static wchar_t* rules[][2] = 
{ 
    {L"性(\\W|_)*爱", L"革命"}, 
    {L"性", L"道德"}, 
    {L"A(\\W|_)*片", L""}, 
    {L"苍(\\W|_)*井(\\W|_)*空(\\W|_)*来(\\W|_)*了", L"(表相信)苍井空来了(这是谣言)"}, 
}; 
static const int RULE_COUNT = sizeof(rules) / sizeof(rules[0]); 
 
static void filter_unicode(std::wstring& ws_text) 
{ 
    for (int i = 0; i < RULE_COUNT; ++i)
        ws_text = std::regex_replace(ws_text, std::wregex(rules[i][0]), std::wstring(rules[i][1])); 
 
} 
static void test1() 
{ 
    std::locale::global(std::locale("chs")); 
    std::wstring ws_text = L"性不爱性a爱性 \t\r\n`~!@#$%^&*()-_=+[{]}\\|;:'\",<.>/?·!@#¥%……()——【】{}、,。《》?爱性6A片333苍井空来了555"; 
    std::wcout << "before:" << ws_text << std::endl; 
 
    filter_unicode(ws_text); 
 
    std::wcout << std::endl << L"---------------------------" << std::endl; 
    std::wcout << "after:" << ws_text << std::endl; 
}

运行结果如下:

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!