阅读C ++使用boost ::精神二维数组 [英] Read 2D array in C++ using boost::spirit

查看:108
本文介绍了阅读C ++使用boost ::精神二维数组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想读一个简单的二维int数组(空格分隔)为<一个href=\"http://stackoverflow.com/questions/7542522/read-irregular-file-into-a-2-dimension-array-using-c\">here:

 齐:: phrase_parse(B,E +补气:: int_%补气:: EOL,补气::空间 - 齐:: EOL,矢量)

有两点不同,虽然:


  1. 我希望把它变成一维的std ::向量,一行行,无需分离

  2. 如果两行有不同量的整数,这应被视为一个解析错误。

是否有可能做到这一点作为一个单行,例如不写我自己的解析器?正如简单的<一个href=\"http://stackoverflow.com/questions/7542522/read-irregular-file-into-a-2-dimension-array-using-c\">the上面提到的链接?


解决方案

假设你的意思是圣灵的版本(为单行),下面是一个改编版,增加了检查的元素的个数。

如果你想要更多的控制权(和动态输入检查,而不是事后,),那么我建议你看一下另外一个答案,我写,显示三种方法来做到这一点:

 的#include&LT;升压/精神/有/ qi.hpp&GT;
#包括LT&;升压/精神/有/ support_istream_iterator.hpp&GT;
#包括LT&;升压/精神/有/ karma.hpp&GT;命名空间的精神=提振精神::;
命名空间补气=的boost ::精神::补气;
命名空间因缘=的boost ::精神::人缘;诠释的main()
{
    的std :: cin.unsetf(性病:: IOS :: skipws);
    精神:: istream_iterator B(的std :: CIN),E;    的std ::矢量&lt;的std ::矢量&lt;&INT GT; &GT;载体;    如果(气:: phrase_parse(B,E +补气:: int_%补气:: EOL&GT;&GT;气虚:: EOI,补气::空白,矢量))
    {
        的std :: CERR&LT;&LT; 解析失败在'&LT;&LT;标准::字符串(B,E)LT;&LT; '\\ n;
        返回255;
    }    //检查所有行具有元素等量:
    常量汽车number_of_elements = vectors.front()的大小()。
    为(自动&安培;五:矢量)
        如果(v.size()!= number_of_elements)
            的std :: CERR&LT;&LT; 意外的数目的元素:&LT;&LT; v.size()&所述;&下; (预期:&LT;&LT; number_of_elements&LT;&LT;)\\ n;    //打印验证数据
    性病::法院
        &LT;&LT;因果报应::格式(因缘:: right_align(8)因缘:: AUTO_]%','%的'\\ n',向量)
        &LT;&LT;的std :: ENDL;    返回0;
}

的业力位是没有必要的(他们只是在那里输出演示了整个事情)。

更新

要建立更积极的错误检查,你可以这样做:

  INT num_elements = 0;
布尔OK =齐:: phrase_parse(B,E,
        (+气:: int_)PHX :: REF(num_elements)= PHX ::大小(气:: _ 1)]
     &GT;&GT; *(气:: EOL&GT;&GT;气虚::重复(PHX :: REF(num_elements))[齐:: int_])
     &GT;&GT; *补气:: EOL,
     齐::空白,矢量);

其中采用齐::重复来期待 num_elements 在后面的行元素的个数。你可以存储成一个一维阵列

 的#include&LT;升压/精神/有/ qi.hpp&GT;
#包括LT&;升压/精神/有/ phoenix.hpp&GT;
#包括LT&;升压/精神/有/ support_istream_iterator.hpp&GT;
#包括LT&;升压/精神/有/ karma.hpp&GT;命名空间补气=的boost ::精神::补气;
命名空间PHX =提振::凤;
命名空间因缘=的boost ::精神::人缘;诠释的main()
{
    的std :: cin.unsetf(性病:: IOS :: skipws);
    提振精神:: :: istream_iterator B(的std :: CIN),E;    //的std ::矢量&lt;的std ::矢量&lt;&INT GT; &GT;载体;
    的std ::矢量&lt;&INT GT;载体;    INT num_elements = 0;
    布尔OK =齐:: phrase_parse(B,E,
            (+气:: int_)PHX :: REF(num_elements)= PHX ::大小(气:: _ 1)]
         &GT;&GT; *(气:: EOL&GT;&GT;气虚::重复(PHX :: REF(num_elements))[齐:: int_])
         &GT;&GT; *补气:: EOL,
         齐::空白,矢量);    性病::法院LT&;&LT; 检测num_elements:&所述;&下; num_elements&LT;&LT; \\ n;    如果(OK!)
    {
        的std :: CERR&LT;&LT; 解析失败在'&LT;&LT;标准::字符串(B,E)LT;&LT; '\\ n;
        返回255;
    }    如果(B!= E)
        性病::法院LT&;&LT; 尾随未解析:'&LT;&LT;标准::字符串(B,E)LT;&LT; '\\ n;    //打印验证数据
    性病::法院
        &LT;&LT;因果报应:: format_delimited(因缘::列(num_elements)+因缘:: int_],'',向量)
        &LT;&LT;的std :: ENDL;    返回0;
}

注意使用因果报应::列(num_elements)来分割输出转换成正确的数字每行的列。

I would like to read a simple 2D int array (whitespace separated) as here:

qi::phrase_parse(b, e, +qi::int_ % qi::eol, qi::space - qi::eol, vectors)

There are two differences, though:

  1. I want to put it into a 1D std::vector, line by line, without separating
  2. If two lines have a different amount of ints, this shall be recognized as a parsing error.

Is it possible to do this as a one liner, e.g. without writing my own parser? Just as simple as in the link mentioned above?

解决方案

Assuming you meant the Spirit version ("as a one liner"), below is an adapted version that adds the check for number of elements.

Should you want more control (and on the fly input checking, instead of 'in hindsight') then I recommend you look at another answer I wrote that shows three approaches to do this:

.

#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/support_istream_iterator.hpp>
#include <boost/spirit/include/karma.hpp>

namespace spirit = boost::spirit;
namespace qi     = boost::spirit::qi;
namespace karma  = boost::spirit::karma;

int main()
{
    std::cin.unsetf(std::ios::skipws);
    spirit::istream_iterator b(std::cin), e;

    std::vector<std::vector<int> > vectors;

    if (qi::phrase_parse(b, e, +qi::int_ % qi::eol >> qi::eoi, qi::blank, vectors))
    {
        std::cerr << "Parse failed at '" << std::string(b,e) << "'\n";
        return 255;
    }

    // check all rows have equal amount of elements:
    const auto number_of_elements = vectors.front().size();
    for (auto& v : vectors)
        if (v.size() != number_of_elements)
            std::cerr << "Unexpected number of elements: " << v.size() << " (expected: " << number_of_elements << ")\n";

    // print the data for verification
    std::cout 
        << karma::format(karma::right_align(8)[karma::auto_] % ',' % '\n', vectors)
        << std::endl;

    return 0;
}

The karma bits are not necessary (they're just there to output the whole thing for demonstration).

UPDATE

To build in more active error checking, you could do:

int num_elements = 0;
bool ok = qi::phrase_parse(b, e, 
        (+qi::int_) [ phx::ref(num_elements) = phx::size(qi::_1) ]
     >> *(qi::eol >> qi::repeat(phx::ref(num_elements)) [ qi::int_ ])
     >> *qi::eol, 
     qi::blank, vectors);

Which uses qi::repeat to expect the num_elements number of elements on subsequent lines. You can just store that into a 1-dimensional array:

#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/spirit/include/support_istream_iterator.hpp>
#include <boost/spirit/include/karma.hpp>

namespace qi     = boost::spirit::qi;
namespace phx    = boost::phoenix;
namespace karma  = boost::spirit::karma;

int main()
{
    std::cin.unsetf(std::ios::skipws);
    boost::spirit::istream_iterator b(std::cin), e;

    //std::vector<std::vector<int> > vectors;
    std::vector<int> vectors;

    int num_elements = 0;
    bool ok = qi::phrase_parse(b, e, 
            (+qi::int_) [ phx::ref(num_elements) = phx::size(qi::_1) ]
         >> *(qi::eol >> qi::repeat(phx::ref(num_elements)) [ qi::int_ ])
         >> *qi::eol, 
         qi::blank, vectors);

    std::cout << "Detected num_elements: " << num_elements << "\n";

    if (!ok)
    {
        std::cerr << "Parse failed at '" << std::string(b,e) << "'\n";
        return 255;
    }

    if (b!=e)
        std::cout << "Trailing unparsed: '" << std::string(b,e) << "'\n";

    // print the data for verification
    std::cout 
        << karma::format_delimited(karma::columns(num_elements)[+karma::int_], ' ', vectors)
        << std::endl;

    return 0;
}

Note the use of karma::columns(num_elements) to split the output into the correct number of columns per row.

这篇关于阅读C ++使用boost ::精神二维数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆