给出一篇文档,要求把里面的“×××”都替换成“革命”,“性”都替换成“道德”。删除里面所有的“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;
- }
运行结果如下:
转载于:https://blog.51cto.com/magicyang/1107911