CSV Parsing with c++

后端 未结 2 1508
佛祖请我去吃肉
佛祖请我去吃肉 2020-12-20 07:57

I\'m trying to create a code that will parse through a csv database with stock information. Currently, I have the code generated so that it will search with a keyword and pr

相关标签:
2条回答
  • 2020-12-20 08:27

    Here it is your solution (the most close to what you requested):

    #include <iostream>
    #include <fstream>
    #include <string>
    #include <sstream>
    #include <vector>
    
    using namespace std;
    
    typedef std::vector<std::string> record;
    
    std::istream&
    operator>>(
      std::istream& is,
      record&       r)
    {
      r.clear();
    
      string line;
      getline(is, line);
    
      istringstream iss(line);
      string field;
    
      while (getline(iss, field, ',' ))
        r.push_back(field);
    
      return is;
    }
    
    int
    main()
    {
    
      ifstream file("Stock Database.csv");
      record headers, r;
    
      if (file.good())
        file >> headers;
    
      while (file >> r)
      {
        for (int i = 0; i < r.size(); i++)
          cout << headers[i] <<  ":\t" << r[i] << endl;
    
        cout << "------------------------------" << endl;
      }
    
      return 0;
    }
    
    // EOF
    

    The content of the "Stock Database.csv" file is:

    Symbol,Name,Price,High Today,Low Today,52 Week Low
    GOOG,Google Inc.,$568.77 ,$570.25 ,$560.35
    AAPL,Apple Inc.,$93.28 ,$63.89 ,$99.44
    

    Just do with the record whatever you want. The first read from the file suppose to bring you headers. Every next read fill each record with csv values.

    0 讨论(0)
  • 2020-12-20 08:30

    First a comma should be parsed as whitespace. You can do this by changing the internal std::ctype<charT> facet in the stream's locale:

    struct csv_classification : std::ctype<char> {
        csv_classification() : ctype(make_table()) { }
    private:
        static mask* make_table() {
            const mask* classic = classic_table();
            static std::vector<mask> v(classic, classic + table_size);
            v[','] |= space;
            v[' '] &= ~space;
            return &v[0];
        }
    };
    

    Then set the locale using:

    ifs.imbue(std::locale(ifs.getloc(), new csv_classification));
    

    Next make a manipulator that checks to see if you're at the end of the line. If you are it sets the std::ios_base::failbit flag in the stream state. Also use internal storage to tell if the record belongs as a key or value in the map. Borrowing a bit from Dietmar...

    static int row_end = std::ios_base::xalloc();
    
    std::istream& record(std::istream& is) {
        while (std::isspace(is.peek())) {
            int c(is.peek());
            is.ignore();
    
            if (c == '\n') {
                is.iword(row_end) = !is.iword(row_end);
                is.setstate(std::ios_base::failbit);
            }
        }
        return is;
    }
    

    Then you can do:

    std::vector<std::string> keys, values;
    
    for (std::string item;;) {
        if (ifs >> record >> item)
            keys.push_back(item);
        else if (ifs.eof())
            break;
        else if (ifs.iword(row_end)) {
            ifs.clear();
            while (ifs >> record >> item)
                values.push_back(item);
        }
        else
            break;
    }
    

    Now we need to apply both the keys and values and print them out. We can create a new algorithm for that:

    template<class Iter1, class Iter2, class Function>
    void for_each_binary_range(Iter1 first1, Iter1 last1,
                               Iter2 first2, Iter2 last2, Function f)
    {
        assert(std::distance(first1, last1) <= std::distance(first2, last2));
    
        while (first1 != last1) {
            f(*first1++, *first2++);
        }
    }
    

    Finally we do:

    for_each_binary_range(std::begin(keys),   std::end(keys),
                          std::begin(values), std::end(values),
    [&] (std::string const& key, std::string const& value)
    {
        std::cout << key << ": " << value << std::endl;
    }
    

    Live Demo

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