словарный фильтрпредставляет собой фильтр, который выполняет замену текста следующим образом. Он содержит набор пар строк, первые компоненты которых являются словами, а вторые компоненты представляют собой заменяющий текст — Я назову такую коллекцию словареми буду называть пары, которые она содержит, определениями.. Когда словарный фильтр встречает слово, которое появляется как первый компонент определения, он пересылает заменяющий текст вместо исходного слова. Другие слова, белое пространство и пунктуация пересылаются без изменений.
Основной алгоритм выглядит следующим образом: Вы исследуете символы по одному за раз, добавляя их к строке, которую я назовутекущим словом. Когда вы сталкиваетесь с неалфавитным персонажем, вы обращаетесь к словарю, чтобы определить, является ли текущее слово первым компонентом определения. Если это так, вы пересылаете текст замены, за которым следует неалфавитный символ. В противном случае вы передаёте текущее слово, за которым следует неалфавитный персонаж. Когда достигается конец потока, вы снова консультируетесь со словарем и пересылаете либо сокращенное слово, либо его замену.
Функция члена<add>преобразует<key>в нижний регистр и добавляет пару<key>,<value>в словарь. Функция члена<replace>ищет определение, первый компонент которого равен результату преобразования<key>в нижний регистр. Если он находит такое определение, он присваивает заменяющий текст<key>, корректируя случай первого символа в соответствии с случаем первого символа<key>. В противном случае он ничего не делает.
dictionary_stdio_filter
Вы можете выразить словарный фильтр как<stdio_filter>следующим образом:
#include<cstdio>// EOF#include<iostream>// cin, cout#include<boost/iostreams/filter/stdio.hpp>namespace boost { namespace iostreams { namespace example {
class dictionary_stdio_filter : public stdio_filter {
public:
dictionary_stdio_filter(dictionary& d) : dictionary_(d) { }
private:
void do_filter()
{
usingnamespace std;
while (true) {
int c = std::cin.get();
if (c == EOF || !std::isalpha((unsignedchar) c)) {
dictionary_.replace(current_word_);
cout.write( current_word_.data(),
static_cast<streamsize>(current_word_.size()) );
current_word_.erase();
if (c == EOF)
break;
cout.put(c);
} else {
current_word_ += c;
}
}
}
dictionary& dictionary_;
std::string current_word_;
};
} } } // End namespace boost::iostreams:example
Реализация<do_filter>просто зацикливается, считывая символы от<std::cin>и<appending>до переменной члена<current_word_>, пока не встречается неалфавитный символ или указание конца потока. Когда это происходит, он использует свой словарь, хранящийся в переменной члена<dictionary_>, чтобы заменить текущее слово, если это необходимо. Наконец, он пишет текущее слово, за которым следует неалфавитный характер, если таковой имеется,<std::cout>.
dictionary_input_filter
Вы можете выразить словарный фильтр какInputFilterследующим образом:
template<typename Source>
int get(Source& src)
{
// Handle unfinished business.if (off_ != std::string::npos && off_ < current_word_.size())
return current_word_[off_++];
if (off_ == current_word_.size()) {
current_word_.erase();
off_ = std::string::npos;
}
if (eof_)
returnEOF;
// Compute curent word.while (true) {
int c;
if ((c = iostreams::get(src)) == WOULD_BLOCK)
return WOULD_BLOCK;
if (c == EOF || !std::isalpha((unsignedchar) c)) {
dictionary_.replace(current_word_);
off_ = 0;
if (c == EOF)
eof_ = true;
else
current_word_ += c;
break;
} else {
current_word_ += c;
}
}
return this->get(src); // Note: current_word_ is not empty.
}
Вы сначала проверяете, есть ли какие-либо символы, которые остаются от предыдущего призыва<get>. Если это так, вы обновите некоторую информацию о хранении книг и вернете первого такого персонажа.
<while>петля очень похожа на петлю<dictionary_stdio_filter::do_filter>: она читает символы изИсточник<src>, добавляя их к<current_word_>до тех пор, пока не будет встречен неалфавитный символ<EOF>или<WOULD_BLOCK>. Значение<WOULD_BLOCK>передается абоненту. В остальных случаях для определения соответствующего заменяющего текста проводится консультация со словарем.
Наконец,<get>называется рекурсивно, чтобы вернуть первый характер текущего слова.
Как обычно, функция<close>сбрасывает состояние фильтра:
Эта функция пытается записать<current_word_>, начиная с смещения<off_>, на предоставленныйSink. Если вся последовательность успешно записана,<current_word_>очищается и функция возвращается<true>. В противном случае переменная<off_>элемента обновляется, чтобы указать на первый неписаный символ, и функция выходит из строя.
С помощью<write_current_word>вы можете реализовать<put>следующим образом:
template<typename Sink>
bool put(Sink& dest, int c)
{
if (off_ != std::string::npos && !write_current_word(dest))
returnfalse;
if (!std::isalpha((unsignedchar) c)) {
dictionary_.replace(current_word_);
off_ = 0;
}
current_word_ += c;
returntrue;
}
Как и в реализации<dictionary_input_filter::get>, сначала проверьте, есть ли какие-либо символы из предыдущего призыва<put>, которые еще предстоит написать. Если это так, вы пытаетесь написать эти символы, используя<write_current_word>. Если вы преуспеете, вы затем исследуете данный персонаж<c>. Если это неалфавитный символ, вы обратитесь к словарю, чтобы определить соответствующий заменяющий текст. В любом случае, вы добавляете<c>к<current_word_>и возвращаете<true>.
Функция<close>имеет больше работы, чем просто сброс состояния фильтра. Если последний символ нефильтрованной последовательности не был алфавитным, содержимое current_word_ еще не было написано:
template<typename Sink>
void close(Sink& dest)
{
// Reset current_word_ and off_, saving old values.
std::string current_word;
std::string::size_type off = 0;
current_word.swap(current_word_);
std::swap(off, off_);
// Write remaining characters to dest.if (off == std::string::npos) {
dictionary_.replace(current_word);
off = 0;
}
if (!current_word.empty())
iostreams::write(
dest,
current_word.data() + off,
static_cast<std::streamsize>(current_word.size() - off)
);
}
Обратите внимание, что вы можете предположить, что аргумент шаблона - этоБлокировкаПотоп, и что вы должны сбросить значения<current_word_>и<off_>, прежде чем звонить<write>, в случае, если<write>бросает исключение.
Статья Tutorial раздела может быть полезна для разработчиков на c++ и boost.
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.