Read from a file C++

前端 未结 3 1312
猫巷女王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:19

    You could try some code that looks like this. It's kind of a combo of C and C++:

    int main ()
    {
      //assuming that you've completely read in the file to a char* called myFileContents
      char * token;
      token = strtok (myFileContents," ");
      while (token != NULL)
      {
        istringstream iss( token );
        int readInData;
        readInData << iss;
        if(!iss){
          //this means that the data wasn't numeric so don't do anything with it
        }
        else{
          //data was numeric, store it how ever you want
        }
        token = strtok (NULL, " ");
      }
      return 0;
    }
    
    0 讨论(0)
  • 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 <boost/spirit/include/qi.hpp>
    #include <boost/spirit/include/karma.hpp>
    #include <boost/fusion/adapted/std_pair.hpp>
    #include <map>
    namespace qi = boost::spirit::qi;
    namespace karma = boost::spirit::karma;
    
    typedef std::vector<double>                  lookuptable_t;
    typedef std::map<std::string, lookuptable_t> lookuptables_t;
    typedef std::pair<double, double>            point_t;
    typedef std::vector<point_t>                 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);
        }
    
    }
    
    0 讨论(0)
  • 2021-01-07 11:36

    You can use the ignore function to throw away lines of text that are not numbers. Use cin >> x to read a value x from the input file. If that fails, the failbit is set in the input stream, which you must clear. Then, ignore the whole line.

    std::vector<int> data;
    while (!cin.eof())
    {
        int x;
        if (cin >> x) {
            data.push_back(x);
            if (data.size() == 8)
            {
                // do whatever you need with the 8 numbers
                data.clear();
            }
        } else {
            cin.clear();
            cin.ignore(1000, '\n'); // assuming maximum line length less than 1000
        }
    }
    

    (This code assumes reading from cin, which is redirected to another input file)

    0 讨论(0)
提交回复
热议问题