使用boost正则表达式解析文本文件

时间:2014-06-06 17:15:36

标签: c++ regex parsing boost expression

我试图使用boost::regex库在C ++中解析文本文件。

我试图将这一行解析为我的程序: 1_3,1,3,0

  • 1_3需要成为字符串
  • 中的名称
  • 1需要成为char
  • 中的X坐标
  • 3需要成为char
  • 中的Y坐标
  • 0,需要成为函数的成本,也是char

你们知道写什么匹配吗?

我试过这个,但它没有工作:

boost::regex rgex("^([0-9]),([0-9]+),([0-9]+),([0-9]+).*");

提前致谢

2 个答案:

答案 0 :(得分:2)

我不会使用正则表达式执行此操作,这使您不得不进行所有类型的转换。

我会直接解析成vector<>个结构

struct record {
    std::string name;
    char x, y, cost;
};

与Boost Spirit一样,

std::vector<record> data;
bool ok = qi::phrase_parse(f, l,
    (qi::lexeme[+~qi::char_(',')] >> ',' >> qi::int_ >> ',' >> qi::int_ >> ',' >> qi::int_) % qi::eol,
    qi::blank,
    data);

if (ok)
{
    std::cout << "Parsed success: " << data.size() << " records\n";
    for(auto& r : data)
        std::cout << r << "\n";
}

请注意,此方法接受并忽略额外的空格(qi::blank)。

查看 Live On Coliru 打印:

Parsed success: 11 records
1_3 1   3   0
16_92   16  92  76
8_31    8   31  13
3_45    3   45  46
12_67   12  67  66
17_27   17  27  2
7_72    7   72  74
0_36    0   36  25
18_30   18  30  50
6_35    6   35  19
16_5    16  5   50

完整代码

供参考

#include <boost/fusion/adapted/struct.hpp>
#include <boost/spirit/include/qi.hpp>

namespace qi = boost::spirit::qi;

struct record {
    std::string name;
    char x, y, cost;

    friend std::ostream& operator<<(std::ostream& os,const record& r) {
        return os << r.name << "\t" << int(r.x) << "\t" << int(r.y) << "\t" << int(r.cost);
    }
};

BOOST_FUSION_ADAPT_STRUCT(record, (std::string, name)(char, x)(char, y)(char, cost))

int main()
{
    std::istringstream iss(
            "1_3,1,3,0\n"
            "16_92,16,92,76\n"
            "8_31,8,31,13\n"
            "3_45,3,45,46\n"
            "12_67,12,67,66\n"
            "17_27,17,27,2\n"
            "7_72,7,72,74\n"
            "0_36,0,36,25\n"
            "18_30,18,30,50\n"
            "6_35,6,35,19\n"
            "16_5,16,5,50"
        );

    boost::spirit::istream_iterator f(iss >> std::noskipws), l;

    std::vector<record> data;
    bool ok = qi::phrase_parse(f, l,
        (qi::lexeme[+~qi::char_(',')]
         >> ',' >> qi::int_ >> ',' >> qi::int_ >> ',' >> qi::int_
        ) % qi::eol,
        qi::blank,
        data);

    if (ok)
    {
        std::cout << "Parsed success: " << data.size() << " records\n";
        for(auto& r : data)
            std::cout << r << "\n";
    } else
    {
        std::cout << "Parse failed\n";
    }

    if (f!=l)
    {
        std::cout << "Remaining unparsed input: '" << std::string(f,l) << "'\n";
    }
}

答案 1 :(得分:1)

在不知道所有可接受的字符的情况下,解析该行的最简单方法是用逗号分隔。

"^([^,]+),([^,]+),([^,]+),(.+)$"

[^,]表示任何非逗号字符。 [^,]+表示一个或多个非逗号字符。