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

Numerics

Boost , ,

Numerics

Похожие наchlit,СтритЦифровые парсеры также являются примитивными. Численные парсеры размещаются на своем участке, чтобы придать этому важному строительному блоку лучшую фокусировку. Фреймворк включает в себя пару предварительно определенных объектов для разбора подписанных и неподписанных целых чисел и реальных чисел. Эти парсеры полностью параметричны. Большинство важных аспектов численного анализа могут быть точно скорректированы в соответствии с требованиями. Это включает в себя основание радикса, минимальное и максимальное количество допустимых цифр, показатель, фракцию и т.д. Политика контролирует поведение парсеров реальных чисел. Существуют некоторые предопределенные политики, охватывающие наиболее распространенные форматы реальных чисел, но при необходимости пользователь может предоставить свои собственные.

uint_parser

Этот класс является самым простым среди членов пакета цифр.uint_parserможет разбирать неподписанные целые числа произвольной длины и размера. Парсерuint_parserможет использоваться для разбора обычных примитивных целых чисел C/C++ или даже пользовательских скалярных чисел, таких как бигинты (неограниченные точные целые числа). Как и большинство классов в Духе,uint_parserявляется классом шаблонов. Шаблонные параметры тонко настраивают его поведение. uint_parser настолько гибкий, что другие числовые парсеры реализуются с использованием его в качестве основы.

    template <
        typename T = unsigned,
        int Radix = 10,
        unsigned MinDigits = 1,
        int MaxDigits = -1>
    struct uint_parser { /*...*/ };
uint_parser template parameters
T The numeric base type of the numeric parser. Defaults to unsigned
Radix The radix base. This can be either 2: binary, 8: octal, 10: decimal and 16: hexadecimal. Defaults to 10; decimal
MinDigits The minimum number of digits allowable
MaxDigits The maximum number of digits allowable. If this is -1, then the maximum limit becomes unbounded

Predefined uint_parsers
bin_p uint_parser<unsigned, 2, 1, -1> const
oct_p uint_parser<unsigned, 8, 1, -1> const
uint_p uint_parser<unsigned, 10, 1, -1> const
hex_p uint_parser<unsigned, 16, 1, -1> const

Следующий пример показывает, как uint_parser может использоваться для разбора тысяч отдельных чисел. Пример может правильно разобрать числа, такие как 1 234 567 890.

    uint_parser<unsigned, 10, 1, 3> uint3_p;        //  1..3 digits
    uint_parser<unsigned, 10, 3, 3> uint3_3_p;      //  exactly 3 digits
    ts_num_p = (uint3_p >> *(',' >> uint3_3_p));    //  our thousand separated number parser

bin_p,oct_p,uint_pиhex_pявляются объектами генератора парсера, предназначенными для использования в выражениях. Вот пример правила, которое анализирует ограниченный список чисел Comma. (Мы видели этодо):

    list_of_numbers = real_p >> *(',' >> real_p);

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

int_parser

int_parserможет разбирать подписанные целые числа произвольной длины и размера. Это почти то же самое, чтоuint_parser. Единственное различие заключается в дополнительной задаче разбора знака'+'или'-', предшествующего числу. Интерфейс класса такой же, как у uint_parser.

A predefined int_parser
int_p int_parser<int, 10, 1, -1> const

real_parser

real_parserможет анализировать реальные числа произвольной длины и размера, ограниченные его параметрическим типомT.real_parser— класс шаблонов с 2 параметрами шаблона. Вот интерфейс шаблонаreal_parser:

    template<
        typename T = double,
        typename RealPoliciesT = ureal_parser_policies<T> >
    struct real_parser;

Первым параметром шаблона является его числовой базовый типТ. Этоудваивается.

Parsing special numeric types

Notice that the numeric base type T can be specified by the user. This means that we can use the numeric parsers to parse user defined numeric types such as fixed_point (fixed point reals) and bigint (unlimited precision integers).

Второй шаблонный параметр — класс, который группирует все политики и по умолчанию вureal_parser_policies. Политика контролирует поведение парсеров реальных чисел. Предоставляемые политики по умолчанию предназначены для разбора реальных номеров формы в стиле C/C++nnn.fff. Eeee, гдеnnnявляется всей числовой частью,fffявляется дробной частью,Eявляется'e'или'E'иeeeявляется экспонентой, необязательно предшествующей'-'или'+'. Это соответствует следующей грамматике, за исключением того, что простые целые числа без десятичной точки также принимаются по умолчанию.

    floatingliteral
        =   fractionalconstant >> !exponentpart
        |  +digit_p >> exponentpart
        ;
    fractionalconstant
        =  *digit_p >> '.' >> +digit_p
        |  +digit_p >> '.'
        ;
    exponentpart
        =   ('e' | 'E') >> !('+' | '-') >> +digit_p
        ;

Политики по умолчанию предоставляются для решения наиболее распространенных случаев (есть много способов представления и, следовательно, анализа реальных чисел). В большинстве случаев достаточно настройки по умолчаниюreal_parserи может использоваться прямо из коробки. На самом деле, существует четыреreal_parser, предварительно определенные для немедленного использования:

Predefined real_parsers
ureal_p real_parser<double, ureal_parser_policies<double> > const
real_p real_parser<double, real_parser_policies<double> > const
strict_ureal_p real_parser<double, strict_ureal_parser_policies<double> > const
strict_real_p real_parser<double, strict_real_parser_policies<double> > const

Мы уже виделиreal_p.ureal_pявляется его неподписанным вариантом.

Strict Reals

Целые числа считаются подмножеством реальных чисел, поэтомуreal_pиureal_pраспознают целые числа (без точки) как реальные числа.strict_real_pиstrict_ureal_pявляются эквивалентными парсерами, которыетребуют наличияточки для числа, которое считается успешным совпадением.

Advanced: real_parser policies

Политика парсера разбивает реальное число на 6 шагов:

1 parse_sign Parse the prefix sign
2 parse_n Parse the integer at the left of the decimal point
3 parse_dot Parse the decimal point
4 parse_frac_n Parse the fraction after the decimal point
5 parse_exp Parse the exponent prefix (e.g. 'e')
6 parse_exp_n Parse the actual exponent

И взаимодействие этих подпарсинговых задач далее контролируется этими 3 политиками:

1 allow_leading_dot Allow a leading dot to be present (".1" becomes equivalent to "0.1")
2 allow_trailing_dot Allow a trailing dot to be present ("1." becomes equivalent to "1.0")
3 expect_dot Require a dot to be present (disallows "1" to be equivalent to "1.0")

[править]Отсюда необходимо читать:Сканер,Углубленный ПарсериУглубленный Сканер

sign_parser and sign_p

Прежде чем мы перейдем к следующему шагу, мы включим небольшой парсер полезности, чтобы облегчить разбор'-'или'+'знака. Хотя легко написать одно:

    sign_p = (ch_p('+') | '-');

Невозможно извлечь фактический знак (положительный или отрицательный), не прибегая к семантическим действиям. У парсера sign_p есть атрибут bool, возвращенный абоненту через объект соответствия, который после парсинга устанавливается наистинное, если парсированный знак отрицательный. Этот атрибут определяет, был ли устранен отрицательный знак. Примеры:

    bool is_negative;
    r = sign_p[assign_a(is_negative)];

или просто...

    // directly extract the result from the match result's value
    bool is_negative = sign_p.parse(scan).value(); 

Парсер Sign_p ожидает, что прилагаемые семантические действия будут иметь подпись (см.Специализированные действиядля более подробной информации), совместимую с:

Подпись для функций:

    void func(bool is_negative);

Подпись для функторов:

    struct ftor
    {
        void operator()(bool is_negative) const;
    };

ureal_parser_policies

    template <typename T>
    struct ureal_parser_policies
    {
        typedef uint_parser<T, 10, 1, -1>   uint_parser_t;
        typedef int_parser<T, 10, 1, -1>    int_parser_t;
        static const bool allow_leading_dot  = true;
        static const bool allow_trailing_dot = true;
        static const bool expect_dot         = false;
template <typename ScannerT> static typename match_result<ScannerT, nil_t>::type parse_sign(ScannerT& scan) { return scan.no_match(); } template <typename ScannerT> static typename parser_result<uint_parser_t, ScannerT>::type parse_n(ScannerT& scan) { return uint_parser_t().parse(scan); } template <typename ScannerT> static typename parser_result<chlit<>, ScannerT>::type parse_dot(ScannerT& scan) { return ch_p('.').parse(scan); } template <typename ScannerT> static typename parser_result<uint_parser_t, ScannerT>::type parse_frac_n(ScannerT& scan) { return uint_parser_t().parse(scan); } template <typename ScannerT> static typename parser_result<chlit<>, ScannerT>::type parse_exp(ScannerT& scan) { return as_lower_d['e'].parse(scan); } template <typename ScannerT> static typename parser_result<int_parser_t, ScannerT>::type parse_exp_n(ScannerT& scan) { return int_parser_t().parse(scan); } };

По умолчанию ureal_parser_policies использует целочисленные числовые парсеры более низкого уровня для выполнения своей работы.

real_parser_policies

    template <typename T>
    struct real_parser_policies : public ureal_parser_policies<T>
    {
        template <typename ScannerT>
        static typename parser_result<sign_parser, ScannerT>::type
        parse_sign(ScannerT& scan)
        { return sign_p.parse(scan); }
    };

Обратите внимание, как политика real_parser_policies заменилаparse_signureal_parser_policies, из которых она подразделяется. По умолчанию real_parser_policies просто используетsign_pвместоscan.no_match()на шагеparse_sign.

strict_ureal_parser_policies and strict_real_parser_policies

    template <typename T>
    struct strict_ureal_parser_policies : public ureal_parser_policies<T>
    {
        static const bool expect_dot = true;
    };
    template <typename T>
    struct strict_real_parser_policies : public real_parser_policies<T>
    {
        static const bool expect_dot = true;
    };

Опять же, эта политика заменила просто политику, которую они хотели, отличную от их суперклассов.

Специализированныеполитики реального парсера могут повторно использовать некоторые из дефолтов при замене нескольких. Например, следующая политика парсера реального числа, которая анализирует тысячи отдельных чисел максимум с двумя десятичными числами и без экспоненты.

Полный исходный код можно посмотреть здесь.

    template <typename T>
    struct ts_real_parser_policies : public ureal_parser_policies<T>
    {
        //  These policies can be used to parse thousand separated
        //  numbers with at most 2 decimal digits after the decimal
        //  point. e.g. 123,456,789.01
        typedef uint_parser<int, 10, 1, 2>  uint2_t;
        typedef uint_parser<T, 10, 1, -1>   uint_parser_t;
        typedef int_parser<int, 10, 1, -1>  int_parser_t;
        //////////////////////////////////  2 decimal places Max
        template <typename ScannerT>
        static typename parser_result<uint2_t, ScannerT>::type
        parse_frac_n(ScannerT& scan)
        { return uint2_t().parse(scan); }
        //////////////////////////////////  No exponent
template <typename ScannerT> static typename parser_result<chlit<>, ScannerT>::type parse_exp(ScannerT& scan) { return scan.no_match(); } ////////////////////////////////// No exponent
template <typename ScannerT> static typename parser_result<int_parser_t, ScannerT>::type parse_exp_n(ScannerT& scan) { return scan.no_match(); } ////////////////////////////////// Thousands separated numbers template <typename ScannerT> static typename parser_result<uint_parser_t, ScannerT>::type parse_n(ScannerT& scan) { typedef typename parser_result<uint_parser_t, ScannerT>::type RT; static uint_parser<unsigned, 10, 1, 3> uint3_p; static uint_parser<unsigned, 10, 3, 3> uint3_3_p; if (RT hit = uint3_p.parse(scan)) { T n; typedef typename ScannerT::iterator_t iterator_t; iterator_t save = scan.first; while (match<> next = (',' >> uint3_3_p[assign_a(n)]).parse(scan)) { hit.value() *= 1000; hit.value() += n; scan.concat_match(hit, next); save = scan.first; } scan.first = save; return hit; // Note: On erroneous input such as "123,45", the result should
// be a partial match "123". 'save' is used to makes sure that
// the scanner position is placed at the last *valid* parse
// position.
}
return scan.no_match(); } };


 

Статья Numerics раздела может быть полезна для разработчиков на c++ и boost.




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



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


реклама


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

Время компиляции файла: 2024-08-30 11:47:00
2025-05-20 08:52:19/0.0083389282226562/0