Read from a file C++

前端 未结 3 1337
猫巷女王i
猫巷女王i 2021-01-07 10:40

Hi I want to read data from a VTK file into my C++ program. Here is how my files will typically look.

POINTS 2 double

1 2

3条回答
  •  天命终不由人
    2021-01-07 11:33

    Once again I couldn't really resist the finger exercise in using Boost Spirit for this purpose.

    Explanation

    Behold this very adhoc and minimalistic sample that

    • parses the given text (using Spirit Qi) into

      • a points collection (vector of pair)
      • a dynamic map of lookup tables (identified by a name - e.g. "pressure") and containing vector)
    • does rudimentary error reporting on unpexpected input

    • prints the parsed data back into compact formatting (this uses Spirit Karma)

    • it is whitespace tolerant (though the newlines are required as in the input)

    Flaws:

    • it is really quick and dirty: it should really be a grammar class with
      • separate rule definitions
        • more readable
        • more debuggable
      • explicit semantic input checks (lookup table names, number of elements in each data table (the counts in POINTS _n and POINT_DATA n are being handsomely ignored now)
      • use phoenix (or c++0x std::move) to prevent the copying of the lookup table data

    Sample

    Output of the code/input as shown (note the intentional 'bogus' input demonstrating the error reporting):

    Parse failed remaining: 'bogus'
    Points: [1.0,2.0], [3.0,4.0]
    density: 7.0, 8.0
    pressure: 5.0, 6.0
    

    And the code (c++, tested with boost 1_47_0):

    #include 
    #include 
    #include 
    #include 
    namespace qi = boost::spirit::qi;
    namespace karma = boost::spirit::karma;
    
    typedef std::vector                  lookuptable_t;
    typedef std::map lookuptables_t;
    typedef std::pair            point_t;
    typedef std::vector                 points_t;
    
    int main()
    {
        std::string input = 
            "POINTS 2 double\n"
            "1 2\n"
            "3 4\n"
            "POINT_DATA 2\n"
            "SCALARS pressure double\n"
            "LOOKUP_TABLE default\n"
            "5\n"
            "6\n"
            "SCALARS density double\n"
            "LOOKUP_TABLE default\n"
            "7\n"
            "8 bogus";
    
        points_t points;
        lookuptables_t lookuptables;
    
        {
            std::string::const_iterator f(input.begin()), l(input.end());
    
            using namespace qi;
            bool ok = phrase_parse(f, l, 
                "POINTS" > omit[ uint_ ] > "double" > eol >>
                (double_ >> double_) % eol > eol >>
                "POINT_DATA" > omit [ uint_ ],
                char_(" \t"), points);
    
            while (ok && f!=l)
            {
                std::string name;
                lookuptable_t table;
    
                ok = phrase_parse(f, l, 
                    eol >> "SCALARS" > +raw [ eps >> "pressure"|"density" ] > "double" > eol >
                    "LOOKUP_TABLE" > "default" > eol >
                    double_ % eol,
                    char_(" \t"), name, table);
    
                if (ok && !lookuptables.insert(std::make_pair(name, table)).second)
                    std::cerr << "duplicate table for '" << name << "' ignored" << std::endl;
            }
    
            if (!ok || (f!=l))
                std::cerr << "Parse " << (ok?"success":"failed") << " remaining: '" << 
                    std::string(f, std::min(f+10, l)) << "'" << std::endl;
        }
    
        {
            using namespace karma;
            std::cout << format(
                    "Points: " << ('[' << double_ << ',' << double_ << ']') % ", " << eol << 
                    +(string << ": " << auto_ % ", " << eol),
                    points, lookuptables);
        }
    
    }
    

提交回复
热议问题