struct add_1000
{
add_1000(unsigned& r_) : r(r_) {}
void operator()(wchar_t) const { r += 1000; }
unsigned& r;
};

struct add_roman
{
add_roman(unsigned& r_) : r(r_) {}
void operator()(unsigned n) const { r += n; }
unsigned& r;
};

///////////////////////////////////////////////////////////////////////////////
//
// roman (numerals) grammar
//
///////////////////////////////////////////////////////////////////////////////
struct roman : public grammar
{
template
struct definition
{
definition(roman const& self)
{
first
= +ch_p(L'M') [add_1000(self.r)]
|| hundreds_p [add_roman(self.r)]
|| tens_p [add_roman(self.r)]
|| ones_p [add_roman(self.r)];

// Note the use of the || operator. The expression
// a || b reads match a or b and in sequence. Try
// defining the roman numerals grammar in YACC or
// PCCTS. Spirit rules! Smile | :)
}

rule first;
rule const&
start() const { return first; }
};

roman(unsigned& r_) : r(r_) {}
unsigned& r;
};
BOOST_SPIRIT_CLASSIC_NAMESPACE_END
}}

上面的代码可以很好地处理字符串,但是当我尝试解析宽字符串时,尽管我没有遇到任何编译错误,但是代码无法完成从罗马到int的转换,反之亦然。我知道+ ch_p(p)仅接受字符或字符串,而不接受宽字符串..我如何设置规则来设置我设置scannerT解析器的宽字符串和wchar_t const *被解析....
RomanNumeralConversion::
RomanToInt(const std::wstring& romanNumeral)
{
    std::wstring upperRoman(romanNumeral);
    FDStringUtils::ToUpper(upperRoman.begin(), upperRoman.end());
    unsigned int result = 0;
    BOOST_SPIRIT_CLASSIC_NS::roman roman_p(result);
    if (parse(upperRoman.c_str(), roman_p).full)
        return result;
    return -1;
}

最佳答案

你真幸运。罗马数字是一个教程项目。让您有机会使用Spirit V2,进入21世纪:)

  • http://www.boost.org/doc/libs/1_57_0/libs/spirit/doc/html/spirit/qi/tutorials/roman_numerals.html

  • 因此,请使用classic/example/fundamental/roman_numerals.cpp代替example/qi/roman.cpp

    更改为使用wchar_t:
  • sed的/ char / wchar_t / g; s / std::cout / std::wcout / g; s / std::cin / std::wcin / g; s / std::string / std::wstring / g'
  • 然后将所有文字标记为“宽”

  • Live On Coliru
    #include <boost/spirit/include/qi.hpp>
    #include <boost/spirit/include/support_standard_wide.hpp>
    #include <boost/spirit/include/phoenix.hpp>
    
    #include <iostream>
    #include <string>
    
    namespace client
    {
        namespace qi   = boost::spirit::qi;
        namespace wide = qi::standard_wide;
    
        ///////////////////////////////////////////////////////////////////////////////
        //  Parse roman hundreds (100..900) numerals using the symbol table.
        //  Notice that the data associated with each slot is the parser's attribute
        //  (which is passed to attached semantic actions).
        ///////////////////////////////////////////////////////////////////////////////
        struct hundreds_ : qi::symbols<wchar_t, unsigned>
        {
            hundreds_()
            {
                add
                    (L"C"    , 100)
                    (L"CC"   , 200)
                    (L"CCC"  , 300)
                    (L"CD"   , 400)
                    (L"D"    , 500)
                    (L"DC"   , 600)
                    (L"DCC"  , 700)
                    (L"DCCC" , 800)
                    (L"CM"   , 900)
                ;
            }
    
        } hundreds;
    
        ///////////////////////////////////////////////////////////////////////////////
        //  Parse roman tens (10..90) numerals using the symbol table.
        ///////////////////////////////////////////////////////////////////////////////
        //[tutorial_roman_tens
        struct tens_ : qi::symbols<wchar_t, unsigned>
        {
            tens_()
            {
                add
                    (L"X"    , 10)
                    (L"XX"   , 20)
                    (L"XXX"  , 30)
                    (L"XL"   , 40)
                    (L"L"    , 50)
                    (L"LX"   , 60)
                    (L"LXX"  , 70)
                    (L"LXXX" , 80)
                    (L"XC"   , 90)
                ;
            }
    
        } tens;
        //]
    
        ///////////////////////////////////////////////////////////////////////////////
        //  Parse roman ones (1..9) numerals using the symbol table.
        ///////////////////////////////////////////////////////////////////////////////
        struct ones_ : qi::symbols<wchar_t, unsigned>
        {
            ones_()
            {
                add
                    (L"I"    , 1)
                    (L"II"   , 2)
                    (L"III"  , 3)
                    (L"IV"   , 4)
                    (L"V"    , 5)
                    (L"VI"   , 6)
                    (L"VII"  , 7)
                    (L"VIII" , 8)
                    (L"IX"   , 9)
                ;
            }
    
        } ones;
    
        ///////////////////////////////////////////////////////////////////////////////
        //  roman (numerals) grammar
        //
        //      Note the use of the || operator. The expression
        //      a || b reads match a or b and in sequence. Try
        //      defining the roman numerals grammar in YACC or
        //      PCCTS. Spirit rules! :-)
        ///////////////////////////////////////////////////////////////////////////////
        template <typename Iterator>
        struct roman : qi::grammar<Iterator, unsigned()>
        {
            roman() : roman::base_type(start)
            {
                using qi::lit;
                using wide::char_;
    
                using qi::eps;
                using qi::_val;
                using qi::_1;
    
                start = eps             [_val = 0] >>
                    (
                        +lit(L'M')      [_val += 1000]
                        ||  hundreds    [_val += _1]
                        ||  tens        [_val += _1]
                        ||  ones        [_val += _1]
                    )
                ;
            }
    
            qi::rule<Iterator, unsigned()> start;
        };
    }
    
    ///////////////////////////////////////////////////////////////////////////////
    //  Main program
    ///////////////////////////////////////////////////////////////////////////////
    int
    main()
    {
        typedef std::wstring::const_iterator iterator_type;
        typedef client::roman<iterator_type> roman;
    
        roman roman_parser; // Our grammar
    
        std::wstring str;
        unsigned result;
        while (std::getline(std::wcin, str))
        {
            if (str.empty() || str[0] == L'q' || str[0] == L'Q')
                break;
    
            std::wstring::const_iterator iter = str.begin();
            std::wstring::const_iterator end = str.end();
            bool r = parse(iter, end, roman_parser, result);
    
            if (r && iter == end)
            {
                std::wcout << L"-------------------------\n";
                std::wcout << L"Parsing succeeded\n";
                std::wcout << L"result = " << result << std::endl;
                std::wcout << L"-------------------------\n";
            }
            else
            {
                std::wstring rest(iter, end);
                std::wcout << L"-------------------------\n";
                std::wcout << L"Parsing failed\n";
                std::wcout << L"stopped at: \": " << rest << L"\"\n";
                std::wcout << L"-------------------------\n";
            }
        }
    
        std::wcout << L"Bye... :-) \n\n";
    }
    

    输入“MDCCXXVII”时打印1727

    关于c++ - 使用宽字符串时解析罗马数字时,Boost Spirit库无法正常工作,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/28984540/

    10-11 22:33
    查看更多