Closed alexey-malov closed 8 years ago
строки передавать по константной ссылке
TCHAR не используй
inFile.close();
Файл открытый только для чтения можно явно не закрывать перед выходом из функции, т.к. деструктор это сделает автоматически.
vector<string> badWords;
vector<string> values = GetExpression(contentOfInFile);
if (values.size())
{
badWords.assign(values.begin(), values.end());
}
inFile.close();
return badWords;
нет необходимости держать 2 вектора стоп-слов
vector<string> GetExpression(string line)
{
boost::regex expression("(\\w+)");
vector<string> values;
if (!boost::regex_split(back_inserter(values), line, expression))
{
return{};
}
return values;
}
regex_split вернет 0, только если ничего не вставит в values. Нет смысла в проверке Название функции не соответствует тому, что она делает
dictionary.txt содержит слова, мало пригодные для практического применения
Требование задания
Программа из каждой вводимой из стандартного потока ввода строки должна удалять присутствующие в ней недопустимые слова и выводить обработанный результат в стандартный поток вывода.
строк может быть несколько
Программа удаляет слова, не входящие в список стоп-слов dic1.txt
Input string: This is a fucking shit! Output string: This fucking !
Воспроизвести проблему в тесте
for_each(badWords.begin(), badWords.end(), [&inputString, &values](string value)
{
if (find(values.begin(), values.end(), value) != values.end())
{
inputString = DeleteSubstring(inputString, value);
}
});
for_each появился еще во времена C++'98, сейчас в использовании этого алгоритма необходимости практически нет, т.к. есть range-based for
использовать for_each больше оправдано, когда действие, совершаемое над элементами конфигурируется извне в runtime-е
string Filter(const TCHAR *fileName, string inputString)
{
auto badWords = ReadBadWordsFromFile(fileName);
return FilterString(badWords, inputString);
}
получается, что для каждой фильтруемой строки придется считывать файл стоп-слов заново, в то время как этот список постоянный для всех вводимых пользователем строк
k=0,6
Проблема с пересборкой не устранена
После получения символа конца файла ожидать какой-либо ввод не стоит. Если перенаправить файл в stdin, то после окончания файла символы поступать не будут.
Трудоемкость алгоритма: O(N^2 * M) - N - размер строки, M - количество стоп-слов в базе Можно сделать O(N*logM) (если использовать set для хранени стоп-слов), либо вообще близко к O(N) (если использовать unordered_set для хранения стоп-слов) Можно искать за логарифмическое время и в отсортированном векторе. Есть (алгоритм binary_search http://www.cplusplus.com/reference/algorithm/binary_search/)
N^2 сложность образовалась из-за
string DeleteSubstring(string& processStr, const string& delSubStr)
{
int pos = processStr.find(delSubStr);
while (pos != string::npos)
{
bool isWordOfBegStr = pos ? !isalpha((unsigned char)processStr[pos - 1]) : true;
if (isWordOfBegStr && !isalpha((unsigned char)processStr[pos + delSubStr.length()]))
{
processStr.erase(pos, delSubStr.length());
}
pos = processStr.find(delSubStr);
}
return processStr;
}
Операция erase имеет линейную сложность. при этом она количество раз, линейно зависящее от длины строки.
Вводить строку exit для окончания не обязательно, т.к. ввод прекратится при встрече EOF
string FilterString(const vector<string>& badWords,const string& inputString)
{
vector<string> values = ParseWordsToVector(inputString);
Переменная values не используется
линейная зависимость от количества стоп-слов сохранилась. вот с этим словариком так и не удалось дождаться окончания обработки 1мегабайтного файла dic1.txt
catch (exception e)
{
cout << e.what();
}
Исключения следует ловить по [константной] ссылке, чтобы избежать срезки (http://rsdn.ru/forum/cpp/917744.1)
В тестах должны использовать строки, которые содержат слова реального языка, а не случайная последовательность символов.