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; 

運行結果如下:

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