Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
Разработка программного обеспечения

Tutorial

Boost , ,

Tutorial

2.2.6. Dictionary Filters

словарный фильтрпредставляет собой фильтр, который выполняет замену текста следующим образом. Он содержит набор пар строк, первые компоненты которых являются словами, а вторые компоненты представляют собой заменяющий текст — Я назову такую коллекцию словареми буду называть пары, которые она содержит, определениями.. Когда словарный фильтр встречает слово, которое появляется как первый компонент определения, он пересылает заменяющий текст вместо исходного слова. Другие слова, белое пространство и пунктуация пересылаются без изменений.

Основной алгоритм выглядит следующим образом: Вы исследуете символы по одному за раз, добавляя их к строке, которую я назовутекущим словом. Когда вы сталкиваетесь с неалфавитным персонажем, вы обращаетесь к словарю, чтобы определить, является ли текущее слово первым компонентом определения. Если это так, вы пересылаете текст замены, за которым следует неалфавитный символ. В противном случае вы передаёте текущее слово, за которым следует неалфавитный персонаж. Когда достигается конец потока, вы снова консультируетесь со словарем и пересылаете либо сокращенное слово, либо его замену.

В следующих разделах я выражаю этот алгоритм как.<stdio_filter>,InputFilterиOutputFilter. Исходный код можно найти в заголовке<<libs/iostreams/example/dictionary_filter.hpp>>.

dictionary

Вы можете представить словарь, используя следующий класс:

#include <map>
#include <string>
namespace boost { namespace iostreams { namespace example {
class dictionary {
public:
    void add(std::string key, const std::string& value);
    void replace(std::string& key);
    /* ... */
};
} } } // End namespace boost::iostreams:example

Функция члена<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()
    {
        using namespace std;
        while (true) {
            int c = std::cin.get();
            if (c == EOF || !std::isalpha((unsigned char) 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следующим образом:

#include <boost/iostreams/char_traits.hpp> // EOF, WOULD_BLOCK
#include <boost/iostreams/concepts.hpp>    // input_filter
#include <boost/iostreams/operations.hpp>  // get
namespace boost { namespace iostreams { namespace example {
class dictionary_input_filter : public input_filter {
public:
    dictionary_input_filter(dictionary& d)
        : dictionary_(d), off_(std::string::npos), eof_(false)
        { }
    template<typename Source>
    int get(Source& src);
    template<typename Source>
    void close(Source&);
private:
    dictionary&             dictionary_;
    std::string             current_word_;
    std::string::size_type  off_;
    bool                    eof_;
};
} } } // End namespace boost::iostreams:example

Функция<get>реализована следующим образом:

    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_)
            return EOF;
        // Compute curent word.
        while (true) {
            int c;
            if ((c = iostreams::get(src)) == WOULD_BLOCK)
                return WOULD_BLOCK;
            if (c == EOF || !std::isalpha((unsigned char) 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>сбрасывает состояние фильтра:

    template<typename Source>
    void close(Source&)
    {
        current_word_.erase();
        off_ = std::string::npos;
        eof_ = false;
    }

dictionary_output_filter

Вы можете выразить словарный фильтр какOutputFilterследующим образом:

#include <algorithm>                      // swap
#include <boost/iostreams/concepts.hpp>   // output_filter
#include <boost/iostreams/operations.hpp> // write
namespace boost { namespace iostreams { namespace example {
class dictionary_output_filter : public output_filter {
public:
    typedef std::map<std::string, std::string> map_type;
    dictionary_output_filter(dictionary& d)
        : dictionary_(d), off_(std::string::npos)
        { }
    template<typename Sink>
    bool put(Sink& dest, int c);
    template<typename Sink>
    void close(Sink& dest);
private:
    template<typename Sink>
    bool write_current_word(Sink& dest);
    dictionary&             dictionary_;
    std::string             current_word_;
    std::string::size_type  off_;
};
} } } // End namespace boost::iostreams:example

Давайте сначала рассмотрим функцию помощника<write_current_word>:

    template<typename Sink>
    bool write_current_word(Sink& dest)
    {
        using namespace std;
        streamsize amt = static_cast<streamsize>(current_word_.size() - off_);
        streamsize result =
            iostreams::write(dest, current_word_.data() + off_, amt);
        if (result == amt) {
            current_word_.erase();
            off_ = string::npos;
            return true;
        } else {
            off_ += static_cast<string::size_type>(result);
            return false;
        }
    }

Эта функция пытается записать<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))
            return false;
        if (!std::isalpha((unsigned char) c)) {
            dictionary_.replace(current_word_);
            off_ = 0;
        }
        current_word_ += c;
        return true;
    }

Как и в реализации<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.




Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.



:: Главная :: ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-08-30 11:47:00
2025-07-05 04:59:58/0.0048048496246338/0