如何使用ifstream逐行解析

时间:2017-12-04 02:51:17

标签: c++ parsing ifstream

如果我想逐行解析文件并将数据存储在单独的变量中,使用getline存储到字符串中并解析/转换为单独的变量似乎有很长的路要走。例如,对于line" ABC a1 1 2 3",如果我想将前两个数据存储到字符串中,而将其余三个数据存储为整数,那么从文件行读取的有效方法是什么逐行并相应地存储它?

1 个答案:

答案 0 :(得分:0)

Boost.Spirit适合用您自己的语法解析自定义数据格式。

#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";
    }
}

Live example