Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ Reading Multiple Variables from Text Line

Tags:

c++

file

text

I'm quite new to C++ and I have a question about reading text file data.

I have a text file that contains data set like this:

The Undertaker 4 3 2 6 
John Cena 22 19 8 5
Kurt Angle 5 9 33 17

and the code I'm using to read it is

for(int i=0; i<numWrestlers; i++)
{
    getline(infile, firstName, " ");
    getline(infile, lastName, " ");
    for(j=1; j<4; i++) 
         {
         getline(infile, score[i], " ")
         }
}

but occasionally the file will have lines that look like:

Rob Van Dam 45 65 35 95
Hitman Bret Hart 34 9 16
Hulk Hogan 9

I don't know how to handle these entries. Any help would be appreciated, if this is a repeat question please link the original. Thanks

like image 659
Luke Boon Avatar asked May 18 '16 08:05

Luke Boon


1 Answers

Here's that Spirit approach that people have been clamouring for suggested:

namespace grammar {
    using namespace x3;
    auto name   = raw [ +(!int_ >> lexeme[+graph]) ];
    auto record = rule<struct _, Record> {} = (name >> *int_);
    auto table  = skip(blank) [record % eol];
}

The trick is to accept words as part of the name until the first data value (!int_ does that part).

The record rule parses into Record:

struct Record {
    std::string name;
    std::vector<int> data;
};

Full Demo Live

Live On Coliru

#include <boost/spirit/include/support_istream_iterator.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/spirit/home/x3.hpp>

#include <iostream>

namespace x3 = boost::spirit::x3;

struct Record {
    std::string name;
    std::vector<int> data;
};

BOOST_FUSION_ADAPT_STRUCT(Record, name, data)

namespace grammar {
    using namespace x3;
    auto name   = raw [ +(!int_ >> lexeme[+graph]) ];
    auto record = rule<struct _, Record> {} = (name >> *int_);
    auto table  = skip(blank) [record % eol];
}

int main()
{
    std::istringstream iss(R"(The Undertaker 4 3 2 6 
    John Cena 22 19 8 5
    Rob Van Dam 45 65 35 95
    Hitman Bret Hart 34 9 16
    Hulk Hogan 9
    Kurt Angle 5 9 33 17)");

    std::vector<Record> table;

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

    if (parse(f, l, grammar::table, table)) {
        for (auto& r : table) {
            std::copy(r.data.begin(), r.data.end(), std::ostream_iterator<int>(std::cout << r.name << ";", ";"));
            std::cout << "\n";
        }
    }
}

Prints

The Undertaker;4;3;2;6;
John Cena;22;19;8;5;
Rob Van Dam;45;65;35;95;
Hitman Bret Hart;34;9;16;
Hulk Hogan;9;
Kurt Angle;5;9;33;17;
like image 74
sehe Avatar answered Sep 22 '22 09:09

sehe