Reputation: 657
I have a CSV file formatted as below:
1,50,a,46,50,b
2, 20,s,56,30,f
3,35,b,5,67,s
...
How can I turn that to a 2D array so that I could do some calculations?
void Core::parseCSV(){
std::ifstream data("test.csv");
std::string line;
while(std::getline(data,line))
{
std::stringstream lineStream(line);
std::string cell;
while(std::getline(lineStream,cell,','))
{
//not sure how to create the 2d array here
}
}
};
Upvotes: 10
Views: 40833
Reputation: 984
Try this,
void Core::parseCSV()
{
std::ifstream data("test.csv");
std::string line;
std::vector<std::vector<std::string> > parsedCsv;
while(std::getline(data,line))
{
std::stringstream lineStream(line);
std::string cell;
std::vector<std::string> parsedRow;
while(std::getline(lineStream,cell,','))
{
parsedRow.push_back(cell);
}
parsedCsv.push_back(parsedRow);
}
};
NOTE: this will not work if the content of the columns have ,
Upvotes: 9
Reputation: 5230
I would go for something like this (untested, incomplete) and eventually refine operator >>
, if you have strings instead of chars, or floats instead of ints.
struct data_t
{
int a ;
int b ;
char c ;
int d ;
int e ;
char f ;
} ;
std::istream &operator>>(std::istream &ist, data_t &data)
{
char comma ;
ist >> data.a >> comma
>> data.b >> comma
>> data.c >> comma
>> data.d >> comma
>> data.e >> comma
>> data.f
;
return ist ;
}
void Core::parseCSV(){
std::ifstream data("test.csv");
std::string line;
std::vector<data_t> datavect ;
while(std::getline(data,line))
{
data_t data ;
std::stringstream lineStream(line);
lineStream >> data ;
datavect.push_back(data) ;
}
};
Upvotes: -1
Reputation: 71
Following code is working. hope it can help you. It has a CSV file istream_iterator-like class. It is a template so that it can read strings, ints, doubles, etc. Its constructors accept a char delimiter, so that it may be used for more than strictly comma-delimited files. It also has a specialization for strings so that white space characters could be retained.
#include <iostream>
#include <sstream>
#include <fstream>
#include <iterator>
using namespace std;
template <class T>
class csv_istream_iterator: public iterator<input_iterator_tag, T>
{
istream * _input;
char _delim;
string _value;
public:
csv_istream_iterator( char delim = ',' ): _input( 0 ), _delim( delim ) {}
csv_istream_iterator( istream & in, char delim = ',' ): _input( &in ), _delim( delim ) { ++*this; }
const T operator *() const {
istringstream ss( _value );
T value;
ss >> value;
return value;
}
istream & operator ++() {
if( !( getline( *_input, _value, _delim ) ) )
{
_input = 0;
}
return *_input;
}
bool operator !=( const csv_istream_iterator & rhs ) const {
return _input != rhs._input;
}
};
template <>
const string csv_istream_iterator<string>::operator *() const {
return _value;
}
int main( int argc, char * args[] )
{
{ // test for integers
ifstream fin( "data.csv" );
if( fin )
{
copy( csv_istream_iterator<int>( fin ),
csv_istream_iterator<int>(),
ostream_iterator<int>( cout, " " ) );
fin.close();
}
}
cout << endl << "----" << endl;
{ // test for strings
ifstream fin( "data.csv" );
if( fin )
{
copy( csv_istream_iterator<string>( fin ),
csv_istream_iterator<string>(),
ostream_iterator<string>( cout, "|" ) );
fin.close();
}
}
return 0;
}
Upvotes: 3