Добавление регулярного выражения в систему цензуры для C++

Я уже некоторое время пытаюсь создать систему цензуры для эмулятора WoW под названием TrinityCore. Что я в основном делаю, так это заполняю таблицу базы данных (chat_filter) «плохими словами», заполняю ими вектор при запуске, и в каждой строке чата, созданной игроком, она проверяется на соответствие содержимому моего вектора. Если оно содержит нецензурное слово, оно заменяется на ** (в то время как количество звездочек * также берется из столбца таблицы базы данных (todo)) и игрок получает наказание (приглушенное или около того).

Теперь у меня возникли проблемы с тем, как сделать правильный фильтр. Прямо сейчас вам нужно будет добавить все возможные комбинации слов, которые вы можете придумать, например, «жопа». также следует читать как «жопа», и я понятия не имею, как это сделать!

Вот важная часть текущего кода, я пропустил извлечение БД, так как оно в любом случае не имело бы никакого смысла (и это сделало бы его менее понятным, поскольку он находится в другом файле).

char* msg3 = strdup(msg.c_str());
char* words = strtok(msg3, " ,.-()&^%$#@!{}'<>/?|\\=+-_1234567890"); // This splits the sentence in seperated words and removes the symbols
ObjectMgr::ChatFilterContainer const& censoredWords = sObjectMgr->GetCensoredWords();

while (words != NULL && !censoredWords.empty())
{
    for (uint32 i = 0; i < censoredWords.size(); ++i)
    {  
        if (!stricmp(censoredWords[i].c_str(), words))
        {
            sLog->outString("%s", words);
            //msg.replace(msg.begin(), msg.end(), msg.c_str(), "***");
            msg.replace(msg.begin(), msg.end(), censoredWords[i].c_str(), '*');
        }
        //msg.replace(msg.begin(), msg.end(), censoredWords[i].c_str(), /*replacement*/ "***");
        //msg.replace(msg.find(censoredWords[i].c_str()), censoredWords.size(), 
    }

    words = strtok(NULL, " ,.-()&^%$#@!{}'<>/?|\=+-_1234567890");
}

Заранее спасибо,

Джаспер

P.S. GetCensoredWords возвращает вектор.

P.S.S. 'msg' - это std::string - это ФАКТИЧЕСКОЕ сообщение, отправленное игроком.


person user1422494    schedule 28.05.2012    source источник
comment
Ну, для начала не используйте strtok, это неработающий API. Вы пропускаете строку, которую создаете с помощью strdup. После того, как вы разметите символы, как вы планируете определить, было ли введено ass как слово?   -  person Jonathan Wakely    schedule 29.05.2012
comment
У меня нет ответа, но предлагаю спрашивающему прочитать thedailywtf.com/Articles/The-Clbuttic -Ошибка-.aspx,   -  person Gort the Robot    schedule 29.05.2012


Ответы (1)


Я бы использовал std::string, а не char*, чтобы управление памятью было автоматическим. Это решило бы проблему утечки памяти в вашем примере кода. Boost.Algorithm предоставляет мощный boost::algorithm::split функция, которая намного лучше, чем strtok.

Невозможно сохранить все возможные перестановки подвергнутых цензуре слов, особенно если вы собираетесь перебирать весь набор слов для каждого ввода. Если вы хотите подвергнуть цензуре «fubar», вам придется хранить «Fubar», «FUbar», «FuBaR», «fub4r», «F.U.B.A.R», «f.u.b.a.r» и т. д. и т. д. и т. д.

Вместо этого вы можете сохранить каждое подвергнутое цензуре слово только один раз в нормализованной форме, например. "fubar", затем преобразуйте каждое введенное слово в нормализованную форму. Итак, если пользователь вводит «F-u-B-a-R», вы нормализуете его до «fubar», тогда вы можете выполнить простой поиск в наборе подвергнутых цензуре слов (который может использовать ассоциированный контейнер, поэтому поиск будет O (log n) или даже O (1) )

person Jonathan Wakely    schedule 28.05.2012