If I wanted to parse from a file line-by-line and store the data in separate variables, using getline to store into a string and parse/convert to separate variables seems like a long way to do it. For example, for line "ABC a1 1 2 3", if I wanted to store the first two data into strings and the rest of the three into integers, what would be an efficient way to read from the file line-by-line and store it accordingly?
Boost.Spirit is suited for parsing custom data formats with your own grammar.
#include <iostream>
#include <sstream>
#include <string>
#include <tuple>
#include <boost/fusion/include/std_tuple.hpp>
#include <boost/spirit/home/x3.hpp>
std::tuple<std::string, std::string, int, int, int>
parse(std::string const &input)
{
auto iter = input.begin();
using namespace boost::spirit::x3;
auto name = rule<class name, std::string>{}
= lexeme[upper >> *upper];
auto ident = rule<class ident, std::string>{}
= lexeme[alpha >> *alnum];
std::tuple<std::string, std::string, int, int, int> result;
bool r = phrase_parse(iter, input.end(),
name > ident > int_ > int_ > int_,
space, result);
if (!r || iter != input.end())
{
std::string rest(iter, input.end());
throw std::invalid_argument("Parsing failed at " + rest);
}
return result;
}
int main()
{
// This could be a file instead with std::ifstream
std::istringstream input;
input.str("ABC a1 1 2 3\nDEF b2 4 5 6\n");
for (std::string line; std::getline(input, line); )
{
std::string name, ident;
int a, b, c;
std::tie(name,ident,a,b,c) = parse(line);
std::cout << "Found the following entries:\n"
<< "Name: " << name << "\n"
<< "Identifier: " << ident << "\n"
<< "a: " << a << "\n"
<< "b: " << b << "\n"
<< "c: " << c << "\n";
}
}