简体   繁体   中英

parsing text files using boost regular expressions

I'm trying to parse a textfile in C++ using the boost::regex library.

I'm trying to parse this line into my program: 1_3,1,3,0

  • 1_3 needs to become the name in string
  • 1 needs to become an X-coordinate in char
  • 3 needs to become an Y-coordinate in char
  • 0,needs to become a cost for a function, also a char

Do you guys know what match to write?

I tried this one but it didn't work:

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

Thanks in advance

I'd not do this using regexes, which leaves you having to the all the type conversions.

I'd parse directly into a vector<> of structs

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

With Boost Spirit, like

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

Note that this approach accepts and ignores extra whitespace ( qi::blank ).

See it Live On Coliru which prints:

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

Full Code

for reference

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

Without knowing all the acceptable characters, the simplest way to parse the line is to separate by the commas.

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

[^,] means any non-comma character. [^,]+ means 1 or more non-comma character.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM