/*
 *   Examples of how to read, process, and save data using files and
 *   a vector of vectors to store the data.
 *
 *  Example input file:
 *  1    10
 *  3e5  30
 *  5    50  500 5000
 *  10   100
 *  20   200   2342.2352345125
 *
 */

#include <fstream>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#include <iomanip>

using namespace std;

int ReadFile(string filename, vector< vector<double> >& data )
/*
 *  Function that reads file into data structure.
 *  Assumption that file contains rows and columns of numbers.
 *  No checks are made to check if all columns have the same size
 *                     to give errors if data can not be interpreted as a double.
 *
 *
 * Notice vector< vector<double> >& data   & means that data is a REFERENCE to
 * not a COPY of the calling data structure. Hence data in the main, ReadFile, Savefile
 * refers to exactly the same data structure 
 */
{

    ifstream fi(filename);

    while (fi)  // As long as theres data:
        {
           // read line from file
           char cstring[256];
           fi.getline(cstring,256);

           if (fi) // Only process line if file is still good.
              {
                  // Process line
                  vector<double> row;

                  // Reinterpret line of characters as a string stream
                  // such that we can use >> to extract and interpret as doubles.
                  stringstream sstream(cstring);
                  while (sstream)
                     {
                        double x;
                        sstream >> x;

                        // sstream is false if we reached the end of the line or
                        // characters could not be interpreted as a double.
                        // in both cases x is invalid and shouldn't be saved.

                        if (sstream) row.push_back(x);
                  }

                  // Now push this row of data onto our data structure.
                  data.push_back(row);
            }
        }
    fi.close(); // Close file.

    return data.size();
}

bool SaveData(string fname, vector< vector<double> >& data)
{
    ofstream fo(fname);

    // We could not open the file for some reason, so return false.
    if (!fo) return false;

    // Now save all the data.
    for (unsigned int r=0;r<data.size() ; r++)
      {
        for (unsigned int c=0;c<data[r].size() ; c++)
          {
              fo << setprecision(10) <<  data[r][c] << " ";
          }
        fo << "\n";
      }
    fo.close();
    return true; // We saved the data.
}

int main()
{
   vector< vector<double> > data;
   ReadFile( "testfile.dat" , data );

// Print out rows/columns sizes of the data we have read.

   cout << "Rows of data: " << data.size() << "\n";
   for (unsigned int r=0;r<data.size() ; r++)
     {
        cout << "Row " << r << " contains " << data[r].size() << " columns\n";
     }

// print out contents:
   for (unsigned int r=0;r<data.size() ; r++)
     {
       for (unsigned int c=0;c<data[r].size() ; c++)
         {
             cout << data[r][c] << " ";
         }
       cout << "\n";
     }

// As an example of how to process the data, we just multiply and divide some
// columns by some numbers, but anything is possible.

// First divide column 1 by 10  data[r][1]  Note c++ counting first column is 0.

   for (unsigned int r=0;r<data.size() ; r++)
     {
         data[r][1]/=10;
     }

// multiply row 4 by 25   data[4][c]    Note C+ counting first row is 0.

   for (unsigned int c=0;c<data[4].size() ; c++)
     {
         data[4][c]*=25;
     }

// Print out contents:

   SaveData("testfileout.dat",data);

   return 0;
}

