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

给出一篇文档,要求把里面的“性爱”都替换成“革命”,“性”都替换成“道德”。删除里面所有的“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|_]*爱
最终完成的代码如下:
  1. #include <regex> 
  2. #include <locale> 
  3. #include <string> 
  4. #include <iostream> 
  5.  
  6. static wchar_t* rules[][2] = 
  7.     {L"性(\\W|_)*爱", L"革命"}, 
  8.     {L"性", L"道德"}, 
  9.     {L"A(\\W|_)*片", L""}, 
  10.     {L"苍(\\W|_)*井(\\W|_)*空(\\W|_)*来(\\W|_)*了", L"(表相信)苍井空来了(这是谣言)"}, 
  11. }; 
  12. static const int RULE_COUNT = sizeof(rules) / sizeof(rules[0]); 
  13.  
  14. static void filter_unicode(std::wstring& ws_text) 
  15.     for (int i = 0; i < RULE_COUNT; ++i)
  16.         ws_text = std::regex_replace(ws_text, std::wregex(rules[i][0]), std::wstring(rules[i][1])); 
  17.  
  18. static void test1() 
  19.     std::locale::global(std::locale("chs")); 
  20.     std::wstring ws_text = L"性不爱性a爱性 \t\r\n`~!@#$%^&*()-_=+[{]}\\|;:'\",<.>/?·!@#¥%……()——【】{}、,。《》?爱性6A片333苍井空来了555"
  21.     std::wcout << "before:" << ws_text << std::endl; 
  22.  
  23.     filter_unicode(ws_text); 
  24.  
  25.     std::wcout << std::endl << L"---------------------------" << std::endl; 
  26.     std::wcout << "after:" << ws_text << std::endl; 

运行结果如下:

 
 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章