C++ 使用Boost Spirit解析具有数组的结构

C++ 使用Boost Spirit解析具有数组的结构,c++,c++11,struct,boost-spirit-qi,C++,C++11,Struct,Boost Spirit Qi,在我开始之前,是的,我知道有很多与这个主题相关的帖子,我花了一天多的时间阅读,但我对Boost::spirit的了解有限,所以我可以找出如何解决我的问题 我以Boost Employee为例,对其进行修改,让我向您展示 #include <boost/config/warning_disable.hpp> #include <boost/spirit/include/qi.hpp> #include <boost/spirit/include/phoenix_cor

在我开始之前,是的,我知道有很多与这个主题相关的帖子,我花了一天多的时间阅读,但我对Boost::spirit的了解有限,所以我可以找出如何解决我的问题

我以Boost Employee为例,对其进行修改,让我向您展示

#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/include/phoenix_object.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/fusion/include/io.hpp>

#include <iostream>
#include <string>
#include <complex>

namespace client
{
    namespace qi = boost::spirit::qi;
    namespace ascii = boost::spirit::ascii;

    ///////////////////////////////////////////////////////////////////////////
    //  Our employee struct
    ///////////////////////////////////////////////////////////////////////////
    //[tutorial_employee_struct
struct employee
{
    char user[31];
    char pass[34];
    uint16_t page;        // Pagina de usuarios
    uint16_t port;        // Puerto por donde es realiza la comunicación
    uint8_t  ip[4];       // Direccion del socket de juego
    uint16_t amount;
    uint16_t cents;
    char nick[9];
    uint8_t already_logged;
    uint8_t version;
    uint8_t extension;
};
}

// We need to tell fusion about our employee struct
// to make it a first-class fusion citizen. This has to
// be in global scope.

//[tutorial_employee_adapt_struct
BOOST_FUSION_ADAPT_STRUCT(
    client::employee,
    (char, user[31])
    (char, pass[34])
    (uint16_t, page)
    (uint16_t, port)
    (uint8_t, ip[4])
    (uint16_t, amount)
    (uint16_t, cents)
    (char, nick[9])
    (uint8_t, already_logged)
    (uint8_t, version)
    (uint8_t, extension)
)
//]

namespace client
{
    ///////////////////////////////////////////////////////////////////////////////
    //  Our employee parser
    ///////////////////////////////////////////////////////////////////////////////
    //[tutorial_employee_parser
    template <typename Iterator>
    struct employee_parser : qi::grammar<Iterator, employee(), ascii::space_type>
    {
        employee_parser() : employee_parser::base_type(start)
        {
            using boost::spirit::qi::ushort_;
            using ascii::char_;

            start %=
                char_ >> ','
                >> char_ >> ','
                >> ushort_ >> ','

                ;
        }

        qi::rule<Iterator, employee(), ascii::space_type> start;
    };
    //]
}

////////////////////////////////////////////////////////////////////////////
//  Main program
////////////////////////////////////////////////////////////////////////////
int
main()
{
    std::cout << "/////////////////////////////////////////////////////////\n\n";
    std::cout << "\t\tAn employee parser for Spirit...\n\n";
    std::cout << "/////////////////////////////////////////////////////////\n\n";

    std::cout
        << "Give me an employee of the form :"
        << "employee{age, \"surname\", \"forename\", salary } \n";
    std::cout << "Type [q or Q] to quit\n\n";

    using boost::spirit::ascii::space;
    typedef std::string::const_iterator iterator_type;
    typedef client::employee_parser<iterator_type> employee_parser;

    employee_parser g; // Our grammar
    std::string str;
    while (getline(std::cin, str))
    {
        if (str.empty() || str[0] == 'q' || str[0] == 'Q')
            break;

        client::employee emp;
        std::string::const_iterator iter = str.begin();
        std::string::const_iterator end = str.end();
        bool r = phrase_parse(iter, end, g, space, emp);

        if (r && iter == end)
        {
            std::cout << boost::fusion::tuple_open('[');
            std::cout << boost::fusion::tuple_close(']');
            std::cout << boost::fusion::tuple_delimiter(", ");

            std::cout << "-------------------------\n";
            std::cout << "Parsing succeeded\n";
            std::cout << "got: " << boost::fusion::as_vector(emp) << std::endl;
            std::cout << "\n-------------------------\n";
        }
        else
        {
            std::cout << "-------------------------\n";
            std::cout << "Parsing failed\n";
            std::cout << "-------------------------\n";
        }
    }

    std::cout << "Bye... :-) \n\n";
    return 0;
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
命名空间客户端
{
名称空间qi=boost::spirit::qi;
名称空间ascii=boost::spirit::ascii;
///////////////////////////////////////////////////////////////////////////
//我们的员工结构
///////////////////////////////////////////////////////////////////////////
//[教程\u员工\u结构
结构雇员
{
字符用户[31];
charpass[34];
uint16\u t第页;//Pagina de usuarios
uint16_t port;//港口实现城市化
uint8_t ip[4];//juego插座目录
uint16_t金额;
16美分;
查尔尼克[9];
uint8尚未记录;
uint8_t版本;
uint8_t扩展;
};
}
//我们需要告诉fusion我们的员工结构
//让它成为一流的融合公民,这必须
//在全球范围内。
//[教程\u员工\u调整\u结构
增强融合适应结构(
客户:雇员,
(字符,用户[31])
(char,pass[34])
(第16页)
(uint16_t,端口)
(uint8_t,ip[4])
(单位16,金额)
(单位16美分)
(查尔,尼克[9])
(uint8\u t,已记录)
(uint8_t,版本)
(uint8_t,扩展)
)
//]
命名空间客户端
{
///////////////////////////////////////////////////////////////////////////////
//我们的员工解析器
///////////////////////////////////////////////////////////////////////////////
//[教程\u员工\u解析器
模板
struct employee_解析器:qi::grammar
{
employee\u parser():employee\u parser::基本类型(开始)
{
使用boost::spirit::qi::ushort;
使用ascii::char;
起始百分比=
字符“,”
>>字符“,”
>>ushort_u>>,'
;
}
qi::规则开始;
};
//]
}
////////////////////////////////////////////////////////////////////////////
//主程序
////////////////////////////////////////////////////////////////////////////
int
main()
{

std::cout您有10多个字段。您需要在
fusion/container/vector/limits.hpp
中提高默认序列大小限制

在包含任何boost fusion标头(或任何boost标头,因为许多库可能会隐式包含它)之前,请先包含此项:


使用
char[]
而不是
std::string
是否有令人信服的理由?你会让事情变得非常困难的。嗨,谢谢你的两个答案。关于char[]vs std::string:也许我错了,但我无法得到一个包含std::string的固定大小结构,这就是使用char[].关于FUSION\u MAX\u VECTOR\u SIZE,我会稍后再试,如果我错了,请纠正我,但这将解决编译错误,但解析器仍然无法正常工作,对吗?。谢谢您并重新考虑如果您使用
std::string
,结构仍然是固定大小的。您需要“固定大小”的原因是什么?您的解析器表达式看起来像
char\u>>,'>>char\u>>,'>>ushort\u>>,'
。它可能会“工作”。但我不知道您期望它做什么。您能摆脱这个问题,问一下您真正想要实现什么吗?在我看来,您似乎在/不是/寻找增强精神(但可能是增强序列化)让我再解释一下。我可以通过两种方式接收相同的信息:1-TCP/IP套接字(使用Boost.Asio实现)作为原始结构。因此,我使用char[]代替std::string,2-Websocket(使用Websocket++)作为字符串,用“,”分隔。你说得对,我不能完全确定解析器规则的结果,因为我对Spirit的认识是有限的。我定义了FUSION_MAX_VECTOR_大小,现在编译示例,但我只解析这样的字符串“m,p,1000”,解析后我得到user=m,pass=m,page=1000;但如果我得到“mm,pp,1000”,解析器返回false。我尝试以这种方式使用repeat“repeat(1,30)[char_3;]”,但我得到另一个编译错误。
In file included from /usr/include/boost/fusion/include/as_vector.hpp:11:0,
                 from /usr/include/boost/spirit/home/support/attributes.hpp:24,
                 from /usr/include/boost/spirit/home/qi/detail/attributes.hpp:12,
                 from /usr/include/boost/spirit/home/qi/action/action.hpp:16,
                 from /usr/include/boost/spirit/home/qi/action.hpp:14,
                 from /usr/include/boost/spirit/home/qi.hpp:14,
                 from /usr/include/boost/spirit/include/qi.hpp:16,
                 from user.cpp:17:
/usr/include/boost/fusion/container/vector/convert.hpp: In instantiation of ‘struct boost::fusion::result_of::as_vector<const client::employee>’:
/usr/include/boost/fusion/container/vector/convert.hpp:43:5:   required by substitution of ‘template<class Sequence> typename boost::fusion::result_of::as_vector<const Sequence>::type boost::fusion::as_vector(const Sequence&) [with Sequence = client::employee]’
user.cpp:140:65:   required from here
/usr/include/boost/fusion/container/vector/convert.hpp:27:13: error: invalid use of incomplete type ‘struct boost::fusion::detail::as_vector<11>’
             type;
             ^
In file included from /usr/include/boost/fusion/container/vector/convert.hpp:11:0,
                 from /usr/include/boost/fusion/include/as_vector.hpp:11,
                 from /usr/include/boost/spirit/home/support/attributes.hpp:24,
                 from /usr/include/boost/spirit/home/qi/detail/attributes.hpp:12,
                 from /usr/include/boost/spirit/home/qi/action/action.hpp:16,
                 from /usr/include/boost/spirit/home/qi/action.hpp:14,
                 from /usr/include/boost/spirit/home/qi.hpp:14,
                 from /usr/include/boost/spirit/include/qi.hpp:16,
                 from user.cpp:17:
/usr/include/boost/fusion/container/vector/detail/as_vector.hpp:26:12: error: declaration of ‘struct boost::fusion::detail::as_vector<11>’
     struct as_vector;
            ^
In file included from /usr/include/boost/fusion/include/as_vector.hpp:11:0,
                 from /usr/include/boost/spirit/home/support/attributes.hpp:24,
                 from /usr/include/boost/spirit/home/qi/detail/attributes.hpp:12,
                 from /usr/include/boost/spirit/home/qi/action/action.hpp:16,
                 from /usr/include/boost/spirit/home/qi/action.hpp:14,
                 from /usr/include/boost/spirit/home/qi.hpp:14,
                 from /usr/include/boost/spirit/include/qi.hpp:16,
                 from user.cpp:17:
/usr/include/boost/fusion/container/vector/convert.hpp: In instantiation of ‘struct boost::fusion::result_of::as_vector<client::employee>’:
/usr/include/boost/fusion/container/vector/convert.hpp:34:5:   required by substitution of ‘template<class Sequence> typename boost::fusion::result_of::as_vector<Sequence>::type boost::fusion::as_vector(Sequence&) [with Sequence = client::employee]’
user.cpp:140:65:   required from here
/usr/include/boost/fusion/container/vector/convert.hpp:27:13: error: invalid use of incomplete type ‘struct boost::fusion::detail::as_vector<11>’
             type;
             ^
In file included from /usr/include/boost/fusion/container/vector/convert.hpp:11:0,
                 from /usr/include/boost/fusion/include/as_vector.hpp:11,
                 from /usr/include/boost/spirit/home/support/attributes.hpp:24,
                 from /usr/include/boost/spirit/home/qi/detail/attributes.hpp:12,
                 from /usr/include/boost/spirit/home/qi/action/action.hpp:16,
                 from /usr/include/boost/spirit/home/qi/action.hpp:14,
                 from /usr/include/boost/spirit/home/qi.hpp:14,
                 from /usr/include/boost/spirit/include/qi.hpp:16,
                 from user.cpp:17:
/usr/include/boost/fusion/container/vector/detail/as_vector.hpp:26:12: error: declaration of ‘struct boost::fusion::detail::as_vector<11>’
     struct as_vector;
            ^
user.cpp: In function ‘int main()’:
user.cpp:140:65: error: no matching function for call to ‘as_vector(client::employee&)’
             std::cout << "got: " << boost::fusion::as_vector(emp) << std::endl;
                                                                 ^
user.cpp:140:65: note: candidates are:
In file included from /usr/include/boost/fusion/include/as_vector.hpp:11:0,
                 from /usr/include/boost/spirit/home/support/attributes.hpp:24,
                 from /usr/include/boost/spirit/home/qi/detail/attributes.hpp:12,
                 from /usr/include/boost/spirit/home/qi/action/action.hpp:16,
                 from /usr/include/boost/spirit/home/qi/action.hpp:14,
                 from /usr/include/boost/spirit/home/qi.hpp:14,
                 from /usr/include/boost/spirit/include/qi.hpp:16,
                 from user.cpp:17:
/usr/include/boost/fusion/container/vector/convert.hpp:34:5: note: template<class Sequence> typename boost::fusion::result_of::as_vector<Sequence>::type boost::fusion::as_vector(Sequence&)
     as_vector(Sequence& seq)
     ^
/usr/include/boost/fusion/container/vector/convert.hpp:34:5: note:   substitution of deduced template arguments resulted in errors seen above
/usr/include/boost/fusion/container/vector/convert.hpp:43:5: note: template<class Sequence> typename boost::fusion::result_of::as_vector<const Sequence>::type boost::fusion::as_vector(const Sequence&)
     as_vector(Sequence const& seq)
     ^
/usr/include/boost/fusion/container/vector/convert.hpp:43:5: note:   substitution of deduced template arguments resulted in errors seen above
#define FUSION_MAX_VECTOR_SIZE 15