CodeNoob - 1 year ago 101
C++ Question

How to calculate something in c++?

I am brand new in C++ and data structure. So I am learning and any advice is appreciated. I am trying to extract a csv file which looks like the following in notepad.

Sig1,Sig2,Sig3,Sig4,Sig5,Sig6,Sig7,Sig8
45,200,45,200,45,200,45,200
45,200,45,200,45,200,45,200
45,200,45,200,45,200,45,200
45,200,45,200,45,200,45,200
45,200,45,200,45,200,45,200
45,200,45,200,45,200,45,200
45,200,45,200,45,200,45,200
45,200,45,200,45,200,45,200

I want to calculate the moving average for each column and print out the results for each column. I do know how to read and print the whole csv file by rows and I also know how to calculate the moving average. But I am finding it difficult to put the two things together because I want to calculate the results by "columns" and not rows.I want to use vector(queue(string)) to read the file.

My idea: Suppose I want to read the 1st cell of the row and put it in queue1, the next in queue2 and so on, then I move on to the 2nd row and repeat the process. So the first column would be vector of queue1, then 2nd column would be vector of queue2 and so on. Then I perform moving average for each vector of queue (or column).

Does this sound like a viable idea? Check my code below.
I used the last code of this link to get an idea about how to extract the table from a csv file:
How to read-write into/from text file with comma separated values

``````#include "stdafx.h"
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <queue>

using namespace std;

void readCSV(istream &input, std::vector< std::queue<std::string> > &output)
{
//fstream file("c://data//test_data.csv", ios::in);
string csvLine;

// read every line from the stream
while( getline(input, csvLine) )
{
istringstream csvStream(csvLine);
queue<string> csvColumn;
string csvElement;
// read every element from the line that is seperated by commas
// and put it into the vector or strings
while( getline(csvStream, csvElement, ',') )
{
csvColumn.push(csvElement);
}
output.push_back(csvColumn);
}

}

int main()
{
ofstream myfile;
string sig;
fstream file("c://data//test_data.csv", ios::in);
if(!file.is_open())
{
return 1;
}
// typedef to save typing for the following object
typedef queue<string> Q;
typedef vector<Q> csvVector;
csvVector csvData;
const int Number_Size = 8;
int n =8;
double sum1 = 0.0;
double movingAverage = 0.0;

// Read data and perform moving average for each column
for(csvVector::iterator i = csvData.begin(); i != csvData.end(); ++i)
{
for(vector<Q>::iterator j = i ->begin(); j !=i ->end(); ++j)
{
for (int i = 0; i <= (Number_Size - n); i++)
{
sum1 = 0.0;

for( int i=0; int j = i; j < i + n; j++)
{
sum1 += sig[j];
movingAverage = sum1/n;
cout << movingAverage << endl;
}

}
}

}

myfile.close();
system("pause");

}
``````

The problem with your approach is the way how you parse the csv file and store it. Your code creates a queue holding strings for each row and adds all created queues in a vector. This becomes problematic when you now want to iterate through a column.
Try to create a vector for each element you find in the first row. When processing any other row than the first, access the already existing vectors and add the strings. If you follow this approach, you will end up with vectors holding the content of the columns instead of the rows as it stands now. Here is some sample code:

``````    void readCSV(istream &input, vector<vector<string>>& vOutput)
{
int iRowCnt = 0;
string csvLine;

// read every line from the stream
while( getline(input, csvLine) )
{
int iColCnt = 0;
istringstream inpStreamLine(csvLine);
string strElement;

// read every element from the line that is separated by commas
while( getline(inpStreamLine, strElement, ',') )
{
// if first line, create vector for each column
if (iRowCnt == 0)
{
vector<string> vColumn;
vOutput.push_back(vColumn);
}
// access the vector with index iColCnt and add sub string
vOutput.at(iColCnt).push_back(strElement);
iColCnt++;
}
iRowCnt++;
}
}

void getNumericValues(vector<vector<string>> &vColumns, vector<vector<int>>& vOutput)
{
// iterate across rows (signals)
for (vector< vector<string> >::iterator iterCol = vColumns.begin() ; iterCol != vColumns.end() ; ++iterCol)
{
vector<int> vColumn;
vector<string> *vCol = &(*iterCol);
// iterate across columns (signal values) while skipping first line
// convert strings to integer values and add them to vNumValues
for (vector<string>::iterator iterRow = vCol->begin()+1; iterRow < vCol->end(); ++iterRow)
{
string strElem = *iterRow;
string::size_type sz;
vColumn.push_back(stoi(strElem, &sz));
}
vOutput.push_back(vColumn);
}
}

void getMovingAveragesColumn(vector<int> &vNumValues, int iWndSize, vector<int>& vOutput)
{
if (vNumValues.size()<iWndSize)        // check if we have enough values
return;

for (vector<int>::iterator iter = vNumValues.begin() ; iter < vNumValues.end()-iWndSize ; ++iter)
{
int iMovAvg = 0;
for (int ii=0; ii<iWndSize; ii++)
{
iMovAvg+= *(iter+ii);
}
iMovAvg /= iWndSize;
vOutput.push_back(iMovAvg);
}
}

void getMovingAveragesMatrix(vector<vector<int>> &vNumValues, int iWndSize, vector<vector<int>>& vOutput)
{
for (vector<vector<int>>::iterator iterCol = vNumValues.begin() ; iterCol < vNumValues.end() ; ++iterCol)
{
vector<int> *vCol = &(*iterCol);
vector<int> vMovAvg;
getMovingAveragesColumn(*vCol, iWndSize, vMovAvg);
vOutput.push_back(vMovAvg);
}
}

int _tmain(int argc, _TCHAR* argv[])
{
ofstream myfile;
fstream file("c://tmp//test_data.csv", ios::in);
if(!file.is_open())
{
return 1;
}
// vector of vectors for storing strings in matrix form
vector<vector<string>> vData;

// convert to integers
vector<vector<int>> vNumValues;
getNumericValues(vData, vNumValues);

// get moving average values
vector<vector<int>> vMovAverages;
getMovingAveragesMatrix(vNumValues, 3, vMovAverages);

// print the moving average values
for (vector<vector<int>>::iterator iterCol = vMovAverages.begin() ; iterCol < vMovAverages.end() ; ++iterCol)
{
vector<int> *vCol = &(*iterCol);
for (vector<int>::iterator iterRow= vCol->begin() ; iterRow < vCol->end() ; ++iterRow)
{
cout<< *iterRow << " ";
}
cout<<"\n";
}

myfile.close();
system("pause");
}
``````
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download