Search code examples
c++excelcsvdequefile-import

Import CSV file, edit it, and output with modified values


I am trying to write a program that takes in a CSV file as input so that I can modify (perform calculations) on the values that are present and output it, again in CSV format with the new values on it.

The struct the values will be stored in is a 2D vector because it allows for large files.

struct data_t: deque <deque <float> >
{
  typedef deque <deque <float> > ::iterator record_iterator;
  typedef deque        <float>   ::iterator field_iterator;
  bool load( const string& filename );
  bool save( const string& filename );
  bool save( ostream& outs );
};

The data is loaded with getline.

bool data_t::load( const string& filename )
{
  string s;
  ifstream f( filename.c_str() );
  while (getline( f, s ))
  {
    deque <float> record;
    istringstream iss( s );
    while (getline( iss, s, ',' ))
    {
      float fieldvalue = 0.0f;
      istringstream( s ) >> fieldvalue;
      record.push_back( fieldvalue );
    }
    this->push_back( record );
  }
  return f.good();
}

And the data is saved with these two functions.

bool data_t::save( const string& filename )
{
  ofstream f( filename.c_str() );
  if (!f) return false;

  return save( f );
}

bool data_t::save( ostream& outs )
{
  for (data_t::record_iterator ri = this->begin(); ri != this->end(); ri++)
  {
    for (data_t::field_iterator fi = ri->begin(); fi != ri->end(); fi++)
      outs << ((fi == ri->begin()) ? "" : ", ") << *fi;
    outs << endl;
  }
  return outs.good();
}

Now, before I output the data, I am trying to create a function that takes the values from specific columns (columns 24, 25 and 48, and 49 since it's a csv file in excel format - rows and columns) and performs several calculations. In essence, I need to be able to access specific values.

Let's just try to pick one value from the first line of column 24. If I use pop_back, this could work considering I pushed values in from the back using push_back when filling up the deque when importing in the first place. Is it something like pop_back(23) since it starts at 0? Would that provide the value that corresponds to row 1, column 24 in the original file?

To help, here is a snapshot of how the data is organized in the file original csv file


Solution

  • There is no such thing as pop_back(int) in std::deque... to gain access to the first cell of column 24 you'd write (*this)[0][23] - the first index is the row index, since you pushed a whole row into your deque of deques, and the second index is the column index.

    or preferably:

    data_t table;
    table.load("bla.csv");
    //process table[0][23]
    //...
    

    or even better: get the load and save member functions out of the struct, and usetypedef vector<vector<float>> table_t - there is no need to inherit deque or vector or any container... in fact, by inheriting a class with no virtual destructor, you're asking for trouble. And you're missing on encapsulation.

    If save and load were free templated functions, it would have been possible to load the CSV to and container, and save you the time if you ever need it.