我是C ++和数据结构的新手。所以我正在学习,任何建议表示赞赏。我试图在记事本中提取一个类似于以下内容的csv文件。
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
我想计算每列的移动平均值并打印出每列的结果。我知道如何按行读取和打印整个csv文件,我也知道如何计算移动平均值。但我发现很难把这两件事放在一起,因为我想通过"列"来计算结果。而不是rows.I想使用vector(queue(string))来读取文件。
我的想法:假设我想读取行的第一个单元格并将其放入queue1,队列2中的下一个单元格,依此类推,然后我转到第二行并重复该过程。所以第一列是queue1的向量,然后第二列是queue2的向量,依此类推。然后我为队列(或列)的每个向量执行移动平均值。
这听起来像是一个可行的想法吗?检查下面的代码。 我使用此链接的最后一个代码来了解如何从csv文件中提取表: 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())
{
cout << "File not found!\n";
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;
readCSV(file, csvData);
// 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");
}
答案 0 :(得分:0)
您的方法的问题在于您解析csv文件并存储它的方式。您的代码创建一个包含每行的字符串的队列,并在向量中添加所有创建的队列。当您现在想要遍历列时,这会成为问题。
尝试为第一行中找到的每个元素创建一个向量。处理除第一行之外的任何其他行时,访问已存在的向量并添加字符串。如果您遵循这种方法,您将最终得到包含列内容的向量而不是现在的行。以下是一些示例代码:
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())
{
cout << "File not found!\n";
return 1;
}
// vector of vectors for storing strings in matrix form
vector<vector<string>> vData;
readCSV(file, 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");
}