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.